class BasePlugin: mqttClient = None def onStart(self): self.debugging = Parameters["Mode6"] if self.debugging == "Verbose": Domoticz.Debugging(2 + 4 + 8 + 16 + 64) if self.debugging == "Debug": Domoticz.Debugging(2) Domoticz.Debug("onStart called") self.base_topic = Parameters["Mode1"].strip() self.pairing_enabled = True if Parameters["Mode2"] == 'true' else False self.subscribed_for_devices = False mqtt_server_address = Parameters["Address"].strip() mqtt_server_port = Parameters["Port"].strip() mqtt_client_id = Parameters["Mode3"].strip() self.mqttClient = MqttClient(mqtt_server_address, mqtt_server_port, mqtt_client_id, self.onMQTTConnected, self.onMQTTDisconnected, self.onMQTTPublish, self.onMQTTSubscribed) self.available_devices = DeviceStorage.getInstance() def checkDevices(self): Domoticz.Debug("checkDevices called") def onStop(self): Domoticz.Debug("onStop called") def handlePairingMode(self): permit_join = 'true' if self.pairing_enabled else 'false' self.mqttClient.publish(self.base_topic + '/bridge/config/permit_join', permit_join) def onCommand(self, Unit, Command, Level, Color): Domoticz.Debug("onCommand: " + Command + ", level (" + str(Level) + ") Color:" + Color) device = Devices[ Unit] #Devices is Domoticz collection of devices for this hardware device_params = device.DeviceID.split('_') device_id = device_params[0] alias = device_params[1] device_data = self.available_devices.get_device_by_id(device_id) if (device_data == None): Domoticz.Log('Device ' + device.Name + ' does not have registered zigbee2mqtt device') return model = device_data['model'] if (model in adapter_by_model): adapter = adapter_by_model[model](Devices) message = adapter.handleCommand(alias, device, device_data, Command, Level, Color) if (message != None): self.mqttClient.publish( self.base_topic + '/' + message['topic'], message['payload']) else: Domoticz.Log('Device ' + device.Name + ' does not have adapter (model: "' + model + '"') def onConnect(self, Connection, Status, Description): Domoticz.Debug("onConnect called") self.mqttClient.onConnect(Connection, Status, Description) def onDisconnect(self, Connection): self.mqttClient.onDisconnect(Connection) def onMessage(self, Connection, Data): self.mqttClient.onMessage(Connection, Data) def onHeartbeat(self): self.mqttClient.onHeartbeat() def onMQTTConnected(self): self.mqttClient.subscribe([self.base_topic + '/bridge/#']) def onMQTTDisconnected(self): self.subscribed_for_devices = False def onMQTTSubscribed(self): Domoticz.Debug("onMQTTSubscribed") def onMQTTPublish(self, topic, message): Domoticz.Debug("MQTT message: " + topic + " " + str(message)) if (topic == self.base_topic + '/bridge/config/permit_join' or topic == self.base_topic + '/bridge/config/devices'): return if (topic == self.base_topic + '/bridge/config'): permit_join = 'enabled' if message['permit_join'] else 'disabled' Domoticz.Debug('Zigbee2mqtt log level is ' + message['log_level']) Domoticz.Log('Joining new devices is ' + permit_join + ' on the zigbee bridge') return if (topic == self.base_topic + '/bridge/state'): Domoticz.Log('Zigbee2mqtt bridge is ' + message) if message == 'online': self.mqttClient.publish( self.base_topic + '/bridge/config/devices', '') self.handlePairingMode() return if (topic == self.base_topic + '/bridge/log'): if message['type'] == 'devices': Domoticz.Log('Received available devices list from bridge') self.available_devices.clear() self.available_devices.update(Devices, message['message']) if self.subscribed_for_devices == False: self.mqttClient.subscribe([self.base_topic + '/+']) self.subscribed_for_devices = True if message['type'] == 'device_connected' or message[ 'type'] == 'device_removed': self.mqttClient.publish( self.base_topic + '/bridge/config/devices', '') return device_name = topic.replace(self.base_topic + "/", "") device_data = self.available_devices.get_device_by_name(device_name) if (device_data != None): model = device_data['model'] if (model in adapter_by_model): zigbee_message = ZigbeeMessage(message) adapter = adapter_by_model[model](Devices) adapter.handleMqttMessage(device_data, zigbee_message) else: Domoticz.Debug('Unsupported zigbee device type with model "' + model + '"') else: Domoticz.Debug('Unhandled message from zigbee2mqtt: ' + topic + ' ' + str(message))
class BasePlugin: enabled = False mqttConn = None counter = 0 def __init__(self): return def onStart(self): if Parameters["Mode6"] == "Debug": Domoticz.Debugging(1) DumpConfigToLog() self.devices = {} Parameters["Username"] = "******" Parameters["Port"] = "8884" Parameters["Protocol"] = "MQTTS" mqtt_server_address = Parameters["Address"].strip() mqtt_server_port = Parameters["Port"].strip() self.mqttClient = MqttClient(mqtt_server_address, mqtt_server_port, "NHCDomoticz", self.onMQTTConnected, self.onMQTTDisconnected, self.onMQTTPublish, self.onMQTTSubscribed) def onStop(self): Domoticz.Debug("onStop called") def onCommand(self, Unit, Command, Level, Hue): for uuid, device in self.devices.items(): if device.getUnit() == Unit: device.handleCommand(Command, Level, Hue) #MQTT forwards.. def onConnect(self, Connection, Status, Description): self.mqttClient.onConnect(Connection, Status, Description) def onMessage(self, Connection, Data): self.mqttClient.onMessage(Connection, Data) def onDisconnect(self, Connection): self.mqttClient.onDisconnect(Connection) def onHeartbeat(self): self.mqttClient.onHeartbeat() # MQTT stuff def onMQTTConnected(self): self.mqttClient.subscribe(['hobby/control/devices/rsp']) self.mqttClient.subscribe(['hobby/control/devices/evt']) self.mqttClient.subscribe(['hobby/control/devices/err']) # fetch all devices self.mqttClient.publish('hobby/control/devices/cmd', '{"Method": "devices.list"}') def onMQTTDisconnected(self): Domoticz.Log("onMQTT disconnected") def onMQTTSubscribed(self): Domoticz.Log("onMQTTSubscribed") def onMQTTPublish(self, topic, message): if topic == "hobby/control/devices/rsp": if message["Params"]: nhcDeviceIDs = [] if message["Params"][0]["Devices"]: for device in message["Params"][0]["Devices"]: if device["Type"] == "action": uuid = device["Uuid"] self.devices[uuid] = Device( Devices, device, self.mqttClient) self.devices[uuid].handleMessage(topic, device) if topic == "hobby/control/devices/evt": if message["Method"] == "devices.status": if message["Params"]: if message["Params"][0]["Devices"]: for device in message["Params"][0]["Devices"]: uuid = device["Uuid"] if uuid in self.devices: self.devices[uuid].handleMessage(topic, device) if topic == "hobby/control/devices/err": Domoticz.Log("Err")
class BasePlugin: mqttClient = None def CS_2_DZ_decoder(self, topic, message): success = 0 Domoticz.Debug("CS_Decoder") EUI = str(topic.split("device/")[1].split("/")[0]) Domoticz.Debug("EUI : " + EUI) ############ ## Devices payload = json.loads(message) Domoticz.Debug("Payload:\n" + str(payload)) if not 'loRaSNR' in str(payload): Domoticz.Log( "Decoding LoRa message problem. Check ChirpStack application.") return success RSSI = payload['rxInfo'][0]['loRaSNR'] RSSI = int(round(mapFromTo(int(RSSI), -20, 0, 0, 10), 0)) #Domoticz : between 0 and 10 Domoticz.Debug("RSSI : " + str(RSSI)) CS_objects = json.loads(payload['objectJSON']) if (len(CS_objects) == 0): Domoticz.Log( "Decoding cayenne message problem. Check ChirpStack application." ) return success #Domoticz.Debug(str(CS_objects))#{'temperatureSensor': {'1': 12}, 'humiditySensor': {'1': 80}} #Reorganize data data = [] for obj in CS_objects: if (str(obj) in CS_cayenne_to_DZ): for channel in CS_objects[str(obj)]: #Get the value of the sensor value = str(CS_objects[str(obj)][str(channel)]) #build DATA : [Channel, value, [Corresp.DZ_TypeName, Corresp.DZ_pType,DZ_sType, Corresp.FancyName, Corresp.UNIT_ID] ] data.append([channel, value, CS_cayenne_to_DZ[str(obj)]]) else: Domoticz.Log("Unfound/Unproccessable Cayenne Data Type : " + str(obj)) Domoticz.Debug("DATA structure:" + str(data)) #[['1', '12', ['Temperature', 243, 17, 'temp']], ['2', '14', ['Temperature', 243, 17, 'temp']], ['3', '15', ['Temperature', 243, 17, 'temp']], ['1', '80', ['Humidity', 243, 3, 'hum']]] # #aggregate several sensor types into one sensor. Decide whi one is nvalue, which one is svalue # # TODO data_ag = data #Devices ID d_ids = [] d_units = [] for x in Devices: d_ids.append([ str(x), str(Devices[x].ID), str(Devices[x].Name), str(Devices[x].DeviceID) ]) d_units.append(int(x)) Domoticz.Debug(str(d_ids)) Domoticz.Debug(str(d_units)) #Device for d in range(0, len(data_ag)): # Case there is Type_Name assigned if data_ag[d][2][0] != "": #Shape the values device_fancyname = str(data_ag[d][2][3]) device_id = "eui-" + EUI + "-" + str( data_ag[d] [0]) + "-" + device_fancyname #eui-a8d4fdf51239f322-1-hum device_Name = "Unknown " + device_fancyname device_TypeName = str(data_ag[d][2][0]) Domoticz.Debug("===================") Domoticz.Debug("device_id: " + str(device_id)) #If not exist, create if (device_id not in str(d_ids)): #Find a new unit ID device_Unit = 0 for u in range(1, 255): if u not in d_units: device_Unit = u d_units.append(u) break if device_Unit == 0: Domoticz.Log( "ERROR - No more UNIT ID to allocate. Device not created" ) return 0 Domoticz.Debug("device_Name: " + str(device_Name)) Domoticz.Debug("device_TypeName: " + str(device_TypeName)) if self.create_new_devices == "True": Domoticz.Log( "ChirpStack Plugin - Create NEW device with ID=" + str(device_id) + ", Name=" + str(device_Name) + ", Type=" + str(device_TypeName)) #Create Domoticz.Device(Name=device_Name, TypeName=device_TypeName, Unit=device_Unit, DeviceID=device_id).Create() else: Domoticz.Log( "ChirpStack Plugin - DISBALED [Create device " + str(device_id) + "]") for x in Devices: #Check if now exists, and update if (str(Devices[x].DeviceID) == device_id): device_svalue = str(data_ag[d][1]) #Update Domoticz.Log("Chirpstack Plugin - Update device (ID=" + str(Devices[x].ID) + ") value =" + data_ag[d][1]) Devices[x].Update(nValue=int(device_svalue), sValue=str(device_svalue), SignalLevel=RSSI) Domoticz.Debug("===================") return success def onStart(self): self.debugging = Parameters["Mode6"] if self.debugging == "Verbose": Domoticz.Debugging(2 + 4 + 8 + 16 + 64) if self.debugging == "Debug": Domoticz.Debugging(2) DumpConfigToLog() Domoticz.Log("Chirpstack2Domoticz Plugin started") #App ID Base TOPIC if (Parameters["Mode1"].strip() != ""): self.base_topic = "application/" + Parameters["Mode1"].strip() else: Domoticz.Log( "Warning : No Application ID submitted. It will subscribe to all application topics" ) self.base_topic = "application" self.subscribed_for_devices = False self.create_new_devices = Parameters["Mode2"].strip() mqtt_server_address = Parameters["Address"].strip() mqtt_server_port = Parameters["Port"].strip() mqtt_client_id = Parameters["Mode3"].strip() self.mqttClient = MqttClient(mqtt_server_address, mqtt_server_port, mqtt_client_id, self.onMQTTConnected, self.onMQTTDisconnected, self.onMQTTPublish, self.onMQTTSubscribed) self.api = API(Devices, self.publishToMqtt) def checkDevices(self): Domoticz.Debug("checkDevices called") def onStop(self): Domoticz.Debug("onStop called") #self.uninstall() def onCommand(self, Unit, Command, Level, Color): Domoticz.Debug("onCommand: " + Command + ", level (" + str(Level) + ") Color:" + Color) message = None device = Devices[ Unit] #Devices is Domoticz collection of devices for this hardware device_params = device.DeviceID.split('_') entity_id = device_params[0] Domoticz.Debug("OnCommand --> Partie desctivee") # if (self.devices_manager.get_device_by_id(entity_id) != None): # message = self.devices_manager.handle_command(Devices, device, Command, Level, Color) # elif(self.groups_manager.get_group_by_deviceid(device.DeviceID) != None): # message = self.groups_manager.handle_command(device, Command, Level, Color) # else: # Domoticz.Log('Can\'t process command from device "' + device.Name + '"') # if (message != None): # self.publishToMqtt(message['topic'], message['payload']) def publishToMqtt(self, topic, payload): self.mqttClient.publish(self.base_topic + '/' + topic, payload) def onConnect(self, Connection, Status, Description): Domoticz.Debug("onConnect called") self.mqttClient.onConnect(Connection, Status, Description) def onDisconnect(self, Connection): self.mqttClient.onDisconnect(Connection) def onDeviceModified(self, unit): if (unit == 255): self.api.handle_request(Devices[unit].sValue) return def onMessage(self, Connection, Data): self.mqttClient.onMessage(Connection, Data) def onHeartbeat(self): self.mqttClient.onHeartbeat() def onMQTTConnected(self): #if connected subscirbe to topic self.mqttClient.subscribe([self.base_topic + "/#"]) Domoticz.Log("MQTT subscribed to : " + self.base_topic + "/#") def onMQTTDisconnected(self): self.subscribed_for_devices = False def onMQTTSubscribed(self): Domoticz.Debug("onMQTTSubscribed") def onMQTTPublish(self, topic, message): Domoticz.Debug("On MQTT Publish") payload = json.dumps(message) Domoticz.Debug("MQTT message: " + topic + " " + str(payload)) topic = topic.replace(self.base_topic + '/', '') #self.api.handle_mqtt_message(topic, message) #Decode the pyaload and message. --> Will automatically add sensors self.CS_2_DZ_decoder(topic, payload)
class BasePlugin: mqttClient = None def onStart(self): self.debugging = Parameters["Mode6"] if self.debugging == "Verbose": Domoticz.Debugging(2+4+8+16+64) if self.debugging == "Debug": Domoticz.Debugging(2) Domoticz.Debug("onStart called") self.install() self.base_topic = Parameters["Mode1"].strip() mqtt_server_address = Parameters["Address"].strip() mqtt_server_port = Parameters["Port"].strip() mqtt_client_id = Parameters["Mode3"].strip() self.mqttClient = MqttClient(mqtt_server_address, mqtt_server_port, mqtt_client_id, self.onMQTTConnected, self.onMQTTDisconnected, self.onMQTTPublish, self.onMQTTSubscribed) self.api = API(Devices, self.onApiCommand) self.devices_manager = DevicesManager() self.groups_manager = GroupsManager() def checkDevices(self): Domoticz.Debug("checkDevices called") def onStop(self): Domoticz.Debug("onStop called") self.uninstall() def onCommand(self, Unit, Command, Level, Color): Domoticz.Debug("onCommand: " + Command + ", level (" + str(Level) + ") Color:" + Color) message = None device = Devices[Unit] #Devices is Domoticz collection of devices for this hardware device_params = device.DeviceID.split('_') entity_id = device_params[0] if (self.devices_manager.get_device_by_id(entity_id) != None): message = self.devices_manager.handle_command(device, Command, Level, Color) elif(self.groups_manager.get_group_by_deviceid(device.DeviceID) != None): message = self.groups_manager.handle_command(device, Command, Level, Color) else: Domoticz.Log('Can\'t process command from device "' + device.Name + '"') if (message != None): self.publishToMqtt(message['topic'], message['payload']) def onApiCommand(self, command, data): if command == 'publish_mqtt': return self.publishToMqtt(data['topic'], data['payload']) elif command == 'remove_device': return self.devices_manager.remove(data) else: Domoticz.Error('Internal API command "' + command +'" is not supported by plugin') def publishToMqtt(self, topic, payload): self.mqttClient.publish(self.base_topic + '/' + topic, payload) def onConnect(self, Connection, Status, Description): Domoticz.Debug("onConnect called") self.mqttClient.onConnect(Connection, Status, Description) def onDisconnect(self, Connection): self.mqttClient.onDisconnect(Connection) def onDeviceModified(self, unit): if (unit == 255): self.api.handle_request(Devices[unit].sValue) return def onMessage(self, Connection, Data): self.mqttClient.onMessage(Connection, Data) def onHeartbeat(self): self.mqttClient.onHeartbeat() def onMQTTConnected(self): self.mqttClient.subscribe([self.base_topic + '/#']) def onMQTTDisconnected(self): Domoticz.Debug('Disconnected from MQTT server') def onMQTTSubscribed(self): Domoticz.Debug('Subscribed to "' + self.base_topic + '/#" topic') def onMQTTPublish(self, topic, message): # Domoticz.Debug("MQTT message: " + topic + " " + str(message)) topic = topic.replace(self.base_topic + '/', '') self.api.handle_mqtt_message(topic, message) if (topic == 'bridge/config/permit_join'): return if (topic == 'bridge/config/logging'): # TODO: Add log feature return if (topic == 'bridge/devices'): Domoticz.Log('Received available devices list from bridge') self.devices_manager.set_devices(message) return if (topic == 'bridge/config'): permit_join = 'enabled' if message['permit_join'] else 'disabled' Domoticz.Debug('Zigbee2mqtt log level is ' + message['log_level']) Domoticz.Log('Joining new devices is ' + permit_join + ' on the zigbee bridge') return if (topic == 'bridge/state'): Domoticz.Log('Zigbee2mqtt bridge is ' + message) if message == 'online': # self.publishToMqtt('bridge/config/devices', '') self.publishToMqtt('bridge/config/groups', '') return if (topic == 'bridge/log'): is_connected = message['type'] == 'device_connected' is_removed = message['type'] == 'device_removed' is_paired = message['type'] == 'pairing' and message['message'] == 'interview_successful' if message['type'] == 'groups': Domoticz.Log('Received groups list from bridge') self.groups_manager.register_groups(message['message']) if is_connected or is_removed or is_paired: self.publishToMqtt('bridge/config/devices/get', '') if message['type'] == 'ota_update': Domoticz.Log(message['message']) if message['type'] == 'zigbee_publish_error': #an error occured on publish to the zigbee network deviceMeta = message['meta'] Domoticz.Error("A Zigbee publish error occured for device '" + deviceMeta['friendly_name'] + "' with error message: " + message['message']) return if (self.devices_manager.get_device_by_name(topic) != None): self.devices_manager.handle_mqtt_message(topic, message) elif (self.groups_manager.get_group_by_name(topic) != None): self.groups_manager.handle_mqtt_message(topic, message) def install(self): Domoticz.Log('Installing plugin custom page...') try: source_path = Parameters['HomeFolder'] + 'frontend' templates_path = Parameters['StartupFolder'] + 'www/templates' dst_plugin_path = templates_path + '/zigbee2mqtt' Domoticz.Debug('Copying files from ' + source_path + ' to ' + templates_path) if not (os.path.isdir(dst_plugin_path)): os.makedirs(dst_plugin_path) copy2(source_path + '/zigbee2mqtt.html', templates_path) copy2(source_path + '/zigbee2mqtt.js', templates_path) copy2(source_path + '/zigbee_devices.js', dst_plugin_path) copy2(source_path + '/zigbee_groups.js', dst_plugin_path) copy2(source_path + '/libs/leaflet.js', dst_plugin_path) copy2(source_path + '/libs/leaflet.css', dst_plugin_path) copy2(source_path + '/libs/viz.js', dst_plugin_path) copy2(source_path + '/libs/viz.full.render.js', dst_plugin_path) Domoticz.Log('Installing plugin custom page completed.') except Exception as e: Domoticz.Error('Error during installing plugin custom page') Domoticz.Error(repr(e)) def uninstall(self): Domoticz.Log('Uninstalling plugin custom page...') try: templates_path = Parameters['StartupFolder'] + 'www/templates' dst_plugin_path = templates_path + '/zigbee2mqtt' Domoticz.Debug('Removing files from ' + templates_path) if (os.path.isdir(dst_plugin_path)): rmtree(dst_plugin_path) if os.path.exists(templates_path + "/zigbee2mqtt.html"): os.remove(templates_path + "/zigbee2mqtt.html") if os.path.exists(templates_path + "/zigbee2mqtt.js"): os.remove(templates_path + "/zigbee2mqtt.js") Domoticz.Log('Uninstalling plugin custom page completed.') except Exception as e: Domoticz.Error('Error during uninstalling plugin custom page') Domoticz.Error(repr(e))
class BasePlugin: mqttClient = None def onStart(self): self.debugging = Parameters["Mode6"] if self.debugging == "Verbose": Domoticz.Debugging(2 + 4 + 8 + 16 + 64) if self.debugging == "Debug": Domoticz.Debugging(2) Domoticz.Debug("onStart called") self.install() self.base_topic = Parameters["Mode1"].strip() self.subscribed_for_devices = False mqtt_server_address = Parameters["Address"].strip() mqtt_server_port = Parameters["Port"].strip() mqtt_client_id = Parameters["Mode3"].strip() self.mqttClient = MqttClient(mqtt_server_address, mqtt_server_port, mqtt_client_id, self.onMQTTConnected, self.onMQTTDisconnected, self.onMQTTPublish, self.onMQTTSubscribed) self.api = API(Devices, self.publishToMqtt) self.devices_manager = DevicesManager() self.groups_manager = GroupsManager() def checkDevices(self): Domoticz.Debug("checkDevices called") def onStop(self): Domoticz.Debug("onStop called") self.uninstall() def onCommand(self, Unit, Command, Level, Color): Domoticz.Debug("onCommand: " + Command + ", level (" + str(Level) + ") Color:" + Color) message = None device = Devices[ Unit] #Devices is Domoticz collection of devices for this hardware device_params = device.DeviceID.split('_') entity_id = device_params[0] if (self.devices_manager.get_device_by_id(entity_id) != None): message = self.devices_manager.handle_command( Devices, device, Command, Level, Color) elif (self.groups_manager.get_group_by_deviceid(device.DeviceID) != None): message = self.groups_manager.handle_command( device, Command, Level, Color) else: Domoticz.Log('Can\'t process command from device "' + device.Name + '"') if (message != None): self.publishToMqtt(message['topic'], message['payload']) def publishToMqtt(self, topic, payload): self.mqttClient.publish(self.base_topic + '/' + topic, payload) def onConnect(self, Connection, Status, Description): Domoticz.Debug("onConnect called") self.mqttClient.onConnect(Connection, Status, Description) def onDisconnect(self, Connection): self.mqttClient.onDisconnect(Connection) def onDeviceModified(self, unit): if (unit == 255): self.api.handle_request(Devices[unit].sValue) return def onMessage(self, Connection, Data): self.mqttClient.onMessage(Connection, Data) def onHeartbeat(self): self.mqttClient.onHeartbeat() def onMQTTConnected(self): self.mqttClient.subscribe([self.base_topic + '/bridge/#']) def onMQTTDisconnected(self): self.subscribed_for_devices = False def onMQTTSubscribed(self): Domoticz.Debug("onMQTTSubscribed") def onMQTTPublish(self, topic, message): Domoticz.Debug("MQTT message: " + topic + " " + str(message)) topic = topic.replace(self.base_topic + '/', '') self.api.handle_mqtt_message(topic, message) if (topic == 'bridge/config/permit_join' or topic == 'bridge/config/devices'): return if (topic == 'bridge/config'): permit_join = 'enabled' if message['permit_join'] else 'disabled' Domoticz.Debug('Zigbee2mqtt log level is ' + message['log_level']) Domoticz.Log('Joining new devices is ' + permit_join + ' on the zigbee bridge') return if (topic == 'bridge/state'): Domoticz.Log('Zigbee2mqtt bridge is ' + message) if message == 'online': self.publishToMqtt('bridge/config/devices', '') self.publishToMqtt('bridge/config/groups', '') return if (topic == 'bridge/log'): if message['type'] == 'devices': Domoticz.Log('Received available devices list from bridge') self.devices_manager.clear() self.devices_manager.update(Devices, message['message']) if self.subscribed_for_devices == False: self.mqttClient.subscribe([self.base_topic + '/+']) self.subscribed_for_devices = True if message['type'] == 'groups': Domoticz.Log('Received groups list from bridge') self.groups_manager.register_groups(Devices, message['message']) if message['type'] == 'device_connected' or message[ 'type'] == 'device_removed': self.publishToMqtt('bridge/config/devices', '') if message['type'] == 'ota_update': Domoticz.Log(message['message']) return if (self.devices_manager.get_device_by_name(topic) != None): self.devices_manager.handle_mqtt_message(Devices, topic, message) elif (self.groups_manager.get_group_by_name(topic) != None): self.groups_manager.handle_mqtt_message(topic, message) def install(self): Domoticz.Log('Installing plugin custom page...') try: source_path = os.path.dirname( os.path.abspath(__file__)) + '/frontend' templates_path = os.path.abspath(source_path + '/../../../www/templates') dst_plugin_path = templates_path + '/zigbee2mqtt' Domoticz.Debug('Copying files from ' + source_path + ' to ' + templates_path) if not (os.path.isdir(dst_plugin_path)): os.makedirs(dst_plugin_path) copy2(source_path + '/zigbee2mqtt.html', templates_path) copy2(source_path + '/zigbee2mqtt.js', templates_path) copy2(source_path + '/zigbee_devices.js', dst_plugin_path) copy2(source_path + '/zigbee_groups.js', dst_plugin_path) copy2(source_path + '/libs/leaflet.js', dst_plugin_path) copy2(source_path + '/libs/leaflet.css', dst_plugin_path) copy2(source_path + '/libs/viz.js', dst_plugin_path) copy2(source_path + '/libs/viz.full.render.js', dst_plugin_path) Domoticz.Log('Installing plugin custom page completed.') except Exception as e: Domoticz.Error('Error during installing plugin custom page') Domoticz.Error(repr(e)) def uninstall(self): Domoticz.Log('Uninstalling plugin custom page...') try: templates_path = os.path.abspath( os.path.dirname(os.path.abspath(__file__)) + '/../../www/templates') dst_plugin_path = templates_path + '/zigbee2mqtt' Domoticz.Debug('Removing files from ' + templates_path) if (os.path.isdir(dst_plugin_path)): rmtree(dst_plugin_path) if os.path.exists(templates_path + "/zigbee2mqtt.html"): os.remove(templates_path + "/zigbee2mqtt.html") if os.path.exists(templates_path + "/zigbee2mqtt.js"): os.remove(templates_path + "/zigbee2mqtt.js") Domoticz.Log('Uninstalling plugin custom page completed.') except Exception as e: Domoticz.Error('Error during uninstalling plugin custom page') Domoticz.Error(repr(e))
class BasePlugin: mqttClient = None def onStart(self): self.debugging = Parameters["Mode6"] if self.debugging == "Verbose": Domoticz.Debugging(2 + 4 + 8 + 16 + 64) if self.debugging == "Debug": Domoticz.Debugging(2) Domoticz.Debug("onStart called") self.base_topic = Parameters["Mode1"].strip() self.pairing_enabled = True if Parameters["Mode2"] == 'true' else False self.subscribed_for_devices = False mqtt_server_address = Parameters["Address"].strip() mqtt_server_port = Parameters["Port"].strip() mqtt_client_id = Parameters["Mode3"].strip() self.mqttClient = MqttClient(mqtt_server_address, mqtt_server_port, mqtt_client_id, self.onMQTTConnected, self.onMQTTDisconnected, self.onMQTTPublish, self.onMQTTSubscribed) self.devices_manager = DevicesManager() self.groups_manager = GroupsManager() def checkDevices(self): Domoticz.Debug("checkDevices called") def onStop(self): Domoticz.Debug("onStop called") def handlePairingMode(self): permit_join = 'true' if self.pairing_enabled else 'false' self.mqttClient.publish(self.base_topic + '/bridge/config/permit_join', permit_join) def onCommand(self, Unit, Command, Level, Color): Domoticz.Debug("onCommand: " + Command + ", level (" + str(Level) + ") Color:" + Color) device = Devices[ Unit] #Devices is Domoticz collection of devices for this hardware device_params = device.DeviceID.split('_') entity_id = device_params[0] if (self.devices_manager.get_device_by_id(entity_id) != None): message = self.devices_manager.handle_command( Devices, device, Command, Level, Color) elif (self.groups_manager.get_group_by_deviceid(device.DeviceID) != None): message = self.groups_manager.handle_command( device, Command, Level, Color) else: Domoticz.Log('Can\'t process command from device "' + device.Name + '"') if (message != None): self.mqttClient.publish(self.base_topic + '/' + message['topic'], message['payload']) def onConnect(self, Connection, Status, Description): Domoticz.Debug("onConnect called") self.mqttClient.onConnect(Connection, Status, Description) def onDisconnect(self, Connection): self.mqttClient.onDisconnect(Connection) def onMessage(self, Connection, Data): self.mqttClient.onMessage(Connection, Data) def onHeartbeat(self): self.mqttClient.onHeartbeat() def onMQTTConnected(self): self.mqttClient.subscribe([self.base_topic + '/bridge/#']) def onMQTTDisconnected(self): self.subscribed_for_devices = False def onMQTTSubscribed(self): Domoticz.Debug("onMQTTSubscribed") def onMQTTPublish(self, topic, message): Domoticz.Debug("MQTT message: " + topic + " " + str(message)) if (topic == self.base_topic + '/bridge/config/permit_join' or topic == self.base_topic + '/bridge/config/devices'): return if (topic == self.base_topic + '/bridge/config'): permit_join = 'enabled' if message['permit_join'] else 'disabled' Domoticz.Debug('Zigbee2mqtt log level is ' + message['log_level']) Domoticz.Log('Joining new devices is ' + permit_join + ' on the zigbee bridge') return if (topic == self.base_topic + '/bridge/state'): Domoticz.Log('Zigbee2mqtt bridge is ' + message) if message == 'online': self.mqttClient.publish( self.base_topic + '/bridge/config/devices', '') self.mqttClient.publish( self.base_topic + '/bridge/config/groups', '') self.handlePairingMode() return if (topic == self.base_topic + '/bridge/log'): if message['type'] == 'devices': Domoticz.Log('Received available devices list from bridge') self.devices_manager.clear() self.devices_manager.update(Devices, message['message']) if self.subscribed_for_devices == False: self.mqttClient.subscribe([self.base_topic + '/+']) self.subscribed_for_devices = True if message['type'] == 'groups': Domoticz.Log('Received groups list from bridge') self.groups_manager.register_groups(Devices, message['message']) if message['type'] == 'device_connected' or message[ 'type'] == 'device_removed': self.mqttClient.publish( self.base_topic + '/bridge/config/devices', '') return entity_name = topic.replace(self.base_topic + "/", "") if (self.devices_manager.get_device_by_name(entity_name) != None): self.devices_manager.handle_mqtt_message(Devices, entity_name, message) elif (self.groups_manager.get_group_by_name(entity_name) != None): self.groups_manager.handle_mqtt_message(entity_name, message) else: Domoticz.Debug('Unhandled message from zigbee2mqtt: ' + topic + ' ' + str(message))
class BasePlugin: mqttClient = None def onStart(self): self.debugging = Parameters["Mode6"] if self.debugging == "Verbose+": Domoticz.Debugging(2+4+8+16+64) if self.debugging == "Verbose": Domoticz.Debugging(2+4+8+16+64) if self.debugging == "Debug": Domoticz.Debugging(2+4+8) self.devices_manager = DevicesManager() self.devices_manager.set_devices(Devices) device_topic = Parameters["Mode1"].strip() if (Parameters["Mode2"] == "Dimmer"): self.controller = Dimmer(self.devices_manager, device_topic) elif (Parameters["Mode2"] == "PwmDimmer"): self.controller = PwmDimmer(self.devices_manager, device_topic) elif (Parameters["Mode2"] == "RGB"): self.controller = ColorDimmer(self.devices_manager, device_topic, 3) elif (Parameters["Mode2"] == "RGBW"): self.controller = ColorDimmer(self.devices_manager, device_topic, 4) elif (Parameters["Mode2"] == "RGBWW"): self.controller = ColorDimmer(self.devices_manager, device_topic, 5) self.controller.checkDevices() self.topics = list(["stat/" + device_topic + "/RESULT", "tele/" + device_topic + "/STATE"]) mqtt_server_address = Parameters["Address"].strip() mqtt_server_port = Parameters["Port"].strip() mqtt_client_id = Parameters["Mode3"].strip() self.mqttClient = MqttClient(mqtt_server_address, mqtt_server_port, mqtt_client_id, self.onMQTTConnected, self.onMQTTDisconnected, self.onMQTTPublish, self.onMQTTSubscribed) def checkDevices(self): Domoticz.Log("checkDevices called") def onStop(self): Domoticz.Log("onStop called") def onCommand(self, Unit, Command, Level, Color): Domoticz.Debug("Command: " + Command + " (" + str(Level) + ") Color:" + Color) self.controller.onCommand(self.mqttClient, Unit, Command, Level, Color) def onConnect(self, Connection, Status, Description): self.mqttClient.onConnect(Connection, Status, Description) def onDisconnect(self, Connection): self.mqttClient.onDisconnect(Connection) def onMessage(self, Connection, Data): self.mqttClient.onMessage(Connection, Data) def onHeartbeat(self): self.mqttClient.onHeartbeat() def onMQTTConnected(self): Domoticz.Debug("onMQTTConnected") self.mqttClient.subscribe(self.topics) def onMQTTDisconnected(self): Domoticz.Debug("onMQTTDisconnected") def onMQTTSubscribed(self): Domoticz.Debug("onMQTTSubscribed") def onMQTTPublish(self, topic, message): Domoticz.Debug("MQTT message: " + topic + " " + str(message)) if (topic in self.topics): self.controller.onMqttMessage(topic, message)
class BasePlugin: mqttClient = None def __init__(self): return def onStart(self): global errmsg self.devnames = [] self.devtimes = [] if errmsg == "": try: Domoticz.Heartbeat(10) self.debugging = Parameters["Mode6"] if self.debugging == "Verbose": Domoticz.Debugging(2 + 4 + 8 + 16 + 64) if self.debugging == "Debug": Domoticz.Debugging(2) self.base_topic = Parameters["Mode1"] self.learnmode = Parameters["Mode2"] self.mqttserveraddress = Parameters["Address"].strip() self.mqttserverport = Parameters["Port"].strip() self.mqttClient = MqttClient(self.mqttserveraddress, self.mqttserverport, "", self.onMQTTConnected, self.onMQTTDisconnected, self.onMQTTPublish, self.onMQTTSubscribed) except Exception as e: Domoticz.Error("MQTT client start error: " + str(e)) self.mqttClient = None else: Domoticz.Error( "Your Domoticz Python environment is not functional! " + errmsg) self.mqttClient = None def checkDevices(self): Domoticz.Debug("checkDevices called") def onStop(self): Domoticz.Debug("onStop called") def onCommand(self, Unit, Command, Level, Color): # react to commands arrived from Domoticz if self.mqttClient is None: return False Domoticz.Debug("Command: " + Command + " (" + str(Level) + ") Color:" + Color) if Command in ["On", "Off"]: if Command == "On": Devices[Unit].Update(nValue=1, sValue=str(Command)) else: Devices[Unit].Update(nValue=0, sValue=str(Command)) def onConnect(self, Connection, Status, Description): if self.mqttClient is not None: self.mqttClient.onConnect(Connection, Status, Description) def onDisconnect(self, Connection): if self.mqttClient is not None: self.mqttClient.onDisconnect(Connection) def onMessage(self, Connection, Data): if self.mqttClient is not None: try: self.mqttClient.onMessage(Connection, Data) except: pass def onHeartbeat(self): Domoticz.Debug("Heartbeating...") if self.mqttClient is not None: try: # Reconnect if connection has dropped if (self.mqttClient._connection is None) or (not self.mqttClient.isConnected): Domoticz.Debug("Reconnecting") self.mqttClient._open() else: self.mqttClient.ping() except Exception as e: Domoticz.Error(str(e)) def onMQTTConnected(self): if self.mqttClient is not None: if self.base_topic and self.base_topic != "#": topic = self.base_topic + '/#' else: topic = "rtl_433/#" # if "events" not in topic: # topic += "/events" self.mqttClient.subscribe([topic]) def onMQTTDisconnected(self): Domoticz.Debug("onMQTTDisconnected") def onMQTTSubscribed(self): Domoticz.Debug("onMQTTSubscribed") def onMQTTPublish(self, topic, message): # process incoming MQTT statuses try: topic = str(topic) message2 = str(message) except: Domoticz.Debug("MQTT message is not a valid string!" ) #if message is not a real string, drop it return False mqttpath = topic.split('/') if "/events" in topic: Domoticz.Debug("MQTT message: " + topic + " " + str(message2)) data = "" if 'rows' in message: # raw data in events - check for Flex encoder output! th = [] for row in message['rows']: try: if int(row['len']) > 4 and str( row['data']).strip() != "": th.append(str(row['data'])) except: pass mf = 0 for i in th: cf = th.count(i) if cf > mf: data = i mf = cf model = "" ch = "" st = "" if 'model' in message: # model name in events model = str(message['model']).replace("-", "_") if 'channel' in message: ch = str(message['channel']) if 'subtype' in message: st = str(message['subtype']) if st == "": if 'unit' in message: st = str(message['unit']) if ch == "" and st == "": if 'id' in message: st = str( message['id'] ) # use id only for last resort, as cheap weather stations generates new id on every restart devname = self.createdevname(model, st, ch, data, "") Domoticz.Debug(devname) if 'time' in message: devtime = str(message['time']) else: devtime = str(time.time()) if devname not in self.devnames: self.devnames.append(devname) self.devtimes.append(devtime) else: didx = self.devnames.index(devname) if didx > 0 and didx < len(self.devtimes): if self.devtimes[ didx] == devtime: # filter duplicated messages return False # Domoticz.Debug(devtime) signal = 12 if "rssi" in message: try: rssi = float(message["rssi"]) except: rssi = 0 if rssi > -0.134: signal = 10 elif rssi <= -7: signal = 0 else: signal = 10 - (rssi * -1.34) try: Domoticz.Debug( str(message["rssi"]) + " " + str(message["snr"]) + " " + str(message["noise"])) except: pass battery = 255 if "battery" in message: if (str(message["battery"]).lower() == "low") or (str( message["battery"]) == "0"): battery = 10 elif (str(message["battery"]).lower() == "ok") or (str( message["battery"]) == "100"): battery = 100 if "battery_ok" in message: if (str(message["battery_ok"]) == "0"): battery = 10 elif (str(message["battery_ok"]) == "1"): battery = 100 state = None # check if is it a binary sensor if "state" in message or "command" in message: state = False if "state" in message: state = (message["state"] == "ON") if "command" in message: state = (message["command"] == "On") elif data != "": if data[:16] == "ffffffffffffffff": # false positive return False state = True if state is not None: self.SendSwitch(devname, state, battery, signal) return True tempc = None if "temperature_C" in message: tempc = message['temperature_C'] elif "temperature_F" in message: tempc = str((float(message['temperature_F']) - 32) * 5.0 / 9.0) try: tempc = float(tempc) except: tempc = None if tempc < -40 or tempc > 80: tempc = None return False # out of range - false positive humi = None if "humidity" in message: if message["humidity"] == "HH": humi = 90 elif message["humidity"] == "LL": humi = 10 else: try: humi = float(message['humidity']) except: humi = None if humi < 0 or humi > 100: humi = None pressure = None if "pressure_hPa" in message: pressure = message['pressure'] if (tempc is not None) and (humi is not None) and (pressure is not None): self.SendTempHumBaroSensor(devname, tempc, humi, pressure, battery, signal) elif (tempc is not None) and (humi is not None): self.SendTempHumSensor(devname, tempc, humi, battery, signal) elif (tempc is not None): self.SendTempSensor(devname, tempc, battery, signal) elif (humi is not None): self.SendHumSensor(devname, humi, battery, signal) rain = None if "rain" in message: rain = message['rain'] elif "rain_mm" in message: rain = message['rain_mm'] elif "rainfall_mm" in message: rain = message['rainfall_mm'] raintotal = None if "rain_total" in message: raintotal = message['rain_total'] if rain is not None: self.SendRainSensor(devname, rain, raintotal, battery, signal) depth = None if "depth_cm" in message: depth = message['depth_cm'] elif "depth" in message: depth = message['depth'] if depth is not None: self.SendDistanceSensor(devname, depth, battery, signal) windstr = None if "windstrength" in message: windstr = message['windstrength'] elif "wind_speed" in message: windstr = message['wind_speed'] elif "average" in message: windstr = message['average'] elif "wind_avg_km_h" in message: windstr = message['wind_avg_km_h'] elif "wind_avg_m_s" in message: windstr = message['wind_avg_m_s'] winddir = None if "winddirection" in message: winddir = message['winddirection'] elif "wind_direction" in message: winddir = message['wind_direction'] elif "direction" in message: winddir = message['direction'] winddirdeg = 0 if "wind_dir_deg" in message: winddirdeg = message['wind_dir_deg'] windgust = None if "wind_gust" in message: windgust = message['wind_gust'] elif "gust" in message: windgust = message['gust'] if winddir is not None: self.SendWind(devname, winddirdeg, winddir, windstr, windgust, tempc, battery, signal) moisture = None if "moisture" in message: moisture = message['moisture'] if (moisture is not None): self.SendMoisture(devname, moisture, battery, signal) power = None if "power_W" in message: power = message['power_W'] if (power is not None): self.SendWattMeter(devname, watt, battery, signal) def getdevID(self, unitname): iUnit = -1 for Device in Devices: try: if (Devices[Device].DeviceID.strip() == unitname): iUnit = Device break except: pass return iUnit def SendSwitch(self, unitname, state, battery, rssi): iUnit = self.getdevID(unitname) if iUnit < 0 and self.learnmode != False: # if device does not exists in Domoticz, than create it try: iUnit = 0 for x in range(1, 256): if x not in Devices: iUnit = x break if iUnit == 0: iUnit = len(Devices) + 1 Domoticz.Device(Name=unitname, Unit=iUnit, TypeName="Switch", Used=0, DeviceID=unitname).Create() except Exception as e: Domoticz.Debug(str(e)) return False if iUnit > 0: try: if state == False or (str(state).strip().lower() in ["0", "off"]): scmd = "Off" ncmd = 0 else: scmd = "On" ncmd = 1 if battery is None: battery = 255 Devices[iUnit].Update(nValue=ncmd, sValue=scmd, BatteryLevel=int(battery), SignalLevel=int(rssi)) except Exception as e: Domoticz.Debug(str(e)) return False def SendTempHumBaroSensor(self, unitname, temp, hum, press, battery, rssi): iUnit = self.getdevID(unitname) if iUnit < 0 and self.learnmode != False: # if device does not exists in Domoticz, than create it try: iUnit = 0 for x in range(1, 256): if x not in Devices: iUnit = x break if iUnit == 0: iUnit = len(Devices) + 1 Domoticz.Device(Name=unitname, Unit=iUnit, Type=84, Subtype=16, Used=0, DeviceID=unitname).Create() # Temp+Hum+Baro except Exception as e: Domoticz.Debug(str(e)) return False if iUnit > 0: sval = str(temp) + ";" + str(hum) + ";" + str( self.gethumstatus(hum)) + ";" + str(press) + ";0" try: if battery is None: battery = 255 Devices[iUnit].Update(nValue=0, sValue=str(sval), BatteryLevel=int(battery), SignalLevel=int(rssi)) except: Domoticz.Debug(str(e)) def SendTempHumSensor(self, unitname, temp, hum, battery, rssi): iUnit = self.getdevID(unitname) if iUnit < 0 and self.learnmode != False: # if device does not exists in Domoticz, than create it try: iUnit = 0 for x in range(1, 256): if x not in Devices: iUnit = x break if iUnit == 0: iUnit = len(Devices) + 1 Domoticz.Device(Name=unitname, Unit=iUnit, TypeName="Temp+Hum", Used=0, DeviceID=unitname).Create() # Temp+Hum except Exception as e: Domoticz.Debug(str(e)) return False if iUnit > 0: sval = str(temp) + ";" + str(hum) + ";" + str( self.gethumstatus(hum)) try: if battery is None: battery = 255 Devices[iUnit].Update(nValue=0, sValue=str(sval), BatteryLevel=int(battery), SignalLevel=int(rssi)) except: Domoticz.Debug(str(e)) def SendTempSensor(self, unitname, temp, battery, rssi): iUnit = self.getdevID(unitname) if iUnit < 0 and self.learnmode != False: # if device does not exists in Domoticz, than create it try: iUnit = 0 for x in range(1, 256): if x not in Devices: iUnit = x break if iUnit == 0: iUnit = len(Devices) + 1 Domoticz.Device(Name=unitname, Unit=iUnit, TypeName="Temperature", Used=0, DeviceID=unitname).Create() # Temp except Exception as e: Domoticz.Debug(str(e)) return False if iUnit > 0: sval = str(temp) try: if battery is None: battery = 255 Devices[iUnit].Update(nValue=0, sValue=str(sval), BatteryLevel=int(battery), SignalLevel=int(rssi)) except: Domoticz.Debug(str(e)) def SendHumSensor(self, unitname, hum, battery, rssi): iUnit = self.getdevID(unitname) if iUnit < 0 and self.learnmode != False: # if device does not exists in Domoticz, than create it try: iUnit = 0 for x in range(1, 256): if x not in Devices: iUnit = x break if iUnit == 0: iUnit = len(Devices) + 1 Domoticz.Device(Name=unitname, Unit=iUnit, TypeName="Humidity", Used=0, DeviceID=unitname).Create() # Hum except Exception as e: Domoticz.Debug(str(e)) return False if iUnit > 0: sval = str(hum) try: if battery is None: battery = 255 Devices[iUnit].Update(nValue=0, sValue=str(sval), BatteryLevel=int(battery), SignalLevel=int(rssi)) except: Domoticz.Debug(str(e)) def SendRainSensor(self, unitname, rain, raintotal, battery, rssi): iUnit = self.getdevID(unitname) if iUnit < 0 and self.learnmode != False: # if device does not exists in Domoticz, than create it try: iUnit = 0 for x in range(1, 256): if x not in Devices: iUnit = x break if iUnit == 0: iUnit = len(Devices) + 1 Domoticz.Device(Name=unitname, Unit=iUnit, TypeName="Rain", Used=0, DeviceID=unitname).Create() # Rain except Exception as e: Domoticz.Debug(str(e)) return False if iUnit > 0: if raintotal is None: try: curval = Devices[iUnit].sValue prevdata = curval.split(";") except: prevdata = [] if len(prevdata) < 2: prevdata.append(0) prevdata.append(0) raintotal = prevdata[1] + rain sval = str(int(float(rain) * 100)) + ";" + str(raintotal) try: if battery is None: battery = 255 Devices[iUnit].Update(nValue=0, sValue=str(sval), BatteryLevel=int(battery), SignalLevel=int(rssi)) except: Domoticz.Debug(str(e)) def SendDistanceSensor(self, unitname, dist, battery, rssi): iUnit = self.getdevID(unitname) if iUnit < 0 and self.learnmode != False: # if device does not exists in Domoticz, than create it try: iUnit = 0 for x in range(1, 256): if x not in Devices: iUnit = x break if iUnit == 0: iUnit = len(Devices) + 1 Domoticz.Device(Name=unitname, Unit=iUnit, TypeName="Distance", Used=0, DeviceID=unitname).Create() # Distance except Exception as e: Domoticz.Debug(str(e)) return False if iUnit > 0: sval = str(dist) try: if battery is None: battery = 255 Devices[iUnit].Update(nValue=0, sValue=str(sval), BatteryLevel=int(battery), SignalLevel=int(rssi)) except: Domoticz.Debug(str(e)) def SendWind(self, unitname, winddirdeg, winddir, windstr, windgust, tempc, battery, rssi): iUnit = self.getdevID(unitname) if iUnit < 0 and self.learnmode != False: # if device does not exists in Domoticz, than create it try: iUnit = 0 for x in range(1, 256): if x not in Devices: iUnit = x break if iUnit == 0: iUnit = len(Devices) + 1 Domoticz.Device(Name=unitname, Unit=iUnit, TypeName="Wind", Used=0, DeviceID=unitname).Create() # Wind except Exception as e: Domoticz.Debug(str(e)) return False if iUnit > 0: sval = str(winddirdeg) if winddir is not None: sval += ";" + str(winddir) else: sval += ";" ts = ";" try: ts = ";" + str(float(windstr) * 10) except: ts = ";" sval += ts ts = ";" try: ts = ";" + str(float(windgust) * 10) except: ts = ";" sval += ts if tempc is not None: sval += ";" + str(tempc) else: sval += ";;" try: if battery is None: battery = 255 Devices[iUnit].Update(nValue=0, sValue=str(sval), BatteryLevel=int(battery), SignalLevel=int(rssi)) except: Domoticz.Debug(str(e)) def SendMoisture(self, unitname, moist, battery, rssi): iUnit = self.getdevID(unitname) if iUnit < 0 and self.learnmode != False: # if device does not exists in Domoticz, than create it try: iUnit = 0 for x in range(1, 256): if x not in Devices: iUnit = x break if iUnit == 0: iUnit = len(Devices) + 1 Domoticz.Device(Name=unitname, Unit=iUnit, TypeName="Soil Moisture", Used=0, DeviceID=unitname).Create() # Moisture except Exception as e: Domoticz.Debug(str(e)) return False if iUnit > 0: sval = str(moist) try: if battery is None: battery = 255 Devices[iUnit].Update(nValue=0, sValue=str(sval), BatteryLevel=int(battery), SignalLevel=int(rssi)) except: Domoticz.Debug(str(e)) def SendWattMeter(self, unitname, watt, battery, rssi): iUnit = self.getdevID(unitname) if iUnit < 0 and self.learnmode != False: # if device does not exists in Domoticz, than create it try: iUnit = 0 for x in range(1, 256): if x not in Devices: iUnit = x break if iUnit == 0: iUnit = len(Devices) + 1 Domoticz.Device(Name=unitname, Unit=iUnit, Type=243, Subtype=29, Used=0, DeviceID=unitname).Create() # kWh except Exception as e: Domoticz.Debug(str(e)) return False if iUnit > 0: try: sval = str(float(watt) / 1000) + ";0" except: sval = "0;0" try: if battery is None: battery = 255 Devices[iUnit].Update(nValue=0, sValue=str(sval), BatteryLevel=int(battery), SignalLevel=int(rssi)) except: Domoticz.Debug(str(e)) def gethumstatus(self, mval): hstat = 0 if int(mval) >= 50 and int(mval) <= 70: hstat = 1 elif int(mval) < 40: hstat = 2 elif int(mval) > 70: hstat = 3 return hstat def createdevname(self, m, s, c, d, t): tn = "" if s: tn += s if c: tn += c if d: tn += "-" + d[:16] if t: tn += "-" + t[:16] lplen = 25 - len(tn) if lplen == 0: return tn elif lplen < 0: return tn[:25] else: if tn[0] != "-": tn = "-" + tn tn = m[:(25 - len(tn) - 1)] + tn return tn
class BasePlugin: mqttClient = None def onStart(self): self.debugging = Parameters["Mode6"] if self.debugging == "Verbose": Domoticz.Debugging(2 + 4 + 8 + 16 + 64) if self.debugging == "Debug": Domoticz.Debugging(2) self.install() self.base_topic = Parameters["Mode1"].strip() mqtt_server_address = Parameters["Address"].strip() mqtt_server_port = Parameters["Port"].strip() mqtt_client_id = Parameters["Mode3"].strip() self.mqttClient = MqttClient(mqtt_server_address, mqtt_server_port, mqtt_client_id, self.onMQTTConnected, self.onMQTTDisconnected, self.onMQTTPublish, self.onMQTTSubscribed) self.api = API(self.onApiCommand) self.devices_manager = DevicesManager() self.groups_manager = GroupsManager() def checkDevices(self): domoticz.debug("checkDevices called") def onStop(self): domoticz.debug("onStop called") self.uninstall() def onCommand(self, device_id, unit, command, Level, Color): domoticz.debug("[Command] Device " + device_id + '(' + str(unit) + '): ' + command + "(level = " + str(Level) + ", color = " + Color + ')') message = None domoticz_device = domoticz.get_device(device_id, unit) zigbee_device_alias = configuration.get_zigbee_feature_data( device_id, unit) if zigbee_device_alias == None: domoticz.log('Can\'t process command from device "' + domoticz_device.Name + '"') if self.groups_manager.get_group_by_id( zigbee_device_alias['zigbee']['address']) != None: message = self.groups_manager.handle_command( device_id, unit, command, Level, Color) else: message = self.devices_manager.handle_command( device_id, unit, command, Level, Color) if (message != None): self.publishToMqtt(message['topic'], message['payload']) def onApiCommand(self, command, data): if command == 'publish_mqtt': return self.publishToMqtt(data['topic'], data['payload']) elif command == 'remove_device': return self.devices_manager.remove(data) else: domoticz.error('Internal API command "' + command + '" is not supported by plugin') def publishToMqtt(self, topic, payload): self.mqttClient.publish(self.base_topic + '/' + topic, payload) def onConnect(self, Connection, Status, Description): domoticz.debug("onConnect called") self.mqttClient.onConnect(Connection, Status, Description) def onDisconnect(self, Connection): self.mqttClient.onDisconnect(Connection) def onDeviceModified(self, device_id, unit): if device_id == 'api_transport' and unit == 255: device = domoticz.get_device(device_id, unit) self.api.handle_request(device.sValue) return def onMessage(self, Connection, Data): self.mqttClient.onMessage(Connection, Data) def onHeartbeat(self): self.mqttClient.onHeartbeat() def onMQTTConnected(self): self.mqttClient.subscribe([self.base_topic + '/#']) def onMQTTDisconnected(self): domoticz.debug('Disconnected from MQTT server') def onMQTTSubscribed(self): domoticz.debug('Subscribed to "' + self.base_topic + '/#" topic') def onMQTTPublish(self, topic, message): # domoticz.debug("MQTT message: " + topic + " " + str(message)) topic = topic.replace(self.base_topic + '/', '') self.api.handle_mqtt_message(topic, message) bridge.handle_mqtt_message(topic, message) if (topic == 'bridge/config/permit_join'): return if (topic == 'bridge/config/logging') or (topic == 'bridge/logging'): # TODO: Add log feature return if (topic == 'bridge/devices'): self.devices_manager.set_devices(message) return if (topic == 'bridge/config'): permit_join = 'enabled' if message['permit_join'] else 'disabled' domoticz.debug('Zigbee2mqtt log level is ' + message['log_level']) domoticz.log('Joining new devices is ' + permit_join + ' on the zigbee bridge') return if (topic == 'bridge/state'): domoticz.log('Zigbee2mqtt bridge is ' + message) return if (topic == 'bridge/log'): is_connected = message['type'] == 'device_connected' is_removed = message['type'] == 'device_removed' is_paired = message['type'] == 'pairing' and message[ 'message'] == 'interview_successful' if message['type'] == 'groups': domoticz.log('Received groups list from bridge') self.groups_manager.register_groups(message['message']) if is_connected or is_removed or is_paired: self.publishToMqtt('bridge/config/devices/get', '') if message['type'] == 'ota_update': domoticz.log(message['message']) if (message['type'] == 'device_renamed'): domoticz.debug("Device renamed from '{0}' to '{1}'".format( message['message']['from'], message['message']['to'])) if (self.devices_manager.get_device_by_name( message['message']['from']) != None): domoticz.debug("attempt to rename on bridge/log") toRename = self.devices_manager.get_device_by_name( message['message']['from']) toRename.zigbee_device['friendly_name'] = message[ 'message']['to'] self.devices_manager.devices[ toRename.zigbee_device['ieee_address']] = toRename else: domoticz.debug("attempt to rename failed on bridge/log") if message['type'] == 'zigbee_publish_error': #an error occured on publish to the zigbee network deviceMeta = message['meta'] domoticz.error("A Zigbee publish error occured for device '" + deviceMeta['friendly_name'] + "' with error message: " + message['message']) return if (self.groups_manager.get_group_by_name(topic) != None): self.groups_manager.handle_mqtt_message(topic, message) elif (self.devices_manager.get_device_by_name(topic) != None): self.devices_manager.handle_mqtt_message(topic, message) def install(self): domoticz.log('Installing plugin custom page...') try: source_path = Parameters['HomeFolder'] + 'frontend' templates_path = Parameters['StartupFolder'] + 'www/templates' dst_plugin_path = templates_path + '/zigbee2mqtt' domoticz.debug('Copying files from ' + source_path + ' to ' + templates_path) if not (os.path.isdir(dst_plugin_path)): os.makedirs(dst_plugin_path) copy2(source_path + '/zigbee2mqtt.html', templates_path) copy2(source_path + '/zigbee2mqtt.js', templates_path) copy2(source_path + '/plugin_config.js', dst_plugin_path) copy2(source_path + '/zigbee_devices.js', dst_plugin_path) copy2(source_path + '/zigbee_groups.js', dst_plugin_path) copy2(source_path + '/libs/leaflet.js', dst_plugin_path) copy2(source_path + '/libs/leaflet.css', dst_plugin_path) copy2(source_path + '/libs/viz.js', dst_plugin_path) copy2(source_path + '/libs/viz.full.render.js', dst_plugin_path) copy2(source_path + '/libs/ace_json_mode.js', dst_plugin_path) copy2(source_path + '/libs/ace_worker_json.js', dst_plugin_path) domoticz.log('Installing plugin custom page completed.') except Exception as e: domoticz.error('Error during installing plugin custom page') domoticz.error(repr(e)) def uninstall(self): domoticz.log('Uninstalling plugin custom page...') try: templates_path = Parameters['StartupFolder'] + 'www/templates' dst_plugin_path = templates_path + '/zigbee2mqtt' domoticz.debug('Removing files from ' + templates_path) if (os.path.isdir(dst_plugin_path)): rmtree(dst_plugin_path) if os.path.exists(templates_path + "/zigbee2mqtt.html"): os.remove(templates_path + "/zigbee2mqtt.html") if os.path.exists(templates_path + "/zigbee2mqtt.js"): os.remove(templates_path + "/zigbee2mqtt.js") domoticz.log('Uninstalling plugin custom page completed.') except Exception as e: domoticz.error('Error during uninstalling plugin custom page') domoticz.error(repr(e))
class EwpeSmartOverMqttPlugin: mqttClient = None def onStart(self): self.debugging = Parameters["Mode6"] if self.debugging == "Verbose": Domoticz.Debugging(2 + 4 + 8 + 16 + 64) if self.debugging == "Debug": Domoticz.Debugging(2) self.devices = {} self.base_topic = Parameters["Mode1"].strip() mqttserver_address = Parameters["Address"].strip() mqttserver_port = Parameters["Port"].strip() mqtt_client_id = Parameters["Mode3"].strip() self.mqttClient = MqttClient(mqttserver_address, mqttserver_port, mqtt_client_id, self.onMQTTConnected, self.onMQTTDisconnected, self.onMQTTPublish, self.onMQTTSubscribed) Domoticz.Debug("onStart called") def onMQTTConnected(self): self.mqttClient.subscribe([self.base_topic + '/#']) self.mqttClient.publish(self.base_topic + '/devices/list', '') def onMQTTDisconnected(self): Domoticz.Debug("onMQTTDisconnected") def onMQTTSubscribed(self): Domoticz.Debug("onMQTTSubscribed") def onMQTTPublish(self, topic, message): Domoticz.Debug("MQTT message: " + topic + " " + str(message)) if topic == self.base_topic + '/devices': Domoticz.Log('Received available devices list') self.devices = {} for item in message: mac = item['mac'] Domoticz.Log('Device ' + item['name'].strip() + ' (MAC: ' + mac + ')') self.devices[mac] = Device(Devices, self.base_topic, item) else: for mac, device in self.devices.items(): if topic.startswith(self.base_topic + '/' + mac): Domoticz.Debug(self.base_topic + '/' + mac) device.handle_message(topic, message) def onStop(self): Domoticz.Debug("onStop called") def onCommand(self, Unit, Command, Level, Color): Domoticz.Debug("onCommand: " + Command + ", level (" + str(Level) + ") Color:" + Color) [mac, alias] = Devices[Unit].DeviceID.split('_') if mac in self.devices: state = self.devices[mac].handle_command(alias, Command, Level, Color) topic = '/'.join([self.base_topic, mac, 'set']) self.mqttClient.publish(topic, json.dumps(state)) def onConnect(self, Connection, Status, Description): Domoticz.Debug("onConnect called") self.mqttClient.onConnect(Connection, Status, Description) def onDisconnect(self, Connection): self.mqttClient.onDisconnect(Connection) def onMessage(self, Connection, Data): self.mqttClient.onMessage(Connection, Data) def onHeartbeat(self): self.mqttClient.onHeartbeat()