From f4118799f58aa8f7c7742499bccc5a2851d0f39f Mon Sep 17 00:00:00 2001 From: Jan Pluskal Date: Fri, 24 Jul 2026 09:45:54 +0200 Subject: [PATCH] fix(state-machine): catch-all block_timer_expires -> idle to prevent stuck-in-blocked When block_timer_expires fires and none of the conditional blocked-source transitions match, the controller stays in `blocked` indefinitely past its block_timeout. Two real cases hit this: state entities still report `on` (slow cloud/gateway feedback, e.g. Overkiz/Tahoma) while the trigger sensor is already off; or state entities are off but no earlier rule applies (the unconditional blocked->idle transition is present only as a commented-out line today). Add an unconditional blocked -> idle fallback, ordered after the conditional "go to active" transitions so those still win when they match. --- custom_components/entity_controller/__init__.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/custom_components/entity_controller/__init__.py b/custom_components/entity_controller/__init__.py index 777b86d..fff8741 100644 --- a/custom_components/entity_controller/__init__.py +++ b/custom_components/entity_controller/__init__.py @@ -330,6 +330,18 @@ async def async_setup(hass, config): dest="idle", conditions=["is_state_entities_on", "is_duration_sensor", "is_sensor_off"], ) + # Catch-all: block_timer_expires -> idle for every case the conditional + # transitions above do not handle. Without it the controller stays stuck in + # `blocked` past its block_timeout when the timer fires and state entities + # are still reported as on (e.g. slow cloud/gateway feedback from + # integrations like Overkiz/Tahoma) while the trigger sensor is already off, + # or when state entities are off but no earlier transition matches. Added + # last so the conditional "go to active" rules are evaluated first. + machine.add_transition( + trigger="block_timer_expires", + source="blocked", + dest="idle", + ) # Active Timer machine.add_transition(