docs(agents): HA snmp two-layer + package dupe-key field lessons [#344]

This commit is contained in:
2026-09-02 20:02:54 -05:00
parent 76e50de25f
commit d9aa989957
+23
View File
@@ -731,3 +731,26 @@ All work is tracked in [Redmine](https://projects.knownelement.com)
(`entity_id`, `item`=<uid>, `rename`); passing `status`/`due` back earns (`entity_id`, `item`=<uid>, `rename`); passing `status`/`due` back earns
a 400. HUD summaries carry `[#NNN]` Redmine prefixes — sync completed a 400. HUD summaries carry `[#NNN]` Redmine prefixes — sync completed
items back to Redmine when the founder asks. items back to Redmine when the founder asks.
- **HA package YAML: NEVER append a second top-level `sensor:` key** — YAML
duplicate keys are last-one-wins and silently shadow the whole first block
at config load (#344 outage 2026-09-02: all 22 fleet temps down after the
restart that pulled the file). Merge new sensors into the existing block.
- **HA 2026.8 snmp add-time crash, general form:** ANY unit-bearing sensor
with a non-numeric native_value at ADD (host down renders '' / literal
string "unknown"; value_template can never yield None — even `{{ none }}`
is stringified to "None") = ValueError, entity vanishes till manual
reload. `check_config` does NOT catch it. Durable pattern: unit-less raw
snmp transport + `template:` layer carrying unit/device_class under the
ORIGINAL unique_ids (KNEL/pfv-bms packages/plant_snmp.yaml header).
- **HA entity_id comes from the NAME slug, not unique_id** — if a sensor's
name and unique_id diverge, cross-references must use the name slug
(garage PDU amps lesson: semantic read a nonexistent `..._amps_raw`).
- **HA entity_id collisions spawn `_2` entities; registry remove no-ops for
LIVE entities** (they re-register on their next write). Clean `_2` by
jq-editing `.storage/core.entity_registry` with core STOPPED, backup
first. Orphaned (dead) entries remove fine via websocket
(ha-ws-call.py — pass commands as JSON files; shell quoting eats argv).
- **git_pull add-on: `ha addons start` is a no-op while it's running** —
use `restart` to force an immediate pull. It auto-restarts core for
files in its restart list; otherwise pull ≠ reload (config lands on
disk, running core keeps the old one until a platform reload/restart).