Files
nixos-servers/docs/plans/completed/zigbee-sensor-battery-monitoring.md
Torjus Håkestad 32968147b5
All checks were successful
Run nix flake check / flake-check (push) Successful in 2m17s
Run nix flake check / flake-check (pull_request) Successful in 2m19s
docs: move zigbee battery plan to completed
Updated plan with:
- Full device inventory from ha1
- Backup verification details
- Branch and commit references

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 22:49:49 +01:00

4.9 KiB

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.