Zone holds: pause_zone action hold with constraints - #23
Conversation
A zone pause can now hold a temperature instead of freezing the climate. `velair.pause_zone` with `action: hold` keeps delivering a target through the normal resilient delivery path, starting from the block the schedule or active Profile would apply now and folding every active hold in start order with a per-hold constraint (`absolute`, `raise_only`, `lower_only`). Holds carry optional hvac_mode, fan_mode and a short label, compose by pause_id like other reasons, expire like other reasons and are re-delivered when a freeze or another hold is removed. Precedence is unchanged for existing behavior: `turn_off` beats everything and a plain pause (including Manual adjustment) freezes the climate above any hold. Manual adjustment can start while a hold is active because Velair is still in control; the hold is delivered again when automatic control resumes. The override sensor gains a `hold` state with the composed effective target, the latest hold's constraint and label, and every active hold; zone runtime reports `hold`; pause lifecycle events carry the hold fields; the overview badge and diagnostics label the state; docs and translations updated. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WJhD4sYeWQvoikjYP2CxUr
|
Thank you for opening this as a draft and for documenting the intended behaviour in detail. I wanted to provide feedback now, before you spend more time on the hardware walkthrough, because there is a design question that needs to be resolved before this implementation can move forward. The Home/Away use case referenced in #5 was intentionally addressed through Profiles and Modes. Presence logic remains in Home Assistant, while Velair applies the selected climate routine. That issue was closed as completed with that design. This proposal goes significantly further: it turns Before adding that complexity to Velair's core, we would need to establish which specific use case is still not covered by Profiles, Modes or Boost, and agree on the expected behaviour independently of the implementation. A preliminary code review has also found several important issues that confirm the behaviour is not yet sufficiently defined:
The added tests cover the main scalar examples, but not these interactions, nor range targets, Fahrenheit migration, restart recovery, Profile/Mode changes, global pause/resume or frontend presentation. The PR also currently has no GitHub check runs. For now, I will leave the draft open for a few days in case you would like to clarify a concrete workflow that Profiles, Modes and Boost cannot represent. However, please do not invest additional time in implementation or hardware testing yet, as the product scope and architecture would need to be agreed first. If there is a concrete workflow that the existing features cannot represent, you are very welcome to describe it here or open a Discussion with a few real examples. We can then evaluate the smallest appropriate abstraction and define its interactions, precedence, persistence, units and recovery behaviour before considering another implementation. If no distinct unmet use case emerges, I will close the PR because the current proposal would add substantial complexity to the scheduler without a previously agreed product requirement. Thank you again for taking the time to explore the idea and for opening it as a draft for early feedback. |
Summary
velair.pause_zonegainsaction: hold: a pause reason that keeps delivering a temperature target instead of freezing the climate, through the normal resilient delivery path. Fields:temperature(or atarget_temp_low/target_temp_highrange), optionalhvac_modeandfan_mode,constraint(absolute|raise_only|lower_only) and a shortlabel.pause_idupdates the hold in place (start time kept);velair.resume_zonereleases only that hold and immediately delivers the remaining holds or the schedule; timed holds expire like other reasons.turn_offbeats everything and a plain pause, including Manual adjustment, freezes the climate above any hold. Manual adjustment can start while a hold is active (Velair is still in control); the hold is delivered again when automatic control resumes. Boost remains unavailable while any reason is active.holdwith the composedeffective_temperature, the latest hold'sconstraintandlabeland every active hold; zone runtime reportshold; pause lifecycle events carry the hold fields; overview badge and diagnostics label the state; docs and all translations updated.pause_id, exactly like the window pause. The same primitive covers vacation parking, sleep setbacks and cooking boosts.Checks
python -m unittest discover -s tests(addstests/backend/test_zone_hold.py, 18 tests: constraints, fold order, in-place update, freeze/turn-off precedence, Manual adjustment interplay, expiry, events, normalization)npx tsc --noEmitnpm run build(bundle committed)docs/user/manual-control.md,docs/user/automation-events.md,docs/user/usage.md, README)Manual testing
Draft: installed on Home Assistant 2026.8.2 with six managed climates (five Midea CCM15 zones and one LocalTuya unit) and configured; the live hold walkthrough on real hardware (hold → update → manual adjustment → resume → expiry) is scheduled next and this PR will be marked ready with the observed behaviour. Opening it now for design feedback.
🤖 Generated with Claude Code
https://claude.ai/code/session_01F2KBugsLZkL6yR7BB95pKK