diff --git a/changelog.md b/changelog.md index 92715e10..f43bb578 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,11 @@ # Changelog All notable changes to this project will be documented in this file. Major releases are documented [here](https://github.com/jgyates/genmon/releases) + +## V1.11.8 - 2018-10-16 +- Improvements for genmqtt.py to allow for integer and float values to be passed as JSON strings +- Added option for Smart Transfer Switch. This will disable the weekly exercise and remote start in the UI since the transfer switch will handled this. + ## V1.11.7 - 2018-10-13 - Add new remote command to reset the current alarm (see Maintenance page) - Fixed bug in power log for H-100, if you experience problems, reset the power log or delete the file kwlog.txt and restart. diff --git a/conf/genmqtt.conf b/conf/genmqtt.conf index c62d2dce..8f5a215a 100644 --- a/conf/genmqtt.conf +++ b/conf/genmqtt.conf @@ -39,6 +39,11 @@ flush_interval = 0 # to make the path be Home/generator. root_topic = +# Optional. This value, if true will return numeric values in the Status topic +# as a JSON string which can be converted to an object with integer or float +# values. This applies to items in on the Status page only. +numeric_json = False + # Optional. By default the program will attempt to export all text data that is # exported by genmon (see the web interface for details). The blacklist # entry is a way to skip some values that are updated frequently that may not @@ -46,4 +51,4 @@ root_topic = # be suppressed from MQTT by adding "Packet Count" in the line below, or # "Platform Stats" will exclude all data in the Platform Stats section. # Multiple entries are separated by commas. -blacklist = Log,System Uptime,Packet Count,Run Time,Monitor Time,Generator Time,External Data +blacklist = Monitor,Log,System Uptime,Packet Count,Run Time,Monitor Time,Generator Time,External Data diff --git a/genmon.py b/genmon.py index d15cee6d..3e1a9728 100644 --- a/genmon.py +++ b/genmon.py @@ -25,7 +25,7 @@ print("Error: " + str(e1)) sys.exit(2) -GENMON_VERSION = "V1.11.7" +GENMON_VERSION = "V1.11.8" #------------ Monitor class ---------------------------------------------------- class Monitor(mysupport.MySupport): @@ -437,6 +437,7 @@ def ProcessCommand(self, command, fromsocket = False): "allregs_json" : [self.Controller.DisplayRegisters, (True, True), True], # display registers "logs_json" : [self.Controller.DisplayLogs, (True, True), True], "status_json" : [self.Controller.DisplayStatus, (True,), True], + "status_num_json" : [self.Controller.DisplayStatus, (True,True), True], "maint_json" : [self.Controller.DisplayMaintenance, (True,), True], "monitor_json" : [self.DisplayMonitor, (True,), True], "weather_json" : [self.DisplayWeather, (True,), True], @@ -851,7 +852,7 @@ def InterfaceServerThread(self): while True: try: conn, addr = self.ServerSocket.accept() - #self.printToString( 'Connected with ' + addr[0] + ':' + str(addr[1])) + #self.LogError('Connected with ' + addr[0] + ':' + str(addr[1])) conn.settimeout(0.5) self.ConnectionList.append(conn) SocketThread = threading.Thread(target=self.SocketWorkThread, args = (conn,), name = "SocketWorkThread") diff --git a/genmonlib/generac_HPanel.py b/genmonlib/generac_HPanel.py index b27b9cec..b7ed530e 100644 --- a/genmonlib/generac_HPanel.py +++ b/genmonlib/generac_HPanel.py @@ -1153,7 +1153,7 @@ def DisplayMaintenance (self, DictOut = False): return "" #------------ HPanel::DisplayStatus ---------------------------------------- - def DisplayStatus(self, DictOut = False): + def DisplayStatus(self, DictOut = False, JSONNum = False): try: Status = collections.OrderedDict() @@ -1170,33 +1170,33 @@ def DisplayStatus(self, DictOut = False): Stat["Time"] = Time - Battery["Battery Voltage"] = self.GetParameter(RegisterEnum.BATTERY_VOLTS, "V", 100.0) - Battery["Battery Charger Current"] = self.GetParameter(RegisterEnum.BATTERY_CHARGE_CURRNT, "A", 10.0) + Battery["Battery Voltage"] = self.ValueOut(self.GetParameter(RegisterEnum.BATTERY_VOLTS, ReturnFloat = True, Divider = 100.0), "V", JSONNum) + Battery["Battery Charger Current"] = self.ValueOut(self.GetParameter(RegisterEnum.BATTERY_CHARGE_CURRNT, ReturnFloat = True, Divider = 10.0), "A", JSONNum) Engine["Current Status"] = self.GetParameterString(RegisterEnum.STATUS_INFO_START, RegisterEnum.STATUS_INFO_END) Engine["Previous Status"] = self.GetParameterString(RegisterEnum.STATUS_2_INFO_START, RegisterEnum.STATUS_2_INFO_END) Engine["Switch State"] = self.GetSwitchState() Engine["Engine State"] = self.GetEngineState() - Engine["Output Power"] = self.GetPowerOutput() - Engine["Output Power Factor"] = self.GetParameter(RegisterEnum.TOTAL_PF, Divider = 100.0) - Engine["RPM"] = self.GetParameter(RegisterEnum.OUTPUT_RPM) - Engine["Frequency"] = self.GetParameter(RegisterEnum.OUTPUT_FREQUENCY, "Hz", 10.0) - Engine["Throttle Position"] = self.GetParameter(RegisterEnum.THROTTLE_POSITION, "Stp") - Engine["Coolant Temp"] = self.GetParameter(RegisterEnum.COOLANT_TEMP, "F") - Engine["Coolant Level"] = self.GetParameter(RegisterEnum.COOLANT_LEVEL, "Stp") - Engine["Oil Pressure"] = self.GetParameter(RegisterEnum.OIL_PRESSURE, "psi") - Engine["Oil Temp"] = self.GetParameter(RegisterEnum.OIL_TEMP, "F") - Engine["Fuel Level"] = self.GetParameter(RegisterEnum.FUEL_LEVEL) - Engine["Oxygen Sensor"] = self.GetParameter(RegisterEnum.O2_SENSOR) - Engine["Current Phase A"] = self.GetParameter(RegisterEnum.CURRENT_PHASE_A,"A") - Engine["Current Phase B"] = self.GetParameter(RegisterEnum.CURRENT_PHASE_B,"A") - Engine["Current Phase C"] = self.GetParameter(RegisterEnum.CURRENT_PHASE_C,"A") - Engine["Average Current"] = self.GetParameter(RegisterEnum.AVG_CURRENT,"A") - Engine["Voltage A-B"] = self.GetParameter(RegisterEnum.VOLTS_PHASE_A_B,"V") - Engine["Voltage B-C"] = self.GetParameter(RegisterEnum.VOLTS_PHASE_B_C,"V") - Engine["Voltage C-A"] = self.GetParameter(RegisterEnum.VOLTS_PHASE_C_A,"V") - Engine["Average Voltage"] = self.GetParameter(RegisterEnum.AVG_VOLTAGE,"V") - Engine["Air Fuel Duty Cycle"] = self.GetParameter(RegisterEnum.A_F_DUTY_CYCLE, Divider = 10.0) + Engine["Output Power"] = self.ValueOut(self.GetPowerOutput(ReturnFloat = True), "kW", JSONNum) + Engine["Output Power Factor"] = self.ValueOut(self.GetParameter(RegisterEnum.TOTAL_PF, ReturnFloat = True, Divider = 100.0), "", JSONNum) + Engine["RPM"] = self.ValueOut(self.GetParameter(RegisterEnum.OUTPUT_RPM, ReturnInt = True), "", JSONNum) + Engine["Frequency"] = self.ValueOut(self.GetParameter(RegisterEnum.OUTPUT_FREQUENCY, ReturnFloat = True, Divider = 10.0), "Hz", JSONNum) + Engine["Throttle Position"] = self.ValueOut(self.GetParameter(RegisterEnum.THROTTLE_POSITION, ReturnInt = True), "Stp", JSONNum) + Engine["Coolant Temp"] = self.ValueOut(self.GetParameter(RegisterEnum.COOLANT_TEMP, ReturnInt = True), "F", JSONNum) + Engine["Coolant Level"] = self.ValueOut(self.GetParameter(RegisterEnum.COOLANT_LEVEL, ReturnInt = True), "Stp", JSONNum) + Engine["Oil Pressure"] = self.ValueOut(self.GetParameter(RegisterEnum.OIL_PRESSURE, ReturnInt = True), "psi", JSONNum) + Engine["Oil Temp"] = self.ValueOut(self.GetParameter(RegisterEnum.OIL_TEMP, ReturnInt = True), "F", JSONNum) + Engine["Fuel Level"] = self.ValueOut(self.GetParameter(RegisterEnum.FUEL_LEVEL, ReturnInt = True), "", JSONNum) + Engine["Oxygen Sensor"] = self.ValueOut(self.GetParameter(RegisterEnum.O2_SENSOR, ReturnInt = True), "", JSONNum) + Engine["Current Phase A"] = self.ValueOut(self.GetParameter(RegisterEnum.CURRENT_PHASE_A, ReturnInt = True), "A", JSONNum) + Engine["Current Phase B"] = self.ValueOut(self.GetParameter(RegisterEnum.CURRENT_PHASE_B,ReturnInt = True), "A", JSONNum) + Engine["Current Phase C"] = self.ValueOut(self.GetParameter(RegisterEnum.CURRENT_PHASE_C,ReturnInt = True), "A", JSONNum) + Engine["Average Current"] = self.ValueOut(self.GetParameter(RegisterEnum.AVG_CURRENT,ReturnInt = True), "A", JSONNum) + Engine["Voltage A-B"] = self.ValueOut(self.GetParameter(RegisterEnum.VOLTS_PHASE_A_B,ReturnInt = True), "V", JSONNum) + Engine["Voltage B-C"] = self.ValueOut(self.GetParameter(RegisterEnum.VOLTS_PHASE_B_C,ReturnInt = True), "V", JSONNum) + Engine["Voltage C-A"] = self.ValueOut(self.GetParameter(RegisterEnum.VOLTS_PHASE_C_A,ReturnInt = True), "V", JSONNum) + Engine["Average Voltage"] = self.ValueOut(self.GetParameter(RegisterEnum.AVG_VOLTAGE,ReturnInt = True), "V", JSONNum) + Engine["Air Fuel Duty Cycle"] = self.ValueOut(self.GetParameter(RegisterEnum.A_F_DUTY_CYCLE, ReturnFloat = True, Divider = 10.0), "", JSONNum) if self.SystemInAlarm(): Engine["System In Alarm"] = self.GetAlarmList() diff --git a/genmonlib/generac_evolution.py b/genmonlib/generac_evolution.py index c7839e15..4234449b 100644 --- a/genmonlib/generac_evolution.py +++ b/genmonlib/generac_evolution.py @@ -2906,13 +2906,16 @@ def GetThresholdVoltage(self, ReturnInt = False): return self.GetParameter("0011", ReturnInt = ReturnInt, Label = "V") #------------ Evolution:GetSetOutputVoltage -------------------------------- - def GetSetOutputVoltage(self): + def GetSetOutputVoltage(self, ReturnInt = False): # get set output voltage if not self.EvolutionController or not self.LiquidCooled: - return "" + if ReturnInt: + return 0 + else: + return "" - return self.GetParameter("0237", Label = "V") + return self.GetParameter("0237", Label = "V", ReturnInt = ReturnInt) #------------ Evolution:GetStartupDelay ------------------------------------ def GetStartupDelay(self): @@ -3255,8 +3258,8 @@ def DisplayOutage(self, DictOut = False): if len(Value): OutageData["Utility Voltage"] = Value - OutageData["Utility Voltage Minimum"] = "%dV " % (self.UtilityVoltsMin) - OutageData["Utility Voltage Maximum"] = "%dV " % (self.UtilityVoltsMax) + OutageData["Utility Voltage Minimum"] = "%d V " % (self.UtilityVoltsMin) + OutageData["Utility Voltage Maximum"] = "%d V " % (self.UtilityVoltsMax) OutageData["Utility Threshold Voltage"] = self.GetThresholdVoltage() @@ -3274,7 +3277,7 @@ def DisplayOutage(self, DictOut = False): return Outage #------------ Evolution:DisplayStatus -------------------------------------- - def DisplayStatus(self, DictOut = False, Reg0001Value = None): + def DisplayStatus(self, DictOut = False, JSONNum = False, Reg0001Value = None): try: Status = collections.OrderedDict() @@ -3299,20 +3302,20 @@ def DisplayStatus(self, DictOut = False, Reg0001Value = None): if self.SystemInAlarm(): Engine["System In Alarm"] = self.GetAlarmState() - Engine["Battery Voltage"] = self.GetBatteryVoltage() + Engine["Battery Voltage"] = self.ValueOut(self.GetBatteryVoltage(ReturnFloat = True), "V", JSONNum) if self.EvolutionController and self.LiquidCooled: Engine["Battery Status"] = self.GetBatteryStatus() - Engine["RPM"] = self.GetRPM() + Engine["RPM"] = self.ValueOut(self.GetRPM(ReturnInt = True), "", JSONNum) - Engine["Frequency"] = self.GetFrequency() - Engine["Output Voltage"] = self.GetVoltageOutput() + Engine["Frequency"] = self.ValueOut(self.GetFrequency(ReturnFloat = True), "Hz", JSONNum) + Engine["Output Voltage"] = self.ValueOut(self.GetVoltageOutput(ReturnInt = True), "V", JSONNum) if self.PowerMeterIsSupported(): - Engine["Output Current"] = self.GetCurrentOutput() - Engine["Output Power (Single Phase)"] = self.GetPowerOutput() + Engine["Output Current"] = self.ValueOut(self.GetCurrentOutput(ReturnFloat = True), "A", JSONNum) + Engine["Output Power (Single Phase)"] = self.ValueOut(self.GetPowerOutput(ReturnFloat = True), "kW", JSONNum) - Engine["Active Rotor Poles (Calculated)"] = self.GetActiveRotorPoles() + Engine["Active Rotor Poles (Calculated)"] = self.ValueOut(self.GetActiveRotorPoles(ReturnInt = True), "", JSONNum) if self.bDisplayUnknownSensors: Engine["Unsupported Sensors"] = self.DisplayUnknownSensors() @@ -3320,15 +3323,15 @@ def DisplayStatus(self, DictOut = False, Reg0001Value = None): if self.EvolutionController and self.LiquidCooled: Line["Transfer Switch State"] = self.GetTransferStatus() - Line["Utility Voltage"] = self.GetUtilityVoltage() + Line["Utility Voltage"] = self.ValueOut(self.GetUtilityVoltage(ReturnInt = True), "V", JSONNum) # - Line["Utility Voltage Max"] = "%dV " % (self.UtilityVoltsMax) - Line["Utility Voltage Min"] = "%dV " % (self.UtilityVoltsMin) - Line["Utility Threshold Voltage"] = self.GetThresholdVoltage() + Line["Utility Voltage Max"] = self.ValueOut(self.UtilityVoltsMax, "V", JSONNum) + Line["Utility Voltage Min"] = self.ValueOut(self.UtilityVoltsMin, "V", JSONNum) + Line["Utility Threshold Voltage"] = self.ValueOut(self.GetThresholdVoltage(ReturnInt = True), "V", JSONNum) if self.EvolutionController and self.LiquidCooled: - Line["Utility Pickup Voltage"] = self.GetPickUpVoltage() - Line["Set Output Voltage"] = self.GetSetOutputVoltage() + Line["Utility Pickup Voltage"] = self.ValueOut(self.GetPickUpVoltage(ReturnInt = True), "V", JSONNum) + Line["Set Output Voltage"] = self.ValueOut(self.GetSetOutputVoltage(ReturnInt = True), "V", JSONNum) # Generator time Time["Monitor Time"] = datetime.datetime.now().strftime("%A %B %-d, %Y %H:%M:%S") diff --git a/genmonlib/mysupport.py b/genmonlib/mysupport.py index 9c60299d..de65acce 100644 --- a/genmonlib/mysupport.py +++ b/genmonlib/mysupport.py @@ -9,7 +9,7 @@ # MODIFICATIONS: #------------------------------------------------------------------------------- -import os, sys, time, collections, threading, socket +import os, sys, time, collections, threading, socket, json from genmonlib import mycommon, myplatform, myconfig @@ -139,6 +139,38 @@ def WaitForExit(self, Name, timeout = None): return Thread.Wait(timeout) + #------------ MySupport::ValueOut ------------------------------------------ + def ValueOut(self, value, unit, NoString = False): + try: + + if NoString: + ReturnDict = collections.OrderedDict() + ReturnDict["unit"] = unit + DefaultReturn = json.dumps({'value': 0}, sort_keys=False) + else: + DefaultReturn = "" + if isinstance(value, int): + if not NoString: + return "%d %s" % (int(value), str(unit)) + else: + ReturnDict["type"] = 'int' + ReturnDict["value"] = value + return json.dumps(ReturnDict, sort_keys=False) + elif isinstance(value, float): + if not NoString: + return "%.2f %s" % (float(value), str(unit)) + else: + ReturnDict = collections.OrderedDict() + ReturnDict["type"] = 'float' + ReturnDict["value"] = round(value, 2) + return json.dumps(ReturnDict, sort_keys=False) + else: + self.LogError("Unsupported type in ValueOut: " + str(type(value))) + return DefaultReturn + except Exception as e1: + self.LogErrorLine("Error in ValueOut: " + str(e1)) + return DefaultReturn + #------------ MySupport::GetDispatchItem ----------------------------------- def GetDispatchItem(self, item): @@ -153,7 +185,7 @@ def GetDispatchItem(self, item): elif isinstance(item, float): return str(item) else: - self.LogError("Unable to convert type %s in GetDispatchItem" % type(item)) + self.LogError("Unable to convert type %s in GetDispatchItem" % str(type(item))) self.LogError("Item: " + str(item)) return "" @@ -179,11 +211,11 @@ def ProcessDispatch(self, node, InputBuffer, indent=0): NewDict2 = collections.OrderedDict() InputBuffer[key].append(self.ProcessDispatch(listitem, NewDict2)) else: - self.LogError("Invalid type in ProcessDispatch %s " % type(node)) + self.LogError("Invalid type in ProcessDispatch %s " % str(type(node))) else: InputBuffer[key] = self.GetDispatchItem(item) else: - self.LogError("Invalid type in ProcessDispatch %s " % type(node)) + self.LogError("Invalid type in ProcessDispatch %s " % str(type(node))) return InputBuffer @@ -208,11 +240,11 @@ def ProcessDispatchToString(self, node, InputBuffer, indent = 0): elif isinstance(listitem, str): InputBuffer += ((" " * (indent +1)) + self.GetDispatchItem(listitem) + "\n") else: - self.LogError("Invalid type in ProcessDispatchToString %s %s (2)" % (key, type(listitem))) + self.LogError("Invalid type in ProcessDispatchToString %s %s (2)" % (key, str(type(listitem)))) else: InputBuffer += ((" " * indent) + str(key) + " : " + self.GetDispatchItem(item) + "\n") else: - self.LogError("Invalid type in ProcessDispatchToString %s " % type(node)) + self.LogError("Invalid type in ProcessDispatchToString %s " % str(type(node))) return InputBuffer #---------- Controller::GetNumBitsChanged---------------------------------- diff --git a/genmqtt.py b/genmqtt.py index 91856ade..ac9443bc 100644 --- a/genmqtt.py +++ b/genmqtt.py @@ -38,11 +38,16 @@ def __init__(self, callback = None, polltime = None, blacklist = None, - flush_interval = float('inf')): + flush_interval = float('inf'), + use_numeric = False, + debug = False): super(MyGenPush, self).__init__() self.Callback = callback + self.UseNumeric = use_numeric + self.Debug = debug + if polltime == None: self.PollTime = 3 else: @@ -103,7 +108,10 @@ def MainPollingThread(self): while True: try: - statusdata = self.SendCommand("generator: status_json") + if not self.UseNumeric: + statusdata = self.SendCommand("generator: status_json") + else: + statusdata = self.SendCommand("generator: status_num_json") outagedata = self.SendCommand("generator: outage_json") monitordata = self.SendCommand("generator: monitor_json") maintdata = self.SendCommand("generator: maint_json") @@ -132,7 +140,7 @@ def MainPollingThread(self): #------------ MySupport::CheckDictForChanges ------------------------------- # This function is recursive, it will turn a nested dict into a flat dict keys - # that have a directory structure with corrposonding values and deteermine if + # that have a directory structure with corrposonding values and determine if # anyting changed. If it has then call our callback function def CheckDictForChanges(self, node, PathPrefix): @@ -155,12 +163,12 @@ def CheckDictForChanges(self, node, PathPrefix): #todo list support pass else: - self.LogError("Invalid type in CheckDictForChanges: %s %s (2)" % (key, type(listitem))) + self.LogError("Invalid type in CheckDictForChanges: %s %s (2)" % (key, str(type(listitem)))) else: CurrentPath = PathPrefix + "/" + str(key) - self.CheckForChanges(CurrentPath, str(item)) + self.CheckForChanges(CurrentPath, item) else: - self.LogError("Invalid type in CheckDictForChanges %s " % type(node)) + self.LogError("Invalid type in CheckDictForChanges %s " % str(type(node))) # ---------- MyGenPush::CheckForChanges------------------------------------- def CheckForChanges(self, Path, Value): @@ -174,11 +182,11 @@ def CheckForChanges(self, Path, Value): LastValue = self.LastValues.get(str(Path), None) LastChange = self.LastChange.get(str(Path), 0) - if LastValue == None or LastValue != str(Value) or (time.time() - LastChange) > self.FlushInterval: - self.LastValues[str(Path)] = str(Value) + if LastValue == None or LastValue != Value or (time.time() - LastChange) > self.FlushInterval: + self.LastValues[str(Path)] = Value self.LastChange[str(Path)] = time.time() if self.Callback != None: - self.Callback(str(Path), str(Value)) + self.Callback(str(Path), Value) except Exception as e1: self.LogErrorLine("Error in mygenpush:CheckForChanges: " + str(e1)) @@ -217,6 +225,7 @@ def __init__(self, log = None): self.Topic = "generator" self.TopicRoot = None self.BlackList = None + self.UseNumeric = False self.PollTime = 2 self.FlushInterval = float('inf') # default to inifite flush interval (e.g., never) self.Debug = False @@ -243,14 +252,22 @@ def __init__(self, log = None): self.PollTime = config.ReadValue('poll_interval', return_type = float, default = 2.0) + self.UseNumeric = config.ReadValue('numeric_json', return_type = bool, default = False) + self.TopicRoot = config.ReadValue('root_topic') BlackList = config.ReadValue('blacklist') + if BlackList != None: - self.BlackList = BlackList.strip().split(",") + if len(BlackList): + BList = BlackList.strip().split(",") + if len(BList): + self.BlackList = [] + for Items in BList: + self.BlackList.append(Items.strip()) self.Debug = config.ReadValue('debug', return_type = bool, default = False) - + if config.HasOption('flush_interval'): self.FlushInterval = config.ReadValue('flush_interval', return_type = float, default = float('inf')) if self.FlushInterval == 0: @@ -272,7 +289,11 @@ def __init__(self, log = None): self.MQTTclient.connect(self.MQTTAddress, self.Port, 60) - self.Push = MyGenPush(host = self.MonitorAddress, log = self.log, callback = self.PublishCallback, polltime = self.PollTime , blacklist = self.BlackList, flush_interval = self.FlushInterval) + self.Push = MyGenPush(host = self.MonitorAddress, + log = self.log, callback = self.PublishCallback, + polltime = self.PollTime , blacklist = self.BlackList, + flush_interval = self.FlushInterval, use_numeric = self.UseNumeric, + debug = self.Debug) atexit.register(self.Close) signal.signal(signal.SIGTERM, self.Close) @@ -294,11 +315,12 @@ def PublishCallback(self, name, value): FullPath = str(name) if self.Debug: - self.console.info("Publish: " + FullPath + ": " + str(value)) + self.console.info("Publish: " + FullPath + ": " + str(value) + ": " + str(type(value))) - self.MQTTclient.publish(FullPath, str(value)) + self.MQTTclient.publish(FullPath, value) except Exception as e1: self.LogErrorLine("Error in MyMQTT:PublishCallback: " + str(e1)) + #------------ MyMQTT::on_connect-------------------------------------------- # The callback for when the client receives a CONNACK response from the server. def on_connect(self, client, userdata, flags, rc): diff --git a/genserv.py b/genserv.py index 912bc00b..d62a300e 100644 --- a/genserv.py +++ b/genserv.py @@ -466,6 +466,13 @@ def GetAddOns(): "(Optional) Time in seconds where even unchanged values will be published to their MQTT topic. Set to zero to disable flushing.", bounds = 'number', display_name = "Flush Interval") + AddOnCfg['genmqtt']['parameters']['numeric_json'] = CreateAddOnParam( + ConfigFiles[GENMQTT_CONFIG].ReadValue("numeric_json", return_type = bool, default = False), + 'boolean', + "If enabled will return numeric values in the Status topic as a JSON string which can be converted to an object with integer or float values.", + bounds = '', + display_name = "JSON for Numerics") + #GENSLACK AddOnCfg['genslack'] = collections.OrderedDict() @@ -817,6 +824,7 @@ def ReadSettingsFromFile(): else: #ControllerType == "generac_evo_nexus": ConfigSettings["enhancedexercise"] = ['boolean', 'Enhanced Exercise Time', 105, False, "", "", GENMON_CONFIG, GENMON_SECTION, "enhancedexercise"] + ConfigSettings["smart_transfer_switch"] = ['boolean', 'Smart Transfer Switch', 110, False, "", "", GENMON_CONFIG, GENMON_SECTION, "smart_transfer_switch"] ConfigSettings["displayunknown"] = ['boolean', 'Display Unknown Sensors', 111, False, "", "", GENMON_CONFIG, GENMON_SECTION, "displayunknown"] # These do not appear to work on reload, some issue with Flask