diff --git a/custom_components/nhc2/__init__.py b/custom_components/nhc2/__init__.py index 935df294..4a9e1bd4 100644 --- a/custom_components/nhc2/__init__.py +++ b/custom_components/nhc2/__init__.py @@ -9,13 +9,10 @@ from .config_flow import Nhc2FlowHandler # noqa pylint_disable=unused-import from .const import DOMAIN, KEY_GATEWAY, CONF_SWITCHES_AS_LIGHTS, BRAND -from .helpers import extract_versions +from .nhccoco.helpers import extract_versions _LOGGER = logging.getLogger(__name__) -DOMAIN = DOMAIN -KEY_GATEWAY = KEY_GATEWAY - CONFIG_SCHEMA = vol.Schema({ DOMAIN: vol.Schema({ vol.Required(CONF_HOST): cv.string, @@ -62,14 +59,15 @@ async def async_setup(hass, config): FORWARD_PLATFORMS = ( "alarm_control_panel", "binary_sensor", + "button", + "camera", "climate", - "switch", - "light", - "fan", "cover", - "sensor", - "button", + "fan", + "light", "lock", + "sensor", + "switch", ) @@ -91,9 +89,8 @@ async def on_hass_stop(event): def get_process_sysinfo(dev_reg): def process_sysinfo(nhc2_sysinfo): coco_image, nhc_version = extract_versions(nhc2_sysinfo) - _LOGGER.debug('Sysinfo: NhcVersion %s - CocoImage %s', - nhc_version, - coco_image) + _LOGGER.debug('systeminfo.published: NhcVersion: %s - CocoImage %s', nhc_version, coco_image) + dev_reg.async_get_or_create( config_entry_id=entry.entry_id, connections=set(), @@ -116,9 +113,7 @@ def process_sysinfo(nhc2_sysinfo): hass.data.setdefault(KEY_GATEWAY, {})[entry.entry_id] = coco hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, on_hass_stop) - _LOGGER.debug('Connecting to %s with %s', - entry.data[CONF_HOST], entry.data[CONF_USERNAME] - ) + _LOGGER.debug('Connecting to %s with %s', entry.data[CONF_HOST], entry.data[CONF_USERNAME]) coco.connect() dev_reg = hass.helpers.device_registry.async_get(hass) coco.get_systeminfo(get_process_sysinfo(dev_reg)) diff --git a/custom_components/nhc2/alarm_control_panel.py b/custom_components/nhc2/alarm_control_panel.py index 643745df..d8d669f8 100644 --- a/custom_components/nhc2/alarm_control_panel.py +++ b/custom_components/nhc2/alarm_control_panel.py @@ -10,7 +10,6 @@ from .const import DOMAIN, KEY_GATEWAY -KEY_GATEWAY = KEY_GATEWAY KEY_ENTITY = 'nhc2_alarm_control_panels' _LOGGER = logging.getLogger(__name__) diff --git a/custom_components/nhc2/binary_sensor.py b/custom_components/nhc2/binary_sensor.py index 8c0dd4f3..697f56f7 100644 --- a/custom_components/nhc2/binary_sensor.py +++ b/custom_components/nhc2/binary_sensor.py @@ -35,7 +35,6 @@ from .const import DOMAIN, KEY_GATEWAY -KEY_GATEWAY = KEY_GATEWAY KEY_ENTITY = 'nhc2_binary_sensors' _LOGGER = logging.getLogger(__name__) diff --git a/custom_components/nhc2/button.py b/custom_components/nhc2/button.py index 3b078672..170059f0 100644 --- a/custom_components/nhc2/button.py +++ b/custom_components/nhc2/button.py @@ -12,7 +12,6 @@ from .const import DOMAIN, KEY_GATEWAY -KEY_GATEWAY = KEY_GATEWAY KEY_ENTITY = 'nhc2_buttons' _LOGGER = logging.getLogger(__name__) diff --git a/custom_components/nhc2/camera.py b/custom_components/nhc2/camera.py index a08a4159..6a611377 100644 --- a/custom_components/nhc2/camera.py +++ b/custom_components/nhc2/camera.py @@ -10,7 +10,6 @@ from .const import DOMAIN, KEY_GATEWAY -KEY_GATEWAY = KEY_GATEWAY KEY_ENTITY = 'nhc2_cameras' _LOGGER = logging.getLogger(__name__) diff --git a/custom_components/nhc2/climate.py b/custom_components/nhc2/climate.py index 3139350a..7f1e8da1 100644 --- a/custom_components/nhc2/climate.py +++ b/custom_components/nhc2/climate.py @@ -13,7 +13,6 @@ from .const import DOMAIN, KEY_GATEWAY -KEY_GATEWAY = KEY_GATEWAY KEY_ENTITY = 'nhc2_thermostats' _LOGGER = logging.getLogger(__name__) diff --git a/custom_components/nhc2/const.py b/custom_components/nhc2/const.py index c567f9d3..74fc18cb 100644 --- a/custom_components/nhc2/const.py +++ b/custom_components/nhc2/const.py @@ -4,24 +4,8 @@ DOMAIN = 'nhc2' KEY_GATEWAY = 'nhc2_gateway' BRAND = 'Niko' -LIGHT = 'Light' -SWITCH = 'Switch' -COVER = 'Cover' -FAN = 'Fan' -CLIMATE = 'Thermostat' -ENERGY = 'CentralMeter' -BUTTON = 'Button' -SMARTPLUG = 'SmartPlug' CONF_SWITCHES_AS_LIGHTS = 'switches_as_lights' -DEFAULT_PORT = 8883 KEY_MANUAL = 'MANUAL_IP_HOST' -ROLL_DOWN_SHUTTER = 'rolldownshutter' -SUN_BLIND = 'sunblind' -GATE = 'gate' -VENETIAN_BLIND = 'venetianblind' -GARAGE_DOOR = 'garagedoor' - SERVICE_SET_LIGHT_BRIGHTNESS = 'set_light_brightness' - ATTR_LIGHT_BRIGHTNESS = 'light_brightness' diff --git a/custom_components/nhc2/cover.py b/custom_components/nhc2/cover.py index 3f40ca2c..599f4e5e 100644 --- a/custom_components/nhc2/cover.py +++ b/custom_components/nhc2/cover.py @@ -15,7 +15,6 @@ from .const import DOMAIN, KEY_GATEWAY -KEY_GATEWAY = KEY_GATEWAY KEY_ENTITY = 'nhc2_covers' _LOGGER = logging.getLogger(__name__) diff --git a/custom_components/nhc2/fan.py b/custom_components/nhc2/fan.py index 80c0bd02..72a6f466 100644 --- a/custom_components/nhc2/fan.py +++ b/custom_components/nhc2/fan.py @@ -10,7 +10,6 @@ from .const import DOMAIN, KEY_GATEWAY -KEY_GATEWAY = KEY_GATEWAY KEY_ENTITY = 'nhc2_fans' _LOGGER = logging.getLogger(__name__) diff --git a/custom_components/nhc2/helpers.py b/custom_components/nhc2/helpers.py deleted file mode 100644 index 315a5d3f..00000000 --- a/custom_components/nhc2/helpers.py +++ /dev/null @@ -1,87 +0,0 @@ -"""Helpers for NHC2.""" - -import logging - -from homeassistant.core import callback - -_LOGGER = logging.getLogger(__name__) - - -def nhc2_entity_processor(hass, - config_entry, - async_add_entities, - key, - obj_create): - """Loops the entities list and creates, updates or deletes HA entities.""" - @callback - def process_entities(entities): - _LOGGER.debug('Processing of %s entities started', key) - # Collect a list of active UUIDs - active_uuids = list(map(lambda x: x.uuid, - hass.data[key][config_entry.entry_id])) - _LOGGER.debug('Active UUIDs: %s', ', '.join(active_uuids)) - - # Sort out existing and new entities - new_entities, existing_entities = [], [] - for entity in entities: - (new_entities, existing_entities)[entity.uuid in active_uuids].append(entity) - - _LOGGER.debug('Existing UUIDs: %s', ', ' - .join(list(map(lambda x: x.uuid, existing_entities)))) - _LOGGER.debug('New UUIDs: %s', ', ' - .join(list(map(lambda x: x.uuid, new_entities)))) - - # Process the new entities - new_hass_entities = [] - for entity in new_entities: - new_entity = obj_create(entity) - hass.data[key][config_entry.entry_id].append(new_entity) - new_hass_entities.append(new_entity) - async_add_entities(new_hass_entities) - _LOGGER.debug('Adding new entities done.') - - # Process the existing entities (update) - for entity in existing_entities: - entity_to_update = \ - next(filter(( - lambda x: x.uuid == entity.uuid), - hass.data[key][config_entry.entry_id]), None) - entity_to_update.nhc2_update(entity) - _LOGGER.debug('Update done.') - - # List UUIDs that should be removed - uuids_from_entities = list(map(lambda x: x.uuid, existing_entities)) - uuids_to_remove = \ - [i for i in uuids_from_entities #+ active_uuids - if i not in uuids_from_entities] - _LOGGER.debug('UUIDs to remove: %s', ', '.join(uuids_to_remove)) - - # Remove entities (the need be removed) - for uuid_to_remove in uuids_to_remove: - entity_to_remove = next(filter(( - lambda x: x.uuid == uuid_to_remove), - hass.data[key][config_entry.entry_id]), None) - hass.add_job(entity_to_remove.async_remove()) - hass.data[key][config_entry.entry_id].remove(entity_to_remove) - _LOGGER.debug('Removals done.') - - return process_entities - - -# Extract version numbers from sysinfo -def extract_versions(nhc2_sysinfo): - """Return the versions, extracted from sysinfo.""" - params = nhc2_sysinfo['Params'] - system_info = next(filter( - (lambda x: x and 'SystemInfo' in x), - params), None)['SystemInfo'] - s_w_versions = next(filter( - (lambda x: x and 'SWversions' in x), - system_info), None)['SWversions'] - coco_image = next(filter( - (lambda x: x and 'CocoImage' in x), - s_w_versions), None)['CocoImage'] - nhc_version = next(filter( - (lambda x: x and 'NhcVersion' in x), - s_w_versions), None)['NhcVersion'] - return coco_image, nhc_version diff --git a/custom_components/nhc2/light.py b/custom_components/nhc2/light.py index 8ad60015..77363c57 100644 --- a/custom_components/nhc2/light.py +++ b/custom_components/nhc2/light.py @@ -14,7 +14,6 @@ from .const import DOMAIN, KEY_GATEWAY, SERVICE_SET_LIGHT_BRIGHTNESS, ATTR_LIGHT_BRIGHTNESS -KEY_GATEWAY = KEY_GATEWAY KEY_ENTITY = 'nhc2_lights' _LOGGER = logging.getLogger(__name__) diff --git a/custom_components/nhc2/lock.py b/custom_components/nhc2/lock.py index 44025b22..6cba22dd 100644 --- a/custom_components/nhc2/lock.py +++ b/custom_components/nhc2/lock.py @@ -10,7 +10,6 @@ from .const import DOMAIN, KEY_GATEWAY -KEY_GATEWAY = KEY_GATEWAY KEY_ENTITY = 'nhc2_locks' _LOGGER = logging.getLogger(__name__) diff --git a/custom_components/nhc2/nhccoco/__init__.py b/custom_components/nhc2/nhccoco/__init__.py deleted file mode 100755 index 5765ff0d..00000000 --- a/custom_components/nhc2/nhccoco/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -from .coco import CoCo -from .coco_entity import CoCoEntity -from .coco_energy import CoCoEnergyMeter -from .coco_device_class import CoCoDeviceClass - -__all__ = ["CoCo", - "CoCoEntity", - "CoCoEnergyMeter", - "CoCoDeviceClass"] diff --git a/custom_components/nhc2/nhccoco/coco.py b/custom_components/nhc2/nhccoco/coco.py index 62799d95..18b7ad99 100755 --- a/custom_components/nhc2/nhccoco/coco.py +++ b/custom_components/nhc2/nhccoco/coco.py @@ -1,17 +1,11 @@ import json -import logging import os import threading from time import sleep -from typing import Callable import sys import paho.mqtt.client as mqtt -from .coco_device_class import CoCoDeviceClass -from .coco_energy import CoCoEnergyMeter -from .coco_generic import CoCoGeneric - from .devices.accesscontrol_action import CocoAccesscontrolAction from .devices.alarms_action import CocoAlarmsAction from .devices.alloff_action import CocoAlloffAction @@ -36,32 +30,14 @@ from .const import * from .helpers import * +import logging + _LOGGER = logging.getLogger(__name__) sem = threading.Semaphore() -DEVICE_SETS = { - CoCoDeviceClass.SWITCHED_FANS: {INTERNAL_KEY_CLASS: CoCoSwitchedFan, INTERNAL_KEY_MODELS: LIST_VALID_SWITCHED_FANS}, - CoCoDeviceClass.FANS: {INTERNAL_KEY_CLASS: CoCoFan, INTERNAL_KEY_MODELS: LIST_VALID_FANS}, - CoCoDeviceClass.COVERS: {INTERNAL_KEY_CLASS: CoCoCover, INTERNAL_KEY_MODELS: LIST_VALID_COVERS}, - CoCoDeviceClass.SWITCHES: {INTERNAL_KEY_CLASS: CoCoSwitch, INTERNAL_KEY_MODELS: LIST_VALID_SWITCHES}, - CoCoDeviceClass.LIGHTS: {INTERNAL_KEY_CLASS: CoCoLight, INTERNAL_KEY_MODELS: LIST_VALID_LIGHTS}, - CoCoDeviceClass.THERMOSTATS: {INTERNAL_KEY_CLASS: CoCoThermostat, INTERNAL_KEY_MODELS: LIST_VALID_THERMOSTATS}, - CoCoDeviceClass.ENERGYMETERS: {INTERNAL_KEY_CLASS: CoCoEnergyMeter, INTERNAL_KEY_MODELS: LIST_VALID_ENERGYMETERS}, - CoCoDeviceClass.ACCESSCONTROL: {INTERNAL_KEY_CLASS: CoCoAccessControl, - INTERNAL_KEY_MODELS: LIST_VALID_ACCESSCONTROL}, - CoCoDeviceClass.BUTTONS: {INTERNAL_KEY_CLASS: CoCoButton, INTERNAL_KEY_MODELS: LIST_VALID_BUTTONS}, - CoCoDeviceClass.SMARTPLUGS: {INTERNAL_KEY_CLASS: CoCoSmartPlug, INTERNAL_KEY_MODELS: LIST_VALID_SMARTPLUGS}, - CoCoDeviceClass.GENERIC: {INTERNAL_KEY_CLASS: CoCoGeneric, INTERNAL_KEY_MODELS: LIST_VALID_GENERICS} -} - class CoCo: def __init__(self, address, username, password, port=8884, ca_path=None, switches_as_lights=False): - - if switches_as_lights: - DEVICE_SETS[CoCoDeviceClass.LIGHTS] = {INTERNAL_KEY_CLASS: CoCoLight, - INTERNAL_KEY_MODELS: LIST_VALID_LIGHTS + LIST_VALID_SWITCHES} - DEVICE_SETS[CoCoDeviceClass.SWITCHES] = {INTERNAL_KEY_CLASS: CoCoSwitch, INTERNAL_KEY_MODELS: []} # The device control buffer fields self._keep_thread_running = True self._device_control_buffer = {} @@ -107,45 +83,47 @@ def _on_message(client, userdata, message): # System info response (/system/rsp, method: systeminfo.publish) if topic == self._profile_creation_id + MQTT_TOPIC_PUBLIC_RSP and \ - response[KEY_METHOD] == MQTT_METHOD_SYSINFO_PUBLISH: + response[MQTT_DATA_METHOD] == MQTT_DATA_METHOD_SYSINFO_PUBLISH: self._system_info = response self._system_info_callback(self._system_info) # Device list response (/control/devices/rsp, method: devices.list) elif topic == (self._profile_creation_id + MQTT_TOPIC_SUFFIX_RSP) and \ - response[KEY_METHOD] == MQTT_METHOD_DEVICES_LIST: + response[MQTT_DATA_METHOD] == MQTT_DATA_METHOD_DEVICES_LIST: # No need to listen for devices anymore. So unsubscribe. self._client.unsubscribe(self._profile_creation_id + MQTT_TOPIC_SUFFIX_RSP) self._process_devices_list(response) # System info published (/system/evt, method: systeminfo.published) elif topic == (self._profile_creation_id + MQTT_TOPIC_SUFFIX_SYS_EVT) and \ - response[KEY_METHOD] == MQTT_METHOD_SYSINFO_PUBLISHED: + response[MQTT_DATA_METHOD] == MQTT_DATA_METHOD_SYSINFO_PUBLISHED: # If the connected controller publishes sysinfo we expect something to have changed. # So ask the list of devices again. # To be honest: I don't think this will do anything usefull, as no new entities will be created. client.subscribe(self._profile_creation_id + MQTT_TOPIC_SUFFIX_RSP, qos=1) client.publish( self._profile_creation_id + MQTT_TOPIC_SUFFIX_CMD, - json.dumps({KEY_METHOD: MQTT_METHOD_DEVICES_LIST}), + json.dumps({MQTT_DATA_METHOD: MQTT_DATA_METHOD_DEVICES_LIST}), 1 ) # Device events (/control/devices/evt, method: devices.status or devices.changed) elif topic == (self._profile_creation_id + MQTT_TOPIC_SUFFIX_EVT) and ( - response[KEY_METHOD] == MQTT_METHOD_DEVICES_STATUS or - response[KEY_METHOD] == MQTT_METHOD_DEVICES_CHANGED + response[MQTT_DATA_METHOD] == MQTT_DATA_METHOD_DEVICES_STATUS or + response[MQTT_DATA_METHOD] == MQTT_DATA_METHOD_DEVICES_CHANGED ): devices = extract_devices(response) for device in devices: - if KEY_UUID not in device: + if MQTT_DATA_PARAMS_DEVICES_UUID not in device: continue try: - self._device_instances[device[KEY_UUID]].on_change(topic, device) + self._device_instances[device[MQTT_DATA_PARAMS_DEVICES_UUID]].on_change(topic, device) except Exception as e: - _LOGGER.debug(f'Failed to invoke callback: {device[KEY_UUID]}. Topic: {topic} | Data: {device}') + _LOGGER.debug( + f'Failed to invoke callback: {device[MQTT_DATA_PARAMS_DEVICES_UUID]}. Topic: {topic} | Data: {device}') + _LOGGER.error(e) pass def _on_connect(client, userdata, flags, rc): @@ -161,14 +139,14 @@ def _on_connect(client, userdata, flags, rc): # ask the system information client.publish( self._profile_creation_id + MQTT_TOPIC_PUBLIC_CMD, - json.dumps({KEY_METHOD: MQTT_METHOD_SYSINFO_PUBLISH}), + json.dumps({MQTT_DATA_METHOD: MQTT_DATA_METHOD_SYSINFO_PUBLISH}), 1 ) # ask the devices list client.publish( self._profile_creation_id + MQTT_TOPIC_SUFFIX_CMD, - json.dumps({KEY_METHOD: MQTT_METHOD_DEVICES_LIST}), + json.dumps({MQTT_DATA_METHOD: MQTT_DATA_METHOD_DEVICES_LIST}), 1 ) elif MQTT_RC_CODES[rc]: @@ -198,11 +176,6 @@ def get_systeminfo(self, callback): if self._system_info: self._system_info_callback(self._system_info) - def get_devices(self, device_class: CoCoDeviceClass, callback: Callable): - self._devices_callback[device_class] = callback - if self._devices and device_class in self._devices: - self._devices_callback[device_class](self._devices[device_class]) - def get_device_instances(self, device_class): if len(self._device_instances) == 0: _LOGGER.warning(f'No devices yet, probably waiting for device list.') @@ -234,7 +207,7 @@ def _publish_device_control_commands(self): ) sleep(0.05) - def _add_device_control(self, uuid, property_key, property_value): + def add_device_control(self, uuid, property_key, property_value): while len(self._device_control_buffer.keys()) >= self._device_control_buffer_size or \ self._device_control_buffer_command_count >= self._device_control_buffer_command_size: pass @@ -248,44 +221,6 @@ def _add_device_control(self, uuid, property_key, property_value): def _process_devices_list(self, response): """Convert the response of devices.list into device instances.""" devices = extract_devices(response) - self._device_instances = self._convert_to_device_instances(devices) - - # for uuid, device in self._device_instances.items(): - # self._device_callbacks[uuid] = device.on_change - - # Only add devices that are actionable - # actionable_devices = list( - # filter(lambda d: d[KEY_TYPE] == DEV_TYPE_ACTION, extract_devices(response))) - # actionable_devices.extend(list( - # filter(lambda d: d[KEY_TYPE] == "thermostat", extract_devices(response)))) - # actionable_devices.extend(list( - # filter(lambda d: d[KEY_TYPE] == "centralmeter", extract_devices(response)))) - # actionable_devices.extend(list( - # filter(lambda d: d[KEY_TYPE] == "smartplug", extract_devices(response)))) - - # Only prepare for devices that don't already exist - # # TODO - Can't we do this when we need it (in initialize_devices ?) - # existing_uuids = list(self._device_callbacks.keys()) - # for actionable_device in actionable_devices: - # if actionable_device[KEY_UUID] not in existing_uuids: - # self._device_callbacks[actionable_device[KEY_UUID]] = \ - # {INTERNAL_KEY_CALLBACK: None, KEY_ENTITY: None} - - # Initialize - # self.initialize_devices(CoCoDeviceClass.SWITCHED_FANS, actionable_devices) - # self.initialize_devices(CoCoDeviceClass.FANS, actionable_devices) - # self.initialize_devices(CoCoDeviceClass.SWITCHES, actionable_devices) - # self.initialize_devices(CoCoDeviceClass.LIGHTS, actionable_devices) - # self.initialize_devices(CoCoDeviceClass.COVERS, actionable_devices) - # self.initialize_devices(CoCoDeviceClass.THERMOSTATS, actionable_devices) - # self.initialize_devices(CoCoDeviceClass.ENERGYMETERS, actionable_devices) - # self.initialize_devices(CoCoDeviceClass.ACCESSCONTROL, actionable_devices) - # self.initialize_devices(CoCoDeviceClass.BUTTONS, actionable_devices) - # self.initialize_devices(CoCoDeviceClass.SMARTPLUGS, actionable_devices) - # self.initialize_devices(CoCoDeviceClass.GENERIC, actionable_devices) - - def _convert_to_device_instances(self, devices: list): - device_instances = {} for device in devices: try: classname = str.replace( diff --git a/custom_components/nhc2/nhccoco/coco_entity.py b/custom_components/nhc2/nhccoco/coco_entity.py deleted file mode 100755 index 277f128b..00000000 --- a/custom_components/nhc2/nhccoco/coco_entity.py +++ /dev/null @@ -1,87 +0,0 @@ -import threading -import logging -from abc import ABC, abstractmethod - -from .const import KEY_NAME, INTERNAL_KEY_CALLBACK, KEY_TYPE, KEY_MODEL, KEY_ONLINE, KEY_DISPLAY_NAME -from .helpers import dev_prop_changed - -_LOGGER = logging.getLogger(__name__) - -class CoCoEntity(ABC): - - @property - def uuid(self): - return self._uuid - - @property - def name(self): - return self._name - - @property - def online(self): - return self._online - - @property - def model(self): - return self._model - - @property - def type(self): - return self._type - - @property - def profile_creation_id(self): - return self._profile_creation_id - - @property - def on_change(self): - return self._on_change - - @on_change.setter - def on_change(self, func): - with self._callback_mutex: - self._on_change = func - - def __init__(self, dev, callback_container, client, profile_creation_id, command_device_control): - self._client = client - self._profile_creation_id = profile_creation_id - self._uuid = dev['Uuid'] - self._name = None - self._online = None - self._model = None - self._type = None - self._command_device_control = command_device_control - self._callback_mutex = threading.RLock() - self._on_change = (lambda: _LOGGER.warning('%s (%s) has no _on_change callback set!' % (self._name, self._uuid))) - self._callback_container = callback_container - - def update_dev(self, dev, callback_container=None): - has_changed = False - if dev_prop_changed(self._name, dev, KEY_NAME): - self._name = dev[KEY_NAME] - has_changed = True - if dev_prop_changed(self._name, dev, KEY_DISPLAY_NAME): - self._name = dev[KEY_DISPLAY_NAME] - has_changed = True - if KEY_ONLINE in dev and self._online != (dev[KEY_ONLINE] == 'True'): - self._online = dev[KEY_ONLINE] == 'True' - has_changed = True - if dev_prop_changed(self._model, dev, KEY_MODEL): - self._model = dev[KEY_MODEL] - has_changed = True - if dev_prop_changed(self._type, dev, KEY_TYPE): - self._type = dev[KEY_TYPE] - has_changed = True - if callback_container: - self._callback_container = callback_container - if not INTERNAL_KEY_CALLBACK in self._callback_container or self._callback_container[INTERNAL_KEY_CALLBACK] == None: - self._callback_container[INTERNAL_KEY_CALLBACK] = self._update - has_changed = True - return has_changed - - @abstractmethod - def _update(self, dev): - pass - - def _state_changed(self): - self.on_change() diff --git a/custom_components/nhc2/nhccoco/coco_generic.py b/custom_components/nhc2/nhccoco/coco_generic.py deleted file mode 100755 index f74b4b42..00000000 --- a/custom_components/nhc2/nhccoco/coco_generic.py +++ /dev/null @@ -1,34 +0,0 @@ -from .coco_entity import CoCoEntity -from .const import KEY_BASICSTATE, VALUE_TRIGGERED, VALUE_ON, KEY_STATUS -from .helpers import extract_property_value_from_device - - -class CoCoGeneric(CoCoEntity): - - @property - def is_on(self): - return self._is_on - - def __init__(self, dev, callback_container, client, profile_creation_id, command_device_control): - super().__init__(dev, callback_container, client, profile_creation_id, command_device_control) - self._is_on = None - self.update_dev(dev, callback_container) - - def turn_on(self): - self._command_device_control(self._uuid, KEY_BASICSTATE, VALUE_TRIGGERED) - - def turn_off(self): - self._command_device_control(self._uuid, KEY_BASICSTATE, VALUE_TRIGGERED) - - def update_dev(self, dev, callback_container=None): - has_changed = super().update_dev(dev, callback_container) - status_value = extract_property_value_from_device(dev, KEY_BASICSTATE) - if status_value and self._is_on != (status_value == VALUE_ON): - self._is_on = (status_value == VALUE_ON) - has_changed = True - return has_changed - - def _update(self, dev): - has_changed = self.update_dev(dev) - if has_changed: - self._state_changed() diff --git a/custom_components/nhc2/nhccoco/coco_notify.py b/custom_components/nhc2/nhccoco/coco_notify.py deleted file mode 100755 index 156245ff..00000000 --- a/custom_components/nhc2/nhccoco/coco_notify.py +++ /dev/null @@ -1,33 +0,0 @@ -import logging - -from .coco_entity import CoCoEntity -from .const import ENERGY_POWER, ENERGY_REPORT -from .helpers import extract_property_value_from_device - -_LOGGER = logging.getLogger(__name__) - - -class CoCoNotification(CoCoEntity): - - def __init__(self, dev, callback_container, client, profile_creation_id, command_device_control): - super().__init__(dev, callback_container, client, profile_creation_id, command_device_control) - self.update_dev(dev, callback_container) - self._command_device_control(self._uuid, ENERGY_REPORT, 'True') - - def update_dev(self, dev, callback_container=None): - has_changed = super().update_dev(dev, callback_container) - status_value = extract_property_value_from_device(dev, ENERGY_POWER) - if status_value: - _LOGGER.debug(status_value) - self._state = status_value - has_changed = True - status_value = extract_property_value_from_device(dev, ENERGY_REPORT) - if status_value == 'False': - _LOGGER.debug(status_value) - self._command_device_control(self._uuid, ENERGY_REPORT, 'True') - return has_changed - - def _update(self, dev): - has_changed = self.update_dev(dev) - if has_changed: - self._state_changed() \ No newline at end of file diff --git a/custom_components/nhc2/nhccoco/const.py b/custom_components/nhc2/nhccoco/const.py index 627e95e7..6c48fd54 100755 --- a/custom_components/nhc2/nhccoco/const.py +++ b/custom_components/nhc2/nhccoco/const.py @@ -1,7 +1,5 @@ import paho.mqtt.client as mqtt -from enum import Enum - MQTT_PROTOCOL = mqtt.MQTTv311 MQTT_TRANSPORT = 'tcp' MQTT_CERT_FILE = '/coco_ca.pem' @@ -9,52 +7,21 @@ DEVICE_CONTROL_BUFFER_SIZE = 16 DEVICE_CONTROL_BUFFER_COMMAND_SIZE = 32 -KEY_ACTION = 'Action' -KEY_DEVICES = 'Devices' -KEY_DISPLAY_NAME = 'DisplayName' -KEY_FAN_SPEED = 'FanSpeed' -KEY_METHOD = 'Method' -KEY_MODEL = 'Model' -KEY_NAME = 'Name' -KEY_ONLINE = 'Online' -KEY_PARAMS = 'Params' -KEY_PROPERTIES = 'Properties' -KEY_POSITION = 'Position' -KEY_STATUS = 'Status' -KEY_TYPE = 'Type' -KEY_UUID = 'Uuid' -KEY_BASICSTATE = "BasicState" - -VALUE_ON = 'On' -VALUE_OFF = 'Off' -VALUE_OPEN = 'Open' -VALUE_STOP = 'Stop' -VALUE_CLOSE = 'Close' -VALUE_TRIGGERED = 'Triggered' - -GATE_VALUE_OPEN = 'On' -GATE_VALUE_CLOSE = 'Off' -GATE_VALUE_TRIGGERED = 'Triggered' -GATE_MOVING = 'Intermediate' -KEY_ALIGNED = "Aligned" - -THERM_PROGRAM = 'Program' -THERM_OVERRULEACTION = 'OverruleActive' -THERM_OVERRULESETPOINT = 'OverruleSetpoint' -THERM_OVERRULETIME = 'OverruleTime' -THERM_ECOSAVE = 'EcoSave' - -ENERGY_REPORT = 'ReportInstantUsage' -ENERGY_POWER = 'ElectricalPower' - -INTERNAL_KEY_CALLBACK = 'callbackHolder' - -MQTT_METHOD_SYSINFO_PUBLISH = 'systeminfo.publish' -MQTT_METHOD_SYSINFO_PUBLISHED = 'systeminfo.published' -MQTT_METHOD_DEVICES_LIST = 'devices.list' -MQTT_METHOD_DEVICES_CONTROL = 'devices.control' -MQTT_METHOD_DEVICES_STATUS = 'devices.status' -MQTT_METHOD_DEVICES_CHANGED = 'devices.changed' +MQTT_DATA_METHOD = 'Method' +MQTT_DATA_METHOD_SYSINFO_PUBLISH = 'systeminfo.publish' +MQTT_DATA_METHOD_SYSINFO_PUBLISHED = 'systeminfo.published' +MQTT_DATA_METHOD_DEVICES_LIST = 'devices.list' +MQTT_DATA_METHOD_DEVICES_CONTROL = 'devices.control' +MQTT_DATA_METHOD_DEVICES_STATUS = 'devices.status' +MQTT_DATA_METHOD_DEVICES_CHANGED = 'devices.changed' +MQTT_DATA_PARAMS = 'Params' +MQTT_DATA_PARAMS_DEVICES = 'Devices' +MQTT_DATA_PARAMS_DEVICES_PROPERTIES = 'Properties' +MQTT_DATA_PARAMS_DEVICES_UUID = 'Uuid' +MQTT_DATA_PARAMS_SYSTEMINFO = 'SystemInfo' +MQTT_DATA_PARAMS_SYSTEMINFO_SWVERSIONS = 'SWversions' +MQTT_DATA_PARAMS_SYSTEMINFO_SWVERSIONS_COCO_IMAGE = 'CocoImage' +MQTT_DATA_PARAMS_SYSTEMINFO_SWVERSIONS_NHC_VERSION = 'NhcVersion' MQTT_RC_CODES = ['', 'Connection refused - incorrect protocol version', diff --git a/custom_components/nhc2/nhccoco/devices/accesscontrol_action.py b/custom_components/nhc2/nhccoco/devices/accesscontrol_action.py index 190d525e..ddfce7a9 100644 --- a/custom_components/nhc2/nhccoco/devices/accesscontrol_action.py +++ b/custom_components/nhc2/nhccoco/devices/accesscontrol_action.py @@ -49,15 +49,15 @@ def on_change(self, topic: str, payload: dict): callback() def press(self, gateway): - gateway._add_device_control( - self._device.uuid, + gateway.add_device_control( + self.uuid, PROPERTY_BASIC_STATE, PROPERTY_BASIC_STATE_VALUE_TRIGGERED ) def open_doorlock(self, gateway): - gateway._add_device_control( - self._device.uuid, + gateway.add_device_control( + self.uuid, PROPERTY_DOORLOCK, PROPERTY_DOORLOCK_VALUE_OPEN ) diff --git a/custom_components/nhc2/nhccoco/devices/alarms_action.py b/custom_components/nhc2/nhccoco/devices/alarms_action.py index 348749d5..f2da60a7 100644 --- a/custom_components/nhc2/nhccoco/devices/alarms_action.py +++ b/custom_components/nhc2/nhccoco/devices/alarms_action.py @@ -41,8 +41,8 @@ def arm(self, gateway): if self.is_on: return - gateway._add_device_control( - self._device.uuid, + gateway.add_device_control( + self.uuid, PROPERTY_BASIC_STATE, PROPERTY_BASIC_STATE_VALUE_TRIGGERED ) @@ -51,8 +51,8 @@ def disarm(self, gateway): if self.is_off: return - gateway._add_device_control( - self._device.uuid, + gateway.add_device_control( + self.uuid, PROPERTY_BASIC_STATE, PROPERTY_BASIC_STATE_VALUE_TRIGGERED ) diff --git a/custom_components/nhc2/nhccoco/devices/alloff_action.py b/custom_components/nhc2/nhccoco/devices/alloff_action.py index 662a2ca7..1263bd4b 100644 --- a/custom_components/nhc2/nhccoco/devices/alloff_action.py +++ b/custom_components/nhc2/nhccoco/devices/alloff_action.py @@ -38,8 +38,8 @@ def on_change(self, topic: str, payload: dict): callback() def press(self, gateway): - gateway._add_device_control( - self._device.uuid, + gateway.add_device_control( + self.uuid, PROPERTY_BASIC_STATE, PROPERTY_BASIC_STATE_VALUE_TRIGGERED ) diff --git a/custom_components/nhc2/nhccoco/devices/dimmer_action.py b/custom_components/nhc2/nhccoco/devices/dimmer_action.py index 8bd6ecde..e861a511 100644 --- a/custom_components/nhc2/nhccoco/devices/dimmer_action.py +++ b/custom_components/nhc2/nhccoco/devices/dimmer_action.py @@ -43,10 +43,10 @@ def on_change(self, topic: str, payload: dict): callback() def turn_on(self, gateway): - gateway._add_device_control(self.uuid, PROPERTY_STATUS, PROPERTY_STATUS_VALUE_ON) + gateway.add_device_control(self.uuid, PROPERTY_STATUS, PROPERTY_STATUS_VALUE_ON) def turn_off(self, gateway): - gateway._add_device_control(self.uuid, PROPERTY_STATUS, PROPERTY_STATUS_VALUE_OFF) + gateway.add_device_control(self.uuid, PROPERTY_STATUS, PROPERTY_STATUS_VALUE_OFF) def set_brightness(self, gateway, brightness: int): - gateway._add_device_control(self.uuid, PROPERTY_BRIGHTNESS, str(brightness)) + gateway.add_device_control(self.uuid, PROPERTY_BRIGHTNESS, str(brightness)) diff --git a/custom_components/nhc2/nhccoco/devices/electricity_clamp_centralmeter.py b/custom_components/nhc2/nhccoco/devices/electricity_clamp_centralmeter.py index 2a6df07a..656aa90b 100644 --- a/custom_components/nhc2/nhccoco/devices/electricity_clamp_centralmeter.py +++ b/custom_components/nhc2/nhccoco/devices/electricity_clamp_centralmeter.py @@ -63,8 +63,8 @@ def on_change(self, topic: str, payload: dict): callback() def enable_report_instant_usage(self, gateway): - gateway._add_device_control( - self._device.uuid, + gateway.add_device_control( + self.uuid, PROPERTY_REPORT_INSTANT_USAGE, PROPERTY_REPORT_INSTANT_USAGE_VALUE_TRUE ) diff --git a/custom_components/nhc2/nhccoco/devices/fan_action.py b/custom_components/nhc2/nhccoco/devices/fan_action.py index 11e21f91..2da8c6a5 100644 --- a/custom_components/nhc2/nhccoco/devices/fan_action.py +++ b/custom_components/nhc2/nhccoco/devices/fan_action.py @@ -32,8 +32,8 @@ def on_change(self, topic: str, payload: dict): callback() def set_fan_speed(self, gateway, speed: str): - gateway._add_device_control( - self._device.uuid, + gateway.add_device_control( + self.uuid, PROPERTY_FAN_SPEED, speed ) diff --git a/custom_components/nhc2/nhccoco/devices/garagedoor_action.py b/custom_components/nhc2/nhccoco/devices/garagedoor_action.py index 04baa706..e9c62030 100644 --- a/custom_components/nhc2/nhccoco/devices/garagedoor_action.py +++ b/custom_components/nhc2/nhccoco/devices/garagedoor_action.py @@ -42,8 +42,8 @@ def on_change(self, topic: str, payload: dict): callback() def trigger(self, gateway): - gateway._add_device_control( - self._device.uuid, + gateway.add_device_control( + self.uuid, PROPERTY_BASIC_STATE, PROPERTY_BASIC_STATE_VALUE_TRIGGERED ) diff --git a/custom_components/nhc2/nhccoco/devices/generic_energyhome.py b/custom_components/nhc2/nhccoco/devices/generic_energyhome.py index 373104cf..3c9e5f68 100644 --- a/custom_components/nhc2/nhccoco/devices/generic_energyhome.py +++ b/custom_components/nhc2/nhccoco/devices/generic_energyhome.py @@ -51,8 +51,8 @@ def on_change(self, topic: str, payload: dict): callback() def enable_report_instant_usage(self, gateway): - gateway._add_device_control( - self._device.uuid, + gateway.add_device_control( + self.uuid, PROPERTY_REPORT_INSTANT_USAGE, PROPERTY_REPORT_INSTANT_USAGE_VALUE_TRUE ) diff --git a/custom_components/nhc2/nhccoco/devices/hvacthermostat_hvac.py b/custom_components/nhc2/nhccoco/devices/hvacthermostat_hvac.py index 1415eeda..255f6903 100644 --- a/custom_components/nhc2/nhccoco/devices/hvacthermostat_hvac.py +++ b/custom_components/nhc2/nhccoco/devices/hvacthermostat_hvac.py @@ -125,71 +125,71 @@ def on_change(self, topic: str, payload: dict): callback() def set_program(self, gateway, program: str): - gateway._add_device_control(self._device.uuid, PROPERTY_PROGRAM, program) + gateway.add_device_control(self.uuid, PROPERTY_PROGRAM, program) def set_temperature(self, gateway, temperature: float): - gateway._add_device_control(self._device.uuid, PROPERTY_OVERRULE_SETPOINT, str(temperature)) - gateway._add_device_control(self._device.uuid, PROPERTY_OVERRULE_TIME, '240') - gateway._add_device_control(self._device.uuid, PROPERTY_OVERRULE_ACTIVE, 'True') + gateway.add_device_control(self.uuid, PROPERTY_OVERRULE_SETPOINT, str(temperature)) + gateway.add_device_control(self.uuid, PROPERTY_OVERRULE_TIME, '240') + gateway.add_device_control(self.uuid, PROPERTY_OVERRULE_ACTIVE, 'True') def set_operation_mode(self, gateway, operation_mode: str): - gateway._add_device_control(self._device.uuid, PROPERTY_OPERATION_MODE, operation_mode) + gateway.add_device_control(self.uuid, PROPERTY_OPERATION_MODE, operation_mode) def set_fan_speed(self, gateway, fan_speed: str): - gateway._add_device_control(self._device.uuid, PROPERTY_FAN_SPEED, fan_speed) + gateway.add_device_control(self.uuid, PROPERTY_FAN_SPEED, fan_speed) def set_overrule_active(self, gateway, active: bool): if active: - gateway._add_device_control( - self._device.uuid, + gateway.add_device_control( + self.uuid, PROPERTY_OVERRULE_ACTIVE, PROPERTY_OVERRULE_ACTIVE_VALUE_TRUE ) else: - gateway._add_device_control( - self._device.uuid, + gateway.add_device_control( + self.uuid, PROPERTY_OVERRULE_ACTIVE, PROPERTY_OVERRULE_ACTIVE_VALUE_FALSE ) def set_ecosave(self, gateway, active: bool): if active: - gateway._add_device_control( - self._device.uuid, + gateway.add_device_control( + self.uuid, PROPERTY_ECOSAVE, PROPERTY_ECOSAVE_VALUE_TRUE ) else: - gateway._add_device_control( - self._device.uuid, + gateway.add_device_control( + self.uuid, PROPERTY_ECOSAVE, PROPERTY_ECOSAVE_VALUE_FALSE ) def set_protect_mode(self, gateway, active: bool): if active: - gateway._add_device_control( - self._device.uuid, + gateway.add_device_control( + self.uuid, PROPERTY_PROTECT_MODE, PROPERTY_PROTECT_MODE_VALUE_TRUE ) else: - gateway._add_device_control( - self._device.uuid, + gateway.add_device_control( + self.uuid, PROPERTY_PROTECT_MODE, PROPERTY_PROTECT_MODE_VALUE_FALSE ) def set_thermostat_on(self, gateway, active: bool): if active: - gateway._add_device_control( - self._device.uuid, + gateway.add_device_control( + self.uuid, PROPERTY_THERMOSTAT_ON, PROPERTY_THERMOSTAT_ON_VALUE_TRUE ) else: - gateway._add_device_control( - self._device.uuid, + gateway.add_device_control( + self.uuid, PROPERTY_THERMOSTAT_ON, PROPERTY_THERMOSTAT_ON_VALUE_FALSE ) diff --git a/custom_components/nhc2/nhccoco/devices/motor_action.py b/custom_components/nhc2/nhccoco/devices/motor_action.py index 3fe8fa84..8c1313ef 100644 --- a/custom_components/nhc2/nhccoco/devices/motor_action.py +++ b/custom_components/nhc2/nhccoco/devices/motor_action.py @@ -39,15 +39,15 @@ def on_change(self, topic: str, payload: dict): callback() def set_action(self, gateway, action: str): - gateway._add_device_control( - self._device.uuid, + gateway.add_device_control( + self.uuid, PROPERTY_ACTION, action ) def set_position(self, gateway, position: int): - gateway._add_device_control( - self._device.uuid, + gateway.add_device_control( + self.uuid, PROPERTY_POSITION, position ) diff --git a/custom_components/nhc2/nhccoco/devices/naso_smartplug.py b/custom_components/nhc2/nhccoco/devices/naso_smartplug.py index c680b9f7..5c3cf983 100644 --- a/custom_components/nhc2/nhccoco/devices/naso_smartplug.py +++ b/custom_components/nhc2/nhccoco/devices/naso_smartplug.py @@ -36,8 +36,8 @@ def on_change(self, topic: str, payload: dict): callback() def enable_report_instant_usage(self, gateway): - gateway._add_device_control( - self._device.uuid, + gateway.add_device_control( + self.uuid, PROPERTY_REPORT_INSTANT_USAGE, PROPERTY_REPORT_INSTANT_USAGE_VALUE_TRUE ) diff --git a/custom_components/nhc2/nhccoco/devices/relay_action.py b/custom_components/nhc2/nhccoco/devices/relay_action.py index 32e5a483..4e9637d2 100644 --- a/custom_components/nhc2/nhccoco/devices/relay_action.py +++ b/custom_components/nhc2/nhccoco/devices/relay_action.py @@ -21,7 +21,7 @@ def on_change(self, topic: str, payload: dict): callback() def turn_on(self, gateway): - gateway._add_device_control(self.uuid, PROPERTY_STATUS, PROPERTY_STATUS_VALUE_ON) + gateway.add_device_control(self.uuid, PROPERTY_STATUS, PROPERTY_STATUS_VALUE_ON) def turn_off(self, gateway): - gateway._add_device_control(self.uuid, PROPERTY_STATUS, PROPERTY_STATUS_VALUE_OFF) + gateway.add_device_control(self.uuid, PROPERTY_STATUS, PROPERTY_STATUS_VALUE_OFF) diff --git a/custom_components/nhc2/nhccoco/devices/thermostat_hvac.py b/custom_components/nhc2/nhccoco/devices/thermostat_hvac.py index 704f73ff..4f8fa0f6 100644 --- a/custom_components/nhc2/nhccoco/devices/thermostat_hvac.py +++ b/custom_components/nhc2/nhccoco/devices/thermostat_hvac.py @@ -88,41 +88,41 @@ def on_change(self, topic: str, payload: dict): callback() def set_program(self, gateway, program: str): - gateway._add_device_control( - self._device.uuid, + gateway.add_device_control( + self.uuid, PROPERTY_PROGRAM, program ) def set_temperature(self, gateway, temperature: float): - gateway._add_device_control(self._device.uuid, PROPERTY_OVERRULE_SETPOINT, str(temperature)) - gateway._add_device_control(self._device.uuid, PROPERTY_OVERRULE_TIME, '240') - gateway._add_device_control(self._device.uuid, PROPERTY_OVERRULE_ACTIVE, PROPERTY_OVERRULE_ACTIVE_VALUE_TRUE) + gateway.add_device_control(self.uuid, PROPERTY_OVERRULE_SETPOINT, str(temperature)) + gateway.add_device_control(self.uuid, PROPERTY_OVERRULE_TIME, '240') + gateway.add_device_control(self.uuid, PROPERTY_OVERRULE_ACTIVE, PROPERTY_OVERRULE_ACTIVE_VALUE_TRUE) def set_overrule_active(self, gateway, active: bool): if active: - gateway._add_device_control( - self._device.uuid, + gateway.add_device_control( + self.uuid, PROPERTY_OVERRULE_ACTIVE, PROPERTY_OVERRULE_ACTIVE_VALUE_TRUE ) else: - gateway._add_device_control( - self._device.uuid, + gateway.add_device_control( + self.uuid, PROPERTY_OVERRULE_ACTIVE, PROPERTY_OVERRULE_ACTIVE_VALUE_FALSE ) def set_ecosave(self, gateway, active: bool): if active: - gateway._add_device_control( - self._device.uuid, + gateway.add_device_control( + self.uuid, PROPERTY_ECOSAVE, PROPERTY_ECOSAVE_VALUE_TRUE ) else: - gateway._add_device_control( - self._device.uuid, + gateway.add_device_control( + self.uuid, PROPERTY_ECOSAVE, PROPERTY_ECOSAVE_VALUE_FALSE ) diff --git a/custom_components/nhc2/nhccoco/helpers.py b/custom_components/nhc2/nhccoco/helpers.py index 3f2fde5a..d3c6d5e6 100755 --- a/custom_components/nhc2/nhccoco/helpers.py +++ b/custom_components/nhc2/nhccoco/helpers.py @@ -1,19 +1,56 @@ -from .const import KEY_DEVICES, KEY_PARAMS, KEY_PROPERTIES, KEY_UUID, KEY_METHOD, MQTT_METHOD_DEVICES_CONTROL +from .const import MQTT_DATA_PARAMS, MQTT_DATA_PARAMS_DEVICES, MQTT_DATA_PARAMS_DEVICES_PROPERTIES, \ + MQTT_DATA_PARAMS_DEVICES_UUID, MQTT_DATA_METHOD, MQTT_DATA_METHOD_DEVICES_CONTROL, MQTT_DATA_PARAMS, \ + MQTT_DATA_PARAMS_SYSTEMINFO, MQTT_DATA_PARAMS_SYSTEMINFO_SWVERSIONS, \ + MQTT_DATA_PARAMS_SYSTEMINFO_SWVERSIONS_COCO_IMAGE, MQTT_DATA_PARAMS_SYSTEMINFO_SWVERSIONS_NHC_VERSION import logging _LOGGER = logging.getLogger(__name__) +def extract_versions(nhc2_sysinfo): + """Return the versions, extracted from sysinfo.""" + params = nhc2_sysinfo[MQTT_DATA_PARAMS] + system_info = next( + filter( + (lambda x: x and MQTT_DATA_PARAMS_SYSTEMINFO in x), + params + ), None + )[MQTT_DATA_PARAMS_SYSTEMINFO] + + s_w_versions = next( + filter( + (lambda x: x and MQTT_DATA_PARAMS_SYSTEMINFO_SWVERSIONS in x), + system_info + ), None + )[MQTT_DATA_PARAMS_SYSTEMINFO_SWVERSIONS] + + coco_image = next( + filter( + (lambda x: x and MQTT_DATA_PARAMS_SYSTEMINFO_SWVERSIONS_COCO_IMAGE in x), + s_w_versions + ), None + )[MQTT_DATA_PARAMS_SYSTEMINFO_SWVERSIONS_COCO_IMAGE] + + nhc_version = next( + filter( + (lambda x: x and MQTT_DATA_PARAMS_SYSTEMINFO_SWVERSIONS_NHC_VERSION in x), + s_w_versions + ), None + )[MQTT_DATA_PARAMS_SYSTEMINFO_SWVERSIONS_NHC_VERSION] + + return coco_image, nhc_version + + def extract_devices(response): - params = response[KEY_PARAMS] - param_with_devices = next(filter((lambda x: x and KEY_DEVICES in x), params), None) - return param_with_devices[KEY_DEVICES] + params = response[MQTT_DATA_PARAMS] + param_with_devices = next(filter((lambda x: x and MQTT_DATA_PARAMS_DEVICES in x), params), None) + return param_with_devices[MQTT_DATA_PARAMS_DEVICES] def extract_property_value_from_device(device, property_key): - if device and KEY_PROPERTIES in device: - properties = device[KEY_PROPERTIES] + if device and MQTT_DATA_PARAMS_DEVICES_PROPERTIES in device: + properties = device[MQTT_DATA_PARAMS_DEVICES_PROPERTIES] if properties: property_object = next(filter((lambda x: x and property_key in x), properties), None) if property_object and property_key in property_object: @@ -37,14 +74,14 @@ def dev_prop_changed(field, dev, prop): def process_device_commands(device_commands_to_process): devices = [] for uuid, properties in device_commands_to_process.items(): - device = {KEY_UUID: uuid, KEY_PROPERTIES: []} + device = {MQTT_DATA_PARAMS_DEVICES_UUID: uuid, MQTT_DATA_PARAMS_DEVICES_PROPERTIES: []} for property_key, property_value in properties.items(): - device[KEY_PROPERTIES].append({property_key: property_value}) + device[MQTT_DATA_PARAMS_DEVICES_PROPERTIES].append({property_key: property_value}) devices.append(device) return { - KEY_METHOD: MQTT_METHOD_DEVICES_CONTROL, - KEY_PARAMS: [{ - KEY_DEVICES: devices + MQTT_DATA_METHOD: MQTT_DATA_METHOD_DEVICES_CONTROL, + MQTT_DATA_PARAMS: [{ + MQTT_DATA_PARAMS_DEVICES: devices }] } @@ -57,6 +94,8 @@ def to_float_or_none(value) -> float | None: if value is None or value == '': return None return float(value) + + def to_int_or_none(value) -> float | None: if value is None or value == '': return None diff --git a/custom_components/nhc2/sensor.py b/custom_components/nhc2/sensor.py index ed2f3692..11539260 100644 --- a/custom_components/nhc2/sensor.py +++ b/custom_components/nhc2/sensor.py @@ -35,7 +35,6 @@ from .const import DOMAIN, KEY_GATEWAY -KEY_GATEWAY = KEY_GATEWAY KEY_ENTITY = 'nhc2_sensors' _LOGGER = logging.getLogger(__name__) diff --git a/custom_components/nhc2/switch.py b/custom_components/nhc2/switch.py index 46f5f703..4f8fc6cd 100644 --- a/custom_components/nhc2/switch.py +++ b/custom_components/nhc2/switch.py @@ -21,7 +21,6 @@ from .const import DOMAIN, KEY_GATEWAY -KEY_GATEWAY = KEY_GATEWAY KEY_ENTITY = 'nhc2_switches' _LOGGER = logging.getLogger(__name__) diff --git a/discover_test.py b/discover_test.py index 09d86bb1..dbf98230 100644 --- a/discover_test.py +++ b/discover_test.py @@ -1,3 +1,4 @@ +"""Script to detect NHC2 controller on the network.""" import socket from time import sleep