PKG-18: cut 0.12.0, so TEL-12's pv_entities can reach an installed 0.11.0
checks / unit (pull_request) Successful in 8m5s
checks / unit (pull_request) Successful in 8m5s
One runtime merge since 0.11.0 (cccb2fa): TEL-12 (#116), a new optional
list option `pv_entities` beside `pv_entity`. Option surface 76 -> 77, so
a minor bump. config.yaml version and a closed `## 0.12.0` section only.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BwRLw7eKYj2byVdwB6kbjU
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
f863ecaa8c
commit
1ad4d3a5bb
@@ -1,5 +1,137 @@
|
||||
# Changelog
|
||||
|
||||
## 0.12.0
|
||||
|
||||
**A MINOR BUMP FOR ONE NEW OPTION: `pv_entities` ([[TEL-12]]), for sites with
|
||||
more than one PV inverter.** The option surface moves **76 keys -> 77**,
|
||||
`options:` and `schema:` in step. 0.11.0's `pv_entity` takes one entity; a roof
|
||||
with two or three inverters, each publishing its own power sensor into Home
|
||||
Assistant, could only record one of them. `pv_entities` is a list, and the
|
||||
Configuration tab renders it as a repeatable field, so you add your second and
|
||||
third inverter there rather than in YAML.
|
||||
|
||||
⚠️ **UNSET, NOTHING CHANGES.** `pv_entities` ships as `[]`, which is what every
|
||||
install that presses *Update* lands on, and empty means "use `pv_entity`" - so
|
||||
an install with no PV entity still has no PV channel, and an install with one
|
||||
`pv_entity` keeps exactly the single-entity channel 0.11.0 gave it. **No rule was
|
||||
added to `validate.py`**, which mentions neither key, so **a stored options blob
|
||||
that starts the add-on on 0.11.0 starts it on 0.12.0**. There is no
|
||||
`SystemExit(78)` to plan around on this hop.
|
||||
|
||||
⚠️ **IT IS INSTRUMENTATION ONLY, NOT A CONTROL INPUT.** `app/control.py`,
|
||||
`allocator.py`, `arbiter.py`, `peakguard.py` and the watchdogs are not in this
|
||||
release's diff; the runtime files that move are `app/pv.py`, `app/main.py`,
|
||||
`app/mqtt.py`, `config.yaml` and `translations/`. `tools/tel11_pv_trace.py`,
|
||||
extended for this card, hashes the controller's decisions on 0.11.0 and on this
|
||||
tree: the control document is **`846a10a5b89e…` with PV unset and with one
|
||||
entity, on both trees** - the same hash TEL-11 recorded - and with a
|
||||
three-entity roster it equals each grid world's unset document, including every
|
||||
cell where one inverter is dead. Neither the total nor any partial total reaches
|
||||
a decision. With PV unset or with one entity, the **telemetry** is byte-identical
|
||||
to 0.11.0's as well.
|
||||
|
||||
Contents of this release, in merge order since 0.11.0 (`cccb2fa`):
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| `f863eca` | TEL-12 - several PV inverters, and one absent member is an absent TOTAL **⚠️ NEW OPTIONAL OPTION, EMPTY ON EVERY EXISTING INSTALL** |
|
||||
|
||||
### TEL-12 — `pv_entities`: the PV channel for a roof with several inverters
|
||||
|
||||
**WHAT TO DO ON A SITE WITH MORE THAN ONE PV INVERTER.** List every inverter's
|
||||
power sensor under `pv_entities`:
|
||||
|
||||
```yaml
|
||||
pv_entities:
|
||||
- sensor.pv_east_power
|
||||
- sensor.pv_west_power
|
||||
- sensor.pv_garage_power
|
||||
```
|
||||
|
||||
`sensor.goodwe_pv_power` then carries the **site total**. Each entity's own
|
||||
`unit_of_measurement` is read, so a kW inverter beside a W one sums correctly;
|
||||
a sensor with no unit or a non-power unit is refused by name on the status
|
||||
page, as in 0.11.0.
|
||||
|
||||
⚠️ **`pv_entities` REPLACES `pv_entity` - IT DOES NOT ADD TO IT.** When the list
|
||||
is set, `pv_entity` is not read at all. **If you are upgrading from 0.11.0 with
|
||||
`pv_entity` already set, the inverter it names must also be in the list**, or it
|
||||
drops out of the total. Put it in the list and it is **counted once**, not
|
||||
twice - that is why the rule is replacement: under a union, the natural action
|
||||
(put all your inverters in the new field) would double-count the one the old
|
||||
key already names. While both keys are set the status page shows a caution
|
||||
saying which one won - *"`pv_entities` is set, so `pv_entity` is IGNORED - the N
|
||||
entities in the list are what is summed. Clear `pv_entity` to remove this
|
||||
caution"*. It is a caution, never a refusal to start and never a NOT READY row.
|
||||
A repeated id inside the list is also counted once.
|
||||
|
||||
⚠️ **IF ANY CONFIGURED PV ENTITY IS ABSENT, THE PUBLISHED TOTAL IS `unknown` -
|
||||
NOT THE SUM OF THE ONES THAT ANSWERED.** Three inverters configured and one
|
||||
`unavailable`: `sensor.goodwe_pv_power` goes to `unknown` and the recorder
|
||||
stores a **gap**. The sum of the other two would be a smaller number
|
||||
indistinguishable from a real one, and a week later it would read as *"there
|
||||
was less sun than there was"* - the conclusion this channel exists to test
|
||||
rather than to manufacture. **A gap in the history, never an understated
|
||||
number.** The status page, read live, still gives you the diagnostic: `PV —`
|
||||
plus a caution that says there is **no site total**, names the missing entity
|
||||
and its reason, and lists what the others reported. An inverter honestly
|
||||
reporting **0 W** is summed, not treated as absent - shading and nightfall are
|
||||
real zeros.
|
||||
|
||||
| what happened | `sensor.goodwe_pv_power` | the status page |
|
||||
|---|---|---|
|
||||
| neither key set | the entity does not exist | no row |
|
||||
| all three answer, 1200 W + 2.1 kW + 450 W | `3750.0` | `PV 3 750 W` |
|
||||
| all three answer, one of them `0 W` | the sum of the two others | the sum |
|
||||
| one (or more) `unavailable` / missing / bad unit | `unknown` - a recorder gap | `PV —` + a caution naming what is missing |
|
||||
|
||||
⚠️ **THE FIX FOR A MISSING INVERTER IS NOT A TEMPLATE SENSOR THAT SUMS THEM.**
|
||||
You can still point `pv_entity` at one if you prefer, but a template sensor
|
||||
summing an `unavailable` source yields the partial total silently - the same
|
||||
defect one layer down, where this add-on cannot see it or report it.
|
||||
|
||||
**WHY A SECOND KEY, RATHER THAN MAKING `pv_entity` A LIST.** Because an 0.11.0
|
||||
install that has `pv_entity` set would not start. Measured against Supervisor
|
||||
**2026.08.0** by `tools/supervisor_shape_probe.py` §G: with `pv_entity` declared
|
||||
as a list, the string an 0.11.0 install has persisted is refused -
|
||||
`Invalid list for option 'pv_entity'` - and a shipped `[]` default does not
|
||||
rescue it, because the Supervisor's merge keeps your stored string. The one
|
||||
single-key spelling that accepts both shapes, `match(.*)?`, validates nothing
|
||||
(it accepts the integer `417`) and renders as a plain text box, so you could not
|
||||
add a second inverter in the UI. So `pv_entity` stays a string, and the same
|
||||
probe shows an 0.11.0 options blob - `pv_entity` set, no `pv_entities` key at
|
||||
all - validating against this version untouched. ⚠️ **Rolling back to 0.11.0 is
|
||||
also safe**: a schema without `pv_entities` drops the key with a warning and
|
||||
leaves `pv_entity` standing.
|
||||
|
||||
**Why it matters now:** [[OPT-10]] needs a week of PV history to attribute the
|
||||
surplus that left the reference site while the pack had room, and that site has
|
||||
several PV inverters. The week starts when the site total is recorded.
|
||||
|
||||
**Full account: `DECISIONS/TEL-12-several-pv-inverters.md`, with the operator's
|
||||
version under "Several PV inverters" in `DOCS.md`.**
|
||||
|
||||
### If you are crossing from a version older than 0.10.0
|
||||
|
||||
⚠️ **THIS SECTION IS NOT THE ONE THAT CAN REFUSE YOU - `## 0.10.0` BELOW IS.**
|
||||
Updating installs 0.12.0 in one step, so every validator rule added in
|
||||
0.8.0, 0.9.0 and 0.10.0 arrives at the same moment. Two of them can refuse a
|
||||
config nobody has edited: [[SAFETY-39]]'s **rule 10** (added in 0.8.0) against
|
||||
0.7.0's shipped default `slew_w: 1000` - the ceiling is **555.6 W** on a 5000 W
|
||||
rail - and [[TARIFF-07]]'s three withdrawn `price_provider` ids,
|
||||
**`engie_dynamic`, `totalenergies_dynamic` and `eneco_eddy`**, each still
|
||||
refused by name at startup on 0.12.0. Neither is new here, and a site already on
|
||||
0.10.0 or later has already met both. **The full account of both, including
|
||||
what to set instead of each withdrawn id, is in `## 0.10.0`**, which withdrew
|
||||
them and is not superseded by this section.
|
||||
|
||||
`tools/predeploy_check.py` checks your live options against this version's
|
||||
validator before you press *Update*, and on this tree reports a real version
|
||||
change from 0.11.0. ⚠️ **Pass it the bare options dict - the `data.options`
|
||||
object - NOT the whole `ha apps info --raw-json` document.** Handed the wrapped
|
||||
export it currently prints CLEARED while having checked nothing ([[SAFETY-60]],
|
||||
open). Extract the options first, e.g. `jq '.data.options'`.
|
||||
|
||||
## 0.11.0
|
||||
|
||||
**A MINOR BUMP, AND ONE NEW OPTION IS THE WHOLE REASON FOR THE SECOND DIGIT:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: GoodWe RS485 Controller
|
||||
version: "0.11.0"
|
||||
version: "0.12.0"
|
||||
slug: goodwe_controller
|
||||
description: >-
|
||||
Drives a GoodWe ES/BP battery inverter over RS485 by emulating its smart
|
||||
|
||||
Reference in New Issue
Block a user