Skip to content

Ignore stale moving operational status for position aware Matter covers - #177571

Draft
agners wants to merge 2 commits into
devfrom
matter-cover-position-target-moving-state
Draft

Ignore stale moving operational status for position aware Matter covers#177571
agners wants to merge 2 commits into
devfrom
matter-cover-position-target-moving-state

Conversation

@agners

@agners agners commented Jul 29, 2026

Copy link
Copy Markdown
Member

Breaking change

Proposed change

Note: stacked on #177540, the first commit belongs to that PR.

Ignore a stale moving OperationalStatus for position aware Matter covers: a covering whose current position(s) match the target position(s) is not moving, regardless of what the operational status claims.

Some devices deliver a single Matter report containing a moving OperationalStatus together with the final positions (current position already at target), without a subsequent report clearing the moving state. This has been observed with Rademacher shutters behind a Matter bridge (see home-assistant/addons#4724, server debug log analysis): the only OperationalStatus reports in a 2 hour debug log arrived together with TargetPositionLiftPercent100ths = CurrentPositionLiftPercent100ths = 10000, claiming "closing" while the device was provably stationary at its target. Since the integration derives is_opening/is_closing solely from OperationalStatus, the cover entity remained stuck in a closing state until the Matter Server was restarted.

The Matter specification provides the tools to detect this: for position aware covers the target position attributes are mandatory alongside the current position attributes (identical conformance, LF & PA_LF resp. TL & PA_TL), the target position "SHALL reflect the requested position" (set upon command receipt, and set to the current position by StopMotion), and the current position "SHALL always reflect the physical position" (section 5.3.4.3). A covering resting at its target is therefore not moving.

The check is deliberately asymmetric: position/target equality only ever forces the moving state off, a position/target mismatch never forces it on. Real-world target values cannot be fully trusted, e.g. the mock_window_covering_pa_lift fixture (a diagnostics dump of a real Eliteu/Longan Link WNCV-DA01) rests with TargetPositionLiftPercent100ths = 0 while CurrentPositionLiftPercent100ths = 4900. With this polarity a bogus target can at most fail to unstick a broken cover, but can never wedge a healthy one into a moving state.

When the positions cannot be compared (non position aware covers, null values, missing target attribute), the operational status remains authoritative, as before. Debug logging now states which movement detection mode is in use for each update.

Minor behavior change for spec-compliant devices: when the final position report (current = target) arrives before the report clearing the operational status, the cover now shows the final state immediately instead of remaining in a moving state until the status clears (observed up to ~800 ms with Eve MotionBlinds).

The target position attributes are added as optional_attributes to the position aware discovery schemas so the entities subscribe to their updates; discovery matching is unchanged.

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

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:

agners and others added 2 commits July 29, 2026 10:12
Some devices report attribute changes which make up a single logical
state change as separate attribute updates shortly after each other,
e.g. Eve MotionBlinds report OperationalStatus stopped before the final
CurrentPositionLiftPercent100ths value. Writing the entity state on each
individual update publishes an intermittent state (e.g. stopped at 1%
open followed by closed), causing state change automations to trigger
twice.

Add opt-in state write debouncing to the Matter entity base class and
enable it for covers, which derive their state from both the operational
status and the current position attributes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Some devices deliver a single Matter report containing a moving
WindowCovering OperationalStatus together with the final positions
(current position already at target), without a subsequent report
clearing the moving state. The Matter Server WebSocket API additionally
splits attribute updates from a single Matter report into separate
per-attribute events, which the integration processes individually.
As a result the cover entity can get stuck in an opening/closing state.

Per the Matter specification, position aware covers must expose target
position attributes which reflect the requested position, while the
current position attributes always reflect the physical position. Use
this to gate the moving state: a covering whose current position(s)
match the target position(s) is not moving, regardless of what the
operational status claims. When positions are unavailable or unknown
(non position aware covers, null values), the operational status remains
authoritative, as before.

Also add debug logging stating which movement detection mode is in use.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 29, 2026 17:02
@home-assistant home-assistant Bot added bugfix cla-signed has-tests integration: matter Top 100 Integration is ranked within the top 100 by usage Top 200 Integration is ranked within the top 200 by usage Top 50 Integration is ranked within the top 50 by usage Quality Scale: No score labels Jul 29, 2026
@home-assistant

Copy link
Copy Markdown
Contributor

Hey there @home-assistant/matter, mind taking a look at this pull request as it has been labeled with an integration (matter) you are listed as a code owner for? Thanks!

Code owner commands

Code owners of matter can trigger bot actions by commenting:

  • @home-assistant close Closes the pull request.
  • @home-assistant mark-draft Mark the pull request as draft.
  • @home-assistant ready-for-review Remove the draft status from the pull request.
  • @home-assistant rename Awesome new title Renames the pull request.
  • @home-assistant reopen Reopen the pull request.
  • @home-assistant unassign matter Removes the current integration label and assignees on the pull request, add the integration domain after the command.
  • @home-assistant update-branch Update the pull request branch with the base branch.
  • @home-assistant add-label needs-more-information Add a label (needs-more-information, problem in dependency, problem in custom component, problem in config, problem in device, feature-request) to the pull request.
  • @home-assistant remove-label needs-more-information Remove a label (needs-more-information, problem in dependency, problem in custom component, problem in config, problem in device, feature-request) on the pull request.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Prevents position-aware Matter covers from remaining stuck in a moving state when current and target positions match.

Changes:

  • Ignores stale moving operational status at the target position.
  • Debounces cover state writes to coalesce split updates.
  • Adds coverage for stale, unknown, and split attribute updates.

Reviewed changes

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

File Description
homeassistant/components/matter/entity.py Adds opt-in state-write debouncing.
homeassistant/components/matter/cover.py Compares target/current positions and subscribes to target updates.
tests/components/matter/test_cover.py Tests debouncing and movement-state handling.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix cla-signed has-tests integration: matter Quality Scale: No score Top 50 Integration is ranked within the top 50 by usage Top 100 Integration is ranked within the top 100 by usage Top 200 Integration is ranked within the top 200 by usage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants