Skip to content

Fix tilt and position support for VenetianBlind covers in Overkiz#170974

Merged
zweckj merged 10 commits into
home-assistant:devfrom
iMicknl:fix/overkiz-dynamic-venetian-blind-tilt
May 18, 2026
Merged

Fix tilt and position support for VenetianBlind covers in Overkiz#170974
zweckj merged 10 commits into
home-assistant:devfrom
iMicknl:fix/overkiz-dynamic-venetian-blind-tilt

Conversation

@iMicknl
Copy link
Copy Markdown
Member

@iMicknl iMicknl commented May 17, 2026

Proposed change

Fixes #170283: Tilt controls not available for DynamicVenetianBlind

  • Devices: ogp:VenetianBlind (OGP protocol), widget DynamicVenetianBlind
  • Commands: setClosure, setOrientation, open, close, stop (no tiltUp/tiltDown)
  • Fix: Now gets SET_POSITION + SET_TILT_POSITION + OPEN + CLOSE + STOP (features: 143)

Fixes #170176: is_closed state unknown for PositionableVenetianBlind

  • Devices: zigbee:SomfyVenetianBlindComponent, widget PositionableVenetianBlind
  • Commands: setClosure, setOrientation, setClosureAndOrientation, open, close, stop
  • The device lacks core:OpenClosedState in its actual states, so is_closed fell through to checking position — but
    without current_position_state set, position was always None → is_closed = None (unknown)
  • Fix: current_position_state=CORE_CLOSURE now set, so is_closed correctly resolves via position

Test fixtures added:

  1. DynamicVenetianBlind (ogp protocol) — matches the exact device reported in Tilt controls are not available for VenetianBlind (DynamicVenetianBlind) after 2026.5 in Overkiz #170283
  2. PositionableVenetianBlind (zigbee protocol) — matches the device reported in is_closed state unknown for VenetianBlind/PositionableVenetianBlind (zigbee:SomfyVenetianBlindComponent) after 2026.5 in Overkiz #170176

Fixes #170176

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New integration (thank you!)
  • New feature (which adds functionality to an existing integration)
  • Deprecation (breaking change to happen in the future)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

  • This PR fixes or closes issue: fixes #
  • This PR is related to issue:
  • Link to documentation pull request:
  • Link to developer documentation pull request:
  • Link to frontend pull request:

Checklist

  • I understand the code I am submitting and can explain how it works.
  • The code change is tested and works locally.
  • Local tests pass. Your PR cannot be merged unless tests pass
  • There is no commented out code in this PR.
  • I have followed the development checklist
  • I have followed the perfect PR recommendations
  • The code has been formatted using Ruff (ruff format homeassistant tests)
  • Tests have been added to verify that the new code works.
  • Any generated code has been carefully reviewed for correctness and compliance with project standards.

If user exposed functionality or configuration variables are added/changed:

If the code communicates with devices, web services, or third-party tools:

  • The manifest file has all fields filled out correctly.
    Updated and included derived files by running: python3 -m script.hassfest.
  • New or updated dependencies have been added to requirements_all.txt.
    Updated by running python3 -m script.gen_requirements_all.
  • For the updated dependencies a diff between library versions and ideally a link to the changelog/release notes is added to the PR description.

To help with the load of incoming pull requests:

Copilot AI review requested due to automatic review settings May 17, 2026 12:12
@iMicknl iMicknl force-pushed the fix/overkiz-dynamic-venetian-blind-tilt branch from 3cc8a82 to 30b6222 Compare May 17, 2026 12:12
@iMicknl iMicknl added this to the 2026.5.3 milestone May 17, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes two regressions in the Overkiz cover integration affecting VenetianBlind UI-class devices: the DynamicVenetianBlind widget (ogp) lost tilt position support, and PositionableVenetianBlind (zigbee Somfy) reported is_closed=unknown because no current_position_state was configured to fall back to. The fix extends the existing UIClass.VENETIAN_BLIND description in cover.py with closure/orientation position states and commands plus a stop_command, so both devices receive features 143 (SET_POSITION + SET_TILT_POSITION + OPEN/CLOSE/STOP) and is_closed resolves from position when core:OpenClosedState is absent.

Changes:

  • Add current_position_state, set_position_command, stop_command, current_tilt_position_state, and set_tilt_position_command to the UIClass.VENETIAN_BLIND OverkizCoverDescription.
  • Add two new devices (DynamicVenetianBlind ogp, PositionableVenetianBlind zigbee) to the shared cloud_somfy_tahoma_v2_europe.json setup fixture.
  • Add parametrized open/close/stop/set_position/set_tilt_position tests, plus an explicit is_closed fallback-from-position regression test; update button/cover snapshots.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
homeassistant/components/overkiz/cover.py Adds closure + slate-orientation state/command bindings and stop_command to the VENETIAN_BLIND description so position/tilt features and is_closed work.
tests/components/overkiz/fixtures/setup/cloud_somfy_tahoma_v2_europe.json Adds two new venetian blind devices reproducing the two reported bugs.
tests/components/overkiz/test_cover.py Adds new FixtureDevices, parametrized open/close/stop/set-position/set-tilt cases, and an is_closed-from-position test.
tests/components/overkiz/snapshots/test_cover.ambr New snapshot entries for the two venetian blind devices; also adds two duplicated full-fixture snapshot blocks (json0/json1/json2) due to shared fixture re-use in SNAPSHOT_FIXTURES.
tests/components/overkiz/snapshots/test_button.ambr Adds identify-button snapshots for the two new venetian blind devices.

Comment thread tests/components/overkiz/test_cover.py Outdated
@iMicknl iMicknl marked this pull request as draft May 17, 2026 12:15
Add position and tilt position state/command fields to the
UIClass.VENETIAN_BLIND entity description. These are safely gated
by has_command() checks, so devices that lack setClosure,
setOrientation, or stop simply won't advertise those features.

Fixes DynamicVenetianBlind (ogp) losing SET_TILT_POSITION after the
entity description migration, and PositionableVenetianBlind (zigbee)
reporting unknown is_closed state due to missing position fallback.

Closes home-assistant#170283
Closes home-assistant#170176
@iMicknl iMicknl force-pushed the fix/overkiz-dynamic-venetian-blind-tilt branch from 30b6222 to 1daffbf Compare May 17, 2026 12:17
The new devices share the same fixture file as SHUTTER, so they
are already captured by the existing snapshot case. Removing them
from SNAPSHOT_FIXTURES eliminates 132 duplicated snapshot lines.
Copilot AI review requested due to automatic review settings May 17, 2026 12:20
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

iMicknl added 3 commits May 17, 2026 12:29
Use 1:1 copies of real device data from issue diagnostics (home-assistant#170283,
home-assistant#170176) instead of simplified versions. This ensures the fixtures
accurately represent real-world devices with all commands, states,
and attributes.
The diagnostics for issue home-assistant#170176 indicate api_type=local, so the
PositionableVenetianBlind device belongs in the local fixture file
rather than the cloud one.
Copilot AI review requested due to automatic review settings May 17, 2026 12:37
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.

The tilt position mapping is already covered by the existing pergola
test which exercises the same setOrientation command and inversion
logic.
@iMicknl iMicknl marked this pull request as ready for review May 17, 2026 12:44
Copilot AI review requested due to automatic review settings May 17, 2026 12:44
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.

@zweckj
Copy link
Copy Markdown
Member

zweckj commented May 18, 2026

@iMicknl this has merge conflicts now

@zweckj zweckj marked this pull request as draft May 18, 2026 11:42
Copilot AI review requested due to automatic review settings May 18, 2026 11:45
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.

@iMicknl iMicknl marked this pull request as ready for review May 18, 2026 11:49
Copilot AI review requested due to automatic review settings May 18, 2026 11:49
@iMicknl iMicknl marked this pull request as draft May 18, 2026 11:49
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

tests/components/overkiz/fixtures/setup/cloud_somfy_tahoma_v2_europe.json:5730

  • These changes re-encode existing French label strings (Télécommande, Entrée, Fenêtre, Détecteur Fumée) from literal UTF-8 characters to \u00XX JSON escape sequences. They are unrelated to the VenetianBlind fix in this PR and appear to have been introduced by re-saving the fixture with ensure_ascii=True. Please revert these incidental encoding changes so the PR is limited to the bugfix.
      "label": "Télécommande Salon",
      "deviceURL": "rtds://1234-1234-6233/124768",
      "shortcut": false,
      "controllableName": "rtds:RTDSRemoteControllerComponent",
      "definition": {
        "commands": [],
        "states": [
          {
            "type": "ContinuousState",
            "qualifiedName": "rtds:ControllerBatteryState"
          },
          {
            "type": "ContinuousState",
            "qualifiedName": "rtds:ControllerBipState"
          },
          {
            "type": "ContinuousState",
            "qualifiedName": "rtds:ControllerOrderTypeState"
          },
          {
            "type": "ContinuousState",
            "qualifiedName": "rtds:ControllerOriginatorState"
          },
          {
            "type": "ContinuousState",
            "qualifiedName": "rtds:ControllerSensingState"
          },
          {
            "type": "ContinuousState",
            "qualifiedName": "rtds:ControllerSirenState"
          }
        ],
        "dataProperties": [],
        "widgetName": "AlarmRemoteController",
        "uiProfiles": ["Specific"],
        "uiClass": "RemoteController",
        "qualifiedName": "rtds:RTDSRemoteControllerComponent",
        "type": "REMOTE_CONTROLLER"
      },
      "states": [
        {
          "name": "rtds:ControllerOriginatorState",
          "type": 1,
          "value": 2
        },
        {
          "name": "rtds:ControllerSensingState",
          "type": 3,
          "value": "KO"
        },
        {
          "name": "rtds:ControllerBatteryState",
          "type": 3,
          "value": "OK"
        },
        {
          "name": "rtds:ControllerOrderTypeState",
          "type": 3,
          "value": "off"
        }
      ],
      "available": true,
      "enabled": true,
      "placeOID": "48200981-d96f-4a75-bcf0-a3c6f0b692dc",
      "widget": "AlarmRemoteController",
      "type": 4,
      "oid": "41e932ea-c52b-48d2-98f2-aebc6f72c51b",
      "uiClass": "RemoteController"
    },
    {
      "creationTime": 1501225074000,
      "lastUpdateTime": 1501225074000,
      "label": "Télécommande Bureau",
      "deviceURL": "rtds://1234-1234-6233/169771",
      "shortcut": false,
      "controllableName": "rtds:RTDSRemoteControllerComponent",
      "definition": {
        "commands": [],
        "states": [
          {
            "type": "ContinuousState",
            "qualifiedName": "rtds:ControllerBatteryState"
          },
          {
            "type": "ContinuousState",
            "qualifiedName": "rtds:ControllerBipState"
          },
          {
            "type": "ContinuousState",
            "qualifiedName": "rtds:ControllerOrderTypeState"
          },
          {
            "type": "ContinuousState",
            "qualifiedName": "rtds:ControllerOriginatorState"
          },
          {
            "type": "ContinuousState",
            "qualifiedName": "rtds:ControllerSensingState"
          },
          {
            "type": "ContinuousState",
            "qualifiedName": "rtds:ControllerSirenState"
          }
        ],
        "dataProperties": [],
        "widgetName": "AlarmRemoteController",
        "uiProfiles": ["Specific"],
        "uiClass": "RemoteController",
        "qualifiedName": "rtds:RTDSRemoteControllerComponent",
        "type": "REMOTE_CONTROLLER"
      },
      "states": [
        {
          "name": "rtds:ControllerOriginatorState",
          "type": 1,
          "value": 2
        },
        {
          "name": "rtds:ControllerSensingState",
          "type": 3,
          "value": "KO"
        },
        {
          "name": "rtds:ControllerBatteryState",
          "type": 3,
          "value": "OK"
        },
        {
          "name": "rtds:ControllerOrderTypeState",
          "type": 3,
          "value": "off"
        }
      ],
      "available": true,
      "enabled": true,
      "placeOID": "48200981-d96f-4a75-bcf0-a3c6f0b692dc",
      "widget": "AlarmRemoteController",
      "type": 4,
      "oid": "7a465c7b-aff4-462d-b03c-40a8918df12a",
      "uiClass": "RemoteController"
    },
    {
      "creationTime": 1501224458000,
      "lastUpdateTime": 1501224458000,
      "label": "Hallway",
      "deviceURL": "rtds://1234-1234-6233/232949",
      "shortcut": false,
      "controllableName": "rtds:RTDSMotionSensor",
      "definition": {
        "commands": [],
        "states": [
          {
            "eventBased": true,
            "type": "DiscreteState",
            "values": ["noPersonInside", "personInside"],
            "qualifiedName": "core:OccupancyState"
          },
          {
            "type": "DiscreteState",
            "values": ["dead", "lowBattery", "maintenanceRequired", "noDefect"],
            "qualifiedName": "core:SensorDefectState"
          }
        ],
        "dataProperties": [],
        "widgetName": "MotionSensor",
        "uiProfiles": ["OccupancyDetector"],
        "uiClass": "OccupancySensor",
        "qualifiedName": "rtds:RTDSMotionSensor",
        "type": "SENSOR"
      },
      "states": [
        {
          "name": "core:OccupancyState",
          "type": 3,
          "value": "noPersonInside"
        }
      ],
      "attributes": [
        {
          "name": "core:PowerSourceType",
          "type": 3,
          "value": "battery"
        }
      ],
      "available": true,
      "enabled": true,
      "placeOID": "bcbb34ef-2241-43a1-9c5b-523aa0563ec3",
      "widget": "MotionSensor",
      "type": 2,
      "oid": "20171297-8c25-4107-ba0b-d750288e04d1",
      "uiClass": "OccupancySensor"
    },
    {
      "creationTime": 1501224970000,
      "lastUpdateTime": 1501224970000,
      "label": "Entrée",
      "deviceURL": "rtds://1234-1234-6233/246258",
      "shortcut": false,
      "controllableName": "rtds:RTDSMotionSensor",
      "definition": {
        "commands": [],
        "states": [
          {
            "eventBased": true,
            "type": "DiscreteState",
            "values": ["noPersonInside", "personInside"],
            "qualifiedName": "core:OccupancyState"
          },
          {
            "type": "DiscreteState",
            "values": ["dead", "lowBattery", "maintenanceRequired", "noDefect"],
            "qualifiedName": "core:SensorDefectState"
          }
        ],
        "dataProperties": [],
        "widgetName": "MotionSensor",
        "uiProfiles": ["OccupancyDetector"],
        "uiClass": "OccupancySensor",
        "qualifiedName": "rtds:RTDSMotionSensor",
        "type": "SENSOR"
      },
      "states": [
        {
          "name": "core:OccupancyState",
          "type": 3,
          "value": "noPersonInside"
        }
      ],
      "attributes": [
        {
          "name": "core:PowerSourceType",
          "type": 3,
          "value": "battery"
        }
      ],
      "available": true,
      "enabled": true,
      "placeOID": "50b9c516-c47a-4e19-bb09-771869349f3f",
      "widget": "MotionSensor",
      "type": 2,
      "oid": "bf1443a2-86ec-4b00-b2fd-173c3abea21a",
      "uiClass": "OccupancySensor"
    },
    {
      "creationTime": 1501224664000,
      "lastUpdateTime": 1501224664000,
      "label": "Kitchen",
      "deviceURL": "rtds://1234-1234-6233/288316",
      "shortcut": false,
      "controllableName": "rtds:RTDSMotionSensor",
      "definition": {
        "commands": [],
        "states": [
          {
            "eventBased": true,
            "type": "DiscreteState",
            "values": ["noPersonInside", "personInside"],
            "qualifiedName": "core:OccupancyState"
          },
          {
            "type": "DiscreteState",
            "values": ["dead", "lowBattery", "maintenanceRequired", "noDefect"],
            "qualifiedName": "core:SensorDefectState"
          }
        ],
        "dataProperties": [],
        "widgetName": "MotionSensor",
        "uiProfiles": ["OccupancyDetector"],
        "uiClass": "OccupancySensor",
        "qualifiedName": "rtds:RTDSMotionSensor",
        "type": "SENSOR"
      },
      "states": [
        {
          "name": "core:OccupancyState",
          "type": 3,
          "value": "noPersonInside"
        }
      ],
      "attributes": [
        {
          "name": "core:PowerSourceType",
          "type": 3,
          "value": "battery"
        }
      ],
      "available": true,
      "enabled": true,
      "placeOID": "9b4aeb55-07b3-4088-920e-c08405000ce6",
      "widget": "MotionSensor",
      "type": 2,
      "oid": "82db9927-fc29-483d-8727-0d8d75d44071",
      "uiClass": "OccupancySensor"
    },
    {
      "creationTime": 1501224830000,
      "lastUpdateTime": 1501224830000,
      "label": "Fenêtre Garage",
      "deviceURL": "rtds://1234-1234-6233/394765",
      "shortcut": false,
      "controllableName": "rtds:RTDSContactSensor",
      "definition": {
        "commands": [],
        "states": [
          {
            "type": "DiscreteState",
            "values": ["closed", "open"],
            "qualifiedName": "core:ContactState"
          },
          {
            "type": "DiscreteState",
            "values": ["dead", "lowBattery", "maintenanceRequired", "noDefect"],
            "qualifiedName": "core:SensorDefectState"
          }
        ],
        "dataProperties": [],
        "widgetName": "ContactSensor",
        "uiProfiles": ["DoorContactSensor", "ContactDetector"],
        "uiClass": "ContactSensor",
        "qualifiedName": "rtds:RTDSContactSensor",
        "type": "SENSOR"
      },
      "states": [
        {
          "name": "core:ContactState",
          "type": 3,
          "value": "closed"
        }
      ],
      "attributes": [
        {
          "name": "core:PowerSourceType",
          "type": 3,
          "value": "battery"
        }
      ],
      "available": true,
      "enabled": true,
      "placeOID": "48200981-d96f-4a75-bcf0-a3c6f0b692dc",
      "widget": "ContactSensor",
      "type": 2,
      "oid": "9cdaf8c7-2cd1-4260-9ff3-3908b023853c",
      "uiClass": "ContactSensor"
    },
    {
      "creationTime": 1501224801000,
      "lastUpdateTime": 1501224801000,
      "label": "Porte",
      "deviceURL": "rtds://1234-1234-6233/394781",
      "shortcut": false,
      "controllableName": "rtds:RTDSContactSensor",
      "definition": {
        "commands": [],
        "states": [
          {
            "type": "DiscreteState",
            "values": ["closed", "open"],
            "qualifiedName": "core:ContactState"
          },
          {
            "type": "DiscreteState",
            "values": ["dead", "lowBattery", "maintenanceRequired", "noDefect"],
            "qualifiedName": "core:SensorDefectState"
          }
        ],
        "dataProperties": [],
        "widgetName": "ContactSensor",
        "uiProfiles": ["DoorContactSensor", "ContactDetector"],
        "uiClass": "ContactSensor",
        "qualifiedName": "rtds:RTDSContactSensor",
        "type": "SENSOR"
      },
      "states": [
        {
          "name": "core:ContactState",
          "type": 3,
          "value": "closed"
        }
      ],
      "attributes": [
        {
          "name": "core:PowerSourceType",
          "type": 3,
          "value": "battery"
        }
      ],
      "available": true,
      "enabled": true,
      "placeOID": "48200981-d96f-4a75-bcf0-a3c6f0b692dc",
      "widget": "ContactSensor",
      "type": 2,
      "oid": "eec4dc5d-a957-4489-9c68-5ca22f07c9f8",
      "uiClass": "ContactSensor"
    },
    {
      "creationTime": 1501225017000,
      "lastUpdateTime": 1501225017000,
      "label": "Détecteur Fumée",

@iMicknl iMicknl marked this pull request as ready for review May 18, 2026 11:54
@zweckj zweckj merged commit 94b3736 into home-assistant:dev May 18, 2026
33 checks passed
@frenck frenck modified the milestone: 2026.5.3 May 19, 2026
@frenck frenck mentioned this pull request May 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

4 participants