From 1ba71f5dbfe6ea5dab0e43adff0a6728813aac6f Mon Sep 17 00:00:00 2001 From: dloveall Date: Tue, 6 Dec 2022 09:23:09 -0500 Subject: [PATCH 1/7] Fix Outlet Autodiscover Need to use deviceId, not childId --- custom_components/hubspace/light.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/custom_components/hubspace/light.py b/custom_components/hubspace/light.py index 5c1ed85..6f3813d 100644 --- a/custom_components/hubspace/light.py +++ b/custom_components/hubspace/light.py @@ -157,7 +157,7 @@ def setup_platform( elif deviceClass == 'light' or deviceClass == 'switch': entities.append(HubspaceLight(hs, friendlyName, debug, childId, model, deviceId, deviceClass)) elif deviceClass == 'power-outlet': - for toggle in hs.getFunctions(childId, 'toggle'): + for toggle in hs.getFunctions(deviceId, 'toggle'): try: _LOGGER.debug(f"Found toggle with id {toggle.get('id')} and instance {toggle.get('functionInstance')}") outletIndex = toggle.get('functionInstance').split('-')[1] @@ -165,7 +165,7 @@ def setup_platform( except IndexError: _LOGGER.debug('Error extracting outlet index') elif deviceClass == 'landscape-transformer': - for toggle in hs.getFunctions(childId, 'toggle'): + for toggle in hs.getFunctions(deviceId, 'toggle'): try: _LOGGER.debug(f"Found toggle with id {toggle.get('id')} and instance {toggle.get('functionInstance')}") outletIndex = toggle.get('functionInstance').split('-')[1] From 9943890f25e19913fae58bab0d521c9fd01d91fb Mon Sep 17 00:00:00 2001 From: dloveall Date: Tue, 6 Dec 2022 17:16:10 -0500 Subject: [PATCH 2/7] Use id instead of deviceId for getFunctions --- custom_components/hubspace/hubspace.py | 4 ++-- custom_components/hubspace/light.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/custom_components/hubspace/hubspace.py b/custom_components/hubspace/hubspace.py index 67d0e30..a965c41 100644 --- a/custom_components/hubspace/hubspace.py +++ b/custom_components/hubspace/hubspace.py @@ -273,11 +273,11 @@ def discoverDeviceIds(self): friendlyName = lis.get('friendlyName') yield child, model, deviceId, deviceClass, friendlyName - def getFunctions(self, deviceId, functionClass): + def getFunctions(self, id, functionClass): response = self.getMetadeviceInfo() for lis in response.json(): - if lis.get('deviceId') == deviceId: + if lis.get('id') == id: for function in lis.get('description', {}).get('functions', []): if function.get('functionClass') == functionClass: yield function diff --git a/custom_components/hubspace/light.py b/custom_components/hubspace/light.py index 6f3813d..c2cfdb5 100644 --- a/custom_components/hubspace/light.py +++ b/custom_components/hubspace/light.py @@ -157,7 +157,7 @@ def setup_platform( elif deviceClass == 'light' or deviceClass == 'switch': entities.append(HubspaceLight(hs, friendlyName, debug, childId, model, deviceId, deviceClass)) elif deviceClass == 'power-outlet': - for toggle in hs.getFunctions(deviceId, 'toggle'): + for toggle in hs.getFunctions(childId, 'toggle'): try: _LOGGER.debug(f"Found toggle with id {toggle.get('id')} and instance {toggle.get('functionInstance')}") outletIndex = toggle.get('functionInstance').split('-')[1] @@ -165,7 +165,7 @@ def setup_platform( except IndexError: _LOGGER.debug('Error extracting outlet index') elif deviceClass == 'landscape-transformer': - for toggle in hs.getFunctions(deviceId, 'toggle'): + for toggle in hs.getFunctions(childId, 'toggle'): try: _LOGGER.debug(f"Found toggle with id {toggle.get('id')} and instance {toggle.get('functionInstance')}") outletIndex = toggle.get('functionInstance').split('-')[1] @@ -250,7 +250,7 @@ def __init__(self, hs, friendlyname, debug, childId = None, model = None, device self._supported_color_modes.extend([ColorMode.BRIGHTNESS]) self._temperature_suffix = 'K' self._temperature_choices = [] - for colorTemperature in self._hs.getFunctions(self._deviceId, 'color-temperature'): + for colorTemperature in self._hs.getFunctions(self._childId, 'color-temperature'): for value in colorTemperature.get('values'): temperatureName = value.get('name') if isinstance(temperatureName, str) and temperatureName.endswith(self._temperature_suffix): From 0b9cb9f2cf790595a1d2a4ac07a4d0b02016ac91 Mon Sep 17 00:00:00 2001 From: dloveall Date: Tue, 6 Dec 2022 17:52:54 -0500 Subject: [PATCH 3/7] Single Discovery API Call Replace the use of hs.getFunctions() with a return of the functions from hs.discoverDeviceIds(). This results in a single call to the API during automatic device discovery. --- custom_components/hubspace/hubspace.py | 3 +- custom_components/hubspace/light.py | 61 ++++++++++++++------------ 2 files changed, 35 insertions(+), 29 deletions(-) diff --git a/custom_components/hubspace/hubspace.py b/custom_components/hubspace/hubspace.py index a965c41..f8c1d2a 100644 --- a/custom_components/hubspace/hubspace.py +++ b/custom_components/hubspace/hubspace.py @@ -271,7 +271,8 @@ def discoverDeviceIds(self): model = lis.get('description', {}).get('device', {}).get('model') deviceClass = lis.get('description', {}).get('device', {}).get('deviceClass') friendlyName = lis.get('friendlyName') - yield child, model, deviceId, deviceClass, friendlyName + functions = lis.get('description', {}).get('functions', []) + yield child, model, deviceId, deviceClass, friendlyName, functions def getFunctions(self, id, functionClass): response = self.getMetadeviceInfo() diff --git a/custom_components/hubspace/light.py b/custom_components/hubspace/light.py index c2cfdb5..a628266 100644 --- a/custom_components/hubspace/light.py +++ b/custom_components/hubspace/light.py @@ -145,33 +145,36 @@ def setup_platform( if config.get(CONF_FRIENDLYNAMES) == [] and config.get(CONF_ROOMNAMES) == []: _LOGGER.debug('Attempting automatic discovery') - for [childId, model, deviceId, deviceClass, friendlyName] in hs.discoverDeviceIds(): + for [childId, model, deviceId, deviceClass, friendlyName, functions] in hs.discoverDeviceIds(): _LOGGER.debug("childId " + childId ) _LOGGER.debug("Switch on Model " + model ) _LOGGER.debug("deviceId: " + deviceId ) _LOGGER.debug("deviceClass: " + deviceClass ) _LOGGER.debug("friendlyName: " + friendlyName ) + _LOGGER.debug("functions: " + functions ) if deviceClass == 'fan': entities.append(HubspaceFan(hs, friendlyName, debug, childId, model, deviceId, deviceClass)) elif deviceClass == 'light' or deviceClass == 'switch': - entities.append(HubspaceLight(hs, friendlyName, debug, childId, model, deviceId, deviceClass)) + entities.append(HubspaceLight(hs, friendlyName, debug, childId, model, deviceId, deviceClass, functions)) elif deviceClass == 'power-outlet': - for toggle in hs.getFunctions(childId, 'toggle'): - try: - _LOGGER.debug(f"Found toggle with id {toggle.get('id')} and instance {toggle.get('functionInstance')}") - outletIndex = toggle.get('functionInstance').split('-')[1] - entities.append(HubspaceOutlet(hs, friendlyName, outletIndex, debug, childId, model, deviceId, deviceClass)) - except IndexError: - _LOGGER.debug('Error extracting outlet index') + for function in functions: + if function.get('functionClass') == 'toggle': + try: + _LOGGER.debug(f"Found toggle with id {function.get('id')} and instance {function.get('functionInstance')}") + outletIndex = function.get('functionInstance').split('-')[1] + entities.append(HubspaceOutlet(hs, friendlyName, outletIndex, debug, childId, model, deviceId, deviceClass)) + except IndexError: + _LOGGER.debug('Error extracting outlet index') elif deviceClass == 'landscape-transformer': - for toggle in hs.getFunctions(childId, 'toggle'): - try: - _LOGGER.debug(f"Found toggle with id {toggle.get('id')} and instance {toggle.get('functionInstance')}") - outletIndex = toggle.get('functionInstance').split('-')[1] - entities.append(HubspaceTransformer(hs, friendlyName, outletIndex, debug, childId, model, deviceId, deviceClass)) - except IndexError: - _LOGGER.debug('Error extracting outlet index') + for function in functions: + if function.get('functionClass') == 'toggle': + try: + _LOGGER.debug(f"Found toggle with id {function.get('id')} and instance {function.get('functionInstance')}") + outletIndex = function.get('functionInstance').split('-')[1] + entities.append(HubspaceTransformer(hs, friendlyName, outletIndex, debug, childId, model, deviceId, deviceClass)) + except IndexError: + _LOGGER.debug('Error extracting outlet index') if not entities: return @@ -192,7 +195,7 @@ def setup_platform( class HubspaceLight(LightEntity): """Representation of an Awesome Light.""" - def __init__(self, hs, friendlyname, debug, childId = None, model = None, deviceId = None, deviceClass = None) -> None: + def __init__(self, hs, friendlyname, debug, childId = None, model = None, deviceId = None, deviceClass = None, functions = None) -> None: """Initialize an AwesomeLight.""" _LOGGER.debug("Light Name: " ) @@ -250,17 +253,19 @@ def __init__(self, hs, friendlyname, debug, childId = None, model = None, device self._supported_color_modes.extend([ColorMode.BRIGHTNESS]) self._temperature_suffix = 'K' self._temperature_choices = [] - for colorTemperature in self._hs.getFunctions(self._childId, 'color-temperature'): - for value in colorTemperature.get('values'): - temperatureName = value.get('name') - if isinstance(temperatureName, str) and temperatureName.endswith(self._temperature_suffix): - try: - temperatureValue = int(temperatureName[:-len(self._temperature_suffix)]) - except ValueError: - _LOGGER.debug(f"Can't convert temperatureName {temperatureName} to int") - temperatureValue = None - if temperatureValue is not None and temperatureValue not in self._temperature_choices: - self._temperature_choices.append(temperatureValue) + if functions is not None: + for function in functions: + if function.get('functionClass') == 'color-temperature': + for value in function.get('values'): + temperatureName = value.get('name') + if isinstance(temperatureName, str) and temperatureName.endswith(self._temperature_suffix): + try: + temperatureValue = int(temperatureName[:-len(self._temperature_suffix)]) + except ValueError: + _LOGGER.debug(f"Can't convert temperatureName {temperatureName} to int") + temperatureValue = None + if temperatureValue is not None and temperatureValue not in self._temperature_choices: + self._temperature_choices.append(temperatureValue) if len(self._temperature_choices): self._supported_color_modes.extend([ColorMode.COLOR_TEMP, ColorMode.WHITE]) self._max_mireds = 1000000//min(self._temperature_choices) + 1 From 510c172634557b4ed94f52e402c6d7f57ad5d202 Mon Sep 17 00:00:00 2001 From: dloveall Date: Tue, 6 Dec 2022 18:04:42 -0500 Subject: [PATCH 4/7] Functions to str for debug --- custom_components/hubspace/light.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/hubspace/light.py b/custom_components/hubspace/light.py index a628266..e4ddf2e 100644 --- a/custom_components/hubspace/light.py +++ b/custom_components/hubspace/light.py @@ -151,7 +151,7 @@ def setup_platform( _LOGGER.debug("deviceId: " + deviceId ) _LOGGER.debug("deviceClass: " + deviceClass ) _LOGGER.debug("friendlyName: " + friendlyName ) - _LOGGER.debug("functions: " + functions ) + _LOGGER.debug("functions: " + str(functions)) if deviceClass == 'fan': entities.append(HubspaceFan(hs, friendlyName, debug, childId, model, deviceId, deviceClass)) From af83ac452f5b90e0d076e84c3a9bf412a637f737 Mon Sep 17 00:00:00 2001 From: dloveall Date: Tue, 6 Dec 2022 18:50:03 -0500 Subject: [PATCH 5/7] Remove True from add_entities --- custom_components/hubspace/light.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/hubspace/light.py b/custom_components/hubspace/light.py index e4ddf2e..7276353 100644 --- a/custom_components/hubspace/light.py +++ b/custom_components/hubspace/light.py @@ -178,7 +178,7 @@ def setup_platform( if not entities: return - add_entities(entities, True) + add_entities(entities) # platform = self.platform From 54097c84eb19cec75d1109f21b8a5544d64a97eb Mon Sep 17 00:00:00 2001 From: dloveall Date: Tue, 6 Dec 2022 19:19:40 -0500 Subject: [PATCH 6/7] Color temperature when not autodiscover Add back in the functionality to automatically discover color temperature when lights are manually defined. --- custom_components/hubspace/hubspace.py | 7 +++++-- custom_components/hubspace/light.py | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/custom_components/hubspace/hubspace.py b/custom_components/hubspace/hubspace.py index f8c1d2a..87674a9 100644 --- a/custom_components/hubspace/hubspace.py +++ b/custom_components/hubspace/hubspace.py @@ -274,12 +274,15 @@ def discoverDeviceIds(self): functions = lis.get('description', {}).get('functions', []) yield child, model, deviceId, deviceClass, friendlyName, functions - def getFunctions(self, id, functionClass): + def getFunctions(self, id, functionClass = None): response = self.getMetadeviceInfo() for lis in response.json(): if lis.get('id') == id: - for function in lis.get('description', {}).get('functions', []): + functions = lis.get('description', {}).get('functions', []) + if functionClass is None: + return functions + for function in functions: if function.get('functionClass') == functionClass: yield function diff --git a/custom_components/hubspace/light.py b/custom_components/hubspace/light.py index 7276353..736fbf1 100644 --- a/custom_components/hubspace/light.py +++ b/custom_components/hubspace/light.py @@ -223,6 +223,8 @@ def __init__(self, hs, friendlyname, debug, childId = None, model = None, device self._temperature_suffix = None if None in (childId, model, deviceId, deviceClass): [self._childId, self._model, self._deviceId, deviceClass] = self._hs.getChildId(self._name) + if functions is None: + functions = self._hs.getFunctions(self._childId) self._supported_color_modes = [] From cf6bf97e3fd25af49c186e9ebc7f5276a9754e91 Mon Sep 17 00:00:00 2001 From: dloveall Date: Tue, 6 Dec 2022 19:28:36 -0500 Subject: [PATCH 7/7] functions is now defined --- custom_components/hubspace/light.py | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/custom_components/hubspace/light.py b/custom_components/hubspace/light.py index 736fbf1..b2be154 100644 --- a/custom_components/hubspace/light.py +++ b/custom_components/hubspace/light.py @@ -255,19 +255,18 @@ def __init__(self, hs, friendlyname, debug, childId = None, model = None, device self._supported_color_modes.extend([ColorMode.BRIGHTNESS]) self._temperature_suffix = 'K' self._temperature_choices = [] - if functions is not None: - for function in functions: - if function.get('functionClass') == 'color-temperature': - for value in function.get('values'): - temperatureName = value.get('name') - if isinstance(temperatureName, str) and temperatureName.endswith(self._temperature_suffix): - try: - temperatureValue = int(temperatureName[:-len(self._temperature_suffix)]) - except ValueError: - _LOGGER.debug(f"Can't convert temperatureName {temperatureName} to int") - temperatureValue = None - if temperatureValue is not None and temperatureValue not in self._temperature_choices: - self._temperature_choices.append(temperatureValue) + for function in functions: + if function.get('functionClass') == 'color-temperature': + for value in function.get('values'): + temperatureName = value.get('name') + if isinstance(temperatureName, str) and temperatureName.endswith(self._temperature_suffix): + try: + temperatureValue = int(temperatureName[:-len(self._temperature_suffix)]) + except ValueError: + _LOGGER.debug(f"Can't convert temperatureName {temperatureName} to int") + temperatureValue = None + if temperatureValue is not None and temperatureValue not in self._temperature_choices: + self._temperature_choices.append(temperatureValue) if len(self._temperature_choices): self._supported_color_modes.extend([ColorMode.COLOR_TEMP, ColorMode.WHITE]) self._max_mireds = 1000000//min(self._temperature_choices) + 1