Repository navigation
Conversation
The instantaneous_demand sensor on the Smart Energy Metering cluster
never got a device_class for water/gas flow-rate units, leaving it
without an icon in the UI. Home Assistant has supported
SensorDeviceClass.VOLUME_FLOW_RATE since 2023.1 for all
UnitOfVolumeFlowRate units, so assign it for the metering device
types that use a supported unit (m³/h, ft³/min, gal/h, L/h).
Also fixes the L/h unit string, which was previously lowercase ("l/h")
and did not match Home Assistant's UnitOfVolumeFlowRate.LITERS_PER_HOUR.
Fixes zigpy#1008
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## dev #1009 +/- ##
=======================================
Coverage 97.48% 97.48%
=======================================
Files 61 61
Lines 10870 10870
=======================================
Hits 10597 10597
Misses 273 273 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
TestingTested on a real Home Assistant OS instance against the actual device from #1008 (DIY Zigbee water pulse meter,
|
zigpy-review-bot
left a comment
There was a problem hiding this comment.
Looks good, no findings. The change is small and correct.
Verified (5 checks)
- Every unit now given
VOLUME_FLOW_RATE(m³/h,ft³/min,gal/h,L/h) is a member ofUnitOfVolumeFlowRatein bothzha/units.pyand HA Core (SensorDeviceClass.VOLUME_FLOW_RATE: set(UnitOfVolumeFlowRate)), so none of them can trip HA's device-class/unit validation. The device class also allowsmeasurement, which these entities use. - The
L/hstring fix is real: the oldf"l/{UnitOfTime.HOURS}"producedl/h, which is not a validUnitOfVolumeFlowRatevalue. The same applies to the oldgal/hf-string, which is now the enum member. - Leaving 0x05 (imperial gal/h) and 0x0A unclassified is right, since neither has a matching HA unit.
- The two regenerated fixtures show only the expected
device_classandunitchange oninstantaneous_demand; unique IDs and the other fields are untouched. tests/test_sensor.pypasses in the PR worktree (114 passed), including the new parametrized test.
There was a problem hiding this comment.
🟢 Approval recommended
No active review issues are reported for the flow-rate device-class and unit updates.
No open issues 🎉
What changed in this PR
Addresses #1008 by assigning the volume-flow-rate device class to supported Smart Energy Metering demand units, enabling default icons in Home Assistant.
Changes:
- Assigns
VOLUME_FLOW_RATEto supported units while leaving unsupported units unchanged. - Uses standard flow-rate constants, correcting
"l/h"to"L/h". - Adds parametrized regression coverage and updates two device diagnostics fixtures.
| File | Description |
|---|---|
zha/application/platforms/sensor/__init__.py |
Sets supported flow-rate device classes and standardizes units. |
tests/test_sensor.py |
Tests demand device classes and units for supported mappings. |
tests/data/devices/tze204-xlppj4f5-ts0601-0x0000004a.json |
Updates expected demand class and liter-per-hour unit. |
tests/data/devices/sinope-technologies-va4220zb.json |
Updates expected demand class and liter-per-hour unit. |
Review effort: Balanced

Summary
instantaneous_demandsensor on the Smart EnergyMeteringcluster never got adevice_classfor water/gas flow-rate units, leaving it without an icon in the Home Assistant UI (unlike the companionsummation_delivered/consumption sensor, which does getdevice_class="volume").SensorDeviceClass.VOLUME_FLOW_RATEsince 2023.1, covering allUnitOfVolumeFlowRateunits. This PR assigns it for the metering device types that use a unit supported by that device class:m³/h(0x01, 0x03),ft³/min(0x02),gal/h(0x04) andL/h(0x07).L/hunit string for unit_of_measure0x07, which was previously built as lowercase"l/h"and did not match Home Assistant'sUnitOfVolumeFlowRate.LITERS_PER_HOUR("L/h").Fixes #1008
Test plan
test_smart_energy_metering_instantaneous_demand_device_class) covering all affectedunit_of_measurevalues for a water metering device, asserting the resultingdevice_classandunit.instantaneous_demandentity changed (tools/regenerate_diagnostics.py).pytest tests/passes (1787 passed).pre-commit run(ruff check/format, mypy, codespell) passes.