def onNotification(self, Data): Domoticz.Log("onNotification: " + str(Data))
def myDebug(self, message): if self.iDebugLevel: Domoticz.Log(message)
def onStart(self): self.myDebug("onStart called") Domoticz.Log( "Ce plugin est compatible avec Domoticz version 3.9517 et plus récent, mais la vue par heure peut ne pas fonctionner avec la version 4.9700" ) self.sUser = Parameters["Username"] self.sPassword = Parameters["Password"] self.iHistoryDaysForHoursView = Parameters["Mode1"] self.iHistoryDaysForDaysView = Parameters["Mode2"] self.bAutoAcceptTerms = Parameters["Mode4"] == "True" self.sConsumptionType = Parameters["Mode5"] try: self.iDebugLevel = int(Parameters["Mode3"]) except ValueError: self.iDebugLevel = 0 if self.iDebugLevel > 1: Domoticz.Debugging(1) # History for short log is 7 days max (default to 7) try: self.iHistoryDaysForHoursView = int(self.iHistoryDaysForHoursView) except: self.iHistoryDaysForHoursView = 7 if self.iHistoryDaysForHoursView < 0: self.iHistoryDaysForHoursView = 0 elif self.iHistoryDaysForHoursView > 7: self.iHistoryDaysForHoursView = 7 # History for short log is 7 days max (default to 366) try: self.iHistoryDaysForDaysView = int(self.iHistoryDaysForDaysView) except: self.iHistoryDaysForDaysView = 366 if self.iHistoryDaysForDaysView < 28: self.iHistoryDaysForDaysView = 28 elif self.iHistoryDaysForDaysView > 100000: self.iHistoryDaysForDaysView = 100000 if (self.sConsumptionType == "month") and (self.iHistoryDaysForDaysView < 32): self.iHistoryDaysForDaysView = 32 if (self.sConsumptionType == "lmonth") and (self.iHistoryDaysForDaysView < 63): self.iHistoryDaysForDaysView = 63 if (self.sConsumptionType == "year") and (self.iHistoryDaysForDaysView < 366): self.iHistoryDaysForDaysView = 366 Domoticz.Log("Adresse e-mail mise à " + self.sUser) if self.sPassword: Domoticz.Log("Mot de passe entré") else: Domoticz.Log("Mot de passe laissé vide") Domoticz.Log("Consommation à montrer sur le tableau de bord mis à " + self.sConsumptionType) Domoticz.Log( "Accepter automatiquement les conditions d'utilisation mis à " + str(self.bAutoAcceptTerms)) Domoticz.Log( "Nombre de jours à récupérer pour la vue par heures mis à " + str(self.iHistoryDaysForHoursView)) Domoticz.Log( "Nombre de jours à récupérer pour les autres vues mis à " + str(self.iHistoryDaysForDaysView)) Domoticz.Log("Debug mis à " + str(self.iDebugLevel)) # most init self.__init__() Domoticz.Log( "Si vous ne voyez pas assez de données dans la vue par heures, augmentez le paramètre Log des capteurs qui se trouve dans Réglages / Paramètres / Historique des logs" ) if self.createDevice(): self.nextConnection = datetime.now() else: self.setNextConnection(False) # Now we can enabling the plugin self.isStarted = True
def onMessage(self, Connection, Data, Status, Extra): Domoticz.Log("onMessage called")
def onDisconnect(self, Connection): Domoticz.Log("onDisconnect called")
def registerDevices(self): unitIds = self.indexRegisteredDevices() if self.hasTimedOut: return ikeaIds = [] # Add unregistred lights try: if self.includeGroups: tradfriDevices = get_devices(groups=True) else: tradfriDevices = get_devices() if tradfriDevices == None: Domoticz.Log("Failed to get Tradfri-devices") return for aLight in tradfriDevices: devID = str(aLight.DeviceID) ikeaIds.append(devID) if not devID in unitIds: Domoticz.Debug( "Processing: {0} - {1}".format(aLight.Description, aLight.Type) ) new_unit_id = firstFree() if aLight.Type == "Plug": Domoticz.Device( Name=aLight.Name, Unit=new_unit_id, Type=244, Subtype=73, Switchtype=0, Image=1, DeviceID=devID, ).Create() self.updateDevice(new_unit_id, devID) if aLight.Type == "Remote": Domoticz.Device( Name=aLight.Name + " - Battery level", Unit=new_unit_id, Type=243, Subtype=6, DeviceID=devID, ).Create() if aLight.Type == "Blind": deviceType = 244 subType = 73 switchType = 13 Domoticz.Device( Name=aLight.Name, Unit=new_unit_id, Type=deviceType, Subtype=subType, Switchtype=switchType, DeviceID=devID, ).Create() self.updateDevice(new_unit_id, devID) if aLight.Type == "Light" or aLight.Type == "Group": deviceType = 244 subType = 73 switchType = 7 # Basic device Domoticz.Device( Name=aLight.Name, Unit=new_unit_id, Type=deviceType, Subtype=subType, Switchtype=switchType, DeviceID=devID, ).Create() self.updateDevice(new_unit_id, devID) if aLight.Color_space == "W": continue if self.monitorBatteries: if aLight.Battery_level is not None and devID+":Battery" not in unitIds: new_unit_id = firstFree() Domoticz.Debug("Registering: {0}:Battery".format(aLight.DeviceID)) Domoticz.Device(Name=aLight.Name + " - Battery", Unit=new_unit_id, TypeName="Custom", Options={"Custom": "1;%"}, DeviceID=devID + ":Battery").Create() self.updateDevice(new_unit_id, devID) if aLight.Color_space == "CWS" and devID + ":CWS" not in unitIds: new_unit_id = firstFree() Domoticz.Debug("Registering: {0}:CWS".format(aLight.DeviceID)) Domoticz.Device( Name=aLight.Name + " - Color", Unit=new_unit_id, TypeName="Selector Switch", Switchtype=18, Options=colorOptions, DeviceID=devID + ":CWS", ).Create() self.updateDevice(new_unit_id, devID) if aLight.Color_space == "WS" and devID + ":WS" not in unitIds: new_unit_id = firstFree() Domoticz.Debug("Registering: {0}:WS".format(aLight.DeviceID)) Domoticz.Device( Name=aLight.Name + " - Color", Unit=new_unit_id, TypeName="Selector Switch", Switchtype=18, Options=WhiteOptions, DeviceID=devID + ":WS", ).Create() self.updateDevice(new_unit_id, devID) # Remove registered lights no longer found on the gateway for aUnit in list(Devices.keys()): devID= str(Devices[aUnit].DeviceID).split(":") if not devID[0] in ikeaIds: Devices[aUnit].Delete() if not self.monitorBatteries and len(devID)==2: if devID[1] == "Battery": Devices[aUnit].Delete() self.hasTimedOut = False except (HandshakeError, ReadTimeoutError, WriteTimeoutError): Domoticz.Debug("Connection to gateway timed out") self.hasTimedOut = True
def onStop(self): Domoticz.Log("onStop called")
def onMessage(self, Connection, Data): global jsonArray global wledData global updateInterval try: # we get answer back from our json request # start update from json data if( Connection.Name == "JSONConn" ): Connection.Disconnect() Status = int(Data["Status"]) if( Status == 200 ): strData = Data["Data"].decode("utf-8", "ignore") jsonArray = json.loads( str(strData) ) if( len( jsonArray ) ): # only update Domoticz from JSON on plugin start if( self.counter == 0 ): #wled data comes from json Domoticz.Log("Updating Domoticz from JSON") wledData["red"] = int(jsonArray['state']['seg'][0]["col"][0][0]) wledData["green"] = int(jsonArray['state']['seg'][0]["col"][0][1]) wledData["blue"] = int(jsonArray['state']['seg'][0]["col"][0][2]) wledData["bri"] = jsonArray['state']['bri'] wledData["preset"] = jsonArray['state']['ps'] if( wledData["preset"] < 0 ): wledData["preset"] = 0 wledData["effectCurrent"] = jsonArray['state']['seg'][0]['fx'] wledData["effectIntensity"] = jsonArray['state']['seg'][0]['ix'] wledData["effectSpeed"] = jsonArray['state']['seg'][0]['sx'] wledData["effectPalette"] = jsonArray['state']['seg'][0]['pal']; # update domoticz wleddata from json UpdateStatusInDomoticz() # every time JSON data is retrieved update effects and palettes in Domoticz UpdateEffectsInDomoticz() UpdatePalettesInDomoticz() if( Connection.Name == "UDPConn" ): # Is it notifier protocol? if ( Data[0] == 0x00 and Data[21] == 0x00 and Data[22] == 0x00 and Data[23] == 0x00 and Data[24] == 0x00): wledData = { "callMode": Data[1], "bri": Data[2], "red": Data[3], "green": Data[4], "blue": Data[5], "nightlightActive": Data[6], "nightlightDelayMins": Data[7], "effectCurrent": Data[8], "effectSpeed": Data[9], "white": Data[10], "redSec": Data[12], "greenSec": Data[13], "blueSec": Data[14], "whiteSec": Data[15], "effectIntensity": Data[16], "transitionDelayHi": Data[17], "transitionDelayLow": Data[18], "effectPalette": Data[19] } # update domoticz with wleddata from UDP Domoticz.Log("Updating Domoticz from UDP") UpdateStatusInDomoticz() except Exception as inst: Domoticz.Error("Exception detail: '"+str(inst)+"'") raise
def onMessage(self, Connection, Data): #Domoticz.Log("onMessage called: " + str(Data) + " , Connection: " + str(Connection) + " , idx: " + str(self.idx)) if 1 == self.idx: self.acInVL1 = int.from_bytes(Data[9:11], byteorder='big', signed=False) / 10 self.acInAL1 = int.from_bytes(Data[15:17], byteorder='big', signed=True) / 10 self.acInFL1 = int.from_bytes(Data[21:23], byteorder='big', signed=True) / 100 self.acInWL1 = int.from_bytes(Data[27:29], byteorder='big', signed=True) * 10 self.acOutVL1 = int.from_bytes(Data[33:35], byteorder='big', signed=False) / 10 self.acOutAL1 = int.from_bytes(Data[39:41], byteorder='big', signed=True) / 10 self.acOutFL1 = int.from_bytes(Data[45:47], byteorder='big', signed=True) / 100 self.acOutWL1 = int.from_bytes(Data[49:51], byteorder='big', signed=True) * 10 self.battV = int.from_bytes(Data[55:57], byteorder='big', signed=False) / 100 self.battA = int.from_bytes(Data[57:59], byteorder='big', signed=True) / 10 self.battSOC = int.from_bytes(Data[63:65], byteorder='big', signed=False) / 10 self.battState = int.from_bytes(Data[65:67], byteorder='big', signed=False) self.battTemp = int.from_bytes(Data[125:127], byteorder='big', signed=True) / 10 if Parameters["Mode6"] == "Debug": Domoticz.Log("acInVL1: " + str(self.acInVL1)) Domoticz.Log("acInAL1: " + str(self.acInAL1)) Domoticz.Log("acInFL1: " + str(self.acInFL1)) Domoticz.Log("acInWL1: " + str(self.acInWL1)) Domoticz.Log("acOutVL1: " + str(self.acOutVL1)) Domoticz.Log("acOutAL1: " + str(self.acOutAL1)) Domoticz.Log("acOutFL1: " + str(self.acOutFL1)) Domoticz.Log("acOutWL1: " + str(self.acOutWL1)) Domoticz.Log("battV: " + str(self.battV)) Domoticz.Log("battA: " + str(self.battA)) Domoticz.Log("battSOC: " + str(self.battSOC)) Domoticz.Log("battState: " + str(self.battState)) Domoticz.Log("battTemp: " + str(self.battTemp)) elif 2 == self.idx: self.acConsumptionWL1 = int.from_bytes(Data[31:33], byteorder='big', signed=False) / 1 self.gridWL1 = int.from_bytes(Data[37:39], byteorder='big', signed=True) / 1 if Parameters["Mode6"] == "Debug": Domoticz.Log("acConsumptionWL1: " + str(self.acConsumptionWL1)) Domoticz.Log("gridWL1: " + str(self.gridWL1)) elif 3 == self.idx: self.battW = int.from_bytes(Data[13:15], byteorder='big', signed=True) / 1 self.battConsumedAh = int.from_bytes(Data[19:21], byteorder='big', signed=False) / -10 self.battTimeToGo = int.from_bytes(Data[21:23], byteorder='big', signed=False) * 100 if Parameters["Mode6"] == "Debug": Domoticz.Log("battW: " + str(self.battW)) Domoticz.Log("battConsumedAh: " + str(self.battConsumedAh)) Domoticz.Log("battTimeToGo: " + str(self.battTimeToGo)) if self.idx < len(self.registers): self.sendPriv() else: self.SyncDevices(0) return
def update(self,client,Domoticz): value = "0" #Domoticz.Log("--> Device:"+self.device.Name+" Address="+str(self.UnitIdForIp)+", Register="+str(self.address)+", Function="+self.function+", Data type="+self.dataType+" Digits:"+str(self.digits)+" Method="+self.method) ################################### # pymodbus section ################################### if (self.method == "rtu" or self.method == "ascii" or self.method == "rtutcp"): Domoticz.Log("Start rtu read") try: # Which function to execute? RTU/ASCII/RTU over TCP or COM if (self.function == "1"): data = client.read_coils(self.address, self.registercount, unit=self.UnitIdForIpUnitIdForIp) elif (self.function == "2"): data = client.read_discrete_inputs(self.address, self.registercount, unit=self.UnitIdForIp) elif (self.function == "3"): data = client.read_holding_registers(self.address, self.registercount, unit=self.UnitIdForIp) elif (self.function == "4"): data = client.read_input_registers(self.address, self.registercount, unit=self.UnitIdForIp) else: Domoticz.Debug("No function selected: " + str(self.function)) return Domoticz.Log("MODBUS DEBUG RESPONSE: " + str(data.registers)) except Exception as e: Domoticz.Log("Modbus error communicating! (RTU/ASCII/RTU over TCP or COM), check your settings!"+repr(e)) data = 0 #self.device.Update(0, "0") # Update device to OFF in Domoticz ################################### # pymodbusTCP section ################################### else: #if (self.method == "tcpip"): #Domoticz.Log("Start tcp read") try: # Which function to execute? TCP/IP if (function == "1"): data = client.read_coils(self.address, self.registercount) if (function == "2"): data = client.read_discrete_inputs(self.address, self.registercount) if (function == "3"): data = client.read_holding_registers(self.address, self.registercount) if (function == "4"): data = client.read_input_registers(self.address, self.registercount) Domoticz.Log("MODBUS DEBUG RESPONSE: " + str(data)) except Exception as e: Domoticz.Log("Modbus error communicating! (TCP/IP), check your settings!"+repr(e)) data = 0 #self.device.Update(0, "0") # Update device to OFF in Domoticz #Domoticz.Log("Modbus Na read" ) if data: try: # How to decode the input? try: decoder = BinaryPayloadDecoder.fromRegisters(data, byteorder=self.byteorder, wordorder=self.wordorder) except: decoder = BinaryPayloadDecoder.fromRegisters(data.registers, byteorder=self.byteorder, wordorder=self.wordorder) if (self.dataType == "noco"): value = data if (self.dataType == "int8LSB"): ignored = decoder.skip_bytes(1) value = decoder.decode_8bit_int() if (self.dataType == "int8MSB"): value = decoder.decode_8bit_int() if (self.dataType == "int16"): value = decoder.decode_16bit_int() if (self.dataType == "int16s"): value = decoder.decode_16bit_int() if (self.dataType == "int32"): value = decoder.decode_32bit_int() if (self.dataType == "int64"): value = decoder.decode_64bit_int() if (self.dataType == "uint8LSB"): ignored = decoder.skip_bytes(1) value = decoder.decode_8bit_uint() if (self.dataType == "uint8MSB"): value = decoder.decode_8bit_uint() if (self.dataType == "uint16"): value = decoder.decode_16bit_uint() if (self.dataType == "uint32"): value = decoder.decode_32bit_uint() if (self.dataType == "uint64"): value = decoder.decode_64bit_uint() if (self.dataType == "float32"): value = decoder.decode_32bit_float() if (self.dataType == "float64"): value = decoder.decode_64bit_float() if (self.dataType == "string2"): value = decoder.decode_string(2) if (self.dataType == "string4"): value = decoder.decode_string(4) if (self.dataType == "string6"): value = decoder.decode_string(6) if (self.dataType == "string8"): value = decoder.decode_string(8) if (self.dataType == "bcd8"): value=decoder.decoder.decode_8bit_int() value=value & 0xf + value & (0xf0&0xf0>>4*10) if (self.dataType == "bcd16"): value=decoder.decoder.decode_8bit_int() value=value & 0xf + (value & 0xf0>>4*10) + (value & 0xf00>>8*100) + (value & 0xf000>>12*1000) if multiplydevice: value=value*domoticz.device(multiplydevice) # Divide the value (decimal)? value = str(round(value / self.devide, self.digits)) Domoticz.Log("MODBUS DEBUG VALUE: " + str(value)+" Old value:"+self.device.sValue+" Old value:"+str(self.device.nValue)) #Domoticz.Log("LastUpdate:"+self.device.LastUpdate) age=(datetime.now()-datetime.strptime(self.device.LastUpdate, '%Y-%m-%d %H:%M:%S')).seconds #Domoticz.Log("LastUpdate seconds ago:"+str(age)) if (self.device.sValue != value ) or age>300: self.device.Update(0, value) # Update value in Domoticz #Domoticz.Debug("Done update: " + str(value)) except Exception as e: Domoticz.Log("Modbus error decoding or received no data (TCP/IP)!, check your settings!"+repr(e)) #self.device.Update(0, "0") # Update value in Domoticz else: Domoticz.Log("No data")
def logConnectStatus(conn): if conn: Domoticz.Log('~~~~~~~~~~~Connecting: ' + str(conn.Connecting()) + ' Connected: ' + str(conn.Connected()))
def load_new_param_definition(self): for key in self.ListOfDevices: if "Model" not in self.ListOfDevices[key]: continue if self.ListOfDevices[key]["Model"] not in self.DeviceConf: continue model_name = self.ListOfDevices[key]["Model"] if "Param" not in self.DeviceConf[model_name]: continue self.ListOfDevices[key]["CheckParam"] = True if "Param" not in self.ListOfDevices[key]: self.ListOfDevices[key]["Param"] = {} for param in self.DeviceConf[model_name]["Param"]: if param in self.ListOfDevices[key]["Param"]: continue # Initiatilize the parameter with the Configuration. self.ListOfDevices[key]["Param"][param] = self.DeviceConf[model_name]["Param"][param] # Overwrite the param by Existing Global parameter # if param in ( 'fadingOff', 'moveToHueSatu' ,'moveToColourTemp','moveToColourRGB','moveToLevel'): # # Use Global as default # if self.DeviceConf[ model_name ]['Param'][ param ] != self.pluginconf.pluginConf[ param ]: # self.ListOfDevices[ key ]['Param'][ param ] = self.pluginconf.pluginConf[ param ] if param in ("PowerOnAfterOffOn"): if "Manufacturer" not in self.ListOfDevices[key]: return if self.ListOfDevices[key]["Manufacturer"] == "100b": # Philips self.ListOfDevices[key]["Param"][param] = self.pluginconf.pluginConf["PhilipsPowerOnAfterOffOn"] elif self.ListOfDevices[key]["Manufacturer"] == "1277": # Enki Leroy Merlin self.ListOfDevices[key]["Param"][param] = self.pluginconf.pluginConf["EnkiPowerOnAfterOffOn"] elif self.ListOfDevices[key]["Manufacturer"] == "1021": # Legrand Netatmo self.ListOfDevices[key]["Param"][param] = self.pluginconf.pluginConf["LegrandPowerOnAfterOffOn"] elif self.ListOfDevices[key]["Manufacturer"] == "117c": # Ikea Tradfri self.ListOfDevices[key]["Param"][param] = self.pluginconf.pluginConf["IkeaPowerOnAfterOffOn"] elif param in ("PowerPollingFreq",): POLLING_TABLE_SPECIFICS = { "_TZ3000_g5xawfcq": "pollingBlitzwolfPower", "LUMI": "pollingLumiPower", "115f": "pollingLumiPower", } devManufCode = devManufName = "" if "Manufacturer" in self.ListOfDevices[key]: devManufCode = self.ListOfDevices[key]["Manufacturer"] if "Manufacturer Name" in self.ListOfDevices[key]: devManufName = self.ListOfDevices[key]["Manufacturer Name"] if devManufCode == devManufName == "": return plugin_generic_param = None if devManufCode in POLLING_TABLE_SPECIFICS: plugin_generic_param = POLLING_TABLE_SPECIFICS[devManufCode] if plugin_generic_param is None and devManufName in POLLING_TABLE_SPECIFICS: plugin_generic_param = POLLING_TABLE_SPECIFICS[devManufName] if plugin_generic_param is None: return False Domoticz.Log("--->PluginConf %s <-- %s" % (param, plugin_generic_param)) self.ListOfDevices[key]["Param"][param] = self.pluginconf.pluginConf[plugin_generic_param] elif param in ("OnOffPollingFreq",): POLLING_TABLE_SPECIFICS = { "100b": "pollingPhilips", "Philips": "pollingPhilips", "GLEDOPTO": "pollingGledopto", } devManufCode = devManufName = "" if "Manufacturer" in self.ListOfDevices[key]: devManufCode = self.ListOfDevices[key]["Manufacturer"] if "Manufacturer Name" in self.ListOfDevices[key]: devManufName = self.ListOfDevices[key]["Manufacturer Name"] if devManufCode == devManufName == "": return plugin_generic_param = None if devManufCode in POLLING_TABLE_SPECIFICS: plugin_generic_param = POLLING_TABLE_SPECIFICS[devManufCode] if plugin_generic_param is None and devManufName in POLLING_TABLE_SPECIFICS: plugin_generic_param = POLLING_TABLE_SPECIFICS[devManufName] if plugin_generic_param is None: return False Domoticz.Log("--->PluginConf %s <-- %s" % (param, plugin_generic_param)) self.ListOfDevices[key]["Param"][param] = self.pluginconf.pluginConf[plugin_generic_param] elif param in ("AC201Polling",): POLLING_TABLE_SPECIFICS = { "OWON": "pollingCasaiaAC201", "CASAIA": "pollingCasaiaAC201", } devManufCode = devManufName = "" if "Manufacturer" in self.ListOfDevices[key]: devManufCode = self.ListOfDevices[key]["Manufacturer"] if "Manufacturer Name" in self.ListOfDevices[key]: devManufName = self.ListOfDevices[key]["Manufacturer Name"] if devManufCode == devManufName == "": return plugin_generic_param = None if devManufCode in POLLING_TABLE_SPECIFICS: plugin_generic_param = POLLING_TABLE_SPECIFICS[devManufCode] if plugin_generic_param is None and devManufName in POLLING_TABLE_SPECIFICS: plugin_generic_param = POLLING_TABLE_SPECIFICS[devManufName] if plugin_generic_param is None: return False Domoticz.Log("--->PluginConf %s <-- %s" % (param, plugin_generic_param)) self.ListOfDevices[key]["Param"][param] = self.pluginconf.pluginConf[plugin_generic_param] elif param == "netatmoLedIfOn": self.ListOfDevices[key]["Param"][param] = self.pluginconf.pluginConf["EnableLedIfOn"] elif param == "netatmoLedInDark": self.ListOfDevices[key]["Param"][param] = self.pluginconf.pluginConf["EnableLedInDark"] elif param == "netatmoLedShutter": self.ListOfDevices[key]["Param"][param] = self.pluginconf.pluginConf["EnableLedShutter"] elif param == "netatmoEnableDimmer": self.ListOfDevices[key]["Param"][param] = self.pluginconf.pluginConf["EnableDimmer"] elif param == "netatmoInvertShutter": self.ListOfDevices[key]["Param"][param] = self.pluginconf.pluginConf["InvertShutter"] elif param == "netatmoReleaseButton": self.ListOfDevices[key]["Param"][param] = self.pluginconf.pluginConf["EnableReleaseButton"]
def LoadDeviceList(self): # Load DeviceList.txt into ListOfDevices # # Let's check if we have a .json version. If so, we will be using it, otherwise # we fall back to the old fashion .txt jsonFormatDB = True # This can be enabled only with Domoticz version 2021.1 build 1395 and above, otherwise big memory leak if Modules.tools.is_domoticz_db_available(self) and self.pluginconf.pluginConf["useDomoticzDatabase"]: ListOfDevices_from_Domoticz, saving_time = _read_DeviceList_Domoticz(self) Domoticz.Log( "Database from Dz is recent: %s Loading from Domoticz Db" % is_domoticz_recent(self, saving_time, self.pluginconf.pluginConf["pluginData"] + self.DeviceListName) ) if self.pluginconf.pluginConf["expJsonDatabase"]: if os.path.isfile(self.pluginconf.pluginConf["pluginData"] + self.DeviceListName[:-3] + "json"): # JSON Format _DeviceListFileName = self.pluginconf.pluginConf["pluginData"] + self.DeviceListName[:-3] + "json" jsonFormatDB = True res = loadJsonDatabase(self, _DeviceListFileName) elif os.path.isfile(self.pluginconf.pluginConf["pluginData"] + self.DeviceListName): _DeviceListFileName = self.pluginconf.pluginConf["pluginData"] + self.DeviceListName jsonFormatDB = False res = loadTxtDatabase(self, _DeviceListFileName) else: # Do not exist self.ListOfDevices = {} return True else: if os.path.isfile(self.pluginconf.pluginConf["pluginData"] + self.DeviceListName): _DeviceListFileName = self.pluginconf.pluginConf["pluginData"] + self.DeviceListName jsonFormatDB = False res = loadTxtDatabase(self, _DeviceListFileName) else: # Do not exist self.ListOfDevices = {} return True self.log.logging("Database", "Debug", "LoadDeviceList - DeviceList filename : " + _DeviceListFileName) _versionFile(_DeviceListFileName, self.pluginconf.pluginConf["numDeviceListVersion"]) # Keep the Size of the DeviceList in order to check changes self.DeviceListSize = os.path.getsize(_DeviceListFileName) for addr in self.ListOfDevices: # Fixing mistake done in the code. fixing_consumption_lumi(self, addr) fixing_iSQN_None(self, addr) # Check if 566 fixs are needed if self.pluginconf.pluginConf["Bug566"]: if "Model" in self.ListOfDevices[addr]: if self.ListOfDevices[addr]["Model"] == "TRADFRI control outlet": fixing_Issue566(self, addr) if self.pluginconf.pluginConf["resetReadAttributes"]: self.log.logging("Database", "Log", "ReadAttributeReq - Reset ReadAttributes data %s" % addr) Modules.tools.reset_datastruct(self, "ReadAttributes", addr) # self.ListOfDevices[addr]['ReadAttributes'] = {} # self.ListOfDevices[addr]['ReadAttributes']['Ep'] = {} # for iterEp in self.ListOfDevices[addr]['Ep']: # self.ListOfDevices[addr]['ReadAttributes']['Ep'][iterEp] = {} if self.pluginconf.pluginConf["resetConfigureReporting"]: self.log.logging("Database", "Log", "Reset ConfigureReporting data %s" % addr) Modules.tools.reset_datastruct(self, "ConfigureReporting", addr) # self.ListOfDevices[addr]['ConfigureReporting'] = {} # self.ListOfDevices[addr]['ConfigureReporting']['Ep'] = {} # for iterEp in self.ListOfDevices[addr]['Ep']: # self.ListOfDevices[addr]['ConfigureReporting']['Ep'][iterEp] = {} if self.pluginconf.pluginConf["resetReadAttributes"]: self.pluginconf.pluginConf["resetReadAttributes"] = False self.pluginconf.write_Settings() if self.pluginconf.pluginConf["resetConfigureReporting"]: self.pluginconf.pluginConf["resetConfigureReporting"] = False self.pluginconf.write_Settings() load_new_param_definition(self) self.log.logging("Database", "Status", "%s Entries loaded from %s" % (len(self.ListOfDevices), _DeviceListFileName)) if Modules.tools.is_domoticz_db_available(self) and self.pluginconf.pluginConf["useDomoticzDatabase"]: self.log.logging( "Database", "Log", "Plugin Database loaded - BUT NOT USE - from Dz: %s from DeviceList: %s, checking deltas " % ( len(ListOfDevices_from_Domoticz), len(self.ListOfDevices), ), ) #try: # import sys # # sys.path.append("/usr/lib/python3.8/site-packages") # import deepdiff # # diff = deepdiff.DeepDiff(self.ListOfDevices, ListOfDevices_from_Domoticz) # self.log.logging("Database", "Log", json.dumps(json.loads(diff.to_json()), indent=4)) # #except: # # self.log.logging("Database", "Log", "Python Module deepdiff not found") # pass return res
def onDisconnect(self): Domoticz.Log("onDisconnect called")
def onHeartbeat(self): #Domoticz.Log("onHeartbeat called") # Wich serial port settings to use? if (Parameters["Mode3"] == "S1B7PN"): StopBits, ByteSize, Parity = 1, 7, "N" if (Parameters["Mode3"] == "S1B7PE"): StopBits, ByteSize, Parity = 1, 7, "E" if (Parameters["Mode3"] == "S1B7PO"): StopBits, ByteSize, Parity = 1, 7, "O" if (Parameters["Mode3"] == "S1B8PN"): StopBits, ByteSize, Parity = 1, 8, "N" if (Parameters["Mode3"] == "S1B8PE"): StopBits, ByteSize, Parity = 1, 8, "E" if (Parameters["Mode3"] == "S1B8PO"): StopBits, ByteSize, Parity = 1, 8, "O" if (Parameters["Mode3"] == "S2B7PN"): StopBits, ByteSize, Parity = 2, 7, "N" if (Parameters["Mode3"] == "S2B7PE"): StopBits, ByteSize, Parity = 2, 7, "E" if (Parameters["Mode3"] == "S2B7PO"): StopBits, ByteSize, Parity = 2, 7, "O" if (Parameters["Mode3"] == "S2B8PN"): StopBits, ByteSize, Parity = 2, 8, "N" if (Parameters["Mode3"] == "S2B8PE"): StopBits, ByteSize, Parity = 2, 8, "E" if (Parameters["Mode3"] == "S2B8PO"): StopBits, ByteSize, Parity = 2, 8, "O" # How many registers to read (depending on data type)? registercount = 1 # Default if (Parameters["Mode6"] == "noco"): registercount = 1 if (Parameters["Mode6"] == "int8"): registercount = 1 if (Parameters["Mode6"] == "int16"): registercount = 1 if (Parameters["Mode6"] == "int32"): registercount = 2 if (Parameters["Mode6"] == "int64"): registercount = 4 if (Parameters["Mode6"] == "uint8"): registercount = 1 if (Parameters["Mode6"] == "uint16"): registercount = 1 if (Parameters["Mode6"] == "uint32"): registercount = 2 if (Parameters["Mode6"] == "uint64"): registercount = 4 if (Parameters["Mode6"] == "float32"): registercount = 2 if (Parameters["Mode6"] == "float64"): registercount = 4 if (Parameters["Mode6"] == "string2"): registercount = 2 if (Parameters["Mode6"] == "string4"): registercount = 4 if (Parameters["Mode6"] == "string6"): registercount = 6 if (Parameters["Mode6"] == "string8"): registercount = 8 ################################### # pymodbus: RTU / ASCII ################################### if (Parameters["Mode1"] == "rtu" or Parameters["Mode1"] == "ascii"): Domoticz.Debug("MODBUS DEBUG USB SERIAL HW - Port=" + Parameters["SerialPort"] + ", BaudRate=" + Parameters["Mode2"] + ", StopBits=" + str(StopBits) + ", ByteSize=" + str(ByteSize) + " Parity=" + Parity) Domoticz.Debug("MODBUS DEBUG USB SERIAL CMD - Method=" + Parameters["Mode1"] + ", Address=" + Parameters["Address"] + ", Register=" + Parameters["Password"] + ", Function=" + Parameters["Username"] + ", Data type=" + Parameters["Mode6"]) try: client = ModbusSerialClient(method=Parameters["Mode1"], port=Parameters["SerialPort"], stopbits=StopBits, bytesize=ByteSize, parity=Parity, baudrate=int(Parameters["Mode2"]), timeout=1, retries=2) except: Domoticz.Log("Error opening Serial interface on " + Parameters["SerialPort"]) Devices[1].Update(0, "0") # Update device in Domoticz ################################### # pymodbus: RTU over TCP ################################### if (Parameters["Mode1"] == "rtutcp"): Domoticz.Debug("MODBUS DEBUG TCP CMD - Method=" + Parameters["Mode1"] + ", Address=" + Parameters["Address"] + ", Port=" + Parameters["Port"] + ", Register=" + Parameters["Password"] + ", Data type=" + Parameters["Mode6"]) try: client = ModbusTcpClient(host=Parameters["Address"], port=int(Parameters["Port"]), timeout=5) except: Domoticz.Log("Error opening TCP interface on address: " + Parameters["Address"]) Devices[1].Update(0, "0") # Update device in Domoticz ################################### # pymodbusTCP: TCP/IP ################################### if (Parameters["Mode1"] == "tcpip"): Domoticz.Debug("MODBUS DEBUG TCP CMD - Method=" + Parameters["Mode1"] + ", Address=" + Parameters["Address"] + ", Port=" + Parameters["Port"] + ", Register=" + Parameters["Password"] + ", Data type=" + Parameters["Mode6"]) try: client = ModbusClient(host=Parameters["Address"], port=int(Parameters["Port"]), auto_open=True, auto_close=True, timeout=5) except: Domoticz.Log("Error opening TCP/IP interface on address: " + Parameters["Address"]) Devices[1].Update(0, "0") # Update device in Domoticz ################################### # pymodbus section ################################### if (Parameters["Mode1"] == "rtu" or Parameters["Mode1"] == "ascii" or Parameters["Mode1"] == "rtutcp"): try: # Which function to execute? RTU/ASCII/RTU over TCP if (Parameters["Username"] == "1"): data = client.read_coils(int(Parameters["Password"]), registercount, unit=int(Parameters["Address"])) if (Parameters["Username"] == "2"): data = client.read_discrete_inputs( int(Parameters["Password"]), registercount, unit=int(Parameters["Address"])) if (Parameters["Username"] == "3"): data = client.read_holding_registers( int(Parameters["Password"]), registercount, unit=int(Parameters["Address"])) if (Parameters["Username"] == "4"): data = client.read_input_registers( int(Parameters["Password"]), registercount, unit=int(Parameters["Address"])) Domoticz.Debug("MODBUS DEBUG RESPONSE: " + str(data)) except: Domoticz.Log( "Modbus error communicating! (RTU/ASCII/RTU over TCP), check your settings!" ) Devices[1].Update(0, "0") # Update device to OFF in Domoticz try: # How to decode the input? decoder = BinaryPayloadDecoder.fromRegisters( data.registers, byteorder=Endian.Big, wordorder=Endian.Big) if (Parameters["Mode6"] == "noco"): value = data.registers[0] if (Parameters["Mode6"] == "int8"): value = decoder.decode_8bit_int() if (Parameters["Mode6"] == "int16"): value = decoder.decode_16bit_int() if (Parameters["Mode6"] == "int32"): value = decoder.decode_32bit_int() if (Parameters["Mode6"] == "int64"): value = decoder.decode_64bit_int() if (Parameters["Mode6"] == "uint8"): value = decoder.decode_8bit_uint() if (Parameters["Mode6"] == "uint16"): value = decoder.decode_16bit_uint() if (Parameters["Mode6"] == "uint32"): value = decoder.decode_32bit_uint() if (Parameters["Mode6"] == "uint64"): value = decoder.decode_64bit_uint() if (Parameters["Mode6"] == "float32"): value = decoder.decode_32bit_float() if (Parameters["Mode6"] == "float64"): value = decoder.decode_64bit_float() if (Parameters["Mode6"] == "string2"): value = decoder.decode_string(2) if (Parameters["Mode6"] == "string4"): value = decoder.decode_string(4) if (Parameters["Mode6"] == "string6"): value = decoder.decode_string(6) if (Parameters["Mode6"] == "string8"): value = decoder.decode_string(8) Domoticz.Debug("MODBUS DEBUG VALUE: " + str(value)) # Divide the value (decimal)? if (Parameters["Mode5"] == "div0"): value = str(value) if (Parameters["Mode5"] == "div10"): value = str(round(value / 10, 1)) if (Parameters["Mode5"] == "div100"): value = str(round(value / 100, 2)) if (Parameters["Mode5"] == "div1000"): value = str(round(value / 1000, 3)) Devices[1].Update(0, value) # Update value in Domoticz except: Domoticz.Log( "Modbus error decoding or recieved no data (RTU/ASCII/RTU over TCP)!, check your settings!" ) Devices[1].Update(0, "0") # Update value in Domoticz ################################### # pymodbusTCP section ################################### if (Parameters["Mode1"] == "tcpip"): try: # Which function to execute? TCP/IP if (Parameters["Username"] == "1"): data = client.read_coils(int(Parameters["Password"]), registercount) if (Parameters["Username"] == "2"): data = client.read_discrete_inputs( int(Parameters["Password"]), registercount) if (Parameters["Username"] == "3"): data = client.read_holding_registers( int(Parameters["Password"]), registercount) if (Parameters["Username"] == "4"): data = client.read_input_registers( int(Parameters["Password"]), registercount) Domoticz.Debug("MODBUS DEBUG RESPONSE: " + str(data[0])) except: Domoticz.Log( "Modbus error communicating! (TCP/IP), check your settings!" ) Devices[1].Update(0, "0") # Update device to OFF in Domoticz try: # How to decode the input? decoder = BinaryPayloadDecoder.fromRegisters( data, byteorder=Endian.Big, wordorder=Endian.Big) if (Parameters["Mode6"] == "noco"): value = data[0] if (Parameters["Mode6"] == "int8"): value = decoder.decode_8bit_int() if (Parameters["Mode6"] == "int16"): value = decoder.decode_16bit_int() if (Parameters["Mode6"] == "int32"): value = decoder.decode_32bit_int() if (Parameters["Mode6"] == "int64"): value = decoder.decode_64bit_int() if (Parameters["Mode6"] == "uint8"): value = decoder.decode_8bit_uint() if (Parameters["Mode6"] == "uint16"): value = decoder.decode_16bit_uint() if (Parameters["Mode6"] == "uint32"): value = decoder.decode_32bit_uint() if (Parameters["Mode6"] == "uint64"): value = decoder.decode_64bit_uint() if (Parameters["Mode6"] == "float32"): value = decoder.decode_32bit_float() if (Parameters["Mode6"] == "float64"): value = decoder.decode_64bit_float() if (Parameters["Mode6"] == "string2"): value = decoder.decode_string(2) if (Parameters["Mode6"] == "string4"): value = decoder.decode_string(4) if (Parameters["Mode6"] == "string6"): value = decoder.decode_string(6) if (Parameters["Mode6"] == "string8"): value = decoder.decode_string(8) Domoticz.Debug("MODBUS DEBUG VALUE: " + str(value)) # Divide the value (decimal)? if (Parameters["Mode5"] == "div0"): value = str(value) if (Parameters["Mode5"] == "div10"): value = str(round(value / 10, 1)) if (Parameters["Mode5"] == "div100"): value = str(round(value / 100, 2)) if (Parameters["Mode5"] == "div1000"): value = str(round(value / 1000, 3)) Devices[1].Update(0, value) # Update value in Domoticz except: Domoticz.Log( "Modbus error decoding or recieved no data (TCP/IP)!, check your settings!" ) Devices[1].Update(0, "0") # Update value in Domoticz
def onDisconnect(self, Connection): if Parameters["Mode6"] == "Debug": Domoticz.Log("Device has disconnected") self.conn = None return
def onStart(self): Domoticz.Heartbeat(20) if Parameters['Mode4'] == 'Debug': Domoticz.Debugging(1) DumpConfigToLog() try: self.myzones = json.loads(Parameters['Mode3']) except Exception: self.myzones={} Domoticz.Debug("Gots zones: %s" % self.myzones) try: self.mytargets = json.loads(Parameters['Mode6']) except Exception: self.mytargets={} Domoticz.Debug("Gots targets: %s" % self.mytargets) self.heartBeatCnt = 0 self.subHost = Parameters['Address'] self.subPort = Parameters['Port'] self.tcpConn = Domoticz.Connection(Name='MIIOServer', Transport='TCP/IP', Protocol='None', Address=self.subHost, Port=self.subPort) if self.iconName not in Images: Domoticz.Image('icons.zip').Create() iconID = Images[self.iconName].ID if self.mainIconName not in Images: Domoticz.Image('xiaomi-mi-robot-vacuum-main.zip').Create() mainIconID = Images[self.mainIconName].ID if self.targetIconName not in Images: Domoticz.Image('xiaomi-mi-robot-vacuum-target.zip').Create() targetIconID = Images[self.targetIconName].ID if self.zoneIconName not in Images: Domoticz.Image('xiaomi-mi-robot-vacuum-zone.zip').Create() zoneIconID = Images[self.zoneIconName].ID if self.sensorsIconName not in Images: Domoticz.Image('xiaomi-mi-robot-vacuum-sensors.zip').Create() sensorsIconID = Images[self.sensorsIconName].ID if self.mbrushIconName not in Images: Domoticz.Image('xiaomi-mi-robot-vacuum-mbrush.zip').Create() mbrushIconID = Images[self.mbrushIconName].ID if self.brushIconName not in Images: Domoticz.Image('xiaomi-mi-robot-vacuum-brush.zip').Create() brushIconID = Images[self.brushIconName].ID if self.filterIconName not in Images: Domoticz.Image('xiaomi-mi-robot-vacuum-filter.zip').Create() filterIconID = Images[self.filterIconName].ID if self.chargeIconName not in Images: Domoticz.Image('xiaomi-mi-robot-vacuum-charge.zip').Create() chargeIconID = Images[self.chargeIconName].ID if self.statusUnit not in Devices: Domoticz.Device(Name='Status', Unit=self.statusUnit, Type=17, Switchtype=17, Image=mainIconID).Create() if self.controlUnit not in Devices: Domoticz.Device(Name='Control', Unit=self.controlUnit, TypeName='Selector Switch', Image=mainIconID, Options=self.controlOptions).Create() if self.fanDimmerUnit not in Devices and Parameters['Mode5'] == 'dimmer': Domoticz.Device(Name='Fan Level', Unit=self.fanDimmerUnit, Type=244, Subtype=73, Switchtype=7, Image=mainIconID).Create() elif self.fanSelectorUnit not in Devices and Parameters['Mode5'] == 'selector': Domoticz.Device(Name='Fan Level', Unit=self.fanSelectorUnit, TypeName='Selector Switch', Image=mainIconID, Options=self.fanOptions).Create() #if self.batteryUnit not in Devices: # Domoticz.Device(Name='Battery', Unit=self.batteryUnit, TypeName='Custom', Image=chargeIconID, # Options=self.customSensorOptions).Create() if self.cMainBrushUnit not in Devices: Domoticz.Device(Name='Care Main Brush', Unit=self.cMainBrushUnit, TypeName='Custom', Image=mbrushIconID, Options=self.customSensorOptions).Create() if self.cSideBrushUnit not in Devices: Domoticz.Device(Name='Care Side Brush', Unit=self.cSideBrushUnit, TypeName='Custom', Image=brushIconID, Options=self.customSensorOptions).Create() if self.cSensorsUnit not in Devices: Domoticz.Device(Name='Care Sensors ', Unit=self.cSensorsUnit, TypeName='Custom', Image=sensorsIconID, Options=self.customSensorOptions).Create() if self.cFilterUnit not in Devices: Domoticz.Device(Name='Care Filter', Unit=self.cFilterUnit, TypeName='Custom', Image=filterIconID, Options=self.customSensorOptions).Create() if self.cResetControlUnit not in Devices: Domoticz.Device(Name='Care Reset Control', Unit=self.cResetControlUnit, TypeName='Selector Switch', Image=mainIconID, Options=self.careOptions).Create() if self.zoneControlUnit not in Devices: i=1 while i <= len(self.myzones): Options=str(i*10) self.zoneOptions["LevelActions"] += "|" self.zoneOptions["LevelNames"] += "|" + str(self.myzones[Options][0]) i += 1 Domoticz.Log("Zone names: %s" % self.zoneOptions["LevelNames"] ) Domoticz.Device(Name='Zone Control', Unit=self.zoneControlUnit, TypeName='Selector Switch', Image=zoneIconID, Options=self.zoneOptions).Create() if self.targetControlUnit not in Devices: i=1 while i <= len(self.mytargets): Options=str(i*10) self.targetOptions["LevelActions"] += "|" self.targetOptions["LevelNames"] += "|" + str(self.mytargets[Options][0]) i += 1 Domoticz.Log("Target names: %s" % self.targetOptions["LevelNames"] ) Domoticz.Device(Name='Target Control', Unit=self.targetControlUnit, TypeName='Selector Switch', Image=targetIconID, Options=self.targetOptions).Create() Domoticz.Heartbeat(int(Parameters['Mode2']))
def onStop(self): Domoticz.Log("onStop called") return True
def onStart(self): # Debug mode Domoticz.Debugging(int(Parameters["Mode6"])) Domoticz.Debug("onStart called") #get parameters self.__address = Parameters["Address"] self.__devID = Parameters["Mode1"] self.__localKey = Parameters["Mode2"] self.__ampere, self.__watt, self.__voltage = Parameters["Mode5"].split(";") #set the next heartbeat self.__runAgain = self.__HB_BASE_FREQ #build internal maps (__unit2dps_id_list and __plugs) self.__unit2dps_id_list = {} self.__plugs = {} max_unit = 0 max_dps = 0 for val in sorted(Parameters["Mode3"].split(";")): self.__unit2dps_id_list[int(val)]=[int(val),] self.__plugs[int(val)]=Plug(int(val)) if(int(val)>max_unit): max_unit=int(val) max_dps = max_unit #groups management: #syntax: 1;2 : 3;4 # +5 instead of +1 to have spare room for the extra devices for Amp, W, kWh max_unit = max_unit + 5 if(Parameters["Mode4"]!="None"): groups = Parameters["Mode4"].split(":") for group in groups: self.__unit2dps_id_list[max_unit]=[] for val in sorted(group.split(";")): self.__unit2dps_id_list[max_unit].append(int(val)) max_unit = max_unit + 1 #create domoticz devices if(len(Devices) == 0): for val in self.__unit2dps_id_list: if(val <= max_dps): #single socket dps Domoticz.Device(Name="Tuya SmartPlug (Switch)", Unit=val, TypeName="Switch").Create() Domoticz.Log("Tuya SmartPlug Device (Switch) #" + str(val) +" created.") ## After the last DPS add the global devices if(val == max_dps): Domoticz.Device(Name="Tuya SmartPlug (A)" , Unit=val+1, TypeName="Current (Single)").Create() Domoticz.Log("Tuya SmartPlug Device (A) #" + str(val+1) +" created.") Domoticz.Device(Name="Tuya SmartPlug (kWh)", Unit=val+2, TypeName="kWh").Create() Domoticz.Log("Tuya SmartPlug Device kWh #" + str(val+2) +" created.") Domoticz.Device(Name="Tuya SmartPlug (V)", Unit=val+3, TypeName="Voltage").Create() Domoticz.Log("Tuya SmartPlug Device (V) #" + str(val+3) +" created.") Domoticz.Device(Name="Tuya SmartPlug (W)", Unit=val+4, TypeName="Usage").Create() Domoticz.Log("Tuya SmartPlug Device (W) #" + str(val+4) +" created.") else: #group: selector switch Options = {"LevelActions": "|", "LevelNames": "Off|On", "LevelOffHidden": "false", "SelectorStyle": "0"} Domoticz.Device(Name="Tuya SmartPlug #" + str(val), Unit=val, TypeName="Selector Switch", Options=Options).Create() Domoticz.Log("Tuya SmartPlug Device #" + str(val) +" created.") #manage always on #if(Parameters["Mode5"]!="None"): # for val in sorted(Parameters["Mode5"].split(";")): # self.__plugs[int(val)].set_alwaysON() #create the pytuya object self.__device = pytuya.OutletDevice(self.__devID, self.__address, self.__localKey) #state machine self.__state_machine = 0 #start the connection self.__connection = Domoticz.Connection(Name="Tuya", Transport="TCP/IP", Address=self.__address, Port="6668") self.__connection.Connect()
def onStart(self): Domoticz.Debug("onStart called") if Parameters["Mode6"] == 'Debug': self.debug = True Domoticz.Debugging(1) DumpConfigToLog() else: Domoticz.Debugging(0) Domoticz.Log("Domoticz Node Name is:" + platform.node()) Domoticz.Log("Domoticz Platform System is:" + platform.system()) Domoticz.Debug("Domoticz Platform Release is:" + platform.release()) Domoticz.Debug("Domoticz Platform Version is:" + platform.version()) Domoticz.Log("Default Python Version is:" + str(sys.version_info[0]) + "." + str(sys.version_info[1]) + "." + str(sys.version_info[2]) + ".") if platform.system() == "Windows": Domoticz.Error("Windows Platform NOT YET SUPPORTED!!") return pluginText = "" pluginAuthor = "" pluginRepository = "" pluginKey = "" pluginKey = Parameters["Mode2"] pluginAuthor = self.plugindata[pluginKey][0] pluginRepository = self.plugindata[pluginKey][1] pluginText = self.plugindata[pluginKey][2] pluginBranch = self.plugindata[pluginKey][3] # GitHub branch to clone if (Parameters["Mode5"] == 'True'): Domoticz.Log("Plugin Security Scan is enabled") # Reading secpoluserFile and populating array of values secpoluserFile = str(os.getcwd()) + "/plugins/PP-MANAGER/secpoluser.txt" Domoticz.Debug("Checking for SecPolUser file on:" + secpoluserFile) if (os.path.isfile(secpoluserFile) == True): Domoticz.Log("secpoluser file found. Processing!!!") # Open the file secpoluserFileHandle = open(secpoluserFile) # use readline() to read the first line line = secpoluserFileHandle.readline() while line: if mid(line,0,4) == "--->": secpoluserSection = mid(line,4,len(line)) Domoticz.Log("secpoluser settings found for plugin:" + secpoluserSection) if ((mid(line,0,4) != "--->") and (line.strip() != "") and (line.strip() != " ")): Domoticz.Debug("SecPolUserList exception (" + secpoluserSection.strip() + "):'" + line.strip() + "'") #SecPolUserList.append(line.strip()) #SecPolUserList[secpoluserSection].append(line.strip()) if secpoluserSection.strip() not in self.SecPolUserList: self.SecPolUserList[secpoluserSection.strip()] = [] self.SecPolUserList[secpoluserSection.strip()].append(line.strip()) # use realine() to read next line line = secpoluserFileHandle.readline() secpoluserFileHandle.close() Domoticz.Log("SecPolUserList exception:" + str(self.SecPolUserList)) else: self.SecPolUserList = {"Global":[]} i = 0 path = str(os.getcwd()) + "/plugins/" for (path, dirs, files) in os.walk(path): for dir in dirs: if str(dir) != "": #self.UpdatePythonPlugin(pluginAuthor, pluginRepository, str(dir)) #parseFileForSecurityIssues(str(os.getcwd()) + "/plugins/PP-MANAGER/plugin.py") if (os.path.isfile(str(os.getcwd()) + "/plugins/" + str(dir) + "/plugin.py") == True): self.parseFileForSecurityIssues(str(os.getcwd()) + "/plugins/" + str(dir) + "/plugin.py", str(dir)) i += 1 if i >= 1: break # Reading exception file and populating array of values exceptionFile = str(os.getcwd()) + "/plugins/PP-MANAGER/exceptions.txt" Domoticz.Debug("Checking for Exception file on:" + exceptionFile) if (os.path.isfile(exceptionFile) == True): Domoticz.Log("Exception file found. Processing!!!") # Open the file f = open(exceptionFile) # use readline() to read the first line line = f.readline() while line: if ((line[:1].strip() != "#") and (line[:1].strip() != " ") and (line[:1].strip() != "")): Domoticz.Log("File ReadLine result:'" + line.strip() + "'") self.ExceptionList.append(line.strip()) # use realine() to read next line line = f.readline() f.close() Domoticz.Debug("self.ExceptionList:" + str(self.ExceptionList)) if Parameters["Mode4"] == 'All': Domoticz.Log("Updating All Plugins!!!") i = 0 path = str(os.getcwd()) + "/plugins/" for (path, dirs, files) in os.walk(path): for dir in dirs: if str(dir) != "": if str(dir) in self.plugindata: self.UpdatePythonPlugin(pluginAuthor, pluginRepository, str(dir)) elif str(dir) == "PP-MANAGER": Domoticz.Debug("PP-Manager Folder found. Skipping!!") else: Domoticz.Log("Plugin:" + str(dir) + " cannot be managed with PP-Manager!!.") i += 1 if i >= 1: break if Parameters["Mode4"] == 'AllNotify': Domoticz.Log("Collecting Updates for All Plugins!!!") i = 0 path = str(os.getcwd()) + "/plugins/" for (path, dirs, files) in os.walk(path): for dir in dirs: if str(dir) != "": if str(dir) in self.plugindata: self.CheckForUpdatePythonPlugin(pluginAuthor, pluginRepository, str(dir)) elif str(dir) == "PP-MANAGER": Domoticz.Debug("PP-Manager Folder found. Skipping!!") else: Domoticz.Log("Plugin:" + str(dir) + " cannot be managed with PP-Manager!!.") i += 1 if i >= 1: break if (Parameters["Mode4"] == 'SelectedNotify'): Domoticz.Log("Collecting Updates for Plugin:" + pluginKey) self.CheckForUpdatePythonPlugin(pluginAuthor, pluginRepository, pluginKey) if pluginKey == "Idle": Domoticz.Log("Plugin Idle") Domoticz.Heartbeat(60) else: Domoticz.Debug("Checking for dir:" + str(os.getcwd()) + "/plugins/" + pluginKey) #If plugin Directory exists if (os.path.isdir(str(os.getcwd()) + "/plugins/" + pluginKey)) == True: Domoticz.Debug("Folder for Plugin:" + pluginKey + " already exists!!!") #Domoticz.Debug("Set 'Python Plugin Manager'/ 'Domoticz plugin' attribute to 'idle' in order t.") if Parameters["Mode4"] == 'Selected': Domoticz.Debug("Updating Enabled for Plugin:" + pluginText + ".Checking For Update!!!") self.UpdatePythonPlugin(pluginAuthor, pluginRepository, pluginKey) Domoticz.Heartbeat(60) else: Domoticz.Log("Installation requested for Plugin:" + pluginText) Domoticz.Debug("Installation URL is:" + "https://github.com/" + pluginAuthor +"/" + pluginRepository) Domoticz.Debug("Current Working dir is:" + str(os.getcwd())) if pluginKey in self.plugindata: Domoticz.Log("Plugin Display Name:" + pluginText) Domoticz.Log("Plugin Author:" + pluginAuthor) Domoticz.Log("Plugin Repository:" + pluginRepository) Domoticz.Log("Plugin Key:" + pluginKey) Domoticz.Log("Plugin Branch:" + pluginBranch) self.InstallPythonPlugin(pluginAuthor, pluginRepository, pluginKey, pluginBranch) Domoticz.Heartbeat(60)
def onConnect(self, Connection, Status, Description): Domoticz.Log("onConnect called")
def onStop(self): Domoticz.Debug("onStop called") Domoticz.Log("Plugin is stopping.") self.UpdatePythonPlugin("ycahome", "pp-manager", "PP-MANAGER") Domoticz.Debugging(0)
def onNotification(self, Name, Subject, Text, Status, Priority, Sound, ImageFile): Domoticz.Log("Notification: " + Name + "," + Subject + "," + Text + "," + Status + "," + str(Priority) + "," + Sound + "," + ImageFile)
def parseFileForSecurityIssues(self, pyfilename, pypluginid): Domoticz.Debug("parseFileForSecurityIssues called") secmonitorOnly = False if Parameters["Mode5"] == 'Monitor': Domoticz.Log("Plugin Security Scan is enabled") secmonitorOnly = True # Open the file file = open(pyfilename, "r") ips = {} #safeStrings = ["['http://schemas.xmlsoap.org/soap/envelope/', 'http://schemas.xmlsoap.org/soap/encoding/']", # "127.0.0.1", # "http://schemas.xmlsoap.org/soap/envelope/'", # "import json", # "import time", # "import platform", # 'import re'] if pypluginid not in self.SecPolUserList: self.SecPolUserList[pypluginid] = [] lineNum = 1 #Domoticz.Error("self.SecPolUserList[pypluginid]:" + str(self.SecPolUserList[pypluginid])) for text in file.readlines(): text = text.rstrip() #Domoticz.Log("'text' is:'" + str(text)) regexFound = re.findall(r'(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})',text) paramFound = re.findall(r'<param field=',text) if ((regexFound) and not (paramFound)): #regexFound[rex] = regexFound[rex].strip('"]') #Domoticz.Error("Security Finding(IPregex):" + str(regexFound) + " LINE: " + str(lineNum) + " FILE:" + pyfilename) for rex in range(0,len(regexFound)): if ((str(text).strip() not in self.SecPolUserList["Global"]) and (str(text).strip() not in self.SecPolUserList[pypluginid]) and (str(text).strip() != "") and (mid(text,0,1) != "#")): Domoticz.Error("Security Finding(IP):-->" + str(text).strip() + "<-- LINE: " + str(lineNum) + " FILE:" + pyfilename) #Domoticz.Error("Security Finding(IPr):" + regexFound[rex] + " LINE: " + str(lineNum) + " FILE:" + pyfilename) ips["IP" + str(lineNum)] = (regexFound[rex], "IP Address") #rex = 0 #regexFound = re.findall('import', text) #if regexFound: #regexFound[rex] = regexFound[rex].strip('"]') #Domoticz.Error("Security Finding(IPregex):" + str(regexFound) + " LINE: " + str(lineNum) + " FILE:" + pyfilename) # for rex in range(0,len(regexFound)): # if ((str(text).strip() not in self.SecPolUserList["Global"]) and (str(text).strip() not in self.SecPolUserList[pypluginid]) and (str(text).strip() != "") and (mid(text,0,1) != "#")): # Domoticz.Error("Security Finding(IMP):-->" + str(text) + "<-- LINE: " + str(lineNum) + " FILE:" + pyfilename) #Domoticz.Error("Security Finding(IPr):" + regexFound[rex] + " LINE: " + str(lineNum) + " FILE:" + pyfilename) # ips["IP" + str(lineNum)] = (regexFound[rex], "Import") #rex = 0 #regexFound = re.findall('subprocess.Popen', text) #if regexFound: #regexFound[rex] = regexFound[rex].strip('"]') #Domoticz.Error("Security Finding(IPregex):" + str(regexFound) + " LINE: " + str(lineNum) + " FILE:" + pyfilename) # for rex in range(0,len(regexFound)): # if ((str(text).strip() not in self.SecPolUserList["Global"]) and (str(text).strip() not in self.SecPolUserList[pypluginid]) and (str(text).strip() != "") and (mid(text,0,1) != "#")): # Domoticz.Error("Security Finding(SUB):-->" + str(text) + "<-- LINE: " + str(lineNum) + " FILE:" + pyfilename) #Domoticz.Error("Security Finding(IPr):" + regexFound[rex] + " LINE: " + str(lineNum) + " FILE:" + pyfilename) # ips["IP" + str(lineNum)] = (regexFound[rex], "Subprocess") #rex = 0 #regexFound = re.findall('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', text) #paramFound = re.findall(r'<param field=',text) #if ((regexFound) and not (paramFound)): #regexFound[rex] = regexFound[rex].strip('"]') #Domoticz.Error("Security Finding(IPregex):" + str(regexFound) + " LINE: " + str(lineNum) + " FILE:" + pyfilename) # for rex in range(0,len(regexFound)): # if ((str(text).strip() not in self.SecPolUserList[pypluginid]) and (str(text).strip() != "") and (mid(text,0,1) != "#")): # Domoticz.Error("Security Finding(HTTP):-->" + str(text) + "<-- LINE: " + str(lineNum) + " FILE:" + pyfilename) #Domoticz.Error("Security Finding(IPr):" + regexFound[rex] + " LINE: " + str(lineNum) + " FILE:" + pyfilename) # ips["IP" + str(lineNum)] = (regexFound[rex], "HTTP Address") lineNum = lineNum + 1 file.close() Domoticz.Debug("IPS Table contents are:" + str(ips))
def onStart(self): global fm if Parameters["Mode6"] != "Normal": Domoticz.Debugging(1) DumpConfigToLog() # Get the location from the Settings if not "Location" in Settings: Domoticz.Log("Location not set in Preferences") return False # The location is stored in a string in the Settings loc = Settings["Location"].split(";") self.myLat = float(loc[0]) self.myLon = float(loc[1]) Domoticz.Debug("Coordinates from Domoticz: " + str(self.myLat) + ";" + str(self.myLon)) if self.myLat == None or self.myLon == None: Domoticz.Log("Unable to parse coordinates") return False # Get the interval specified by the user self.interval = int(Parameters["Mode2"]) if self.interval == None: Domoticz.Log("Unable to parse interval, so set it to 5 minutes") self.interval = 5 # Allowing values below 10 minutes will not get you more info if self.interval < 5: Domoticz.Log("Interval too small, changed to 5 minutes because iPhone battery will fast discharging") self.interval = 5 # Get devices list self.dev = Parameters["Mode3"].split(',') for mydevname in self.dev: self.prevdistance[mydevname] = 0 # Get the iCloud name and password self.iCloudname = Parameters["Username"] self.iCloudpass = Parameters["Password"] # Get Google API self.googleapikey = Parameters["Mode4"] # Get Radius self.radius = float(Parameters["Mode5"]) fm = FindMyiPhone(self.iCloudname, self.iCloudpass, self.interval, self.radius, self.googleapikey) # Check if devices need to be created un=1 for devname in self.dev: if un not in Devices: Domoticz.Device(Name=devname, Unit=un, TypeName="Switch", Used=1).Create() un+=1 if un not in Devices: Domoticz.Device(Name=devname + " position", Unit=un, TypeName="Text", Used=1).Create() un+=1 if un not in Devices: Domoticz.Device(Name=devname + " battery", Unit=un, TypeName="Percentage", Used=1).Create() un+=1 if len(Devices) > len(self.dev)*3: un = len(Devices) while un > len(self.dev)*3: Devices[un].Delete() un -=1 Domoticz.Log("Devices checked and created/updated if necessary") self.lastupdate = datetime.now() # Get data from iCloud if fm.getdevlist(): u=1 for mydevicename in self.dev: if fm.getfmidata(mydevicename): distance = round(math.sqrt(((fm.lon - self.myLon) * 111.320 * math.cos(math.radians(fm.lat)))**2 + ((fm.lat - self.myLat) * 110.547)**2), 2) address = fm.address Domoticz.Log("Заряд: " + str(fm.battery) + "%") Domoticz.Log("Адрес: "+ address + ". " + str(distance) + "km") if distance > self.radius: UpdateDevice(u, 0, 0, True) else: UpdateDevice(u, 1, 0, True) u+=1 UpdateDevice(u, 0, str(address) + " " + str(distance) + "km", True) self.prevdistance[mydevicename] = distance Domoticz.Log(str(self.prevdistance)) u+=1 UpdateDevice(u, 0, str(fm.battery)) u+=1 self.lastupdate = datetime.now() else: Domoticz.Log('Error, may be iCloud username or password incorrect or not connection') Domoticz.Heartbeat(30) return True
def onMessage(self, Connection, Data): Domoticz.Log("onMessage called")
def handleConnection(self, Data=None): # First and last step if self.sConnectionStep == "idle": Domoticz.Log("Récupération des données...") # Reset failed state self.bHasAFail = False if self.httpConn and self.httpConn.Connected(): self.httpConn.Disconnect() self.httpConn = Domoticz.Connection(Name="HTTPS connection", Transport="TCP/IP", Protocol="HTTPS", Address=LOGIN_BASE_URI, Port=BASE_PORT) self.myDebug("Connect") self.sConnectionStep = "logconnecting" self.httpConn.Connect() # Connected, we need to log in elif self.sConnectionStep == "logconnecting": if not self.httpConn.Connected(): Domoticz.Error("Connexion échouée au login") self.sConnectionStep = "idle" self.bHasAFail = True else: self.sConnectionStep = "logconnected" self.login(self.sUser, self.sPassword) # Connected, check that the authentication cookie has been received elif self.sConnectionStep == "logconnected": if self.httpConn and self.httpConn.Connected(): self.httpConn.Disconnect() self.dumpDictToLog(Data) # Grab cookies from received data, if we have "iPlanetDirectoryPro", we're good self.getCookies(Data) if ("iPlanetDirectoryPro" in self.dCookies) and self.dCookies["iPlanetDirectoryPro"]: # Proceed to data page self.sConnectionStep = "getcookies" self.httpConn = Domoticz.Connection(Name="HTTPS connection", Transport="TCP/IP", Protocol="HTTPS", Address=API_BASE_URI, Port=BASE_PORT) self.httpConn.Connect() else: Domoticz.Error("Login échoué, réessaiera plus tard") self.sConnectionStep = "idle" self.bHasAFail = True # If we are connected, we must show the authentication cookie elif self.sConnectionStep == "getcookies": if not self.httpConn.Connected(): Domoticz.Error("Connexion échouée à la lecture des cookies") self.sConnectionStep = "idle" self.bHasAFail = True else: self.getCookies(Data) self.sConnectionStep = "dataconnecting" # Dummy action to show that we have the authentication cookie self.getData("urlCdcJour", self.dateBeginDays, self.dateEndDays) # We are now connected to data page, ask for hours data elif self.sConnectionStep == "dataconnecting" or self.sConnectionStep == "dataconnecting2": if not self.httpConn.Connected(): Domoticz.Error( "Connexion échouée à la réception des premières données") self.sConnectionStep = "idle" self.bHasAFail = True else: self.getCookies(Data) strData = "" if Data and ("Data" in Data): strData = Data["Data"].decode() if "terms_of_use" in strData: if self.bAutoAcceptTerms: Domoticz.Status("Auto-accepting new terms of use") self.acceptTerms() self.sConnectionStep = "dataconnecting" else: Domoticz.Error( "Vous devez acceptez les conditions d'utilisation en vous rendant sur https://" + LOGIN_BASE_URI) self.sConnectionStep = "idle" self.bHasAFail = True else: self.dumpDictToLog(Data) # Dummy action again to show that we have the authentication cookie if self.sConnectionStep == "dataconnecting": self.sConnectionStep = "dataconnecting2" else: self.sConnectionStep = "getdatadays" self.resetDayAccumulate(self.dateEndDays) # Ask data for days self.getData("urlCdcJour", self.dateBeginDays, self.dateEndDays) # Now we should received data for real elif self.sConnectionStep == "getdatadays": if not self.httpConn.Connected(): self.showStepError( False, "Récupération des données pour la vue par jours") self.sConnectionStep = "idle" self.bHasAFail = True else: # Analyse data for days if not self.exploreDataDays(Data): self.bHasAFail = True if self.iDaysLeft > 0: self.calculateDaysLeft() self.sConnectionStep = "getdatadays" self.getData("urlCdcJour", self.dateBeginDays, self.dateEndDays) else: if not self.updateDashboard(): self.bHasAFail = True # user set Mode1 to 0, he doesn't want to grab hours data if self.iHistoryDaysForHoursView < 1: self.sConnectionStep = "idle" Domoticz.Log("Done") else: self.sConnectionStep = "getdatahours" self.getData("urlCdcHeure", self.dateBeginHours, self.dateEndHours) # Ask data for hours elif self.sConnectionStep == "getdatahours": if not self.httpConn.Connected(): self.showStepError( True, "Récupération des données pour la vue par heures") self.sConnectionStep = "idle" self.bHasAFail = True else: # Analyse data for hours if not self.exploreDataHours(Data): self.bHasAFail = True self.sConnectionStep = "idle" Domoticz.Log("Fait") # Next connection time depends on success if self.sConnectionStep == "idle": if self.bHasAFail: self.setNextConnection(False) Domoticz.Log("Prochaine connexion : " + datetimeToSQLDateTimeString(self.nextConnection))
def onCommand(self, Unit, Command, Level, Hue): Domoticz.Log("onCommand called for Unit " + str(Unit) + ": Parameter '" + str(Command) + "', Level: " + str(Level))
def _updateDevices(self): Domoticz.Debug('Updating devices') try: with verisure.Session(Parameters['Username'], Parameters['Password']) as session: overview = session.get_overview() except verisure.Error as e: Domoticz.Error('Verisure exception: {}'.format(e)) return False pass current_devices = self._getDomoticzDeviceList() remote_devices = set() for plug in overview['smartPlugs']: is_on = (plug['currentState'] == 'ON') device = plug['deviceLabel'] remote_devices.add(device) if device not in current_devices: Domoticz.Log('Adding smart plug ({label}) in {area}'.format(label=plug['deviceLabel'], area=plug['area'])) Domoticz.Device(Name='Smart plug', Unit=self.next_unit, TypeName='Switch', Options={'deviceLabel': device}).Create() current_devices[device] = self.next_unit self.next_unit = self.next_unit + 1 unit = current_devices[device] Devices[unit].Update(nValue=1 if is_on else 0, sValue='On' if is_on else 'Off') for climate in overview['climateValues']: has_humidity = 'humidity' in climate device = climate['deviceLabel'] remote_devices.add(device) if device not in current_devices: Domoticz.Log('Adding climate sensor ({label}) in {area}'.format(label=climate['deviceLabel'], area=climate['deviceArea'])) if has_humidity: Domoticz.Device(Name='Climate sensor', Unit=self.next_unit, TypeName='Temp+Hum', Options={'deviceLabel': device}).Create() else: Domoticz.Device(Name='Climate sensor', Unit=self.next_unit, TypeName='Temperature', Options={'deviceLabel': device}).Create() current_devices[device] = self.next_unit self.next_unit = self.next_unit + 1 unit = current_devices[device] temperature = climate['temperature'] if has_humidity: humidity = int(climate['humidity']) Devices[unit].Update(nValue=0, sValue='{t:.1f} C;{h};1'.format(t=temperature, h=humidity)) else: Devices[unit].Update(nValue=0, sValue='{t:.1f} C'.format(t=temperature)) # for doorWindow in overview['doorWindow']['doorWindowDevice']: # device = doorWindow['deviceLabel'] # remote_devices.add(device) # if device not in current_devices: # Domoticz.Log('Adding door/window sensor ({label}) in {area}'.format(label=doorWindow['deviceLabel'], area=doorWindow['area'])) # Domoticz.Device(Name='Door/window sensor', Unit=self.next_unit, TypeName='Switch', Switchtype=2, Options={'deviceLabel': device}).Create() # current_devices[device] = self.next_unit # self.next_unit = self.next_unit + 1 removed_devices = current_devices.keys() - remote_devices for device in removed_devices: unit = current_devices[device] Domoticz.Log('Removing device {unit} (\'{device}\')'.format(unit=unit, device=device)) Devices[unit].Delete() Domoticz.Debug('Updating devices - done') return True
def StatusToLog(level, text): if level == STATUSLEVELOK: Domoticz.Log(text) if level == STATUSLEVELERROR: Domoticz.Error(text) return