From 45a30241cfc429f4ddebde4337157e50f1d46b29 Mon Sep 17 00:00:00 2001 From: vlebourl Date: Mon, 29 Jun 2020 08:47:51 +0200 Subject: [PATCH 1/8] [Refactor] Add helper functions select_command and select_state. Add two functions to select first existing command or state from a list. Implement in cover.py --- custom_components/tahoma/cover.py | 101 ++++++---------------- custom_components/tahoma/tahoma_device.py | 20 ++++- 2 files changed, 46 insertions(+), 75 deletions(-) diff --git a/custom_components/tahoma/cover.py b/custom_components/tahoma/cover.py index 0fc4040a3..f8db90667 100644 --- a/custom_components/tahoma/cover.py +++ b/custom_components/tahoma/cover.py @@ -187,15 +187,16 @@ def set_cover_position(self, **kwargs): # HorizontalAwning devices need a reversed position that can not be obtained via the API if "Horizontal" in self.tahoma_device.widget: position = kwargs.get(ATTR_POSITION, 0) - - if COMMAND_SET_POSITION in self.tahoma_device.command_definitions: - return self.apply_action(COMMAND_SET_POSITION, position) - - if COMMAND_SET_CLOSURE in self.tahoma_device.command_definitions: - return self.apply_action(COMMAND_SET_CLOSURE, position) - - if COMMAND_SET_PEDESTRIAN_POSITION in self.tahoma_device.command_definitions: - return self.apply_action(COMMAND_SET_PEDESTRIAN_POSITION, position) + self.apply_action( + self.select_command( + [ + COMMAND_SET_POSITION, + COMMAND_SET_CLOSURE, + COMMAND_SET_PEDESTRIAN_POSITION, + ] + ), + position, + ) def set_cover_tilt_position(self, **kwargs): """Move the cover tilt to a specific position.""" @@ -206,35 +207,17 @@ def set_cover_tilt_position(self, **kwargs): @property def is_closed(self): """Return if the cover is closed.""" - - if "core:OpenClosedState" in self.tahoma_device.active_states: - return ( - self.tahoma_device.active_states.get("core:OpenClosedState") == "closed" - ) - - if "core:SlatsOpenClosedState" in self.tahoma_device.active_states: - return ( - self.tahoma_device.active_states.get("core:SlatsOpenClosedState") - == "closed" - ) - - if "core:OpenClosedPartialState" in self.tahoma_device.active_states: - return ( - self.tahoma_device.active_states.get("core:OpenClosedPartialState") - == "closed" - ) - - if "core:OpenClosedPedestrianState" in self.tahoma_device.active_states: - return ( - self.tahoma_device.active_states.get("core:OpenClosedPedestrianState") - == "closed" - ) - - if "core:OpenClosedUnknownState" in self.tahoma_device.active_states: - return ( - self.tahoma_device.active_states.get("core:OpenClosedUnknownState") - == "closed" - ) + state = self.select_state( + [ + "core:OpenClosedState", + "core:SlatsOpenClosedState", + "core:OpenClosedPartialState", + "core:OpenClosedPedestrianState", + "core:OpenClosedUnknownState", + ] + ) + if state is not None: + return state == "closed" if getattr(self, "_position", None) is not None: return self._position == 0 @@ -290,57 +273,27 @@ def icon(self): def open_cover(self, **kwargs): """Open the cover.""" - - if "open" in self.tahoma_device.command_definitions: - return self.apply_action("open") - - if "up" in self.tahoma_device.command_definitions: - return self.apply_action("up") + self.apply_action(self.select_command(["open", "up"])) def open_cover_tilt(self, **kwargs): """Open the cover tilt.""" - - if "openSlats" in self.tahoma_device.command_definitions: - return self.apply_action("openSlats") + self.apply_action(self.select_command(["openSlats"])) def close_cover(self, **kwargs): """Close the cover.""" - - if "close" in self.tahoma_device.command_definitions: - return self.apply_action("close") - - if "down" in self.tahoma_device.command_definitions: - return self.apply_action("down") + self.apply_action(self.select_command(["close", "down"])) def close_cover_tilt(self, **kwargs): """Close the cover tilt.""" - - if "closeSlats" in self.tahoma_device.command_definitions: - return self.apply_action("closeSlats") + self.apply_action(self.select_command(["closeSlats"])) def stop_cover(self, **kwargs): """Stop the cover.""" - - if "stop" in self.tahoma_device.command_definitions: - return self.apply_action("stop") - - if "stopIdentify" in self.tahoma_device.command_definitions: - return self.apply_action("stopIdentify") - - if "my" in self.tahoma_device.command_definitions: - return self.apply_action("my") + self.apply_action(self.select_command(["stop", "stopIdentify", "my"])) def stop_cover_tilt(self, **kwargs): """Stop the cover.""" - - if "stopIdentify" in self.tahoma_device.command_definitions: - return self.apply_action("stopIdentify") - - if "stop" in self.tahoma_device.command_definitions: - return self.apply_action("stop") - - if "my" in self.tahoma_device.command_definitions: - return self.apply_action("my") + self.apply_action(self.select_command(["stopIdentify", "stop", "my"])) @property def supported_features(self): diff --git a/custom_components/tahoma/tahoma_device.py b/custom_components/tahoma/tahoma_device.py index 7471345f9..1ac33f900 100644 --- a/custom_components/tahoma/tahoma_device.py +++ b/custom_components/tahoma/tahoma_device.py @@ -113,13 +113,31 @@ def device_info(self): "sw_version": self.tahoma_device.type, } + def select_command(self, commands): + """Select first existing command in a list of commands.""" + return next( + (c for c in self.tahoma_device.command_definitions if c in commands), None + ) + + def select_state(self, active_states): + """Select first existing active state in a list of states.""" + return next( + ( + v + for k, v in self.tahoma_device.active_states.items() + if k in active_states + ), + None, + ) + async def async_apply_action(self, cmd_name, *args): """Apply Action to Device in async context.""" await self.hass.async_add_executor_job(self.apply_action, cmd_name, *args) def apply_action(self, cmd_name, *args): """Apply Action to Device.""" - + if cmd_name is None: + raise NotImplementedError action = Action(self.tahoma_device.url) action.add_command(cmd_name, *args) exec_id = self.controller.apply_actions("HomeAssistant", [action]) From 69ffcf312661629fb7ffa5dca16a87e51d2ff6d5 Mon Sep 17 00:00:00 2001 From: vlebourl Date: Mon, 29 Jun 2020 08:58:40 +0200 Subject: [PATCH 2/8] [WIP] Use async apply action to prevent sequential execution. Related Github issues: #91 --- custom_components/tahoma/cover.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/custom_components/tahoma/cover.py b/custom_components/tahoma/cover.py index f8db90667..cea752e8e 100644 --- a/custom_components/tahoma/cover.py +++ b/custom_components/tahoma/cover.py @@ -187,7 +187,7 @@ def set_cover_position(self, **kwargs): # HorizontalAwning devices need a reversed position that can not be obtained via the API if "Horizontal" in self.tahoma_device.widget: position = kwargs.get(ATTR_POSITION, 0) - self.apply_action( + self.async_apply_action( self.select_command( [ COMMAND_SET_POSITION, @@ -200,7 +200,7 @@ def set_cover_position(self, **kwargs): def set_cover_tilt_position(self, **kwargs): """Move the cover tilt to a specific position.""" - self.apply_action( + self.async_apply_action( COMMAND_SET_ORIENTATION, 100 - kwargs.get(ATTR_TILT_POSITION, 0) ) @@ -273,27 +273,27 @@ def icon(self): def open_cover(self, **kwargs): """Open the cover.""" - self.apply_action(self.select_command(["open", "up"])) + self.async_apply_action(self.select_command(["open", "up"])) def open_cover_tilt(self, **kwargs): """Open the cover tilt.""" - self.apply_action(self.select_command(["openSlats"])) + self.async_apply_action(self.select_command(["openSlats"])) def close_cover(self, **kwargs): """Close the cover.""" - self.apply_action(self.select_command(["close", "down"])) + self.async_apply_action(self.select_command(["close", "down"])) def close_cover_tilt(self, **kwargs): """Close the cover tilt.""" - self.apply_action(self.select_command(["closeSlats"])) + self.async_apply_action(self.select_command(["closeSlats"])) def stop_cover(self, **kwargs): """Stop the cover.""" - self.apply_action(self.select_command(["stop", "stopIdentify", "my"])) + self.async_apply_action(self.select_command(["stop", "stopIdentify", "my"])) def stop_cover_tilt(self, **kwargs): """Stop the cover.""" - self.apply_action(self.select_command(["stopIdentify", "stop", "my"])) + self.async_apply_action(self.select_command(["stopIdentify", "stop", "my"])) @property def supported_features(self): From e714f404d921bcb744c089a5b0778b2aa3284bfe Mon Sep 17 00:00:00 2001 From: vlebourl Date: Mon, 29 Jun 2020 08:58:40 +0200 Subject: [PATCH 3/8] [WIP] Use async apply action to prevent sequential execution. Related Github issues: #92 --- custom_components/tahoma/cover.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/custom_components/tahoma/cover.py b/custom_components/tahoma/cover.py index f8db90667..cea752e8e 100644 --- a/custom_components/tahoma/cover.py +++ b/custom_components/tahoma/cover.py @@ -187,7 +187,7 @@ def set_cover_position(self, **kwargs): # HorizontalAwning devices need a reversed position that can not be obtained via the API if "Horizontal" in self.tahoma_device.widget: position = kwargs.get(ATTR_POSITION, 0) - self.apply_action( + self.async_apply_action( self.select_command( [ COMMAND_SET_POSITION, @@ -200,7 +200,7 @@ def set_cover_position(self, **kwargs): def set_cover_tilt_position(self, **kwargs): """Move the cover tilt to a specific position.""" - self.apply_action( + self.async_apply_action( COMMAND_SET_ORIENTATION, 100 - kwargs.get(ATTR_TILT_POSITION, 0) ) @@ -273,27 +273,27 @@ def icon(self): def open_cover(self, **kwargs): """Open the cover.""" - self.apply_action(self.select_command(["open", "up"])) + self.async_apply_action(self.select_command(["open", "up"])) def open_cover_tilt(self, **kwargs): """Open the cover tilt.""" - self.apply_action(self.select_command(["openSlats"])) + self.async_apply_action(self.select_command(["openSlats"])) def close_cover(self, **kwargs): """Close the cover.""" - self.apply_action(self.select_command(["close", "down"])) + self.async_apply_action(self.select_command(["close", "down"])) def close_cover_tilt(self, **kwargs): """Close the cover tilt.""" - self.apply_action(self.select_command(["closeSlats"])) + self.async_apply_action(self.select_command(["closeSlats"])) def stop_cover(self, **kwargs): """Stop the cover.""" - self.apply_action(self.select_command(["stop", "stopIdentify", "my"])) + self.async_apply_action(self.select_command(["stop", "stopIdentify", "my"])) def stop_cover_tilt(self, **kwargs): """Stop the cover.""" - self.apply_action(self.select_command(["stopIdentify", "stop", "my"])) + self.async_apply_action(self.select_command(["stopIdentify", "stop", "my"])) @property def supported_features(self): From fe7ede4776d3f06c0af1921dc8bd216fdc00a227 Mon Sep 17 00:00:00 2001 From: vlebourl Date: Mon, 29 Jun 2020 09:30:56 +0200 Subject: [PATCH 4/8] [WIP] Use a queue and update when the queue is empty As an async apply_action doesn't prevent the lock, I propose to add an execution queue to tahoma_device entities, and only perform the update once the queue is empty. Having `update` instead of `schedule_update` line 97 doesn't prevent the lock... Related Github issues: #92 --- custom_components/tahoma/cover.py | 22 ++++++++++++++-------- custom_components/tahoma/tahoma_device.py | 5 +++-- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/custom_components/tahoma/cover.py b/custom_components/tahoma/cover.py index cea752e8e..715f169f3 100644 --- a/custom_components/tahoma/cover.py +++ b/custom_components/tahoma/cover.py @@ -91,6 +91,12 @@ def update(self): """Update method.""" self.controller.get_states([self.tahoma_device]) + exec_queue = self.controller.get_current_executions() + for exec_id in self._exec_queue: + if exec_id in exec_queue: + self.schedule_update_ha_state(True) + return + # Set current position. # Home Assistant: 0 is closed, 100 is fully open. # core:ClosureState: 100 is closed, 0 is fully open. @@ -187,7 +193,7 @@ def set_cover_position(self, **kwargs): # HorizontalAwning devices need a reversed position that can not be obtained via the API if "Horizontal" in self.tahoma_device.widget: position = kwargs.get(ATTR_POSITION, 0) - self.async_apply_action( + self.apply_action( self.select_command( [ COMMAND_SET_POSITION, @@ -200,7 +206,7 @@ def set_cover_position(self, **kwargs): def set_cover_tilt_position(self, **kwargs): """Move the cover tilt to a specific position.""" - self.async_apply_action( + self.apply_action( COMMAND_SET_ORIENTATION, 100 - kwargs.get(ATTR_TILT_POSITION, 0) ) @@ -273,27 +279,27 @@ def icon(self): def open_cover(self, **kwargs): """Open the cover.""" - self.async_apply_action(self.select_command(["open", "up"])) + self.apply_action(self.select_command(["open", "up"])) def open_cover_tilt(self, **kwargs): """Open the cover tilt.""" - self.async_apply_action(self.select_command(["openSlats"])) + self.apply_action(self.select_command(["openSlats"])) def close_cover(self, **kwargs): """Close the cover.""" - self.async_apply_action(self.select_command(["close", "down"])) + self.apply_action(self.select_command(["close", "down"])) def close_cover_tilt(self, **kwargs): """Close the cover tilt.""" - self.async_apply_action(self.select_command(["closeSlats"])) + self.apply_action(self.select_command(["closeSlats"])) def stop_cover(self, **kwargs): """Stop the cover.""" - self.async_apply_action(self.select_command(["stop", "stopIdentify", "my"])) + self.apply_action(self.select_command(["stop", "stopIdentify", "my"])) def stop_cover_tilt(self, **kwargs): """Stop the cover.""" - self.async_apply_action(self.select_command(["stopIdentify", "stop", "my"])) + self.apply_action(self.select_command(["stopIdentify", "stop", "my"])) @property def supported_features(self): diff --git a/custom_components/tahoma/tahoma_device.py b/custom_components/tahoma/tahoma_device.py index 1ac33f900..9dbf96721 100644 --- a/custom_components/tahoma/tahoma_device.py +++ b/custom_components/tahoma/tahoma_device.py @@ -21,6 +21,7 @@ def __init__(self, tahoma_device, controller): self.tahoma_device = tahoma_device self._name = self.tahoma_device.label self.controller = controller + self._exec_queue = [] async def async_added_to_hass(self): """Entity created.""" @@ -141,5 +142,5 @@ def apply_action(self, cmd_name, *args): action = Action(self.tahoma_device.url) action.add_command(cmd_name, *args) exec_id = self.controller.apply_actions("HomeAssistant", [action]) - while exec_id in self.controller.get_current_executions(): - continue + self._exec_queue.append(exec_id) + return exec_id From c98c52689af6d497b0b0f9f1fae0cd8fd7cb30ec Mon Sep 17 00:00:00 2001 From: vlebourl Date: Mon, 29 Jun 2020 10:11:54 +0200 Subject: [PATCH 5/8] [WIP] Add the wait to all entities. Also clear the exec_queue if it's not executing anymore. Related Github issues: #92 --- custom_components/tahoma/binary_sensor.py | 6 ++++++ custom_components/tahoma/climate.py | 6 ++++++ custom_components/tahoma/cover.py | 12 ++++++------ custom_components/tahoma/light.py | 9 ++++++--- custom_components/tahoma/lock.py | 6 ++++++ custom_components/tahoma/sensor.py | 6 ++++++ custom_components/tahoma/switch.py | 6 ++++++ 7 files changed, 42 insertions(+), 9 deletions(-) diff --git a/custom_components/tahoma/binary_sensor.py b/custom_components/tahoma/binary_sensor.py index 10c4454f7..6b4ca4e03 100644 --- a/custom_components/tahoma/binary_sensor.py +++ b/custom_components/tahoma/binary_sensor.py @@ -60,6 +60,12 @@ def device_class(self): def update(self): """Update the state.""" + exec_queue = self.controller.get_current_executions() + self._exec_queue = [e for e in self._exec_queue if e in exec_queue] + if self._exec_queue: + self.schedule_update_ha_state(True) + return + self.controller.get_states([self.tahoma_device]) if CORE_CONTACT_STATE in self.tahoma_device.active_states: diff --git a/custom_components/tahoma/climate.py b/custom_components/tahoma/climate.py index 34f81c925..33b2f7c0b 100644 --- a/custom_components/tahoma/climate.py +++ b/custom_components/tahoma/climate.py @@ -299,6 +299,12 @@ def update_temp(self, state=None): def update(self): """Update the state.""" + exec_queue = self.controller.get_current_executions() + self._exec_queue = [e for e in self._exec_queue if e in exec_queue] + if self._exec_queue: + self.schedule_update_ha_state(True) + return + self.controller.get_states([self.tahoma_device]) self.update_temp(None) if self._widget == W_ST: diff --git a/custom_components/tahoma/cover.py b/custom_components/tahoma/cover.py index 715f169f3..86a1a0dd6 100644 --- a/custom_components/tahoma/cover.py +++ b/custom_components/tahoma/cover.py @@ -89,13 +89,13 @@ def __init__(self, tahoma_device, controller): def update(self): """Update method.""" - self.controller.get_states([self.tahoma_device]) - exec_queue = self.controller.get_current_executions() - for exec_id in self._exec_queue: - if exec_id in exec_queue: - self.schedule_update_ha_state(True) - return + self._exec_queue = [e for e in self._exec_queue if e in exec_queue] + if self._exec_queue: + self.schedule_update_ha_state(True) + return + + self.controller.get_states([self.tahoma_device]) # Set current position. # Home Assistant: 0 is closed, 100 is fully open. diff --git a/custom_components/tahoma/light.py b/custom_components/tahoma/light.py index e37b7e975..d0b2dfc5e 100644 --- a/custom_components/tahoma/light.py +++ b/custom_components/tahoma/light.py @@ -130,10 +130,13 @@ def effect(self) -> str: return self._effect def update(self): - """Fetch new state data for this light. + """Fetch new state data for this light.""" - This is the only method that should fetch new data for Home Assistant. - """ + exec_queue = self.controller.get_current_executions() + self._exec_queue = [e for e in self._exec_queue if e in exec_queue] + if self._exec_queue: + self.schedule_update_ha_state(True) + return self.controller.get_states([self.tahoma_device]) diff --git a/custom_components/tahoma/lock.py b/custom_components/tahoma/lock.py index a164c712c..d5a996156 100644 --- a/custom_components/tahoma/lock.py +++ b/custom_components/tahoma/lock.py @@ -42,6 +42,12 @@ def __init__(self, tahoma_device, controller): def update(self): """Update method.""" + exec_queue = self.controller.get_current_executions() + self._exec_queue = [e for e in self._exec_queue if e in exec_queue] + if self._exec_queue: + self.schedule_update_ha_state(True) + return + self.controller.get_states([self.tahoma_device]) self._battery_level = self.tahoma_device.active_states["core:BatteryState"] self._name = self.tahoma_device.active_states["core:NameState"] diff --git a/custom_components/tahoma/sensor.py b/custom_components/tahoma/sensor.py index 7e35b7e64..cfa8e65b8 100644 --- a/custom_components/tahoma/sensor.py +++ b/custom_components/tahoma/sensor.py @@ -105,6 +105,12 @@ def device_class(self) -> Optional[str]: def update(self): """Update the state.""" + exec_queue = self.controller.get_current_executions() + self._exec_queue = [e for e in self._exec_queue if e in exec_queue] + if self._exec_queue: + self.schedule_update_ha_state(True) + return + self.controller.get_states([self.tahoma_device]) if CORE_LUMINANCE_STATE in self.tahoma_device.active_states: diff --git a/custom_components/tahoma/switch.py b/custom_components/tahoma/switch.py index 6575cb10d..cbf1aebab 100644 --- a/custom_components/tahoma/switch.py +++ b/custom_components/tahoma/switch.py @@ -41,6 +41,12 @@ def update(self): self._skip_update = False return + exec_queue = self.controller.get_current_executions() + self._exec_queue = [e for e in self._exec_queue if e in exec_queue] + if self._exec_queue: + self.schedule_update_ha_state(True) + return + self.controller.get_states([self.tahoma_device]) _LOGGER.debug("Update %s, state: %s", self._name, self._state) From ff7dfd19df14eb378f6efca702fa4f03eb3d98e1 Mon Sep 17 00:00:00 2001 From: vlebourl Date: Mon, 29 Jun 2020 10:13:36 +0200 Subject: [PATCH 6/8] Revert "[Refactor] Add helper functions select_command and select_state." This reverts commit 45a30241 --- custom_components/tahoma/cover.py | 101 ++++++++++++++++------ custom_components/tahoma/tahoma_device.py | 20 +---- 2 files changed, 75 insertions(+), 46 deletions(-) diff --git a/custom_components/tahoma/cover.py b/custom_components/tahoma/cover.py index 86a1a0dd6..6b85aab38 100644 --- a/custom_components/tahoma/cover.py +++ b/custom_components/tahoma/cover.py @@ -193,16 +193,15 @@ def set_cover_position(self, **kwargs): # HorizontalAwning devices need a reversed position that can not be obtained via the API if "Horizontal" in self.tahoma_device.widget: position = kwargs.get(ATTR_POSITION, 0) - self.apply_action( - self.select_command( - [ - COMMAND_SET_POSITION, - COMMAND_SET_CLOSURE, - COMMAND_SET_PEDESTRIAN_POSITION, - ] - ), - position, - ) + + if COMMAND_SET_POSITION in self.tahoma_device.command_definitions: + return self.apply_action(COMMAND_SET_POSITION, position) + + if COMMAND_SET_CLOSURE in self.tahoma_device.command_definitions: + return self.apply_action(COMMAND_SET_CLOSURE, position) + + if COMMAND_SET_PEDESTRIAN_POSITION in self.tahoma_device.command_definitions: + return self.apply_action(COMMAND_SET_PEDESTRIAN_POSITION, position) def set_cover_tilt_position(self, **kwargs): """Move the cover tilt to a specific position.""" @@ -213,17 +212,35 @@ def set_cover_tilt_position(self, **kwargs): @property def is_closed(self): """Return if the cover is closed.""" - state = self.select_state( - [ - "core:OpenClosedState", - "core:SlatsOpenClosedState", - "core:OpenClosedPartialState", - "core:OpenClosedPedestrianState", - "core:OpenClosedUnknownState", - ] - ) - if state is not None: - return state == "closed" + + if "core:OpenClosedState" in self.tahoma_device.active_states: + return ( + self.tahoma_device.active_states.get("core:OpenClosedState") == "closed" + ) + + if "core:SlatsOpenClosedState" in self.tahoma_device.active_states: + return ( + self.tahoma_device.active_states.get("core:SlatsOpenClosedState") + == "closed" + ) + + if "core:OpenClosedPartialState" in self.tahoma_device.active_states: + return ( + self.tahoma_device.active_states.get("core:OpenClosedPartialState") + == "closed" + ) + + if "core:OpenClosedPedestrianState" in self.tahoma_device.active_states: + return ( + self.tahoma_device.active_states.get("core:OpenClosedPedestrianState") + == "closed" + ) + + if "core:OpenClosedUnknownState" in self.tahoma_device.active_states: + return ( + self.tahoma_device.active_states.get("core:OpenClosedUnknownState") + == "closed" + ) if getattr(self, "_position", None) is not None: return self._position == 0 @@ -279,27 +296,57 @@ def icon(self): def open_cover(self, **kwargs): """Open the cover.""" - self.apply_action(self.select_command(["open", "up"])) + + if "open" in self.tahoma_device.command_definitions: + return self.apply_action("open") + + if "up" in self.tahoma_device.command_definitions: + return self.apply_action("up") def open_cover_tilt(self, **kwargs): """Open the cover tilt.""" - self.apply_action(self.select_command(["openSlats"])) + + if "openSlats" in self.tahoma_device.command_definitions: + return self.apply_action("openSlats") def close_cover(self, **kwargs): """Close the cover.""" - self.apply_action(self.select_command(["close", "down"])) + + if "close" in self.tahoma_device.command_definitions: + return self.apply_action("close") + + if "down" in self.tahoma_device.command_definitions: + return self.apply_action("down") def close_cover_tilt(self, **kwargs): """Close the cover tilt.""" - self.apply_action(self.select_command(["closeSlats"])) + + if "closeSlats" in self.tahoma_device.command_definitions: + return self.apply_action("closeSlats") def stop_cover(self, **kwargs): """Stop the cover.""" - self.apply_action(self.select_command(["stop", "stopIdentify", "my"])) + + if "stop" in self.tahoma_device.command_definitions: + return self.apply_action("stop") + + if "stopIdentify" in self.tahoma_device.command_definitions: + return self.apply_action("stopIdentify") + + if "my" in self.tahoma_device.command_definitions: + return self.apply_action("my") def stop_cover_tilt(self, **kwargs): """Stop the cover.""" - self.apply_action(self.select_command(["stopIdentify", "stop", "my"])) + + if "stopIdentify" in self.tahoma_device.command_definitions: + return self.apply_action("stopIdentify") + + if "stop" in self.tahoma_device.command_definitions: + return self.apply_action("stop") + + if "my" in self.tahoma_device.command_definitions: + return self.apply_action("my") @property def supported_features(self): diff --git a/custom_components/tahoma/tahoma_device.py b/custom_components/tahoma/tahoma_device.py index 9dbf96721..7159f1024 100644 --- a/custom_components/tahoma/tahoma_device.py +++ b/custom_components/tahoma/tahoma_device.py @@ -114,31 +114,13 @@ def device_info(self): "sw_version": self.tahoma_device.type, } - def select_command(self, commands): - """Select first existing command in a list of commands.""" - return next( - (c for c in self.tahoma_device.command_definitions if c in commands), None - ) - - def select_state(self, active_states): - """Select first existing active state in a list of states.""" - return next( - ( - v - for k, v in self.tahoma_device.active_states.items() - if k in active_states - ), - None, - ) - async def async_apply_action(self, cmd_name, *args): """Apply Action to Device in async context.""" await self.hass.async_add_executor_job(self.apply_action, cmd_name, *args) def apply_action(self, cmd_name, *args): """Apply Action to Device.""" - if cmd_name is None: - raise NotImplementedError + action = Action(self.tahoma_device.url) action.add_command(cmd_name, *args) exec_id = self.controller.apply_actions("HomeAssistant", [action]) From f3a26772016a25453838b1876e1a2b09867388f2 Mon Sep 17 00:00:00 2001 From: vlebourl Date: Wed, 1 Jul 2020 15:21:17 +0200 Subject: [PATCH 7/8] Move the exec_queue checking to tahoma_device.py. --- custom_components/tahoma/binary_sensor.py | 4 +--- custom_components/tahoma/climate.py | 4 +--- custom_components/tahoma/cover.py | 4 +--- custom_components/tahoma/light.py | 4 +--- custom_components/tahoma/lock.py | 4 +--- custom_components/tahoma/sensor.py | 4 +--- custom_components/tahoma/switch.py | 4 ++++ custom_components/tahoma/tahoma_device.py | 6 ++++++ 8 files changed, 16 insertions(+), 18 deletions(-) diff --git a/custom_components/tahoma/binary_sensor.py b/custom_components/tahoma/binary_sensor.py index 6b4ca4e03..a7c686947 100644 --- a/custom_components/tahoma/binary_sensor.py +++ b/custom_components/tahoma/binary_sensor.py @@ -60,9 +60,7 @@ def device_class(self): def update(self): """Update the state.""" - exec_queue = self.controller.get_current_executions() - self._exec_queue = [e for e in self._exec_queue if e in exec_queue] - if self._exec_queue: + if self.should_wait(): self.schedule_update_ha_state(True) return diff --git a/custom_components/tahoma/climate.py b/custom_components/tahoma/climate.py index 33b2f7c0b..28b435223 100644 --- a/custom_components/tahoma/climate.py +++ b/custom_components/tahoma/climate.py @@ -299,9 +299,7 @@ def update_temp(self, state=None): def update(self): """Update the state.""" - exec_queue = self.controller.get_current_executions() - self._exec_queue = [e for e in self._exec_queue if e in exec_queue] - if self._exec_queue: + if self.should_wait(): self.schedule_update_ha_state(True) return diff --git a/custom_components/tahoma/cover.py b/custom_components/tahoma/cover.py index 6b85aab38..231fb86ee 100644 --- a/custom_components/tahoma/cover.py +++ b/custom_components/tahoma/cover.py @@ -89,9 +89,7 @@ def __init__(self, tahoma_device, controller): def update(self): """Update method.""" - exec_queue = self.controller.get_current_executions() - self._exec_queue = [e for e in self._exec_queue if e in exec_queue] - if self._exec_queue: + if self.should_wait(): self.schedule_update_ha_state(True) return diff --git a/custom_components/tahoma/light.py b/custom_components/tahoma/light.py index d0b2dfc5e..032630379 100644 --- a/custom_components/tahoma/light.py +++ b/custom_components/tahoma/light.py @@ -132,9 +132,7 @@ def effect(self) -> str: def update(self): """Fetch new state data for this light.""" - exec_queue = self.controller.get_current_executions() - self._exec_queue = [e for e in self._exec_queue if e in exec_queue] - if self._exec_queue: + if self.should_wait(): self.schedule_update_ha_state(True) return diff --git a/custom_components/tahoma/lock.py b/custom_components/tahoma/lock.py index d5a996156..989b91720 100644 --- a/custom_components/tahoma/lock.py +++ b/custom_components/tahoma/lock.py @@ -42,9 +42,7 @@ def __init__(self, tahoma_device, controller): def update(self): """Update method.""" - exec_queue = self.controller.get_current_executions() - self._exec_queue = [e for e in self._exec_queue if e in exec_queue] - if self._exec_queue: + if self.should_wait(): self.schedule_update_ha_state(True) return diff --git a/custom_components/tahoma/sensor.py b/custom_components/tahoma/sensor.py index cfa8e65b8..c1010f7d5 100644 --- a/custom_components/tahoma/sensor.py +++ b/custom_components/tahoma/sensor.py @@ -105,9 +105,7 @@ def device_class(self) -> Optional[str]: def update(self): """Update the state.""" - exec_queue = self.controller.get_current_executions() - self._exec_queue = [e for e in self._exec_queue if e in exec_queue] - if self._exec_queue: + if self.should_wait(): self.schedule_update_ha_state(True) return diff --git a/custom_components/tahoma/switch.py b/custom_components/tahoma/switch.py index cbf1aebab..069405829 100644 --- a/custom_components/tahoma/switch.py +++ b/custom_components/tahoma/switch.py @@ -37,6 +37,10 @@ def __init__(self, tahoma_device, controller): def update(self): """Update method.""" # Postpone the immediate state check for changes that take time. + if self.should_wait(): + self.schedule_update_ha_state(True) + return + if self._skip_update: self._skip_update = False return diff --git a/custom_components/tahoma/tahoma_device.py b/custom_components/tahoma/tahoma_device.py index 7159f1024..fed2d2d70 100644 --- a/custom_components/tahoma/tahoma_device.py +++ b/custom_components/tahoma/tahoma_device.py @@ -114,6 +114,12 @@ def device_info(self): "sw_version": self.tahoma_device.type, } + def should_wait(self): + """Wait for actions to finish.""" + exec_queue = self.controller.get_current_executions() + self._exec_queue = [e for e in self._exec_queue if e in exec_queue] + return True if self._exec_queue else False + async def async_apply_action(self, cmd_name, *args): """Apply Action to Device in async context.""" await self.hass.async_add_executor_job(self.apply_action, cmd_name, *args) From f9f471c40fd7a2645b43703a9d43d040399e4169 Mon Sep 17 00:00:00 2001 From: Vincent Le Bourlot Date: Thu, 2 Jul 2020 10:32:05 +0200 Subject: [PATCH 8/8] Update switch.py --- custom_components/tahoma/switch.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/custom_components/tahoma/switch.py b/custom_components/tahoma/switch.py index 069405829..92dd143a1 100644 --- a/custom_components/tahoma/switch.py +++ b/custom_components/tahoma/switch.py @@ -45,12 +45,6 @@ def update(self): self._skip_update = False return - exec_queue = self.controller.get_current_executions() - self._exec_queue = [e for e in self._exec_queue if e in exec_queue] - if self._exec_queue: - self.schedule_update_ha_state(True) - return - self.controller.get_states([self.tahoma_device]) _LOGGER.debug("Update %s, state: %s", self._name, self._state)