HA can take minutes to start (2026-10-05, 502 from the proxy). Then TZ holds, which the Supervisor sets from HA's zone, so the hour stays right; only a TZ of UTC there now logs a WARNING asking for a restart. A test pins the 3 s budget on the zone request (a mutant without it survived). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
68 lines
3.6 KiB
Markdown
68 lines
3.6 KiB
Markdown
# MAINT-10 — the maintenance start hour is local time, default 19:00
|
|
|
|
Owner decision 2026-09-29 (option A). `maintenance_start_hour` was compared
|
|
with the UTC hour, so the shipped 10 started at 12:00 in a Belgian summer and
|
|
11:00 in winter. It is now read on the site's local clock, and the default moves
|
|
to 19 so the drain runs into the evening and night rather than the solar day.
|
|
|
|
Evening drains meet higher house loads; SAFETY-83 (merged first) lets the
|
|
peak guard outrank the drain.
|
|
|
|
## 1. Which zone
|
|
|
|
Home Assistant's `time_zone` (`GET /core/api/config`, 3 s budget) at startup,
|
|
else the container's `TZ`, else UTC. One log line says which (WARNING only for
|
|
UTC). Resolved once per start: a zone change in HA takes effect on the next
|
|
add-on restart. HA can still be starting when the add-on starts (502 from the
|
|
proxy, 2026-10-05); then `TZ` holds. HA pushes its zone to the Supervisor
|
|
(hassio `push_config`), which stores it and sets it as the add-on's `TZ`
|
|
(`docker/app.py`, Supervisor 2026.08.0), so the hour stays right. Only a `TZ` of
|
|
UTC there logs a WARNING asking for a restart. No later re-resolve: the fallback
|
|
already is HA's zone, so the rare UTC case gets a warning rather than more code.
|
|
The add-on image has tzdata (checked in `amd64-base:3.20`); the CI image does
|
|
not, so the tests grade DST on `tariff._EUTimezone` too.
|
|
|
|
## 2. DST
|
|
|
|
`maintenance.in_start_slot()` works from UTC instants only, so it does not
|
|
depend on how a tzinfo resolves a missing or doubled wall time:
|
|
|
|
- normally the slot is the local hour `start_hour`;
|
|
- clocks forward and the hour does not exist: the first hour after the jump;
|
|
- clocks back and the hour happens twice: the first pass only. Without this an
|
|
aborted start (90 min cooldown) would start again in the 120 min repeated hour.
|
|
|
|
Every day has exactly one 60 min slot for every hour 0-23: checked against
|
|
zoneinfo for Europe/Brussels, America/New_York, America/Santiago (midnight
|
|
transitions), Asia/Kathmandu (+05:45) and Australia/Lord_Howe (30 min DST)
|
|
over all of 2026.
|
|
|
|
## 3. Existing installs
|
|
|
|
The Supervisor merges the shipped defaults under the STORED options, and saving
|
|
the settings stores every key (the reference install's blob has all 76). So
|
|
almost every existing install keeps its stored 10, which now means 10:00 local
|
|
instead of 12:00 (summer) or 11:00 (winter). Only a blob without the key gets 19.
|
|
The add-on does not rewrite a stored option: a silent migration would override
|
|
an operator's choice with no way to tell it apart from the old default. A site
|
|
that set an earlier hour to make up for UTC (17 for 19:00 summer) must set it
|
|
back to 19 after the upgrade, or it starts two hours early. DOCS and the release
|
|
note (drafted on the PR, for the version bump) say this.
|
|
`tools/supervisor_shape_probe.py` §I measures this on Supervisor 2026.08.0.
|
|
|
|
## 4. Two inverters
|
|
|
|
`Controller` hands the same zone to every pack's `Maintenance`, so every pack's
|
|
`wants_start()` reads the local hour. `arbitrate()` is unchanged: one pack
|
|
cycles at a time, and the one that lost the slot starts in the first start
|
|
slot after the other is done (a later day: a cycle outlasts its start hour). On the day the clocks go back, a pack freed during the second pass of
|
|
a repeated hour does not start there. `test_maint10.py` part 10.
|
|
|
|
## 5. What does not change
|
|
|
|
Only the start decision (`Maintenance.wants_start`) and the Home screen's shown
|
|
start time read the zone. `test_maint10.py` parts 9 and 10 run the real
|
|
Controller at N=1 and N=2 with start hour 11 UTC against 13 Europe/Brussels (the
|
|
same instant): every command, claim, reason and log line is identical. A
|
|
`Maintenance` built without a zone reads UTC, as before.
|