def _on_message(self, client, topic, payload, qos, properties): # print(f'RECV MSG: {topic}', payload) payload = payload.decode("utf-8") device_topic_match = self._device_meta_topic_re.match(topic) control_meta_topic_match = self._control_meta_topic_re.match(topic) control_state_topic_match = self._control_state_topic_re.match(topic) if device_topic_match: self._on_device_meta_change(device_topic_match.group(1), device_topic_match.group(2), payload) elif control_meta_topic_match: self._on_control_meta_change(control_meta_topic_match.group(1), control_meta_topic_match.group(2), control_meta_topic_match.group(3), payload) elif control_state_topic_match: device = WirenBoardDeviceRegistry().get_device(control_state_topic_match.group(1)) control = device.get_control(control_state_topic_match.group(2)) control.state = payload self.hass.publish_state(device, control)
def _on_message(self, client, topic, payload, qos, properties): # print(f'RECV MSG: {topic}', payload) payload = payload.decode("utf-8") if topic == self._status_topic: if payload == self._status_payload_online: logger.info('Home assistant changed status to online. Pushing all devices') self._publish_all_controls() elif payload == self._status_payload_offline: logger.info('Home assistant changed status to offline') else: logger.error(f'Invalid payload for status topic ({topic} -> {payload})') else: control_set_state_topic_match = self._control_set_topic_re.match(topic) if control_set_state_topic_match: device = WirenBoardDeviceRegistry().get_device(control_set_state_topic_match.group(1)) control = device.get_control(control_set_state_topic_match.group(2)) self.wiren.set_control_state(device, control, payload)
def _on_control_meta_change(self, device_id, control_id, meta_name, meta_value): device = WirenBoardDeviceRegistry().get_device(device_id) control = device.get_control(control_id) # print(f'CONTROL: {device_id} / {control_id} / {meta_name} ==> {meta_value}') if meta_name == 'error': # publish availability separately. do not publish all device if control.apply_error(False if not meta_value else True): self.hass.publish_availability(device, control) else: has_changes = False if control.error is None: # We assume that there is no error by default control.error = False has_changes = True if meta_name == 'order': return # Ignore elif meta_name == 'type': try: has_changes |= control.apply_type( WirenControlType(meta_value)) if control.type in WIREN_UNITS_DICT: has_changes |= control.apply_units( WIREN_UNITS_DICT[control.type]) except ValueError: if not meta_value in self._unknown_types: logger.warning( f'Unknown type for wirenboard control: {meta_value}' ) self._unknown_types.append(meta_value) elif meta_name == 'readonly': has_changes |= control.apply_read_only(True if meta_value == '1' else False) elif meta_name == 'units': has_changes |= control.apply_units(meta_value) elif meta_name == 'max': has_changes |= control.apply_max( int(meta_value) if meta_value else None) if has_changes: self.hass.publish_config(device, control)
def _publish_config_sync(self, device: WirenDevice, control: WirenControl): """ Publish discovery topic to the HA """ if self._entity_prefix: entity_id_prefix = self._entity_prefix.lower().replace(" ", "_").replace("-", "_") + '_' else: entity_id_prefix = '' if WirenBoardDeviceRegistry().is_local_device(device): device_unique_id = entity_id_prefix + 'wirenboard' device_name = self._entity_prefix + ' Wirenboard' else: device_unique_id = entity_id_prefix + device.id device_name = self._entity_prefix + ' ' + device.name device_unique_id = device_unique_id.lower().replace(" ", "_").replace("-", "_") entity_unique_id = f"{entity_id_prefix}{device.id}_{control.id}".lower().replace(" ", "_").replace("-", "_") object_id = f"{control.id}".lower().replace(" ", "_").replace("-", "_") entity_name = f"{self._entity_prefix} {device.id} {control.id}".replace("_", " ").title() if device_unique_id in self._split_devices or entity_unique_id in self._split_entities: device_unique_id = entity_unique_id device_name = entity_name node_id = device_unique_id # common payload payload = { 'device': { 'name': device_name, 'identifiers': device_unique_id }, 'name': entity_name, 'unique_id': entity_unique_id, 'availability_topic': self._get_availability_topic(device, control), 'payload_available': "1", 'payload_not_available': "0" } inverse = entity_unique_id in self._inverse control_topic = self._get_control_topic(device, control) component = apply_payload_for_component(payload, device, control, control_topic, inverse=inverse) self._component_types[control.id] = component if not component: return # Topic path: <discovery_topic>/<component>/[<node_id>/]<object_id>/config topic = self._discovery_prefix + '/' + component + '/' + node_id + '/' + object_id + '/config' logger.info(f"[{device.debug_id}/{control.debug_id}] publish config to '{topic}'") self._publish(topic, json.dumps(payload), qos=self._config_qos, retain=self._config_retain)
def _publish_all_controls(self): for device in WirenBoardDeviceRegistry().devices.values(): for control in device.controls.values(): self.publish_config(device, control)
def _on_device_meta_change(device_id, meta_name, meta_value): device = WirenBoardDeviceRegistry().get_device(device_id) if meta_name == 'name': device.name = meta_value