SMA-2 round 2: keep the driver keys out of the schema, translations and labels
Owner decision 2026-11-07: clients see nothing new until SMA-4. config.yaml, translations, labels and the page layout are back to 23ff9d0's. The validation of the keys stays for callers that skip the schema. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude
parent
0b20f53cf8
commit
c015230452
@@ -243,6 +243,8 @@ show("the per-entry BASELINE is ACCEPTED, so every refusal below has nowhere "
|
||||
"else to come from", ok, json.dumps(out.get("inverters")) if ok else out)
|
||||
for title, entry, expect in (
|
||||
("no name", {k: v for k, v in D_FULL.items() if k != "name"}, "name"),
|
||||
("no setpoint_entity",
|
||||
{k: v for k, v in D_FULL.items() if k != "setpoint_entity"}, "setpoint_entity"),
|
||||
("no max_w", {k: v for k, v in D_FULL.items() if k != "max_w"}, "max_w"),
|
||||
("no bms_soc_floor (SAFETY-32)",
|
||||
{k: v for k, v in D_FULL.items() if k != "bms_soc_floor"}, "bms_soc_floor"),
|
||||
@@ -255,39 +257,22 @@ for title, entry, expect in (
|
||||
ok, out = validate(dict(D_BASE, inverters="[]"))
|
||||
show("a JSON STRING where the list belongs is refused", not ok, out)
|
||||
|
||||
print("\n== K. SMA-2: the driver keys on an inverter entry ==")
|
||||
# `setpoint_entity` is OPTIONAL per entry since SMA-2 (it is the GoodWe driver's
|
||||
# own key; validate.py rule 9(d) requires it for GoodWe), beside `driver`,
|
||||
# `host`, `port`, `unit_id` and `maintenance`. Same method as §D: an ACCEPTED
|
||||
# baseline, ONE value varied, the refusal asserted on the KEY'S NAME.
|
||||
K_FULL = dict(D_FULL, driver="goodwe_esphome", host="inverter.local", port=502,
|
||||
unit_id=1, maintenance=False)
|
||||
ok, out = validate(dict(D_BASE, inverters=[K_FULL]))
|
||||
show("an entry carrying every new key is ACCEPTED, and the keys survive",
|
||||
ok and all(out["inverters"][0].get(k) == K_FULL[k]
|
||||
for k in ("driver", "host", "port", "unit_id", "maintenance")),
|
||||
json.dumps(out.get("inverters")) if ok else out)
|
||||
print("\n== K. SMA-2: the driver keys are NOT in the schema (owner, 2026-11-07) ==")
|
||||
# `driver`, `host`, `port`, `unit_id` and `maintenance` are graded by validate.py
|
||||
# rule 9(h) but kept out of config.yaml so the Configuration tab shows nothing
|
||||
# new. This pins both halves: the shipped entry is the one it always was, and the
|
||||
# Supervisor (measured) silently DROPS an unknown key from an entry, so they
|
||||
# cannot arrive by the form or by YAML.
|
||||
ok, out = validate(dict(D_BASE, inverters=[D_FULL]))
|
||||
show("an entry from before SMA-2 (none of the new keys) is ACCEPTED unchanged",
|
||||
ok and out["inverters"] == [D_FULL], out)
|
||||
ok, out = validate(dict(D_BASE, inverters=[
|
||||
{k: v for k, v in D_FULL.items() if k != "setpoint_entity"}]))
|
||||
show("an entry with NO setpoint_entity is now accepted by the schema "
|
||||
"(rule 9(d) refuses it for GoodWe, at startup)", ok, out)
|
||||
# ⚠️ THE SUPERVISOR'S REFUSAL NAMES THE VALUE'S RULE, NOT THE KEY, FOR A NESTED
|
||||
# ENTRY (§D's "at most 5000"), so the expectation is that rule's own words.
|
||||
for title, entry, expect in (
|
||||
("driver other than goodwe_esphome", dict(K_FULL, driver="sma"),
|
||||
"one of ['goodwe_esphome']"),
|
||||
("port 0", dict(K_FULL, port=0), "at least 1"),
|
||||
("port 70000", dict(K_FULL, port=70000), "at most 65535"),
|
||||
("unit_id 248", dict(K_FULL, unit_id=248), "at most 247"),
|
||||
("host a number", dict(K_FULL, host=5), "expected str"),
|
||||
("maintenance a word that is not a boolean",
|
||||
dict(K_FULL, maintenance="banana"), "boolean")):
|
||||
ok, out = validate(dict(D_BASE, inverters=[entry]))
|
||||
show(f"an entry with {title} is refused, with the rule's own words",
|
||||
(not ok) and expect in str(out), out)
|
||||
show("the pre-SMA-2 entry is ACCEPTED unchanged", ok and out["inverters"] == [D_FULL], out)
|
||||
for _k in ("driver", "host", "port", "unit_id", "maintenance"):
|
||||
ok, out = validate(dict(D_BASE, inverters=[dict(D_FULL, **{_k: "x"})]))
|
||||
show(f"an entry carrying `{_k}` is accepted and the key is dropped",
|
||||
ok and out["inverters"] == [D_FULL], out)
|
||||
show("the per-entry schema has exactly the eight keys it had",
|
||||
sorted(schema["inverters"][0]) == sorted(["name", "setpoint_entity", "max_w",
|
||||
"bms_soc_floor", "soc_entity", "batt_entity", "batt_invert", "capacity_kwh"]),
|
||||
json.dumps(schema["inverters"]))
|
||||
|
||||
|
||||
print("\n== E. the ROLLBACK direction, and the operator's UI ==")
|
||||
|
||||
Reference in New Issue
Block a user