diff --git a/creek_modeling/CHANGELOG.md b/creek_modeling/CHANGELOG.md index 0730ba4..ca492cb 100644 --- a/creek_modeling/CHANGELOG.md +++ b/creek_modeling/CHANGELOG.md @@ -3,6 +3,23 @@ All notable changes to the **Ackerly Creek Modeling** add-on are documented here. The version matches `version:` in `config.yaml`; bump it to trigger the GUI Update button. +## 0.12.2 + +- **Fixed: the annotation text box from 0.12.1 never actually existed in Home Assistant.** + Its discovery config set `max: 500`, but 255 is Home Assistant's hard ceiling for MQTT + text entities (`homeassistant.components.text`'s `native_max_value` is clamped to + `(0, 255)`, inherited by every platform including MQTT). A `max` above that is not + clamped down to fit — MQTT discovery validates the payload against the platform schema + *before* creating anything, so the whole discovery message for that one entity was + rejected and silently dropped. Every other entity in this release has no such + constraint, so nothing else was affected and nothing in the add-on's own logs pointed at + it — confirmed missing only from the HA-side MQTT device page, not from anything this + service could see about itself. + + Set to 255. A `test_annotate_text_entity_max_is_within_the_mqtt_text_platform_ceiling` + guard now checks every entity with a `max` against that ceiling, verified to fail on the + 0.12.1 config before this fix. + ## 0.12.1 - **Annotate storms from the Operator tab** — no more SSH/Samba/`sqlite3` for the normal diff --git a/creek_modeling/app/discovery.py b/creek_modeling/app/discovery.py index fb2ceff..df959b2 100644 --- a/creek_modeling/app/discovery.py +++ b/creek_modeling/app/discovery.py @@ -152,7 +152,15 @@ def _specs(self) -> list[tuple[str, str, dict]]: ("text", "creek_annotate_latest_storm", { "name": "Creek Annotate Latest Storm", "command_topic": f"{b}/cmd/annotate", - "mode": "text", "max": 500, "icon": "mdi:note-edit-outline"}), + # 255 is the platform's own hard ceiling for MQTT text entities, not a + # choice — HA's `text` component clamps native_max_value to (0, 255) + # regardless of what discovery asks for, and MQTT discovery validates + # against that schema *before* creating the entity: a `max` above 255 + # does not get clamped, the whole discovery payload for that entity is + # rejected and nothing is created — silently, with no error the add-on + # itself can see. This entity did not exist in Home Assistant at all + # until this was caught (0.12.1 shipped with 500). + "mode": "text", "max": 255, "icon": "mdi:note-edit-outline"}), ("sensor", "creek_lag_response_series", { "name": "Creek Lag Response Series", "state_topic": f"{b}/status/lag", diff --git a/creek_modeling/config.yaml b/creek_modeling/config.yaml index b0814be..f827631 100644 --- a/creek_modeling/config.yaml +++ b/creek_modeling/config.yaml @@ -1,5 +1,5 @@ name: Ackerly Creek Modeling -version: "0.12.1" +version: "0.12.2" slug: creek_modeling description: Flood-probability + predicted-stage inference and nightly retrain for Ackerly Creek. url: https://github.com/ryanbuiltthat/ewfa diff --git a/creek_modeling/tests/test_discovery.py b/creek_modeling/tests/test_discovery.py index 1d5719a..7cd5f06 100644 --- a/creek_modeling/tests/test_discovery.py +++ b/creek_modeling/tests/test_discovery.py @@ -64,7 +64,18 @@ def test_annotate_text_entity_has_the_right_command_topic(): cfgs = {c["object_id"]: c for _, c in pub.configs()} annotate = cfgs["creek_annotate_latest_storm"] assert annotate["command_topic"] == "creek/cmd/annotate" - assert annotate["max"] >= 500 # a real note (times + basement + culvert) exceeds 255 + + +def test_annotate_text_entity_max_is_within_the_mqtt_text_platform_ceiling(): + """255 is not a preference, it is HA's hard limit for MQTT text entities. A `max` + above it does not get clamped -- the whole discovery payload for that entity is + rejected and the entity is never created, silently. That shipped once (0.12.1: 500) + and the entity simply did not exist in Home Assistant; this is the regression guard.""" + pub, _ = build() + cfgs = {c["object_id"]: c for _, c in pub.configs()} + for object_id, cfg in cfgs.items(): + if "max" in cfg: + assert 0 <= cfg["max"] <= 255, f"{object_id}: max={cfg['max']} exceeds the MQTT text ceiling" def test_storm_to_annotate_sensor_reads_latest_closed_not_latest():