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)
group.add_argument('-d', '--debug', action='store_true', default=False) group.add_argument('-q', '--quiet', action='store_true', default=False) parsed = parser.parse_args() if parsed.debug: _LOGGER.setLevel(logging.DEBUG) else: _LOGGER.setLevel(logging.INFO) _LOGGER.debug('Starting') mqtt = MqttClient(settings['mqtt']) manager = WorkersManager() manager.register_workers(settings['manager']).start(mqtt) running = True try: while running: try: mqtt.publish(_WORKERS_QUEUE.get(block=True).execute()) except (KeyboardInterrupt, SystemExit): raise except Exception as e: if not parsed.quiet: _LOGGER.exception(e) except KeyboardInterrupt: running = False _LOGGER.info( 'Exiting allowing jobs to finish. If you need force exit use kill')
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.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.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))
_LOGGER.setLevel(logging.INFO) logger.suppress_update_failures(parsed.suppress) _LOGGER.info('Starting') global_topic_prefix = settings['mqtt'].get('topic_prefix') mqtt = MqttClient(settings['mqtt']) manager = WorkersManager(settings['manager']) manager.register_workers(global_topic_prefix).start(mqtt) running = True while running: try: mqtt.publish(_WORKERS_QUEUE.get(timeout=10).execute()) except queue.Empty: # Allow for SIGINT processing pass except TimeoutError as e: logger.log_exception( _LOGGER, str(e) if str(e) else 'Timeout while executing worker command', suppress=True) except (KeyboardInterrupt, SystemExit): running = False _LOGGER.info( 'Finish current jobs and shut down. If you need force exit use kill' ) except Exception as e: logger.log_exception(_LOGGER, "Fatal error while executing worker command: %s",
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()