|
@@ -92,8 +92,9 @@ for instance in influxdb_yaml:
|
|
|
|
|
|
data_energy = dict()
|
|
|
data_momentary = dict()
|
|
|
-saved_todays_date = dict()
|
|
|
+saved_today_date = dict()
|
|
|
influxdb_energy_lastWriteTime = dict()
|
|
|
+energy_history_lastPublished = dict()
|
|
|
|
|
|
saved_energy_today_min = dict()
|
|
|
saved_energy_yesterday_total = dict()
|
|
@@ -144,19 +145,26 @@ def processMeterData(data):
|
|
|
#print(json.dumps(meters_yaml[cJson['C']]))
|
|
|
#print(json.dumps(cJson))
|
|
|
|
|
|
+ # parse JSON object received from DualS0ImpCounter hardware
|
|
|
if cJson:
|
|
|
+
|
|
|
+ # extract variables from JSON
|
|
|
cNum = cJson.get('C')
|
|
|
- cReading = float(cJson.get('reading', None))
|
|
|
#print(cNum)
|
|
|
-
|
|
|
+ cReading = float(cJson.get('reading', None))
|
|
|
dTime = cJson.get('dTime', None)
|
|
|
|
|
|
+ # declare variables for program sequence control
|
|
|
write_energy_to_influxdb = False
|
|
|
|
|
|
- cName = meters_yaml[cNum].get('name', False)
|
|
|
+ # get config data for this meter number
|
|
|
+ cName = meters_yaml[cNum].get('name', None)
|
|
|
statTopic = meters_yaml[cNum].get('statTopic', None)
|
|
|
unit = meters_yaml[cNum].get('unit', None)
|
|
|
+ publishJSON = meters_yaml[cNum].get('MQTTPublishJSON', False)
|
|
|
|
|
|
+ extendJSON = False
|
|
|
+ if publishJSON or verbose: extendJSON = True
|
|
|
|
|
|
conv_unit = meters_yaml[cNum].get('conv_unit', None)
|
|
|
conv_factor = meters_yaml[cNum].get('conv_factor', None)
|
|
@@ -167,7 +175,6 @@ def processMeterData(data):
|
|
|
cost_per_unit = meters_yaml[cNum].get('cost_per_unit', None)
|
|
|
cost_from_conv = meters_yaml[cNum].get('cost_from_conv', False)
|
|
|
|
|
|
-
|
|
|
momUnit = meters_yaml[cNum].get('momUnit', None)
|
|
|
momType = meters_yaml[cNum].get('momType', None)
|
|
|
|
|
@@ -179,31 +186,28 @@ def processMeterData(data):
|
|
|
|
|
|
impPerUnit = meters_yaml[cNum].get('impPerUnit', None)
|
|
|
|
|
|
- if cName:
|
|
|
- cJson['name'] = cName
|
|
|
-
|
|
|
momFactor = meters_yaml[cNum].get('momFactor', None)
|
|
|
- if not momFactor:
|
|
|
+ if momFactor is None:
|
|
|
momFactor = 1
|
|
|
|
|
|
momDigits = meters_yaml[cNum].get('momDigits', None)
|
|
|
- if momDigits == None:
|
|
|
+ if momDigits is None:
|
|
|
momDigits = 3
|
|
|
|
|
|
momFactor_conv1 = meters_yaml[cNum].get('momFactor_conv1', None)
|
|
|
- if not momFactor_conv1:
|
|
|
+ if momFactor_conv1 is None:
|
|
|
momFactor_conv1 = 1
|
|
|
|
|
|
momDigits_conv1 = meters_yaml[cNum].get('momDigits_conv1', None)
|
|
|
- if momDigits_conv1 == None:
|
|
|
+ if momDigits_conv1 is None:
|
|
|
momDigits_conv1 = 3
|
|
|
|
|
|
momFactor_conv2 = meters_yaml[cNum].get('momFactor_conv2', None)
|
|
|
- if not momFactor_conv2:
|
|
|
+ if momFactor_conv2 is None:
|
|
|
momFactor_conv2 = 1
|
|
|
|
|
|
momDigits_conv2 = meters_yaml[cNum].get('momDigits_conv2', None)
|
|
|
- if momDigits_conv2 == None:
|
|
|
+ if momDigits_conv2 is None:
|
|
|
momDigits_conv2 = 3
|
|
|
|
|
|
digits = meters_yaml[cNum].get('digits', None)
|
|
@@ -211,34 +215,114 @@ def processMeterData(data):
|
|
|
influxMinWriteInterval = meters_yaml[cNum].get('influxMinWriteInterval_energy', None)
|
|
|
if influxMinWriteInterval == None: influxMinWriteInterval = 0
|
|
|
|
|
|
+ historyPublishInterval = meters_yaml[cNum].get('historyPublishInterval', 300)
|
|
|
+
|
|
|
+ billingStartDate = meters_yaml[cNum].get('billingStartDate', None)
|
|
|
+
|
|
|
+ # add meter name to JSON object
|
|
|
+ if cName is not None and extendJSON:
|
|
|
+ cJson['name'] = cName
|
|
|
+
|
|
|
|
|
|
# check for date rollover since last impulse
|
|
|
today = datetime.date.today()
|
|
|
today_str = today.strftime('%Y%m%d')
|
|
|
+ today_year_str = today.strftime('%Y')
|
|
|
+ today_mon_str = today.strftime('%m')
|
|
|
+
|
|
|
yesterday = today - datetime.timedelta(days = 1)
|
|
|
yesterday_str = yesterday.strftime('%Y%m%d')
|
|
|
+ yesterday_year_str = yesterday.strftime('%Y')
|
|
|
+ yesterday_mon_str = yesterday.strftime('%m')
|
|
|
+
|
|
|
+
|
|
|
+ # needed for calendar week
|
|
|
+ isocal = datetime.date.fromisoformat(today.strftime('%Y-%m-%d')).isocalendar()
|
|
|
+ week = isocal[1]
|
|
|
+ year = isocal[0]
|
|
|
+ #print(year)
|
|
|
+ #print(week)
|
|
|
+
|
|
|
+ # this week
|
|
|
+ ## week_day1 = datetime.date.fromisocalendar(year, week, 1) # works only from python 3.8 - RPi only has 3.7.3
|
|
|
+ week_d = str(year) + "-W" + str(week)
|
|
|
+ #print(week_d)
|
|
|
+ week_day1 = datetime.datetime.strptime(week_d + '-1', "%Y-W%W-%w") # for python 3.7
|
|
|
+ week_day1_str = week_day1.strftime('%Y%m%d')
|
|
|
+ #print(week_day1_str)
|
|
|
+ week_day1_year_str = week_day1.strftime('%Y')
|
|
|
+ week_day1_mon_str = week_day1.strftime('%m')
|
|
|
+
|
|
|
+
|
|
|
+ # last week
|
|
|
+ if week > 1:
|
|
|
+ lastweek = week - 1
|
|
|
+ lastweek_year = year
|
|
|
+ else:
|
|
|
+ # get highest week number of last year
|
|
|
+ lastweek_year = year - 1
|
|
|
+ lastyearlastweek = datetime.date.fromisoformat(str(lastweek_year) + "-12-31").isocalendar().week
|
|
|
+ lastweek = lastyearlastweek
|
|
|
+ lastweek_d = str(lastweek_year) + "-W" + str(lastweek)
|
|
|
+ #lastweek_day1 = datetime.date.fromisocalendar(lastweek_year, lastweek, 1) # works only from python 3.8 - RPi only has 3.7.3
|
|
|
+ lastweek_day1 = datetime.datetime.strptime(lastweek_d + '-1', "%Y-W%W-%w") # for python 3.7
|
|
|
+ lastweek_day1_str = lastweek_day1.strftime('%Y%m%d')
|
|
|
+ lastweek_day1_year_str = lastweek_day1.strftime('%Y')
|
|
|
+ lastweek_day1_mon_str = lastweek_day1.strftime('%m')
|
|
|
+
|
|
|
+ # this month
|
|
|
+ month = int(today.strftime('%m'))
|
|
|
+ month_day1_str = str(year) + str(month) + "01"
|
|
|
+
|
|
|
+
|
|
|
+ # last month
|
|
|
+ lastmonth_year = None
|
|
|
+ lastmonth = None
|
|
|
+ if month > 1:
|
|
|
+ lastmonth = month - 1
|
|
|
+ lastmonth_year = year
|
|
|
+ else:
|
|
|
+ lastmonth = 12
|
|
|
+ lastmonth_year = year - 1
|
|
|
+ lastmonth_day1_str = str(lastmonth_year) + str(lastmonth) + "01"
|
|
|
+
|
|
|
+
|
|
|
+ # billing start date
|
|
|
+ if billingStartDate is not None:
|
|
|
+ tmp_billdate = billingStartDate.split("-")
|
|
|
+ bill_year = tmp_billdate[0]
|
|
|
+ bill_month = tmp_billdate[1]
|
|
|
+ bill_day = tmp_billdate[2]
|
|
|
+ ##print("bill_year=" + str(bill_year))
|
|
|
+ ##print("bill_month=" + str(bill_month))
|
|
|
+ ##print("bill_day=" + str(bill_day))
|
|
|
+
|
|
|
+
|
|
|
dateRollover = False
|
|
|
- savedtoday = saved_todays_date.get(cName, False)
|
|
|
- if not savedtoday or savedtoday != today:
|
|
|
+ savedtodaydate = saved_today_date.get(cName, False)
|
|
|
+ if not savedtodaydate or savedtodaydate != today:
|
|
|
if debug:
|
|
|
print("date rollover happened or no date has been saved yet for meter " + str(cName))
|
|
|
- if savedtoday and savedtoday == yesterday:
|
|
|
- # a date rollover just happened, so change todays date to current and proceed with what has to be done
|
|
|
+ if savedtodaydate and savedtodaydate == yesterday:
|
|
|
+ # date rollover just happened, so change todays date to current and proceed
|
|
|
dateRollover = True
|
|
|
- #log.debug(savedtoday)
|
|
|
- saved_todays_date[cName] = today
|
|
|
+ #log.debug(savedtodaydate)
|
|
|
+ saved_today_date[cName] = today
|
|
|
|
|
|
|
|
|
strformat = "{:.3f}"
|
|
|
cReading_formatted = None
|
|
|
- if digits:
|
|
|
+ if digits is not None:
|
|
|
strformat = "{:."+str(digits)+"f}"
|
|
|
cReading_formatted = strformat.format(cReading)
|
|
|
- cJson['reading'] = round(cReading, digits)
|
|
|
+ if extendJSON: cJson['reading'] = round(cReading, digits)
|
|
|
|
|
|
- if unit:
|
|
|
+ # add unit to JSON object
|
|
|
+ if unit is not None and extendJSON:
|
|
|
cJson['unit'] = unit
|
|
|
|
|
|
+ # calculate momentane usage
|
|
|
+ # if impulses per unit are set and measured time between last impulses is known
|
|
|
if impPerUnit and dTime is not None:
|
|
|
if dTime == 0:
|
|
|
momValue = 0.0
|
|
@@ -272,37 +356,30 @@ def processMeterData(data):
|
|
|
momValue_conv2 = round(momValue_conv2)
|
|
|
|
|
|
|
|
|
- #cJson['momValue'] = momValue
|
|
|
- #if momType:
|
|
|
- # cJson['momType'] = momType
|
|
|
- #if momUnit:
|
|
|
- # cJson['momUnit'] = momUnit
|
|
|
-
|
|
|
- if momType:
|
|
|
+ if momType is not None and extendJSON:
|
|
|
cJson[momType] = momValue
|
|
|
|
|
|
- if momType_conv1:
|
|
|
+ if momType_conv1 is not None and extendJSON:
|
|
|
cJson[momType_conv1] = momValue_conv1
|
|
|
|
|
|
- if momType_conv2:
|
|
|
+ if momType_conv2 is not None and extendJSON:
|
|
|
cJson[momType_conv2] = momValue_conv2
|
|
|
|
|
|
- if statTopic:
|
|
|
+ if statTopic and MQTTenabled:
|
|
|
if momType is not None:
|
|
|
- if MQTTenabled:
|
|
|
- mqttc.publish(statTopic + "/" + momType, str(momValue), qos=0, retain=False)
|
|
|
-
|
|
|
- if momType_conv1 is not None:
|
|
|
- mqttc.publish(statTopic + "/" + momType_conv1, str(momValue_conv1), qos=0, retain=False)
|
|
|
-
|
|
|
- if momType_conv2 is not None:
|
|
|
- mqttc.publish(statTopic + "/" + momType_conv2, str(momValue_conv2), qos=0, retain=False)
|
|
|
+ mqttc.publish(statTopic + "/" + momType, str(momValue), qos=0, retain=False)
|
|
|
+
|
|
|
+ if momType_conv1 is not None:
|
|
|
+ mqttc.publish(statTopic + "/" + momType_conv1, str(momValue_conv1), qos=0, retain=False)
|
|
|
+
|
|
|
+ if momType_conv2 is not None:
|
|
|
+ mqttc.publish(statTopic + "/" + momType_conv2, str(momValue_conv2), qos=0, retain=False)
|
|
|
|
|
|
-
|
|
|
+
|
|
|
+ # publish current reading to MQTT
|
|
|
if statTopic:
|
|
|
- if cReading_formatted != None:
|
|
|
- if MQTTenabled:
|
|
|
- mqttc.publish(statTopic + "/reading", str(cReading_formatted), qos=0, retain=False)
|
|
|
+ if MQTTenabled and cReading_formatted is not None:
|
|
|
+ mqttc.publish(statTopic + "/reading", str(cReading_formatted), qos=0, retain=False)
|
|
|
|
|
|
|
|
|
data_energy[cNum][meters_yaml[cNum].get('influxFieldName_energy', 'energyTotal')] = round(float(cReading), digits)
|
|
@@ -323,29 +400,49 @@ def processMeterData(data):
|
|
|
#print(data_momentary[cNum])
|
|
|
#print()
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+ # check history publish interval - only publish if interval elapsed or first run after program start
|
|
|
+ publishEnergyHistory = False
|
|
|
+ ts = int(time.time())
|
|
|
+ energyHistoryPublish_elapsedTime = 0
|
|
|
+ if energy_history_lastPublished.get(cNum, None) != None:
|
|
|
+ energyHistoryPublish_elapsedTime = ts - energy_history_lastPublished.get(cNum)
|
|
|
+ if energyHistoryPublish_elapsedTime >= historyPublishInterval:
|
|
|
+ # write interval elapsed -> write to InfluxDB
|
|
|
+ publishEnergyHistory = True
|
|
|
+ energy_history_lastPublished[cNum] = ts
|
|
|
+ else:
|
|
|
+ # first run -> write to InfluxDB immediately
|
|
|
+ publishEnergyHistory = True
|
|
|
+ energy_history_lastPublished[cNum] = ts
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
# InfluxDB
|
|
|
t_utc = datetime.datetime.utcnow()
|
|
|
t_str = t_utc.isoformat() + 'Z'
|
|
|
|
|
|
|
|
|
-
|
|
|
- # InfluxDB - energy readings
|
|
|
+ # write to InfluxDB after date rollover
|
|
|
if dateRollover:
|
|
|
write_energy_to_influxdb = True
|
|
|
|
|
|
+ # check write interval - only write if interval elapsed or first run after program start
|
|
|
ts = int(time.time())
|
|
|
influxEnergyWrite_elapsedTime = 0
|
|
|
if influxdb_energy_lastWriteTime.get(cNum, None) != None:
|
|
|
influxEnergyWrite_elapsedTime = ts - influxdb_energy_lastWriteTime.get(cNum)
|
|
|
if influxEnergyWrite_elapsedTime >= influxMinWriteInterval:
|
|
|
+ # write interval elapsed -> write to InfluxDB
|
|
|
write_energy_to_influxdb = True
|
|
|
- influxdb_energy_lastWriteTime[cNum] = ts
|
|
|
else:
|
|
|
- # first run - do write immediately
|
|
|
+ # first run -> write to InfluxDB immediately
|
|
|
write_energy_to_influxdb = True
|
|
|
- influxdb_energy_lastWriteTime[cNum] = ts
|
|
|
|
|
|
|
|
|
+ # InfluxDB - energy readings
|
|
|
influxInstance_energy = meters_yaml[cNum].get('influxInstance_energy', None)
|
|
|
if influxInstance_energy is not None:
|
|
|
if write_energy_to_influxdb:
|
|
@@ -367,8 +464,11 @@ def processMeterData(data):
|
|
|
print("Writing ENERGY to InfluxDB:")
|
|
|
print(json.dumps(jsondata_energy, indent = 4))
|
|
|
try:
|
|
|
- #influxclient_energy.write_points(jsondata_energy)
|
|
|
influxclient[influxInstance_energy].write_points(jsondata_energy)
|
|
|
+
|
|
|
+ # remember write time to maintain interval
|
|
|
+ influxdb_energy_lastWriteTime[cNum] = int(time.time())
|
|
|
+
|
|
|
except Exception as e:
|
|
|
print('Data not written!')
|
|
|
#log.error('Data not written!')
|
|
@@ -400,7 +500,6 @@ def processMeterData(data):
|
|
|
print("Writing MOMENTARY to InfluxDB:")
|
|
|
print(json.dumps(jsondata_momentary, indent = 4))
|
|
|
try:
|
|
|
- #influxclient_momentary.write_points(jsondata_momentary)
|
|
|
influxclient[influxInstance_mom].write_points(jsondata_momentary)
|
|
|
except Exception as e:
|
|
|
print('Data not written!')
|
|
@@ -409,23 +508,35 @@ def processMeterData(data):
|
|
|
#log.error(e)
|
|
|
|
|
|
|
|
|
- # file log
|
|
|
+ # file log and calculation of today/yesterday values
|
|
|
if config['filelog'].getboolean('enable'):
|
|
|
# save and restore yesterday´s total energy to calculate today´s energy
|
|
|
# check if total energy from yesterday is stored in memory, if not try to get it from saved file
|
|
|
|
|
|
- file_path_meter = conf_storage_path + cName + "/"
|
|
|
+ file_path_meter_base = conf_storage_path + cName + "/"
|
|
|
+
|
|
|
+ file_path_meter_year = conf_storage_path + cName + "/" + today_year_str + "/"
|
|
|
+ file_path_meter = conf_storage_path + cName + "/" + today_year_str + "/" + today_mon_str + "/"
|
|
|
file_today_min = file_path_meter + today_str + "_min.txt"
|
|
|
- file_yesterday_total = file_path_meter + yesterday_str + "_total.txt"
|
|
|
|
|
|
+ file_path_meter_year_yday = conf_storage_path + cName + "/" + yesterday_year_str + "/"
|
|
|
+ file_path_meter_yday = conf_storage_path + cName + "/" + yesterday_year_str + "/" + yesterday_mon_str + "/"
|
|
|
+
|
|
|
+ file_yesterday_total = file_path_meter_yday + yesterday_str + "_total.txt"
|
|
|
+ file_yesterday_min = file_path_meter_yday + yesterday_str + "_min.txt"
|
|
|
+
|
|
|
+ energy_today_min = saved_energy_today_min.get(cName, None)
|
|
|
energy_today_total = 0
|
|
|
energy_yesterday_min = 0
|
|
|
- energy_today_min = saved_energy_today_min.get(cName, None)
|
|
|
+
|
|
|
+ energy_yesterday_total = None
|
|
|
|
|
|
try:
|
|
|
+ # handle energy_today_min
|
|
|
if dateRollover:
|
|
|
+ # after date rollover set to None in order to read from last saved file
|
|
|
energy_today_min = None
|
|
|
-
|
|
|
+
|
|
|
if energy_today_min == None:
|
|
|
exists = os.path.isfile(file_today_min)
|
|
|
if exists:
|
|
@@ -439,11 +550,21 @@ def processMeterData(data):
|
|
|
saved_energy_today_min[cName] = energy_today_min
|
|
|
if verbose:
|
|
|
print(cName + " - Energy Today min read from file -> = " + str(energy_today_min))
|
|
|
- else: energy_today_min = None
|
|
|
+ else:
|
|
|
+ #energy_today_min = None
|
|
|
+ energy_today_min = cReading # file was empty - take current reading as value
|
|
|
else:
|
|
|
- # save current Energy_total to min-file
|
|
|
- if not os.path.exists(file_path_meter):
|
|
|
- os.mkdir(file_path_meter)
|
|
|
+ # save current energy_today to min-file
|
|
|
+ try:
|
|
|
+ if not os.path.exists(file_path_meter_base):
|
|
|
+ os.mkdir(file_path_meter_base)
|
|
|
+ if not os.path.exists(file_path_meter_year):
|
|
|
+ os.mkdir(file_path_meter_year)
|
|
|
+ if not os.path.exists(file_path_meter):
|
|
|
+ os.mkdir(file_path_meter)
|
|
|
+ except:
|
|
|
+ e = sys.exc_info()[0]
|
|
|
+ print( "Error creating directory: %s" % e )
|
|
|
f = open(file_today_min, "w+")
|
|
|
energy_today_min = cReading
|
|
|
saved_energy_today_min[cName] = energy_today_min
|
|
@@ -452,16 +573,18 @@ def processMeterData(data):
|
|
|
f.write(strformat.format(energy_today_min))
|
|
|
f.close()
|
|
|
|
|
|
- #try:
|
|
|
+ # calculate energy_today_total
|
|
|
if energy_today_min != None:
|
|
|
energy_today_total = cReading - energy_today_min
|
|
|
if verbose:
|
|
|
print(cName + " - Energy Today total: " + str('{0:.3f}'.format(energy_today_total)))
|
|
|
|
|
|
-
|
|
|
+ # handle energy_yesterday_total
|
|
|
energy_yesterday_total = saved_energy_yesterday_total.get(cName, None)
|
|
|
if dateRollover:
|
|
|
+ # after date rollover set to None in order to read from last saved file
|
|
|
energy_yesterday_total = None
|
|
|
+
|
|
|
if energy_yesterday_total == None:
|
|
|
exists = os.path.isfile(file_yesterday_total)
|
|
|
if exists:
|
|
@@ -477,12 +600,10 @@ def processMeterData(data):
|
|
|
print(cName + " - Energy Yesterday total read from file -> = " + str(energy_yesterday_total))
|
|
|
else: energy_yesterday_total = None
|
|
|
else:
|
|
|
- file_yesterday_min = file_path_meter + yesterday_str + "_min.txt"
|
|
|
+ # no yesterday_total file exists - create one using file_yesterday_min
|
|
|
exists = os.path.isfile(file_yesterday_min)
|
|
|
if exists:
|
|
|
# load yesterday_min from file
|
|
|
- #if args_output_verbose1:
|
|
|
- # print("file file_yesterday_min exists")
|
|
|
f = open(file_yesterday_min, "r")
|
|
|
if f.mode == 'r':
|
|
|
contents =f.read()
|
|
@@ -496,54 +617,315 @@ def processMeterData(data):
|
|
|
|
|
|
if energy_yesterday_min != None:
|
|
|
energy_yesterday_total = round(energy_today_min - energy_yesterday_min, 3)
|
|
|
- ###log.debug(meter_id_name[meter['id']] + " - Energy yesterday total: " + str(energy_yesterday_total))
|
|
|
-
|
|
|
- if not os.path.exists(file_path_meter):
|
|
|
- os.mkdir(file_path_meter)
|
|
|
+ saved_energy_yesterday_total[cName] = energy_yesterday_total
|
|
|
+ try:
|
|
|
+ if not os.path.exists(file_path_meter_base):
|
|
|
+ os.mkdir(file_path_meter_base)
|
|
|
+ if not os.path.exists(file_path_meter_year_yday):
|
|
|
+ os.mkdir(file_path_meter_year_yday)
|
|
|
+ if not os.path.exists(file_path_meter):
|
|
|
+ os.mkdir(file_path_meter)
|
|
|
+ except:
|
|
|
+ e = sys.exc_info()[0]
|
|
|
+ print( "Error creating directory: %s" % e )
|
|
|
f = open(file_yesterday_total, "w+")
|
|
|
- #f.write(str('{0:.3f}'.format(energy_yesterday_total)))
|
|
|
f.write(strformat.format(energy_yesterday_total))
|
|
|
f.close()
|
|
|
- #else:
|
|
|
- # # file yesterday_min does not exist
|
|
|
+
|
|
|
except:
|
|
|
e = sys.exc_info()[0]
|
|
|
- print( "<p>Error in file log: %s</p>" % e )
|
|
|
+ print( "Error in file log: %s" % e )
|
|
|
|
|
|
- if energy_today_total is not None:
|
|
|
- cJson['Today__' + unit] = round(energy_today_total, digits)
|
|
|
- if MQTTenabled:
|
|
|
- mqttc.publish(statTopic + "/today__" + unit, str(round(energy_today_total, digits)), qos=0, retain=False)
|
|
|
+
|
|
|
+ # calculate and MQTT publish energy_today and conversions/cost
|
|
|
+ if energy_today_total is not None and MQTTenabled:
|
|
|
+ # today in base unit
|
|
|
+ mqttc.publish(statTopic + "/Today__" + unit, str(round(energy_today_total, digits)), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['Today__' + unit] = round(energy_today_total, digits)
|
|
|
+
|
|
|
+ # conversion
|
|
|
+ if conv_unit and conv_factor is not None:
|
|
|
+ conv_value = energy_today_total * conv_factor
|
|
|
+ mqttc.publish(statTopic + "/Today__" + conv_unit, str(round(conv_value, conv_digits)), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['Today__' + conv_unit] = round(conv_value, conv_digits)
|
|
|
+
|
|
|
+ # cost from conversion
|
|
|
+ if cost_unit and cost_per_unit is not None and cost_from_conv:
|
|
|
+ cost_value = round(conv_value * cost_per_unit, 2)
|
|
|
+ mqttc.publish(statTopic + "/Today_cost__" + cost_unit, str(cost_value), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['Today_cost__' + cost_unit] = round(cost_value, 2)
|
|
|
+
|
|
|
+ # cost from base unit, not conversion
|
|
|
+ if not cost_from_conv:
|
|
|
+ cost_value = round(energy_today_total * cost_per_unit, 2)
|
|
|
+ mqttc.publish(statTopic + "/Today_cost__" + cost_unit, str(cost_value), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['Today_cost__' + cost_unit] = round(cost_value, 2)
|
|
|
+
|
|
|
+
|
|
|
+ # calculate and MQTT publish energy_yesterday and conversions/cost
|
|
|
+ if energy_yesterday_total is not None and MQTTenabled and publishEnergyHistory:
|
|
|
+ # yesterday in base unit
|
|
|
+ mqttc.publish(statTopic + "/Yesterday__" + unit, str(round(energy_yesterday_total, digits)), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['Yesterday__' + unit] = round(energy_yesterday_total, digits)
|
|
|
+
|
|
|
+ # conversion
|
|
|
+ if conv_unit and conv_factor is not None:
|
|
|
+ conv_value = energy_yesterday_total * conv_factor
|
|
|
+ mqttc.publish(statTopic + "/Yesterday__" + conv_unit, str(round(conv_value, conv_digits)), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['Yesterday__' + conv_unit] = round(conv_value, conv_digits)
|
|
|
+
|
|
|
+ # cost from conversion
|
|
|
+ if cost_unit and cost_per_unit is not None and cost_from_conv:
|
|
|
+ cost_value = round(conv_value * cost_per_unit, 2)
|
|
|
+ mqttc.publish(statTopic + "/Yesterday_cost__" + cost_unit, str(cost_value), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['Yesterday_cost__' + cost_unit] = round(cost_value, 2)
|
|
|
+
|
|
|
+ # cost from base unit, not conversion
|
|
|
+ if not cost_from_conv:
|
|
|
+ cost_value = round(energy_yesterday_total * cost_per_unit, 2)
|
|
|
+ mqttc.publish(statTopic + "/Yesterday_cost__" + cost_unit, str(cost_value), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['Yesterday_cost__' + cost_unit] = round(cost_value, 2)
|
|
|
+
|
|
|
+
|
|
|
+ # calculate this weeks total
|
|
|
+ energy_week_minfile = file_path_meter_base + week_day1_year_str + "/" + week_day1_mon_str + "/" + week_day1_str + "_min.txt"
|
|
|
+ energy_week_min = None
|
|
|
+ if os.path.isfile(energy_week_minfile) and MQTTenabled and publishEnergyHistory:
|
|
|
+ # load energy_week_minfile from file if exists
|
|
|
+ f = open(energy_week_minfile, "r")
|
|
|
+ if f.mode == 'r':
|
|
|
+ contents = f.read()
|
|
|
+ f.close()
|
|
|
+ if contents != '':
|
|
|
+ energy_week_min = float(contents)
|
|
|
+ energy_week_total = cReading - energy_week_min
|
|
|
+ if verbose:
|
|
|
+ print(cName + " - Energy Week min read from file '" + energy_week_minfile + "'")
|
|
|
+ print(" -> = " + str(energy_week_min))
|
|
|
+ mqttc.publish(statTopic + "/Week__" + unit, str(round(energy_week_total, digits)), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['Week__' + unit] = round(energy_week_total, digits)
|
|
|
if conv_unit and conv_factor is not None:
|
|
|
- conv_value = energy_today_total * conv_factor
|
|
|
- mqttc.publish(statTopic + "/today__" + conv_unit, str(round(conv_value, conv_digits)), qos=0, retain=False)
|
|
|
- cJson['Today__' + conv_unit] = round(conv_value, conv_digits)
|
|
|
+ conv_value = energy_week_total * conv_factor
|
|
|
+ mqttc.publish(statTopic + "/Week__" + conv_unit, str(round(conv_value, conv_digits)), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['Week__' + conv_unit] = round(conv_value, conv_digits)
|
|
|
+
|
|
|
+ # cost from conversion
|
|
|
if cost_unit and cost_per_unit is not None and cost_from_conv:
|
|
|
cost_value = round(conv_value * cost_per_unit, 2)
|
|
|
- mqttc.publish(statTopic + "/cost_today__" + cost_unit, str(cost_value), qos=0, retain=False)
|
|
|
- cJson['cost_today__' + cost_unit] = round(cost_value, 2)
|
|
|
- elif not cost_from_conv:
|
|
|
- cost_value = round(energy_today_total * cost_per_unit, 2)
|
|
|
- mqttc.publish(statTopic + "/cost_today__" + cost_unit, str(cost_value), qos=0, retain=False)
|
|
|
- cJson['cost_today__' + cost_unit] = round(cost_value, 2)
|
|
|
-
|
|
|
- if energy_yesterday_total is not None:
|
|
|
- cJson['Yesterday__' + unit] = round(energy_yesterday_total, digits)
|
|
|
- if MQTTenabled:
|
|
|
- mqttc.publish(statTopic + "/yesterday__" + unit, str(round(energy_yesterday_total, digits)), qos=0, retain=False)
|
|
|
+ mqttc.publish(statTopic + "/Week_cost__" + cost_unit, str(cost_value), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['Week_cost__' + cost_unit] = round(cost_value, 2)
|
|
|
+
|
|
|
+ # cost from base unit, not conversion
|
|
|
+ if not cost_from_conv:
|
|
|
+ cost_value = round(energy_week_total * cost_per_unit, 2)
|
|
|
+ mqttc.publish(statTopic + "/Week_cost__" + cost_unit, str(cost_value), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['Week_cost__' + cost_unit] = round(cost_value, 2)
|
|
|
+
|
|
|
+
|
|
|
+ # calculate last weeks total
|
|
|
+ energy_lastweek_minfile = file_path_meter_base + lastweek_day1_year_str + "/" + lastweek_day1_mon_str + "/" + lastweek_day1_str + "_min.txt"
|
|
|
+ if os.path.isfile(energy_lastweek_minfile) and MQTTenabled and energy_week_min is not None and publishEnergyHistory:
|
|
|
+ # load energy_lastweek_minfile from file if exists
|
|
|
+ f = open(energy_lastweek_minfile, "r")
|
|
|
+ if f.mode == 'r':
|
|
|
+ contents = f.read()
|
|
|
+ f.close()
|
|
|
+ if contents != '':
|
|
|
+ energy_lastweek_min = float(contents)
|
|
|
+ energy_lastweek_total = energy_week_min - energy_lastweek_min
|
|
|
+ if verbose:
|
|
|
+ print(cName + " - Energy LastWeek min read from file '" + energy_lastweek_minfile + "'")
|
|
|
+ print(" -> = " + str(energy_week_min))
|
|
|
+ mqttc.publish(statTopic + "/LastWeek__" + unit, str(round(energy_lastweek_total, digits)), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['LastWeek__' + unit] = round(energy_lastweek_total, digits)
|
|
|
+ if conv_unit and conv_factor is not None:
|
|
|
+ conv_value = energy_lastweek_total * conv_factor
|
|
|
+ mqttc.publish(statTopic + "/LastWeek__" + conv_unit, str(round(conv_value, conv_digits)), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['LastWeek__' + conv_unit] = round(conv_value, conv_digits)
|
|
|
+
|
|
|
+ # cost from conversion
|
|
|
+ if cost_unit and cost_per_unit is not None and cost_from_conv:
|
|
|
+ cost_value = round(conv_value * cost_per_unit, 2)
|
|
|
+ mqttc.publish(statTopic + "/LastWeek_cost__" + cost_unit, str(cost_value), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['LastWeek_cost__' + cost_unit] = round(cost_value, 2)
|
|
|
+
|
|
|
+ # cost from base unit, not conversion
|
|
|
+ if not cost_from_conv:
|
|
|
+ cost_value = round(energy_lastweek_total * cost_per_unit, 2)
|
|
|
+ mqttc.publish(statTopic + "/LastWeek_cost__" + cost_unit, str(cost_value), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['LastWeek_cost__' + cost_unit] = round(cost_value, 2)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ # calculate this months total
|
|
|
+ energy_month_minfile = file_path_meter_base + str(year) + "/" + str(month) + "/" + month_day1_str + "_min.txt"
|
|
|
+ energy_month_min = None
|
|
|
+ if os.path.isfile(energy_month_minfile) and MQTTenabled and publishEnergyHistory:
|
|
|
+ # load energy_month_minfile from file if exists
|
|
|
+ f = open(energy_month_minfile, "r")
|
|
|
+ if f.mode == 'r':
|
|
|
+ contents = f.read()
|
|
|
+ f.close()
|
|
|
+ if contents != '':
|
|
|
+ energy_month_min = float(contents)
|
|
|
+ energy_month_total = cReading - energy_month_min
|
|
|
+ if verbose:
|
|
|
+ print(cName + " - Energy Month min read from file '" + energy_month_minfile + "'")
|
|
|
+ print(" -> = " + str(energy_month_min))
|
|
|
+ mqttc.publish(statTopic + "/Month__" + unit, str(round(energy_month_total, digits)), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['Month__' + unit] = round(energy_month_total, digits)
|
|
|
+ if conv_unit and conv_factor is not None:
|
|
|
+ conv_value = energy_month_total * conv_factor
|
|
|
+ mqttc.publish(statTopic + "/Month__" + conv_unit, str(round(conv_value, conv_digits)), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['Month__' + conv_unit] = round(conv_value, conv_digits)
|
|
|
+
|
|
|
+ # cost from conversion
|
|
|
+ if cost_unit and cost_per_unit is not None and cost_from_conv:
|
|
|
+ cost_value = round(conv_value * cost_per_unit, 2)
|
|
|
+ mqttc.publish(statTopic + "/Month_cost__" + cost_unit, str(cost_value), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['Month_cost__' + cost_unit] = round(cost_value, 2)
|
|
|
+
|
|
|
+ # cost from base unit, not conversion
|
|
|
+ if not cost_from_conv:
|
|
|
+ cost_value = round(energy_month_total * cost_per_unit, 2)
|
|
|
+ mqttc.publish(statTopic + "/Month_cost__" + cost_unit, str(cost_value), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['Month_cost__' + cost_unit] = round(cost_value, 2)
|
|
|
+
|
|
|
+
|
|
|
+ # calculate last months total
|
|
|
+ energy_lastmonth_minfile = file_path_meter_base + str(lastmonth_year) + "/" + str(lastmonth) + "/" + lastmonth_day1_str + "_min.txt"
|
|
|
+ if os.path.isfile(energy_lastmonth_minfile) and MQTTenabled and energy_month_min is not None and publishEnergyHistory:
|
|
|
+ # load energy_lastmonth_minfile from file if exists
|
|
|
+ f = open(energy_lastmonth_minfile, "r")
|
|
|
+ if f.mode == 'r':
|
|
|
+ contents = f.read()
|
|
|
+ f.close()
|
|
|
+ if contents != '':
|
|
|
+ energy_lastmonth_min = float(contents)
|
|
|
+ energy_lastmonth_total = energy_month_min - energy_lastmonth_min
|
|
|
+ if verbose:
|
|
|
+ print(cName + " - Energy LastMonth min read from file '" + energy_lastmonth_minfile + "'")
|
|
|
+ print(" -> = " + str(energy_lastmonth_min))
|
|
|
+ mqttc.publish(statTopic + "/LastMonth__" + unit, str(round(energy_lastmonth_total, digits)), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['LastMonth__' + unit] = round(energy_lastmonth_total, digits)
|
|
|
if conv_unit and conv_factor is not None:
|
|
|
- conv_value = energy_yesterday_total * conv_factor
|
|
|
- mqttc.publish(statTopic + "/yesterday__" + conv_unit, str(round(conv_value, conv_digits)), qos=0, retain=False)
|
|
|
- cJson['Yesterday__' + conv_unit] = round(conv_value, conv_digits)
|
|
|
- if cost_unit and cost_per_unit is not None:
|
|
|
- if cost_from_conv:
|
|
|
- cost_value = round(conv_value * cost_per_unit, 2)
|
|
|
- mqttc.publish(statTopic + "/cost_yesterday__" + cost_unit, str(cost_value), qos=0, retain=False)
|
|
|
- cJson['cost_yesterday__' + cost_unit] = round(cost_value, 2)
|
|
|
- elif not cost_from_conv:
|
|
|
- cost_value = round(energy_yesterday_total * cost_per_unit, 2)
|
|
|
- mqttc.publish(statTopic + "/cost_yesterday__" + cost_unit, str(cost_value), qos=0, retain=False)
|
|
|
- cJson['cost_yesterday__' + cost_unit] = round(cost_value, 2)
|
|
|
+ conv_value = energy_lastmonth_total * conv_factor
|
|
|
+ mqttc.publish(statTopic + "/LastMonth__" + conv_unit, str(round(conv_value, conv_digits)), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['LastMonth__' + conv_unit] = round(conv_value, conv_digits)
|
|
|
+
|
|
|
+ # cost from conversion
|
|
|
+ if cost_unit and cost_per_unit is not None and cost_from_conv:
|
|
|
+ cost_value = round(conv_value * cost_per_unit, 2)
|
|
|
+ mqttc.publish(statTopic + "/LastMonth_cost__" + cost_unit, str(cost_value), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['LastMonth_cost__' + cost_unit] = round(cost_value, 2)
|
|
|
+
|
|
|
+ # cost from base unit, not conversion
|
|
|
+ if not cost_from_conv:
|
|
|
+ cost_value = round(energy_lastmonth_total * cost_per_unit, 2)
|
|
|
+ mqttc.publish(statTopic + "/LastMonth_cost__" + cost_unit, str(cost_value), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['LastMonth_cost__' + cost_unit] = round(cost_value, 2)
|
|
|
+
|
|
|
+
|
|
|
+ # calculate this years total
|
|
|
+ energy_year_minfile = file_path_meter_base + str(year) + "/01/" + str(year) + "0101_min.txt"
|
|
|
+ energy_year_min = None
|
|
|
+ if os.path.isfile(energy_year_minfile) and MQTTenabled and publishEnergyHistory:
|
|
|
+ # load energy_year_minfile from file if exists
|
|
|
+ f = open(energy_year_minfile, "r")
|
|
|
+ if f.mode == 'r':
|
|
|
+ contents = f.read()
|
|
|
+ f.close()
|
|
|
+ if contents != '':
|
|
|
+ energy_year_min = float(contents)
|
|
|
+ energy_year_total = cReading - energy_year_min
|
|
|
+ if verbose:
|
|
|
+ print(cName + " - Energy Year min read from file '" + energy_year_minfile + "'")
|
|
|
+ print(" -> = " + str(energy_year_min))
|
|
|
+ mqttc.publish(statTopic + "/Year__" + unit, str(round(energy_year_total, digits)), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['Year__' + unit] = round(energy_year_total, digits)
|
|
|
+ if conv_unit and conv_factor is not None:
|
|
|
+ conv_value = energy_year_total * conv_factor
|
|
|
+ mqttc.publish(statTopic + "/Year__" + conv_unit, str(round(conv_value, conv_digits)), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['Year__' + conv_unit] = round(conv_value, conv_digits)
|
|
|
+
|
|
|
+ # cost from conversion
|
|
|
+ if cost_unit and cost_per_unit is not None and cost_from_conv:
|
|
|
+ cost_value = round(conv_value * cost_per_unit, 2)
|
|
|
+ mqttc.publish(statTopic + "/Year_cost__" + cost_unit, str(cost_value), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['Year_cost__' + cost_unit] = round(cost_value, 2)
|
|
|
+
|
|
|
+ # cost from base unit, not conversion
|
|
|
+ if not cost_from_conv:
|
|
|
+ cost_value = round(energy_year_total * cost_per_unit, 2)
|
|
|
+ mqttc.publish(statTopic + "/Year_cost__" + cost_unit, str(cost_value), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['Year_cost__' + cost_unit] = round(cost_value, 2)
|
|
|
+
|
|
|
+ # calculate last years total
|
|
|
+ energy_lastyear_minfile = file_path_meter_base + str(year-1) + "/01/" + str(year-1) + "0101_min.txt"
|
|
|
+ if os.path.isfile(energy_lastyear_minfile) and MQTTenabled and energy_year_min is not None and publishEnergyHistory:
|
|
|
+ # load energy_lastyear_minfile from file if exists
|
|
|
+ f = open(energy_lastyear_minfile, "r")
|
|
|
+ if f.mode == 'r':
|
|
|
+ contents = f.read()
|
|
|
+ f.close()
|
|
|
+ if contents != '':
|
|
|
+ energy_lastyear_min = float(contents)
|
|
|
+ energy_lastyear_total = energy_year_min - energy_lastyear_min
|
|
|
+ if verbose:
|
|
|
+ print(cName + " - Energy LastYear min read from file '" + energy_lastyear_minfile + "'")
|
|
|
+ print(" -> = " + str(energy_lastyear_min))
|
|
|
+ mqttc.publish(statTopic + "/LastYear__" + unit, str(round(energy_lastyear_total, digits)), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['LastYear__' + unit] = round(energy_lastyear_total, digits)
|
|
|
+ if conv_unit and conv_factor is not None:
|
|
|
+ conv_value = energy_lastyear_total * conv_factor
|
|
|
+ mqttc.publish(statTopic + "/LastYear__" + conv_unit, str(round(conv_value, conv_digits)), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['LastYear__' + conv_unit] = round(conv_value, conv_digits)
|
|
|
+
|
|
|
+ # cost from conversion
|
|
|
+ if cost_unit and cost_per_unit is not None and cost_from_conv:
|
|
|
+ cost_value = round(conv_value * cost_per_unit, 2)
|
|
|
+ mqttc.publish(statTopic + "/LastYear_cost__" + cost_unit, str(cost_value), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['LastYear_cost__' + cost_unit] = round(cost_value, 2)
|
|
|
+
|
|
|
+ # cost from base unit, not conversion
|
|
|
+ if not cost_from_conv:
|
|
|
+ cost_value = round(energy_lastyear_total * cost_per_unit, 2)
|
|
|
+ mqttc.publish(statTopic + "/LastYear_cost__" + cost_unit, str(cost_value), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['LastYear_cost__' + cost_unit] = round(cost_value, 2)
|
|
|
+
|
|
|
+ # calculate total since last billing
|
|
|
+ energy_bill_minfile = file_path_meter_base + str(bill_year) + "/" + str(bill_month) + "/" + str(bill_year) + str(bill_month) + str(bill_day) + "_min.txt"
|
|
|
+ if os.path.isfile(energy_bill_minfile) and MQTTenabled and publishEnergyHistory and billingStartDate is not None:
|
|
|
+ # load energy_bill_minfile from file if exists
|
|
|
+ f = open(energy_bill_minfile, "r")
|
|
|
+ if f.mode == 'r':
|
|
|
+ contents = f.read()
|
|
|
+ f.close()
|
|
|
+ if contents != '':
|
|
|
+ energy_bill_min = float(contents)
|
|
|
+ energy_bill_total = cReading - energy_bill_min
|
|
|
+ if verbose:
|
|
|
+ print(cName + " - Energy Year min read from file '" + energy_bill_minfile + "'")
|
|
|
+ print(" -> = " + str(energy_bill_min))
|
|
|
+ mqttc.publish(statTopic + "/SinceLastBill__" + unit, str(round(energy_bill_total, digits)), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['SinceLastBill__' + unit] = round(energy_bill_total, digits)
|
|
|
+ if conv_unit and conv_factor is not None:
|
|
|
+ conv_value = energy_bill_total * conv_factor
|
|
|
+ mqttc.publish(statTopic + "/SinceLastBill__" + conv_unit, str(round(conv_value, conv_digits)), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['SinceLastBill__' + conv_unit] = round(conv_value, conv_digits)
|
|
|
+
|
|
|
+ # cost from conversion
|
|
|
+ if cost_unit and cost_per_unit is not None and cost_from_conv:
|
|
|
+ cost_value = round(conv_value * cost_per_unit, 2)
|
|
|
+ mqttc.publish(statTopic + "/SinceLastBill_cost__" + cost_unit, str(cost_value), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['SinceLastBill_cost__' + cost_unit] = round(cost_value, 2)
|
|
|
+
|
|
|
+ # cost from base unit, not conversion
|
|
|
+ if not cost_from_conv:
|
|
|
+ cost_value = round(energy_bill_total * cost_per_unit, 2)
|
|
|
+ mqttc.publish(statTopic + "/SinceLastBill_cost__" + cost_unit, str(cost_value), qos=0, retain=False)
|
|
|
+ if extendJSON: cJson['SinceLastBill_cost__' + cost_unit] = round(cost_value, 2)
|
|
|
+
|
|
|
|
|
|
# END file log
|
|
|
|
|
@@ -553,7 +935,7 @@ def processMeterData(data):
|
|
|
else:
|
|
|
print("meterData:", json.dumps(cJson))
|
|
|
|
|
|
- if MQTTenabled:
|
|
|
+ if MQTTenabled and publishJSON:
|
|
|
mqttc.publish(statTopic + "/json", json.dumps(cJson), qos=0, retain=False)
|
|
|
|
|
|
def publishStatMsg(data):
|