From 92a80c09b24564f74d7c5d128f47ebf28740f3c6 Mon Sep 17 00:00:00 2001 From: OPT-17 reviewer Date: Sun, 11 Oct 2026 05:12:35 +0200 Subject: [PATCH] OPT-17 review: title the forecast row on Home; test the hint and blank rows The new status row's id `solar_forecast` had no Home title, so Home showed it under the fallback "Inverter connection". Add "Solar forecast" / "Zonneprognose" to ui_text, and checks for the title, the tomorrow-gap hint and blank list rows (review mutations R7, R9, R14 now killed). Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Bdqr7PiaHcBnzPituu2yTC --- .../DECISIONS/OPT-17-several-forecast-entities.md | 5 +++-- goodwe_controller/app/ui_text/en.json | 1 + goodwe_controller/app/ui_text/nl.json | 1 + goodwe_controller/test_opt17.py | 13 ++++++++++++- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/goodwe_controller/DECISIONS/OPT-17-several-forecast-entities.md b/goodwe_controller/DECISIONS/OPT-17-several-forecast-entities.md index d18c830..2512f79 100644 --- a/goodwe_controller/DECISIONS/OPT-17-several-forecast-entities.md +++ b/goodwe_controller/DECISIONS/OPT-17-several-forecast-entities.md @@ -47,8 +47,9 @@ day can list them. gather that reads the inverters, so a slow sensor does not delay control. 7. **Shown and logged once.** With two or more members, each one not usable is named on the status page by its place in the list (STYLE.md: no entity - ids on the page), as a caution row. The action log names the entity id, - once when the set of failing members changes. + ids on the page), as a caution row titled "Solar forecast" on Home. The + action log names the entity id, once when the set of failing members + changes. 8. **One member is the single key.** A one-member list reads, plans, shows and logs exactly as the single key with that entity. diff --git a/goodwe_controller/app/ui_text/en.json b/goodwe_controller/app/ui_text/en.json index 6700896..40b6f28 100644 --- a/goodwe_controller/app/ui_text/en.json +++ b/goodwe_controller/app/ui_text/en.json @@ -449,6 +449,7 @@ "delivery": "An inverter is not delivering", "estop": "Emergency stop", "pv": "Solar reading", + "solar_forecast": "Solar forecast", "none": "Inverter connection" }, "months": ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"] diff --git a/goodwe_controller/app/ui_text/nl.json b/goodwe_controller/app/ui_text/nl.json index 5d45c32..2748196 100644 --- a/goodwe_controller/app/ui_text/nl.json +++ b/goodwe_controller/app/ui_text/nl.json @@ -372,6 +372,7 @@ "delivery": "Een omvormer levert niet", "estop": "Noodstop", "pv": "Meting van de zonnepanelen", + "solar_forecast": "Zonneprognose", "none": "Verbinding met de omvormer" }, "months": ["januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september", "oktober", "november", "december"] diff --git a/goodwe_controller/test_opt17.py b/goodwe_controller/test_opt17.py index d0f4521..fbb3a87 100644 --- a/goodwe_controller/test_opt17.py +++ b/goodwe_controller/test_opt17.py @@ -28,7 +28,8 @@ sys.path.insert(0, os.path.join(HERE, "tools")) logging.disable(logging.WARNING) import opt11p3_replay as rp # noqa: E402 -from app import dayplan, messages, solarfc, validate # noqa: E402 +from app import (dayplan, homeview, messages, solarfc, uitext, # noqa: E402 + validate) fails = [] @@ -240,6 +241,9 @@ for one, many in (solarfc.TODAY_KEYS, solarfc.TOMORROW_KEYS): not F({many: ["sensor.b", "sensor.c"]}) and not F({one: "sensor.a"}) and not F({one: "sensor.a", many: []}) and not F({one: "", many: ["sensor.b"]})) + check(f"...blank rows in {many} are ignored, alone or beside {one}", + not F({many: ["", None, "sensor.b"]}) + and not F({one: "sensor.a", many: ["", None]})) p = F({many: ["sensor.b", "number.x"]}) check(f"...an entry in {many} that is not a sensor is refused", len(p) == 1 and "only sensors" in p[0] and "number.x" in p[0]) @@ -454,6 +458,13 @@ check("a tomorrow member down: today is used, tomorrow is not, and the row " "Solar forecast for tomorrow: not used, source 2 of 2 has no " "reading"] and len(fc_events(c)) == 1 and "sensor.tom_down" in fc_events(c)[0]) +check("...and the page hint says tomorrow's forecast is not used", + (c.hint or "").endswith(messages.hint("forecast_no_tomorrow"))) +check("...and Home titles the row as the solar forecast, in EN and NL", + [a["title"] for a in homeview.attention(fc_rows(c))] + == ["Solar forecast"] + and uitext.words("nl")["home_words"]["attn"]["solar_forecast"] + == "Zonneprognose") first = CALLS[:8] check("every member of both days is read in one gather (all four start " "before any ends)",