docs(zigbee2mqtt): record the WS90 ZCL reporting configuration #564

Merged
k.renner merged 1 commits from ws90-reporting-config into master 2026-08-24 17:58:49 +00:00
Member

Documents the non-default ZCL reporting configuration now on the Wetterstation, and how to restore it. No behaviour change from this PR — the device was reconfigured at runtime; this records it.

Adds zigbee2mqtt-ws90-reporting.md plus a pointer from the device stanza in zigbee2mqtt-config.yaml.

Why it needs a document rather than a manifest

Zigbee2MQTT has no settings-schema field for reporting configuration. It is applied over MQTT (bridge/request/device/configure_reporting) and stored on the device and in database.db. Flux cannot reconcile it, and a fresh PVC will not have it.

What changed on the device

attribute cluster min change was
temperature 1026 5 10 → 0.1 °C 10 / 100 (1 °C)
humidity 1029 5 50 → 0.5 % 10 / 100 (1 %)
pressure 1027 5 1 → 1 hPa 10 / 50 (50 hPa)
illuminance 1024 5 5 10 / 5
wind ×3 0xfc01 5 1 10 / 1
UV 0xfc02 5 1 10 / 1
rain ×2 0xfc03 5 1 10 / 1

Battery (cluster 1) left at its hourly default.

The interval

min is a hold-off, and it was 10 s against an 8.8 s transmit interval — so every change-triggered report was held past a cycle and landed on the next. Attributes reported at best every 17.6 s and drifted out of phase with each other; the published stream showed no 8.8 s periodicity at all, just a smear across 2–8 s.

At min: 5 each attribute reports on its own transmit:

17:06:07  17:06:15  17:06:24  17:06:33  17:06:42  17:06:50  17:06:59  17:07:08 ...
        8s        9s        9s        9s        8s        9s        9s

Mean gap 8.69 s — the transmit cycle, visible in MQTT for the first time. Publish volume fell, ~631/h → ~445/h, because each publish is now a whole cycle rather than a fragment of one.

The deadbands

These come from the shared modernExtend helpers, which the WS90 definition in shelly.ts composes without overrides — anti-chatter values sized for battery-powered indoor sensors, where report volume costs coin-cell life and mesh airtime.

  • temperature was 1.00 °C: a staircase moving ~twice an hour. Now 0.1 °C, matching the resolution the device reports.
  • pressure was change: 50 with scale: 10 — a 5 kPa (50 hPa) deadband, which real barometric pressure never traverses. Pressure only ever updated on the hourly max heartbeat, and pressure_trend / weather_condition derive from it. Worth noting the same library configures the identical ZCL attribute with change: 5 (5 hPa) in its older reporting.ts helper — the two code paths disagree by 10×, and the modernExtend value is the outlier.

Durability

Anything that makes Z2M re-run configure reverts all of it: re-pairing, an explicit bridge/request/device/configure, or a converter update that changes the definition. The document says so and carries the restore commands.

Those commands are written out literally, one per attribute, rather than generated by a shell helper — the nested quoting through kubectl exec -- sh -c is exactly where this goes wrong. Each was executed and verified in the form given, including the POD extraction and the read-back, and re-applying is a genuine no-op.

The lasting fix is upstream: the WS90 definition should pass explicit reporting overrides instead of inheriting indoor-sensor defaults. Noted at the end of the document.

🤖 Generated with Claude Code

Documents the non-default ZCL reporting configuration now on the Wetterstation, and how to restore it. **No behaviour change from this PR** — the device was reconfigured at runtime; this records it. Adds `zigbee2mqtt-ws90-reporting.md` plus a pointer from the device stanza in `zigbee2mqtt-config.yaml`. ## Why it needs a document rather than a manifest Zigbee2MQTT has no settings-schema field for reporting configuration. It is applied over MQTT (`bridge/request/device/configure_reporting`) and stored on the device and in `database.db`. Flux cannot reconcile it, and a fresh PVC will not have it. ## What changed on the device | attribute | cluster | min | change | was | |---|---|---|---|---| | temperature | 1026 | 5 | 10 → 0.1 °C | 10 / 100 (1 °C) | | humidity | 1029 | 5 | 50 → 0.5 % | 10 / 100 (1 %) | | pressure | 1027 | 5 | 1 → 1 hPa | 10 / 50 (50 hPa) | | illuminance | 1024 | 5 | 5 | 10 / 5 | | wind ×3 | 0xfc01 | 5 | 1 | 10 / 1 | | UV | 0xfc02 | 5 | 1 | 10 / 1 | | rain ×2 | 0xfc03 | 5 | 1 | 10 / 1 | Battery (cluster 1) left at its hourly default. ## The interval `min` is a hold-off, and it was 10 s against an 8.8 s transmit interval — so every change-triggered report was held past a cycle and landed on the next. Attributes reported at best every 17.6 s and drifted out of phase with each other; the published stream showed **no 8.8 s periodicity at all**, just a smear across 2–8 s. At `min: 5` each attribute reports on its own transmit: ``` 17:06:07 17:06:15 17:06:24 17:06:33 17:06:42 17:06:50 17:06:59 17:07:08 ... 8s 9s 9s 9s 8s 9s 9s ``` Mean gap **8.69 s** — the transmit cycle, visible in MQTT for the first time. Publish volume *fell*, ~631/h → ~445/h, because each publish is now a whole cycle rather than a fragment of one. ## The deadbands These come from the shared `modernExtend` helpers, which the WS90 definition in `shelly.ts` composes without overrides — anti-chatter values sized for battery-powered indoor sensors, where report volume costs coin-cell life and mesh airtime. - **temperature** was 1.00 °C: a staircase moving ~twice an hour. Now 0.1 °C, matching the resolution the device reports. - **pressure** was `change: 50` with `scale: 10` — a **5 kPa (50 hPa)** deadband, which real barometric pressure never traverses. Pressure only ever updated on the hourly `max` heartbeat, and `pressure_trend` / `weather_condition` derive from it. Worth noting the same library configures the *identical* ZCL attribute with `change: 5` (5 hPa) in its older `reporting.ts` helper — the two code paths disagree by 10×, and the modernExtend value is the outlier. ## Durability Anything that makes Z2M re-run `configure` reverts all of it: re-pairing, an explicit `bridge/request/device/configure`, or a converter update that changes the definition. The document says so and carries the restore commands. Those commands are written out literally, one per attribute, rather than generated by a shell helper — the nested quoting through `kubectl exec -- sh -c` is exactly where this goes wrong. Each was executed and verified in the form given, including the `POD` extraction and the read-back, and re-applying is a genuine no-op. The lasting fix is upstream: the WS90 definition should pass explicit `reporting` overrides instead of inheriting indoor-sensor defaults. Noted at the end of the document. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
claude-bot added 1 commit 2026-08-24 17:15:54 +00:00
docs(zigbee2mqtt): record the WS90 ZCL reporting configuration
ci/woodpecker/pr/ci-scripts-test Pipeline was successful
ci/woodpecker/pr/ci-manifests-test Pipeline was successful
ci/woodpecker/pr/pr-review Pipeline was successful
c0791e2747
The Wetterstation now carries a non-default reporting configuration: min
interval 5s on all ten reportable attributes, and tighter reportable-change
deadbands on temperature, humidity and pressure. None of it is expressible
in configuration.yaml - Zigbee2MQTT has no settings-schema field for
reporting configuration - so it lives only on the device and in Z2M's
database.db. This documents it and how to restore it.

min was 10s against an 8.8s transmit interval. Since min is a hold-off, every
change-triggered report was held past a transmit cycle and landed on the
next, so attributes reported at best every 17.6s and drifted out of phase.
The published stream showed no 8.8s periodicity at all. At min 5 each
attribute reports on its own transmit and the stream carries one publish per
cycle, measured at a mean gap of 8.69s. Publish volume fell from ~631/h to
~445/h because each publish is now a whole cycle rather than a fragment.

The deadbands come from the shared modernExtend helpers, which the WS90
definition composes without overrides. They are anti-chatter values sized for
battery-powered indoor sensors. Temperature was 1.00 C, giving a staircase
that moved about twice an hour; it is now 0.1 C, matching the resolution the
device actually reports. Pressure was 5 kPa - 50 hPa, which real barometric
pressure never traverses, so it only ever updated on the hourly heartbeat
that pressure_trend and weather_condition derive from. Note the same library
configures the identical ZCL attribute with a 5 hPa deadband in its older
reporting.ts helper, so the two code paths disagree by 10x.

Anything that makes Z2M re-run configure on the device reverts all of it, and
a fresh PVC will not have it. The restore commands are written out literally
rather than generated by a shell helper, because the nested quoting through
`kubectl exec -- sh -c` is where this goes wrong; each was executed and
verified as written, including the read-back, and re-applying is a no-op.

No behaviour change from this commit itself - the device was reconfigured at
runtime, this only records it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
review-bot left a comment
Member

🤖 Automated review — model claude-haiku-4-5-20251001 (complexity: trivial), commit c0791e2747d17f3f2285becd0b9e4e88ada62a00.

Advisory review by the review-bot pipeline. It never approves; a human merges. Push new commits to get a fresh review.


Summary

This PR documents the ZCL reporting configuration applied to the Ecowitt WS90 weather station, which lives on the device and in Z2M's database.db rather than in version control. It adds a comprehensive guide with restore commands, verification steps, and context on why the configuration differs from library defaults. The changes are documentation only; no behavioral changes to the system.

🟡 Suggestions

Documentation clarity on $BASE_TOPIC variable (line 122): The restore commands reference $BASE_TOPIC in the mosquitto_pub -t flag, but there's no explicit setup shown. While the author states these commands were executed and verified, adding one line like BASE_TOPIC=zigbee2mqtt or noting that it's set by the sidecar would make the commands copy-paste ready for future operators unfamiliar with the discovery-guard environment.

Verification command database format (line 156): The verification command pipes grep output through jq, which assumes database.db is JSON-formatted. A brief note that Z2M's database.db is JSONL or similar would help future readers understand the format and troubleshoot if the format changes.

🟢 Nits

Minor: Comment style consistency (zigbee2mqtt-config.yaml, lines 182–187): The added comment uses — (em-dash) while surrounding comments don't consistently use it. This is very minor; the style matches the rest of the codebase's doc comments fine.

Tests

This is documentation. The author has verified the restore commands by executing them against the device and confirmed idempotency. The verification section provides a concrete way to validate restored state. No automated tests needed for documentation.

Recommendation

Looks reasonable — no blocking issues; suggestions above are optional polish to reduce friction for future operators restoring this configuration.

🤖 **Automated review** — model `claude-haiku-4-5-20251001` (complexity: trivial), commit `c0791e2747d17f3f2285becd0b9e4e88ada62a00`. > Advisory review by the `review-bot` pipeline. It never approves; a human merges. Push new commits to get a fresh review. --- ## Summary This PR documents the ZCL reporting configuration applied to the Ecowitt WS90 weather station, which lives on the device and in Z2M's database.db rather than in version control. It adds a comprehensive guide with restore commands, verification steps, and context on why the configuration differs from library defaults. The changes are documentation only; no behavioral changes to the system. ## 🟡 Suggestions **Documentation clarity on `$BASE_TOPIC` variable** (line 122): The restore commands reference `$BASE_TOPIC` in the mosquitto_pub `-t` flag, but there's no explicit setup shown. While the author states these commands were executed and verified, adding one line like `BASE_TOPIC=zigbee2mqtt` or noting that it's set by the sidecar would make the commands copy-paste ready for future operators unfamiliar with the `discovery-guard` environment. **Verification command database format** (line 156): The verification command pipes `grep` output through `jq`, which assumes `database.db` is JSON-formatted. A brief note that Z2M's database.db is JSONL or similar would help future readers understand the format and troubleshoot if the format changes. ## 🟢 Nits **Minor: Comment style consistency** (zigbee2mqtt-config.yaml, lines 182–187): The added comment uses `—` (em-dash) while surrounding comments don't consistently use it. This is very minor; the style matches the rest of the codebase's doc comments fine. ## Tests This is documentation. The author has verified the restore commands by executing them against the device and confirmed idempotency. The verification section provides a concrete way to validate restored state. No automated tests needed for documentation. ## Recommendation Looks reasonable — no blocking issues; suggestions above are optional polish to reduce friction for future operators restoring this configuration. <!-- pr-review:sha=c0791e2747d17f3f2285becd0b9e4e88ada62a00 -->
k.renner merged commit a8a7aa9765 into master 2026-08-24 17:58:49 +00:00
Sign in to join this conversation.