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 _create_device(self, device_data): device_address = device_data['ieee_addr'] feature_name = self._get_feature_name() endpoint = self._get_zigbee_endpoint() alias_config = configuration.get_alias_by_zigbee( device_address, feature_name, endpoint) if alias_config: domoticz.log( 'Alias for handling ' + feature_name + '(endpoint: ' + str(endpoint) + ') feature of device ' + device_address + ' already exists in plugin configuration but Domoticz logical device with ID ' + alias_config['domoticz']['device_id'] + '(unit: ' + str(alias_config['domoticz']['unit']) + ') is not found. If you have removed device and want plugin to recreate it, please remove alias from configuration as well.' ) return None domoticz.debug('Creating domoticz device to handle "' + self.value_key + '" key for device with ieeeAddr ' + device_address) device_id = device_address if self.device_name_suffix != '': device_name = device_data['friendly_name'] + self.device_name_suffix elif hasattr(self, 'feature'): device_name = device_data['friendly_name'] + ' (' + self.feature[ 'property'] + ')' else: device_name = device_data['friendly_name'] unit = configuration.get_device_available_unit(device_address) feature_name = self._get_feature_name() endpoint = self._get_zigbee_endpoint() if blacklist.has(device_id + '_' + feature_name): domoticz.debug('Device is in blacklist, skipped.') return None if unit == None: domoticz.error( 'Can not create new Domoticz device: maximum of 255 logical devices per phisical is reached.' ) return None device = self.create_device(unit, device_id, device_name) configuration.set_zigbee_feature_device(device_address, feature_name, endpoint, device_id, unit, self.alias) return device
def handle_mqtt_message(topic, message): if topic == 'bridge/devices': domoticz.log('Received available devices list from bridge') global zigbee_devices zigbee_devices = message return if topic == 'bridge/groups': domoticz.log('Received available devices groups from bridge') global zigbee_groups zigbee_groups = message return if topic == 'bridge/info': global bridge_info bridge_info = message return
def handle_command(self, alias, device, command, level, color): topic = self.name + '/set' if (alias == 'spoint' or alias == 'sp_eco' or alias == 'sp_cmf') and command == 'Set Level': switch = self.get_device_by_alias(alias) key = switch.value_key return { 'topic': topic, 'payload': json.dumps({ key: level }) } if alias == 'mode' or alias == 'preset': switch = self.get_device_by_alias(alias) level_index = int(level / 10) msg = json.dumps({ alias: switch.level_values[level_index] }) return { 'topic': topic, 'payload': msg } if alias == 'week': domoticz.log('zigbee2mqtt does not support week update') if alias == 'wnd': return { 'topic': topic, 'payload': json.dumps({ 'window_detection': command.upper() }) } if alias == 'child': return { 'topic': topic, 'payload': json.dumps({ 'child_lock': 'LOCK' if command.upper() == 'ON' else 'UNLOCK' }) } if alias == 'level': domoticz.log('zigbee2mqtt does not support valve position update')
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))
def register_groups(self, groups): self.groups = {} for item in groups: group_name = item['friendly_name'] group_id = self._get_group_address_by_name(group_name) device_data = { 'type': 'Group', 'definition': { 'model': 'Group', }, 'ieee_address': group_id, 'friendly_name': group_name } domoticz.log('Group ' + group_name) adapter = self._get_adapter(group_name) adapter.name = group_name adapter.zigbee_device = device_data adapter.register() self.groups[group_id] = adapter
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 set_devices(self, zigbee_devices): self.devices = {} for item in zigbee_devices: device_adress = item['ieee_address'] if 'type' in item and item['type'] == 'Coordinator': domoticz.debug('Coordinator address is ' + device_adress) continue if 'definition' not in item: domoticz.log(item['friendly_name'] + ': device definiton not found, skipping...') continue if item['definition'] == None: domoticz.log(item['friendly_name'] + ': device definiton not found, skipping...') continue if 'model' not in item['definition']: domoticz.log( item['friendly_name'] + ': device definiton does not contain model, skipping...') domoticz.debug(json.dumps(item)) continue model = item['definition']['model'] if model in adapter_by_model: adapter = adapter_by_model[model]() adapter.name = item['friendly_name'] adapter.zigbee_device = item adapter.register() self.devices[device_adress] = adapter else: self.devices[device_adress] = UniversalAdapter(item)
# similar to http://www.domoticz.com/wiki/Smart_Lua_Scripts # name is PIR <options> <switch controlled> # options can be day/night/all # example names: # Pir day-night Slaapkamer groot # PIR all Slaapkamer groot # PIR night Slaapkamer groot if 1: # to disable set to if 0: parts = changed_device.name.split(" ", 2) if len(parts) == 3 and parts[0].lower() == "pir": # case insensitive options = parts[1] device_name_controlled = parts[2] if (is_daytime and "day" in options) or ( is_nighttime and "night" in options) or "all" in options: if device_name_controlled in domoticz.devices: device = domoticz.devices[device_name_controlled] device.on( ) # will only trigger a command when device is off (so we don't have to check device.is_off()) # 240 seconds is default, overrride with pir-timeout user variable # see https://docs.python.org/2/library/stdtypes.html#dict for understanding .get timeon = domoticz.user_variables.get("pir-timeout", 10) domoticz.log( "PIR action, turned on %s, will turn off after %d seconds" % (device_name_controlled, timeon)) device.off(after=timeon) else: domoticz.log("Device not found:", device_name_controlled)
import domoticz # similar to http://www.domoticz.com/wiki/Smart_Lua_Scripts # name is PIR <options> <switch controlled> # options can be day/night/all # example names: # Pir day-night Slaapkamer groot # PIR all Slaapkamer groot # PIR night Slaapkamer groot if 1: # to disable set to if 0: parts = changed_device.name.split(" ", 2) if len(parts) == 3 and parts[0].lower() == "pir": # case insensitive options = parts[1] device_name_controlled = parts[2] if (is_daytime and "day" in options) or (is_nighttime and "night" in options) or "all" in options: if device_name_controlled in domoticz.devices: device = domoticz.devices[device_name_controlled] device.on() # will only trigger a command when device is off (so we don't have to check device.is_off()) # 240 seconds is default, overrride with pir-timeout user variable # see https://docs.python.org/2/library/stdtypes.html#dict for understanding .get timeon = domoticz.user_variables.get("pir-timeout", 10) domoticz.log("PIR action, turned on %s, will turn off after %d seconds" % (device_name_controlled, timeon)) device.off(after=timeon) else: domoticz.log("Device not found:", device_name_controlled)
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)