Skip to content

Expose zone runtime context on the override sensor - #22

Open
Cloudore wants to merge 1 commit into
cgonfer:mainfrom
Cloudore:feat/runtime-attributes
Open

Expose zone runtime context on the override sensor#22
Cloudore wants to merge 1 commit into
cgonfer:mainfrom
Cloudore:feat/runtime-attributes

Conversation

@Cloudore

@Cloudore Cloudore commented Sep 4, 2026

Copy link
Copy Markdown

Summary

  • Adds compact runtime context to the per-zone override sensor attributes so a dashboard or automation can explain a zone without opening the panel: runtime_state, control_mode, the Manual adjustment manual_source / manual_policy / manual_since / manual_until / manual_changed_fields, the effective Profile (effective_profile_id, effective_profile_name, schedule_source: default | profile | profile_pause), and the last target Velair delivered (last_applied_source, last_applied_at, last_applied_action, last_applied_temperature or range, last_applied_hvac_mode).
  • Backed by a new VelairScheduler.get_zone_context(); the last-applied register is runtime only and starts empty after a restart. Existing attributes are unchanged.
  • Motivation: a Lovelace dashboard that shows "why is this room at 27°" (schedule, manual by app, profile) today needs the WebSocket zone_runtime payload; these attributes make that available to plain cards and state-triggered automations.

Checks

  • Backend tests pass with python -m unittest discover -s tests (adds tests/backend/test_runtime_attributes.py)
  • Frontend TypeScript check passes with npx tsc --noEmit (no frontend changes)
  • Frontend build passes with npm run build (bundle unchanged)
  • Documentation was updated when behavior changed (docs/user/usage.md, Zone override entity)

Manual testing

Installed on Home Assistant 2026.8.2 with six managed climates (five Midea CCM15 zones and one LocalTuya unit). The override sensors expose the new attributes immediately after setup (runtime_state: paused while the scheduler is paused, control_mode: automatic, schedule_source: default); after a delivery, last_applied_* reflects the applied block and its source.

🤖 Generated with Claude Code

https://claude.ai/code/session_01F2KBugsLZkL6yR7BB95pKK

The per-zone override sensor now carries compact runtime context so a
dashboard or automation can explain a zone without opening the panel:
runtime_state and control_mode, the Manual adjustment source, policy, start
and expiry, the effective Profile and schedule source, and the last target
Velair delivered with its source, time, action, temperature or range and
HVAC mode. The last-applied values are runtime only. A new
`get_zone_context` scheduler method backs the attributes; existing
attributes are unchanged.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WJhD4sYeWQvoikjYP2CxUr
@cgonfer

cgonfer commented Sep 4, 2026

Copy link
Copy Markdown
Owner

Thank you for the contribution and for explaining the use case so clearly. Making per-zone runtime context available to standard Home Assistant dashboards and automations is a useful idea.

Before merging, I think we need to clarify the public contract and reconsider parts of the implementation. In particular, it is currently unclear whether last_applied_* represents the last scheduled intent or the last command physically delivered to the climate entity. Those can differ when features such as Room Assist or restoration logic are involved.

I found several cases that the current implementation does not handle consistently:

  • velair.set_temperature emits climate_target_applied directly but does not update the new _last_applied register.
  • Updating _last_applied does not directly notify the entity, so its attributes may remain stale until another scheduler update occurs.
  • Room Assist can send a different final target from the scheduled target stored here.
  • Data reset and Celsius/Fahrenheit migration do not clear or convert the cached temperatures.
  • A profile zone with behavior: normal uses the Default schedule, but schedule_source is currently reported as profile.
  • Runtime diagnostics already maintains last-application information, so introducing a second register creates two sources that can diverge.

I also have concerns about adding this amount of independently useful runtime information to the existing Zone override sensor. Home Assistant generally recommends separate entities for independently useful values, both to keep entity contracts clear and to avoid unnecessary Recorder growth.

The backend test suite passes, which is a good starting point. However, the new tests mainly exercise the getter directly. We would also need coverage for actual entity publication, velair.set_temperature, Room Assist, reset, unit migration, scalar and range targets, failed deliveries, and the different profile behaviors.

I am also planning, as one of the next Velair tasks, a dedicated Lovelace card intended to expose useful Velair information in regular dashboards. That work will require defining how this runtime data should be obtained and represented. It may address part or all of the use case behind this PR, or help identify a smaller backend contract that can support both the card and third-party automations without duplicating runtime state.

Since this affects the public entity model and there are several possible approaches, I suggest opening a GitHub Discussion before continuing with the implementation. We can use it to agree on:

  • the exact user-facing problem and common use cases;
  • whether we want to expose scheduled intent or the last physical command;
  • which information belongs in entities, attributes, events, diagnostics, or a dedicated card;
  • the expected behavior after restart, reset, and unit changes;
  • how to maintain a single authoritative source without increasing Recorder usage unnecessarily.

Once that contract is agreed—and after considering the planned dashboard card—we can decide whether to revise this PR, replace it with a smaller backend change, or cover the use case through the card. This should avoid asking you to repeatedly rework the code while the design is still being defined.

Thanks again for taking the time to contribute. The use case is worth discussing, but I’m not comfortable merging the current implementation until we agree on the model and resolve the consistency issues above.

@cgonfer

cgonfer commented Sep 4, 2026

Copy link
Copy Markdown
Owner

@Cloudore, I have opened a Discussion to define the public per-zone runtime contract before we continue changing the implementation:

Designing public per-zone runtime context for dashboards and automations

I have linked PR #22 as the starting point and credited your contribution there. The Discussion also includes the planned Velair Lovelace card, since that work may address part of this use case or help us define the smallest shared backend contract.

Your input would be very welcome, especially regarding the dashboard or automation you are trying to build and whether you need the scheduled intent, the final physical command, or both.

I suggest continuing the product and architecture discussion there. Once we agree on the expected contract, we can return to this PR and decide whether it should be revised, reduced in scope, or replaced by the resulting implementation.

Thanks again for bringing up the use case and for the work you have already put into it.

@Cloudore

Cloudore commented Sep 4, 2026

Copy link
Copy Markdown
Author

Replying in the Discussion with our production dashboard's answers to your eight questions: #26 (comment)

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants