Files
goodwe-addon/goodwe_controller/DECISIONS/MAINT-10-local-start-hour.md
T
glenn schrooyenandClaude Opus 5.5 1d28daf8a0
checks / unit (pull_request) Successful in 31m18s
infra-pin / fresh (pull_request) Successful in 1s
MAINT-10 review: warn when HA did not answer and TZ is UTC; test the 3 s budget
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>
2026-10-05 23:24:02 +02:00

3.6 KiB

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.