# Zigbee Sensor Battery Monitoring **Status:** Completed **Branch:** `zigbee-battery-fix` **Commit:** `c515a6b home-assistant: fix zigbee sensor battery reporting` ## Problem Three Aqara Zigbee temperature sensors report `battery: 0` in their MQTT payload, making the `hass_sensor_battery_percent` Prometheus metric useless for battery monitoring on these devices. Affected sensors: - **Temp Living Room** (`0x54ef441000a54d3c`) — WSDCGQ12LM - **Temp Office** (`0x54ef441000a547bd`) — WSDCGQ12LM - **temp_server** (`0x54ef441000a564b6`) — WSDCGQ12LM The **Temp Bedroom** sensor (`0x00124b0025495463`) is a SONOFF SNZB-02 and reports battery correctly. ## Findings - All three sensors are actively reporting temperature, humidity, and pressure data — they are not dead. - The Zigbee2MQTT payload includes a `voltage` field (e.g., `2707` = 2.707V), which indicates healthy battery levels (~40-60% for a CR2032 coin cell). - CR2032 voltage reference: ~3.0V fresh, ~2.7V mid-life, ~2.1V dead. - The `voltage` field is not exposed as a Prometheus metric — it exists only in the MQTT payload. - This is a known firmware quirk with some Aqara WSDCGQ12LM sensors that always report 0% battery. ## Device Inventory Full list of Zigbee devices on ha1 (12 total): | Device | IEEE Address | Model | Type | |--------|-------------|-------|------| | temp_server | 0x54ef441000a564b6 | WSDCGQ12LM | Temperature sensor (battery fix applied) | | (Temp Living Room) | 0x54ef441000a54d3c | WSDCGQ12LM | Temperature sensor (battery fix applied) | | (Temp Office) | 0x54ef441000a547bd | WSDCGQ12LM | Temperature sensor (battery fix applied) | | (Temp Bedroom) | 0x00124b0025495463 | SNZB-02 | Temperature sensor (battery works) | | (Water leak) | 0x54ef4410009ac117 | SJCGQ12LM | Water leak sensor | | btn_livingroom | 0x54ef441000a1f907 | WXKG13LM | Wireless mini switch | | btn_bedroom | 0x54ef441000a1ee71 | WXKG13LM | Wireless mini switch | | (Hue bulb) | 0x001788010dc35d06 | 9290024688 | Hue E27 1100lm (Router) | | (Hue bulb) | 0x001788010dc5f003 | 9290024688 | Hue E27 1100lm (Router) | | (Hue ceiling) | 0x001788010e371aa4 | 915005997301 | Hue Infuse medium (Router) | | (Hue ceiling) | 0x001788010d253b99 | 915005997301 | Hue Infuse medium (Router) | | (Hue wall) | 0x001788010d1b599a | 929003052901 | Hue Sana wall light (Router, transition=5) | ## Implementation ### Solution 1: Calculate battery from voltage in Zigbee2MQTT (Implemented) Override the Home Assistant battery entity's `value_template` in Zigbee2MQTT device configuration to calculate battery percentage from voltage. **Formula:** `(voltage - 2100) / 9` (maps 2100-3000mV to 0-100%) **Changes in `services/home-assistant/default.nix`:** - Device configuration moved from external `devices.yaml` to inline NixOS config - Three affected sensors have `homeassistant.sensor_battery.value_template` override - All 12 devices now declaratively managed **Expected battery values based on current voltages:** | Sensor | Voltage | Expected Battery | |--------|---------|------------------| | Temp Living Room | 2710 mV | ~68% | | Temp Office | 2658 mV | ~62% | | temp_server | 2765 mV | ~74% | ### Solution 2: Alert on sensor staleness (Implemented) Added Prometheus alert `zigbee_sensor_stale` in `services/monitoring/rules.yml` that fires when a Zigbee temperature sensor hasn't updated in over 1 hour. This provides defense-in-depth for detecting dead sensors regardless of battery reporting accuracy. **Alert details:** - Expression: `(time() - hass_last_updated_time_seconds{entity=~"sensor\\.(0x[0-9a-f]+|temp_server)_temperature"}) > 3600` - Severity: warning - For: 5m ## Pre-Deployment Verification ### Backup Verification Before deployment, verified ha1 backup configuration and ran manual backup: **Backup paths:** - `/var/lib/hass` ✓ - `/var/lib/zigbee2mqtt` ✓ - `/var/lib/mosquitto` ✓ **Manual backup (2026-02-05 22:45:23):** - Snapshot ID: `59704dfa` - Files: 77 total (0 new, 13 changed, 64 unmodified) - Data: 62.635 MiB processed, 6.928 MiB stored (compressed) ### Other directories reviewed - `/var/lib/vault` — Contains AppRole credentials; not backed up (can be re-provisioned via Ansible) - `/var/lib/sops-nix` — Legacy; ha1 uses Vault now ## Post-Deployment Steps After deploying to ha1: 1. Restart zigbee2mqtt service (automatic on NixOS rebuild) 2. In Home Assistant, the battery entities may need to be re-discovered: - Go to Settings → Devices & Services → MQTT - The new `value_template` should take effect after entity re-discovery - If not, try disabling and re-enabling the battery entities ## Notes - Device configuration is now declarative in NixOS. Future device additions via Zigbee2MQTT frontend will need to be added to the NixOS config to persist. - The `devices.yaml` file on ha1 will be overwritten on service start but can be removed after confirming the new config works. - The NixOS zigbee2mqtt module defaults to `devices = "devices.yaml"` but our explicit inline config overrides this.