From bd2a12e7ecec91d2e23a9bf87bece06237a851f7 Mon Sep 17 00:00:00 2001 From: Mick Vleeshouwer Date: Sat, 16 May 2026 15:43:06 +0000 Subject: [PATCH 1/3] Fix controls for OpenCloseGate4T in Overkiz MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The OpenCloseGate4T widget (rts:GateOpenerRTS4TComponent) only supports a cycle command—not the standard open/close/stop commands expected by the UIClass.GATE default. Without a dedicated override, the entity got zero supported features and became unusable after the 2026.5 rewrite. Add a widget override that maps cycle as the open command, restoring the toggle functionality for these RTS gate openers. Fixes #170214 --- homeassistant/components/overkiz/cover.py | 9 ++++ .../setup/cloud_somfy_tahoma_v2_europe.json | 32 +++++++++++ .../overkiz/snapshots/test_button.ambr | 52 ++++++++++++++++++ .../overkiz/snapshots/test_cover.ambr | 54 +++++++++++++++++++ tests/components/overkiz/test_cover.py | 9 ++++ 5 files changed, 156 insertions(+) diff --git a/homeassistant/components/overkiz/cover.py b/homeassistant/components/overkiz/cover.py index df73113cd438bd..0cc141618b8e05 100644 --- a/homeassistant/components/overkiz/cover.py +++ b/homeassistant/components/overkiz/cover.py @@ -199,6 +199,15 @@ class OverkizCoverDescription(CoverEntityDescription): is_closed_state=OverkizState.CORE_OPEN_CLOSED_PEDESTRIAN, stop_command=OverkizCommand.STOP, ), + # Needs override since OpenCloseGate4T only supports the cycle command + # (rts:GateOpenerRTS4TComponent) + # uiClass is Gate + OverkizCoverDescription( + key=UIWidget.OPEN_CLOSE_GATE_4T, + device_class=CoverDeviceClass.GATE, + open_command=OverkizCommand.CYCLE, + close_command=OverkizCommand.CYCLE, + ), # Needs override to support this Generic device (rts:GenericRTSComponent) # uiClass is Generic (not mapped to cover as this is a Generic device class) OverkizCoverDescription( diff --git a/tests/components/overkiz/fixtures/setup/cloud_somfy_tahoma_v2_europe.json b/tests/components/overkiz/fixtures/setup/cloud_somfy_tahoma_v2_europe.json index d69c75e548ff1c..0a59862cef7724 100644 --- a/tests/components/overkiz/fixtures/setup/cloud_somfy_tahoma_v2_europe.json +++ b/tests/components/overkiz/fixtures/setup/cloud_somfy_tahoma_v2_europe.json @@ -7441,6 +7441,38 @@ "oid": "6ba9b1de-8037-41d7-9150-21f7d5f49a3f", "uiClass": "Gate" }, + { + "creationTime": 1434967095000, + "lastUpdateTime": 1434967095000, + "label": "RTS Gate", + "deviceURL": "rts://1234-1234-6233/16730717", + "shortcut": false, + "controllableName": "rts:GateOpenerRTS4TComponent", + "definition": { + "commands": [ + { + "commandName": "cycle", + "nparams": 1 + } + ], + "states": [], + "dataProperties": [], + "widgetName": "OpenCloseGate4T", + "uiProfiles": ["CyclicGateOpener", "Cyclic"], + "uiClass": "Gate", + "qualifiedName": "rts:GateOpenerRTS4TComponent", + "type": "ACTUATOR" + }, + "states": [], + "attributes": [], + "available": true, + "enabled": true, + "placeOID": "bcbb34ef-2241-43a1-9c5b-523aa0563ec3", + "widget": "OpenCloseGate4T", + "type": 1, + "oid": "a1b2c3d4-e5f6-7890-abcd-ef1234567891", + "uiClass": "Gate" + }, { "creationTime": 1521964729000, "lastUpdateTime": 1521964729000, diff --git a/tests/components/overkiz/snapshots/test_button.ambr b/tests/components/overkiz/snapshots/test_button.ambr index d01827f1bbb877..416443d68c3ef6 100644 --- a/tests/components/overkiz/snapshots/test_button.ambr +++ b/tests/components/overkiz/snapshots/test_button.ambr @@ -4308,6 +4308,58 @@ 'state': 'unknown', }) # --- +# name: test_button_entities_snapshot[cloud_somfy_tahoma_v2_europe.json][button.rts_gate_toggle-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'button', + 'entity_category': None, + 'entity_id': 'button.rts_gate_toggle', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Toggle', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': 'mdi:sync', + 'original_name': 'Toggle', + 'platform': 'overkiz', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'rts://1234-1234-6233/16730717-cycle', + 'unit_of_measurement': None, + }) +# --- +# name: test_button_entities_snapshot[cloud_somfy_tahoma_v2_europe.json][button.rts_gate_toggle-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'assumed_state': True, + 'friendly_name': 'RTS Gate Toggle', + 'icon': 'mdi:sync', + }), + 'context': , + 'entity_id': 'button.rts_gate_toggle', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unknown', + }) +# --- # name: test_button_entities_snapshot[cloud_somfy_tahoma_v2_europe.json][button.side_garage_door_identify-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ diff --git a/tests/components/overkiz/snapshots/test_cover.ambr b/tests/components/overkiz/snapshots/test_cover.ambr index c208b4440b4106..4e12a6e6069d6b 100644 --- a/tests/components/overkiz/snapshots/test_cover.ambr +++ b/tests/components/overkiz/snapshots/test_cover.ambr @@ -1993,6 +1993,60 @@ 'state': 'closed', }) # --- +# name: test_cover_entities_snapshot[cloud_somfy_tahoma_v2_europe.json][cover.rts_gate-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'cover', + 'entity_category': None, + 'entity_id': 'cover.rts_gate', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': None, + 'platform': 'overkiz', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': , + 'translation_key': None, + 'unique_id': 'rts://1234-1234-6233/16730717', + 'unit_of_measurement': None, + }) +# --- +# name: test_cover_entities_snapshot[cloud_somfy_tahoma_v2_europe.json][cover.rts_gate-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'assumed_state': True, + 'device_class': 'gate', + 'friendly_name': 'RTS Gate', + 'is_closed': None, + 'supported_features': , + }), + 'context': , + 'entity_id': 'cover.rts_gate', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unknown', + }) +# --- # name: test_cover_entities_snapshot[cloud_somfy_tahoma_v2_europe.json][cover.side_garage_door-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ diff --git a/tests/components/overkiz/test_cover.py b/tests/components/overkiz/test_cover.py index c6bd568a51debb..5c01fa0528df2f 100644 --- a/tests/components/overkiz/test_cover.py +++ b/tests/components/overkiz/test_cover.py @@ -129,6 +129,11 @@ "io://1234-1234-6233/7433515", "cover.partial_garage_door", ) +RTS_GATE_4T = FixtureDevice( + "setup/cloud_somfy_tahoma_v2_europe.json", + "rts://1234-1234-6233/16730717", + "cover.rts_gate", +) DYNAMIC_GATE = FixtureDevice( "setup/cloud_somfy_tahoma_v2_europe.json", "ogp://1234-1234-6233/10410217", @@ -182,6 +187,7 @@ async def test_cover_entities_snapshot( (DYNAMIC_GARAGE_DOOR, SERVICE_OPEN_COVER, "open", None, CoverState.OPENING), (DYNAMIC_GARAGE_DOOR_OGP, SERVICE_OPEN_COVER, "open", None, CoverState.OPENING), (DYNAMIC_GATE, SERVICE_OPEN_COVER, "open", None, CoverState.OPENING), + (RTS_GATE_4T, SERVICE_OPEN_COVER, "cycle", [0], CoverState.OPENING), (PARTIAL_GARAGE_DOOR, SERVICE_OPEN_COVER, "open", None, CoverState.OPENING), ( UP_DOWN_BIOCLIMATIC_PERGOLA, @@ -205,6 +211,7 @@ async def test_cover_entities_snapshot( CoverState.CLOSING, ), (DYNAMIC_GATE, SERVICE_CLOSE_COVER, "close", None, CoverState.CLOSING), + (RTS_GATE_4T, SERVICE_CLOSE_COVER, "cycle", [0], CoverState.OPENING), (PARTIAL_GARAGE_DOOR, SERVICE_CLOSE_COVER, "close", None, CoverState.CLOSING), ( UP_DOWN_BIOCLIMATIC_PERGOLA, @@ -310,6 +317,7 @@ async def test_cover_entities_snapshot( "open-dynamic-garage-door", "open-dynamic-garage-door-ogp", "open-dynamic-gate", + "open-rts-gate-4t", "open-partial-garage-door", "open-up-down-bioclimatic-pergola", "open-tilt-only-venetian-blind", @@ -321,6 +329,7 @@ async def test_cover_entities_snapshot( "close-dynamic-garage-door", "close-dynamic-garage-door-ogp", "close-dynamic-gate", + "close-rts-gate-4t", "close-partial-garage-door", "close-up-down-bioclimatic-pergola", "close-tilt-only-venetian-blind", From a8c79f750be766845c9015f5238c66c45ad6cdef Mon Sep 17 00:00:00 2001 From: Mick Vleeshouwer Date: Sun, 17 May 2026 16:53:25 +0200 Subject: [PATCH 2/3] Add comment explaining RTS_GATE_4T cycle command behavior --- tests/components/overkiz/test_cover.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/components/overkiz/test_cover.py b/tests/components/overkiz/test_cover.py index 16e842419514c5..ba3179f5f8cd13 100644 --- a/tests/components/overkiz/test_cover.py +++ b/tests/components/overkiz/test_cover.py @@ -217,6 +217,8 @@ async def test_cover_entities_snapshot( CoverState.CLOSING, ), (DYNAMIC_GATE, SERVICE_CLOSE_COVER, "close", None, CoverState.CLOSING), + # Cycle command is used for both open and close; device reports OPENING + # since the RTS protocol has no directional feedback. (RTS_GATE_4T, SERVICE_CLOSE_COVER, "cycle", [0], CoverState.OPENING), (SLIDING_DISCRETE_GATE, SERVICE_CLOSE_COVER, "close", None, CoverState.CLOSING), (PARTIAL_GARAGE_DOOR, SERVICE_CLOSE_COVER, "close", None, CoverState.CLOSING), From 35306059f29830d445e8e1cdef81bf374994f4a3 Mon Sep 17 00:00:00 2001 From: Mick Vleeshouwer Date: Sun, 17 May 2026 17:12:32 +0000 Subject: [PATCH 3/3] Add support for cyclic cover devices (CyclicGarageDoor, CyclicSwingingGateOpener, CyclicSlidingGateOpener) These devices only support the cycle command instead of separate open/close commands. Without explicit widget overrides, they fall through to their UIClass default which expects open/close/stop commands, resulting in no supported features and a non-functional entity. --- homeassistant/components/overkiz/cover.py | 25 ++ .../setup/cloud_somfy_tahoma_v2_europe.json | 379 ++++++++++++++++ .../overkiz/snapshots/test_button.ambr | 410 ++++++++++++++++++ .../overkiz/snapshots/test_cover.ambr | 106 +++++ tests/components/overkiz/test_cover.py | 18 + 5 files changed, 938 insertions(+) diff --git a/homeassistant/components/overkiz/cover.py b/homeassistant/components/overkiz/cover.py index 5389d81b84bad4..0675d3f9ea75f5 100644 --- a/homeassistant/components/overkiz/cover.py +++ b/homeassistant/components/overkiz/cover.py @@ -208,6 +208,31 @@ class OverkizCoverDescription(CoverEntityDescription): open_command=OverkizCommand.CYCLE, close_command=OverkizCommand.CYCLE, ), + # Needs override since CyclicGarageDoor only supports the cycle command + # (io:CyclicGarageOpenerIOComponent) + # uiClass is GarageDoor + OverkizCoverDescription( + key=UIWidget.CYCLIC_GARAGE_DOOR, + device_class=CoverDeviceClass.GARAGE, + open_command=OverkizCommand.CYCLE, + close_command=OverkizCommand.CYCLE, + ), + # Needs override since CyclicSlidingGateOpener only supports the cycle command + # uiClass is Gate + OverkizCoverDescription( + key=UIWidget.CYCLIC_SLIDING_GATE_OPENER, + device_class=CoverDeviceClass.GATE, + open_command=OverkizCommand.CYCLE, + close_command=OverkizCommand.CYCLE, + ), + # Needs override since CyclicSwingingGateOpener only supports the cycle command + # uiClass is Gate + OverkizCoverDescription( + key=UIWidget.CYCLIC_SWINGING_GATE_OPENER, + device_class=CoverDeviceClass.GATE, + open_command=OverkizCommand.CYCLE, + close_command=OverkizCommand.CYCLE, + ), # Needs override since SlidingDiscreteGateWithPedestrianPosition reports # core:OpenClosedPedestrianState instead of core:OpenClosedState # uiClass is Gate diff --git a/tests/components/overkiz/fixtures/setup/cloud_somfy_tahoma_v2_europe.json b/tests/components/overkiz/fixtures/setup/cloud_somfy_tahoma_v2_europe.json index 116a674e4b74cb..b674741430742e 100644 --- a/tests/components/overkiz/fixtures/setup/cloud_somfy_tahoma_v2_europe.json +++ b/tests/components/overkiz/fixtures/setup/cloud_somfy_tahoma_v2_europe.json @@ -7756,6 +7756,385 @@ "oid": "2492f7ae-3711-4160-9dae-e8910b708ce1", "uiClass": "GarageDoor" }, + { + "creationTime": 1685039520000, + "lastUpdateTime": 1685039520000, + "label": "Cyclic Garage Door", + "deviceURL": "io://1234-1234-6233/6416929", + "shortcut": false, + "controllableName": "io:CyclicGarageOpenerIOComponent", + "definition": { + "commands": [ + { + "commandName": "advancedRefresh", + "nparams": 2 + }, + { + "commandName": "cycle", + "nparams": 0 + }, + { + "commandName": "delayedStopIdentify", + "nparams": 1 + }, + { + "commandName": "getName", + "nparams": 0 + }, + { + "commandName": "identify", + "nparams": 0 + }, + { + "commandName": "setName", + "nparams": 1 + }, + { + "commandName": "startIdentify", + "nparams": 0 + }, + { + "commandName": "stopIdentify", + "nparams": 0 + }, + { + "commandName": "wink", + "nparams": 1 + }, + { + "commandName": "pairOneWayController", + "nparams": 2 + }, + { + "commandName": "setConfigState", + "nparams": 1 + }, + { + "commandName": "unpairAllOneWayControllers", + "nparams": 0 + }, + { + "commandName": "unpairOneWayController", + "nparams": 2 + } + ], + "states": [ + { + "type": "DiscreteState", + "values": ["good", "low", "normal", "verylow"], + "qualifiedName": "core:DiscreteRSSILevelState" + }, + { + "type": "DataState", + "qualifiedName": "core:NameState" + }, + { + "type": "ContinuousState", + "qualifiedName": "core:PriorityLockTimerState" + }, + { + "type": "ContinuousState", + "qualifiedName": "core:RSSILevelState" + }, + { + "type": "DiscreteState", + "values": ["available", "unavailable"], + "qualifiedName": "core:StatusState" + }, + { + "type": "DiscreteState", + "values": [ + "comfortLevel1", + "comfortLevel2", + "comfortLevel3", + "comfortLevel4", + "environmentProtection", + "humanProtection", + "userLevel1", + "userLevel2" + ], + "qualifiedName": "io:PriorityLockLevelState" + }, + { + "type": "DiscreteState", + "values": [ + "LSC", + "SAAC", + "SFC", + "UPS", + "externalGateway", + "localUser", + "myself", + "rain", + "security", + "temperature", + "timer", + "user", + "wind" + ], + "qualifiedName": "io:PriorityLockOriginatorState" + } + ], + "dataProperties": [ + { + "value": "500", + "qualifiedName": "core:identifyInterval" + } + ], + "widgetName": "CyclicGarageDoor", + "uiProfiles": ["CyclicGarageOpener", "Cyclic"], + "uiClass": "GarageDoor", + "qualifiedName": "io:CyclicGarageOpenerIOComponent", + "type": "ACTUATOR" + }, + "states": [ + { + "name": "core:NameState", + "type": 3, + "value": "Cyclic Garage Door" + }, + { + "name": "core:PriorityLockTimerState", + "type": 1, + "value": 0 + }, + { + "name": "core:StatusState", + "type": 3, + "value": "available" + }, + { + "name": "core:DiscreteRSSILevelState", + "type": 3, + "value": "normal" + }, + { + "name": "core:RSSILevelState", + "type": 2, + "value": 72.0 + } + ], + "attributes": [ + { + "name": "core:Manufacturer", + "type": 3, + "value": "Somfy" + }, + { + "name": "core:FirmwareRevision", + "type": 3, + "value": "5127170A01" + } + ], + "available": true, + "enabled": true, + "placeOID": "bcbb34ef-2241-43a1-9c5b-523aa0563ec3", + "widget": "CyclicGarageDoor", + "type": 1, + "oid": "42a91c8c-2f55-4442-9af8-fa93862fbeff", + "uiClass": "GarageDoor" + }, + { + "creationTime": 1711109596000, + "lastUpdateTime": 1711109596000, + "label": "Swinging Gate", + "deviceURL": "io://1234-1234-8983/1959462", + "shortcut": false, + "controllableName": "io:CyclicSwingingGateOpenerIOComponent", + "definition": { + "commands": [ + { + "commandName": "addLockLevel", + "nparams": 2 + }, + { + "commandName": "advancedRefresh", + "nparams": 2 + }, + { + "commandName": "cycle", + "nparams": 0 + }, + { + "commandName": "delayedStopIdentify", + "nparams": 1 + }, + { + "commandName": "getName", + "nparams": 0 + }, + { + "commandName": "identify", + "nparams": 0 + }, + { + "commandName": "removeLockLevel", + "nparams": 1 + }, + { + "commandName": "resetLockLevels", + "nparams": 0 + }, + { + "commandName": "setName", + "nparams": 1 + }, + { + "commandName": "startIdentify", + "nparams": 0 + }, + { + "commandName": "stopIdentify", + "nparams": 0 + }, + { + "commandName": "wink", + "nparams": 1 + }, + { + "commandName": "pairOneWayController", + "nparams": 2 + }, + { + "commandName": "setConfigState", + "nparams": 1 + }, + { + "commandName": "unpairAllOneWayControllers", + "nparams": 0 + }, + { + "commandName": "unpairOneWayController", + "nparams": 2 + } + ], + "states": [ + { + "eventBased": true, + "type": "DataState", + "qualifiedName": "core:CommandLockLevelsState" + }, + { + "type": "DiscreteState", + "values": ["good", "low", "normal", "verylow"], + "qualifiedName": "core:DiscreteRSSILevelState" + }, + { + "type": "DataState", + "qualifiedName": "core:NameState" + }, + { + "type": "ContinuousState", + "qualifiedName": "core:PriorityLockTimerState" + }, + { + "type": "ContinuousState", + "qualifiedName": "core:RSSILevelState" + }, + { + "type": "DiscreteState", + "values": ["available", "unavailable"], + "qualifiedName": "core:StatusState" + }, + { + "type": "DiscreteState", + "values": [ + "comfortLevel1", + "comfortLevel2", + "comfortLevel3", + "comfortLevel4", + "environmentProtection", + "humanProtection", + "userLevel1", + "userLevel2" + ], + "qualifiedName": "io:PriorityLockLevelState" + }, + { + "type": "DiscreteState", + "values": [ + "LSC", + "SAAC", + "SFC", + "UPS", + "externalGateway", + "localUser", + "myself", + "rain", + "security", + "temperature", + "timer", + "user", + "wind" + ], + "qualifiedName": "io:PriorityLockOriginatorState" + } + ], + "dataProperties": [ + { + "value": "500", + "qualifiedName": "core:identifyInterval" + } + ], + "widgetName": "CyclicSwingingGateOpener", + "uiProfiles": ["CyclicGateOpener", "Cyclic"], + "uiClass": "Gate", + "qualifiedName": "io:CyclicSwingingGateOpenerIOComponent", + "type": "ACTUATOR" + }, + "states": [ + { + "name": "core:NameState", + "type": 3, + "value": "Swinging Gate" + }, + { + "name": "core:PriorityLockTimerState", + "type": 1, + "value": 0 + }, + { + "name": "core:CommandLockLevelsState", + "type": 3, + "value": "[]", + "lastUpdateTime": 1742634864000 + }, + { + "name": "core:StatusState", + "type": 3, + "value": "available" + }, + { + "name": "core:DiscreteRSSILevelState", + "type": 3, + "value": "low" + }, + { + "name": "core:RSSILevelState", + "type": 2, + "value": 32.0 + } + ], + "attributes": [ + { + "name": "core:FirmwareRevision", + "type": 3, + "value": "5127170B02" + }, + { + "name": "core:Manufacturer", + "type": 3, + "value": "Somfy" + } + ], + "available": true, + "enabled": true, + "placeOID": "bcbb34ef-2241-43a1-9c5b-523aa0563ec3", + "widget": "CyclicSwingingGateOpener", + "type": 1, + "oid": "83371762-4f7c-4e1b-846b-d5b7f8e9aa53", + "uiClass": "Gate" + }, { "creationTime": 1521964729000, "lastUpdateTime": 1521964729000, diff --git a/tests/components/overkiz/snapshots/test_button.ambr b/tests/components/overkiz/snapshots/test_button.ambr index ced8389b1c3ff0..f200dceadada0d 100644 --- a/tests/components/overkiz/snapshots/test_button.ambr +++ b/tests/components/overkiz/snapshots/test_button.ambr @@ -1999,6 +1999,211 @@ 'state': 'unknown', }) # --- +# name: test_button_entities_snapshot[cloud_somfy_tahoma_v2_europe.json][button.cyclic_garage_door_identify-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'button', + 'entity_category': , + 'entity_id': 'button.cyclic_garage_door_identify', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Identify', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': 'mdi:human-greeting-variant', + 'original_name': 'Identify', + 'platform': 'overkiz', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'io://1234-1234-6233/6416929-startIdentify', + 'unit_of_measurement': None, + }) +# --- +# name: test_button_entities_snapshot[cloud_somfy_tahoma_v2_europe.json][button.cyclic_garage_door_identify-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'identify', + 'friendly_name': 'Cyclic Garage Door Identify', + 'icon': 'mdi:human-greeting-variant', + }), + 'context': , + 'entity_id': 'button.cyclic_garage_door_identify', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unknown', + }) +# --- +# name: test_button_entities_snapshot[cloud_somfy_tahoma_v2_europe.json][button.cyclic_garage_door_start_identify-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'button', + 'entity_category': , + 'entity_id': 'button.cyclic_garage_door_start_identify', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Start identify', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': 'mdi:human-greeting-variant', + 'original_name': 'Start identify', + 'platform': 'overkiz', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'io://1234-1234-6233/6416929-identify', + 'unit_of_measurement': None, + }) +# --- +# name: test_button_entities_snapshot[cloud_somfy_tahoma_v2_europe.json][button.cyclic_garage_door_start_identify-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Cyclic Garage Door Start identify', + 'icon': 'mdi:human-greeting-variant', + }), + 'context': , + 'entity_id': 'button.cyclic_garage_door_start_identify', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unknown', + }) +# --- +# name: test_button_entities_snapshot[cloud_somfy_tahoma_v2_europe.json][button.cyclic_garage_door_stop_identify-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'button', + 'entity_category': , + 'entity_id': 'button.cyclic_garage_door_stop_identify', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Stop identify', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': 'mdi:human-greeting-variant', + 'original_name': 'Stop identify', + 'platform': 'overkiz', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'io://1234-1234-6233/6416929-stopIdentify', + 'unit_of_measurement': None, + }) +# --- +# name: test_button_entities_snapshot[cloud_somfy_tahoma_v2_europe.json][button.cyclic_garage_door_stop_identify-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Cyclic Garage Door Stop identify', + 'icon': 'mdi:human-greeting-variant', + }), + 'context': , + 'entity_id': 'button.cyclic_garage_door_stop_identify', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unknown', + }) +# --- +# name: test_button_entities_snapshot[cloud_somfy_tahoma_v2_europe.json][button.cyclic_garage_door_toggle-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'button', + 'entity_category': None, + 'entity_id': 'button.cyclic_garage_door_toggle', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Toggle', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': 'mdi:sync', + 'original_name': 'Toggle', + 'platform': 'overkiz', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'io://1234-1234-6233/6416929-cycle', + 'unit_of_measurement': None, + }) +# --- +# name: test_button_entities_snapshot[cloud_somfy_tahoma_v2_europe.json][button.cyclic_garage_door_toggle-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Cyclic Garage Door Toggle', + 'icon': 'mdi:sync', + }), + 'context': , + 'entity_id': 'button.cyclic_garage_door_toggle', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unknown', + }) +# --- # name: test_button_entities_snapshot[cloud_somfy_tahoma_v2_europe.json][button.dining_room_shutter_identify-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ @@ -5178,6 +5383,211 @@ 'state': 'unknown', }) # --- +# name: test_button_entities_snapshot[cloud_somfy_tahoma_v2_europe.json][button.swinging_gate_identify-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'button', + 'entity_category': , + 'entity_id': 'button.swinging_gate_identify', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Identify', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': 'mdi:human-greeting-variant', + 'original_name': 'Identify', + 'platform': 'overkiz', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'io://1234-1234-8983/1959462-startIdentify', + 'unit_of_measurement': None, + }) +# --- +# name: test_button_entities_snapshot[cloud_somfy_tahoma_v2_europe.json][button.swinging_gate_identify-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'identify', + 'friendly_name': 'Swinging Gate Identify', + 'icon': 'mdi:human-greeting-variant', + }), + 'context': , + 'entity_id': 'button.swinging_gate_identify', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unknown', + }) +# --- +# name: test_button_entities_snapshot[cloud_somfy_tahoma_v2_europe.json][button.swinging_gate_start_identify-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'button', + 'entity_category': , + 'entity_id': 'button.swinging_gate_start_identify', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Start identify', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': 'mdi:human-greeting-variant', + 'original_name': 'Start identify', + 'platform': 'overkiz', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'io://1234-1234-8983/1959462-identify', + 'unit_of_measurement': None, + }) +# --- +# name: test_button_entities_snapshot[cloud_somfy_tahoma_v2_europe.json][button.swinging_gate_start_identify-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Swinging Gate Start identify', + 'icon': 'mdi:human-greeting-variant', + }), + 'context': , + 'entity_id': 'button.swinging_gate_start_identify', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unknown', + }) +# --- +# name: test_button_entities_snapshot[cloud_somfy_tahoma_v2_europe.json][button.swinging_gate_stop_identify-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'button', + 'entity_category': , + 'entity_id': 'button.swinging_gate_stop_identify', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Stop identify', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': 'mdi:human-greeting-variant', + 'original_name': 'Stop identify', + 'platform': 'overkiz', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'io://1234-1234-8983/1959462-stopIdentify', + 'unit_of_measurement': None, + }) +# --- +# name: test_button_entities_snapshot[cloud_somfy_tahoma_v2_europe.json][button.swinging_gate_stop_identify-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Swinging Gate Stop identify', + 'icon': 'mdi:human-greeting-variant', + }), + 'context': , + 'entity_id': 'button.swinging_gate_stop_identify', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unknown', + }) +# --- +# name: test_button_entities_snapshot[cloud_somfy_tahoma_v2_europe.json][button.swinging_gate_toggle-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'button', + 'entity_category': None, + 'entity_id': 'button.swinging_gate_toggle', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Toggle', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': 'mdi:sync', + 'original_name': 'Toggle', + 'platform': 'overkiz', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'io://1234-1234-8983/1959462-cycle', + 'unit_of_measurement': None, + }) +# --- +# name: test_button_entities_snapshot[cloud_somfy_tahoma_v2_europe.json][button.swinging_gate_toggle-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Swinging Gate Toggle', + 'icon': 'mdi:sync', + }), + 'context': , + 'entity_id': 'button.swinging_gate_toggle', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unknown', + }) +# --- # name: test_button_entities_snapshot[local_somfy_tahoma_switch_europe_2.json][button.back_door_shutter_identify-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ diff --git a/tests/components/overkiz/snapshots/test_cover.ambr b/tests/components/overkiz/snapshots/test_cover.ambr index 6118467f5d6dbf..29c823d3fc4e0d 100644 --- a/tests/components/overkiz/snapshots/test_cover.ambr +++ b/tests/components/overkiz/snapshots/test_cover.ambr @@ -1242,6 +1242,59 @@ 'state': 'closed', }) # --- +# name: test_cover_entities_snapshot[cloud_somfy_tahoma_v2_europe.json][cover.cyclic_garage_door-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'cover', + 'entity_category': None, + 'entity_id': 'cover.cyclic_garage_door', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': None, + 'platform': 'overkiz', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': , + 'translation_key': None, + 'unique_id': 'io://1234-1234-6233/6416929', + 'unit_of_measurement': None, + }) +# --- +# name: test_cover_entities_snapshot[cloud_somfy_tahoma_v2_europe.json][cover.cyclic_garage_door-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'garage', + 'friendly_name': 'Cyclic Garage Door', + 'is_closed': None, + 'supported_features': , + }), + 'context': , + 'entity_id': 'cover.cyclic_garage_door', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unknown', + }) +# --- # name: test_cover_entities_snapshot[cloud_somfy_tahoma_v2_europe.json][cover.dining_room_shutter-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ @@ -2208,6 +2261,59 @@ 'state': 'closed', }) # --- +# name: test_cover_entities_snapshot[cloud_somfy_tahoma_v2_europe.json][cover.swinging_gate-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'cover', + 'entity_category': None, + 'entity_id': 'cover.swinging_gate', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': None, + 'platform': 'overkiz', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': , + 'translation_key': None, + 'unique_id': 'io://1234-1234-8983/1959462', + 'unit_of_measurement': None, + }) +# --- +# name: test_cover_entities_snapshot[cloud_somfy_tahoma_v2_europe.json][cover.swinging_gate-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'gate', + 'friendly_name': 'Swinging Gate', + 'is_closed': None, + 'supported_features': , + }), + 'context': , + 'entity_id': 'cover.swinging_gate', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unknown', + }) +# --- # name: test_cover_entities_snapshot[local_somfy_connexoon_europe.json][cover.terrace_awning-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ diff --git a/tests/components/overkiz/test_cover.py b/tests/components/overkiz/test_cover.py index ba3179f5f8cd13..10afa594fb21d0 100644 --- a/tests/components/overkiz/test_cover.py +++ b/tests/components/overkiz/test_cover.py @@ -134,6 +134,16 @@ "rts://1234-1234-6233/16730717", "cover.rts_gate", ) +CYCLIC_GARAGE_DOOR = FixtureDevice( + "setup/cloud_somfy_tahoma_v2_europe.json", + "io://1234-1234-6233/6416929", + "cover.cyclic_garage_door", +) +CYCLIC_SWINGING_GATE = FixtureDevice( + "setup/cloud_somfy_tahoma_v2_europe.json", + "io://1234-1234-8983/1959462", + "cover.swinging_gate", +) SLIDING_DISCRETE_GATE = FixtureDevice( "setup/cloud_somfy_tahoma_v2_europe.json", "io://1234-1234-6233/16730051", @@ -193,6 +203,8 @@ async def test_cover_entities_snapshot( (DYNAMIC_GARAGE_DOOR_OGP, SERVICE_OPEN_COVER, "open", None, CoverState.OPENING), (DYNAMIC_GATE, SERVICE_OPEN_COVER, "open", None, CoverState.OPENING), (RTS_GATE_4T, SERVICE_OPEN_COVER, "cycle", [0], CoverState.OPENING), + (CYCLIC_GARAGE_DOOR, SERVICE_OPEN_COVER, "cycle", None, CoverState.OPENING), + (CYCLIC_SWINGING_GATE, SERVICE_OPEN_COVER, "cycle", None, CoverState.OPENING), (SLIDING_DISCRETE_GATE, SERVICE_OPEN_COVER, "open", None, CoverState.OPENING), (PARTIAL_GARAGE_DOOR, SERVICE_OPEN_COVER, "open", None, CoverState.OPENING), ( @@ -220,6 +232,8 @@ async def test_cover_entities_snapshot( # Cycle command is used for both open and close; device reports OPENING # since the RTS protocol has no directional feedback. (RTS_GATE_4T, SERVICE_CLOSE_COVER, "cycle", [0], CoverState.OPENING), + (CYCLIC_GARAGE_DOOR, SERVICE_CLOSE_COVER, "cycle", None, CoverState.OPENING), + (CYCLIC_SWINGING_GATE, SERVICE_CLOSE_COVER, "cycle", None, CoverState.OPENING), (SLIDING_DISCRETE_GATE, SERVICE_CLOSE_COVER, "close", None, CoverState.CLOSING), (PARTIAL_GARAGE_DOOR, SERVICE_CLOSE_COVER, "close", None, CoverState.CLOSING), ( @@ -328,6 +342,8 @@ async def test_cover_entities_snapshot( "open-dynamic-garage-door-ogp", "open-dynamic-gate", "open-rts-gate-4t", + "open-cyclic-garage-door", + "open-cyclic-swinging-gate", "open-sliding-discrete-gate", "open-partial-garage-door", "open-up-down-bioclimatic-pergola", @@ -341,6 +357,8 @@ async def test_cover_entities_snapshot( "close-dynamic-garage-door-ogp", "close-dynamic-gate", "close-rts-gate-4t", + "close-cyclic-garage-door", + "close-cyclic-swinging-gate", "close-sliding-discrete-gate", "close-partial-garage-door", "close-up-down-bioclimatic-pergola",