From 9ce3e00e87af1702985cd88c772d7af5ddee852d Mon Sep 17 00:00:00 2001 From: Mick Vleeshouwer Date: Mon, 18 May 2026 13:40:48 +0200 Subject: [PATCH] Fix is_closed state for DiscretePositionableGarageDoor in Overkiz (#170981) --- homeassistant/components/overkiz/cover.py | 11 + .../setup/local_somfy_tahoma_v2_europe.json | 230 ++++++++++++++++++ .../overkiz/snapshots/test_cover.ambr | 53 ++++ tests/components/overkiz/test_cover.py | 11 + 4 files changed, 305 insertions(+) diff --git a/homeassistant/components/overkiz/cover.py b/homeassistant/components/overkiz/cover.py index 1d6db65fee80..b343603968ea 100644 --- a/homeassistant/components/overkiz/cover.py +++ b/homeassistant/components/overkiz/cover.py @@ -177,6 +177,17 @@ COVER_DESCRIPTIONS: list[OverkizCoverDescription] = [ stop_command=OverkizCommand.STOP, is_closed_state=OverkizState.CORE_OPEN_CLOSED_UNKNOWN, ), + # Needs override since DiscretePositionableGarageDoor reports + # core:OpenClosedUnknownState instead of core:OpenClosedState + # uiClass is GarageDoor + OverkizCoverDescription( + key=UIWidget.DISCRETE_POSITIONABLE_GARAGE_DOOR, + device_class=CoverDeviceClass.GARAGE, + open_command=OverkizCommand.OPEN, + close_command=OverkizCommand.CLOSE, + stop_command=OverkizCommand.STOP, + is_closed_state=OverkizState.CORE_OPEN_CLOSED_UNKNOWN, + ), # Needs override since PositionableGarageDoorWithPartialPosition reports # core:OpenClosedPartialState instead of core:OpenClosedState # uiClass is GarageDoor diff --git a/tests/components/overkiz/fixtures/setup/local_somfy_tahoma_v2_europe.json b/tests/components/overkiz/fixtures/setup/local_somfy_tahoma_v2_europe.json index 62f5241f39b5..4b8666dde8c5 100644 --- a/tests/components/overkiz/fixtures/setup/local_somfy_tahoma_v2_europe.json +++ b/tests/components/overkiz/fixtures/setup/local_somfy_tahoma_v2_europe.json @@ -1674,6 +1674,236 @@ ], "uiClass": "Light" } + }, + { + "deviceURL": "io://1234-5678-3293/12745774", + "available": true, + "synced": true, + "type": 1, + "states": [ + { + "type": 3, + "name": "core:StatusState", + "value": "available" + }, + { + "type": 11, + "name": "core:CommandLockLevelsState", + "value": [] + }, + { + "type": 3, + "name": "core:DiscreteRSSILevelState", + "value": "good" + }, + { + "type": 1, + "name": "core:RSSILevelState", + "value": 100 + }, + { + "type": 3, + "name": "core:OpenClosedUnknownState", + "value": "closed" + }, + { + "type": 3, + "name": "core:NameState", + "value": "Garage Door Rollixo" + }, + { + "type": 1, + "name": "core:PriorityLockTimerState", + "value": 0 + }, + { + "type": 3, + "name": "io:PriorityLockOriginatorState", + "value": "unknown" + } + ], + "attributes": [ + { + "name": "core:Manufacturer", + "type": 3, + "value": "Somfy" + }, + { + "name": "core:FirmwareRevision", + "type": 3, + "value": "5105491C15" + } + ], + "enabled": true, + "label": "Garage Door Rollixo", + "controllableName": "io:DiscreteGarageOpenerIOComponent", + "subsystemId": 0, + "definition": { + "commands": [ + { + "nparams": 0, + "commandName": "up" + }, + { + "nparams": 0, + "commandName": "close" + }, + { + "nparams": 1, + "commandName": "addLockLevel", + "paramsSig": "p1,*p2" + }, + { + "nparams": 0, + "commandName": "resetLockLevels" + }, + { + "nparams": 1, + "commandName": "removeLockLevel", + "paramsSig": "p1" + }, + { + "nparams": 1, + "commandName": "executeManufacturerProcedure", + "paramsSig": "p1,*p2" + }, + { + "nparams": 1, + "commandName": "writeManufacturerData", + "paramsSig": "p1" + }, + { + "nparams": 1, + "commandName": "readManufacturerData", + "paramsSig": "p1" + }, + { + "nparams": 0, + "commandName": "unpairAllOneWayControllers" + }, + { + "nparams": 0, + "commandName": "stopIdentify" + }, + { + "nparams": 0, + "commandName": "startIdentify" + }, + { + "nparams": 1, + "commandName": "pairOneWayController", + "paramsSig": "p1,*p2" + }, + { + "nparams": 1, + "commandName": "delayedStopIdentify", + "paramsSig": "p1" + }, + { + "nparams": 0, + "commandName": "sendIOKey" + }, + { + "nparams": 0, + "commandName": "unpairAllOneWayControllersAndDeleteNode" + }, + { + "nparams": 1, + "commandName": "wink", + "paramsSig": "p1" + }, + { + "nparams": 1, + "commandName": "setConfigState", + "paramsSig": "p1" + }, + { + "nparams": 1, + "commandName": "advancedRefresh", + "paramsSig": "p1,*p2" + }, + { + "nparams": 1, + "commandName": "setName", + "paramsSig": "p1" + }, + { + "nparams": 1, + "commandName": "unpairOneWayController", + "paramsSig": "p1,*p2" + }, + { + "nparams": 2, + "commandName": "runManufacturerSettingsCommand", + "paramsSig": "p1,p2" + }, + { + "nparams": 0, + "commandName": "getName" + }, + { + "nparams": 0, + "commandName": "stop" + }, + { + "nparams": 0, + "commandName": "open" + }, + { + "nparams": 0, + "commandName": "keepOneWayControllersAndDeleteNode" + }, + { + "nparams": 0, + "commandName": "identify" + }, + { + "nparams": 0, + "commandName": "down" + } + ], + "states": [ + { + "name": "core:AdditionalStatusState" + }, + { + "name": "core:PriorityLockTimerState" + }, + { + "name": "io:PriorityLockLevelState" + }, + { + "name": "io:PriorityLockOriginatorState" + }, + { + "name": "core:StatusState" + }, + { + "name": "core:ManufacturerSettingsState" + }, + { + "name": "core:ManufacturerDiagnosticsState" + }, + { + "name": "core:CommandLockLevelsState" + }, + { + "name": "core:NameState" + }, + { + "name": "core:DiscreteRSSILevelState" + }, + { + "name": "core:RSSILevelState" + }, + { + "name": "core:OpenClosedUnknownState" + } + ], + "widgetName": "DiscretePositionableGarageDoor", + "uiClass": "GarageDoor", + "type": "ACTUATOR" + } } ] } diff --git a/tests/components/overkiz/snapshots/test_cover.ambr b/tests/components/overkiz/snapshots/test_cover.ambr index 29c823d3fc4e..48c0f73cd386 100644 --- a/tests/components/overkiz/snapshots/test_cover.ambr +++ b/tests/components/overkiz/snapshots/test_cover.ambr @@ -3676,6 +3676,59 @@ 'state': 'open', }) # --- +# name: test_cover_entities_snapshot[local_somfy_tahoma_v2_europe.json][cover.garage_door_rollixo-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.garage_door_rollixo', + '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-5678-3293/12745774', + 'unit_of_measurement': None, + }) +# --- +# name: test_cover_entities_snapshot[local_somfy_tahoma_v2_europe.json][cover.garage_door_rollixo-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'garage', + 'friendly_name': 'Garage Door Rollixo', + 'is_closed': True, + 'supported_features': , + }), + 'context': , + 'entity_id': 'cover.garage_door_rollixo', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'closed', + }) +# --- # name: test_cover_entities_snapshot[local_somfy_tahoma_v2_europe.json][cover.garden_pergola-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ diff --git a/tests/components/overkiz/test_cover.py b/tests/components/overkiz/test_cover.py index 10afa594fb21..c556e0acbd85 100644 --- a/tests/components/overkiz/test_cover.py +++ b/tests/components/overkiz/test_cover.py @@ -114,6 +114,11 @@ UP_DOWN_SHEER_SCREEN = FixtureDevice( "rts://1234-1234-6362/16753206", "cover.kitchen_sheer_screen", ) +DISCRETE_GARAGE_DOOR = FixtureDevice( + "setup/local_somfy_tahoma_v2_europe.json", + "io://1234-5678-3293/12745774", + "cover.garage_door_rollixo", +) DYNAMIC_GARAGE_DOOR = FixtureDevice( "setup/cloud_somfy_tahoma_v2_europe.json", "io://1234-1234-6233/16730050", @@ -199,6 +204,7 @@ async def test_cover_entities_snapshot( (SHUTTER, SERVICE_OPEN_COVER, "open", None, CoverState.OPENING), (AWNING, SERVICE_OPEN_COVER, "deploy", None, CoverState.OPENING), (GARAGE, SERVICE_OPEN_COVER, "open", None, CoverState.OPENING), + (DISCRETE_GARAGE_DOOR, SERVICE_OPEN_COVER, "open", None, CoverState.OPENING), (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), @@ -220,6 +226,7 @@ async def test_cover_entities_snapshot( (SHUTTER, SERVICE_CLOSE_COVER, "close", None, CoverState.CLOSING), (AWNING, SERVICE_CLOSE_COVER, "undeploy", None, CoverState.CLOSING), (GARAGE, SERVICE_CLOSE_COVER, "close", None, CoverState.CLOSING), + (DISCRETE_GARAGE_DOOR, SERVICE_CLOSE_COVER, "close", None, CoverState.CLOSING), (DYNAMIC_GARAGE_DOOR, SERVICE_CLOSE_COVER, "close", None, CoverState.CLOSING), ( DYNAMIC_GARAGE_DOOR_OGP, @@ -255,6 +262,7 @@ async def test_cover_entities_snapshot( (SHUTTER, SERVICE_STOP_COVER, "stop", None, CoverState.CLOSED), (AWNING, SERVICE_STOP_COVER, "stop", None, CoverState.CLOSED), (GARAGE, SERVICE_STOP_COVER, "stop", None, CoverState.CLOSED), + (DISCRETE_GARAGE_DOOR, SERVICE_STOP_COVER, "stop", None, CoverState.CLOSED), (DYNAMIC_GARAGE_DOOR, SERVICE_STOP_COVER, "stop", None, CoverState.CLOSED), (DYNAMIC_GARAGE_DOOR_OGP, SERVICE_STOP_COVER, "stop", None, CoverState.CLOSED), (DYNAMIC_GATE, SERVICE_STOP_COVER, "stop", None, CoverState.OPEN), @@ -338,6 +346,7 @@ async def test_cover_entities_snapshot( "open-roller-shutter", "open-awning", "open-garage-door", + "open-discrete-garage-door", "open-dynamic-garage-door", "open-dynamic-garage-door-ogp", "open-dynamic-gate", @@ -353,6 +362,7 @@ async def test_cover_entities_snapshot( "close-roller-shutter", "close-awning", "close-garage-door", + "close-discrete-garage-door", "close-dynamic-garage-door", "close-dynamic-garage-door-ogp", "close-dynamic-gate", @@ -368,6 +378,7 @@ async def test_cover_entities_snapshot( "stop-roller-shutter", "stop-awning", "stop-garage-door", + "stop-discrete-garage-door", "stop-dynamic-garage-door", "stop-dynamic-garage-door-ogp", "stop-dynamic-gate",