SMA-10: two idle states, hold 0 W or hand the inverter back
A driver now says whether its release() hands the inverter back (Driver.hands_back; GoodWe is False, so release() stays write(0) and the Controller never calls it). command_site_release() sits next to command_site_zero(): the Stop button and shutdown() (so SIGTERM, restart, control task death and a late config refusal) hand a hand-back unit back, once, and zero every other unit as before. Safety stops and refusals still hold 0 W for every unit. Shadow mode releases a hand-back unit. After a release nothing is written to the unit (heartbeat and cycle included) until control starts again. release() is bounded by RELEASE_BUDGET_S (= the write budget), runs concurrently per unit, and a raising or hanging release on one unit does not stop the others. The "set to 0 W" sentences for Stop, restart, shadow mode and the stopped banner are built from the roster (app/handback.py, EN and NL, words from the driver); a GoodWe-only roster keeps every old literal. A handed-back unit shows "Back under <its control>" on Home. Existing test edited: test_messages.py (two classification entries for the CRITICAL line that moved into a roster builder, and the new release bound). Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude
parent
57c8d1b912
commit
a1be9c48b3
@@ -793,6 +793,7 @@ from datetime import datetime as _dt, timedelta as _td, timezone as _tz # noqa:
|
||||
|
||||
from app import clamp as _clamp, freshness as _fresh, peakguard as _pg # noqa: E402
|
||||
from app import store as _store # noqa: E402
|
||||
from app import handback # noqa: E402
|
||||
from app.circulation import CirculationConfig, CirculationWatchdog # noqa: E402
|
||||
from app.control import Tuning, compute # noqa: E402
|
||||
from app.delivery import (DeliveryConfig, DeliveryWatchdog, UnitDelivery, # noqa: E402
|
||||
@@ -850,7 +851,7 @@ DATA = {
|
||||
"main.py:inv.batt_fresh.bound.release_s", "main.py:inv.batt_fresh.bound.move_w",
|
||||
"main.py:inv.batt_fresh.bound.unchanged_s", "main.py:inv.batt_fresh.held",
|
||||
"main.py:value", "main.py:float(value)",
|
||||
"main.py:entity", "main.py:WRITE_BUDGET_S",
|
||||
"main.py:entity", "main.py:WRITE_BUDGET_S", "main.py:RELEASE_BUDGET_S",
|
||||
"main.py:_e",
|
||||
"main.py:messages.times(self.clamp_wd.engagements)",
|
||||
"main.py:messages.when(brussels(self.tariff_at))",
|
||||
@@ -1058,6 +1059,12 @@ TEXT = {
|
||||
"main.py:messages.reason_code(inv.batt_fresh.reason)": _coded(_stale_texts),
|
||||
"main.py:rep.explain()": _migration_texts,
|
||||
"store.py:rep.explain()": _migration_texts,
|
||||
# SMA-10: the control-task CRITICAL line's state, for a GoodWe-only roster
|
||||
# (the sentence it always was) and a mixed one.
|
||||
"main.py:handback.task_died_state(handback.current())": lambda: [
|
||||
handback.task_died_state(()),
|
||||
handback.task_died_state((handback.Unit("inverter-a"),
|
||||
handback.Unit("inverter-b", True)))],
|
||||
"main.py:plan.words": _tariff_texts,
|
||||
# OPT-11 P2: why an MQTT command was ignored.
|
||||
"main.py:why": lambda: list(messages.PACK_REFUSED.values()),
|
||||
|
||||
Reference in New Issue
Block a user