Don't poll ZHA electrical measurement sensors unnecessarily (#92330)

This commit is contained in:
David F. Mulcahey 2023-05-01 12:32:40 -04:00 committed by GitHub
parent adaae46178
commit 2bc2c4a651
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 32 additions and 18 deletions

View file

@ -248,13 +248,16 @@ class Battery(Sensor):
return state_attrs return state_attrs
@MULTI_MATCH(cluster_handler_names=CLUSTER_HANDLER_ELECTRICAL_MEASUREMENT) @MULTI_MATCH(
cluster_handler_names=CLUSTER_HANDLER_ELECTRICAL_MEASUREMENT,
stop_on_match_group=CLUSTER_HANDLER_ELECTRICAL_MEASUREMENT,
models={"VZM31-SN", "SP 234", "outletv4"},
)
class ElectricalMeasurement(Sensor): class ElectricalMeasurement(Sensor):
"""Active power measurement.""" """Active power measurement."""
SENSOR_ATTR = "active_power" SENSOR_ATTR = "active_power"
_attr_device_class: SensorDeviceClass = SensorDeviceClass.POWER _attr_device_class: SensorDeviceClass = SensorDeviceClass.POWER
_attr_should_poll = True # BaseZhaEntity defaults to False
_attr_state_class: SensorStateClass = SensorStateClass.MEASUREMENT _attr_state_class: SensorStateClass = SensorStateClass.MEASUREMENT
_attr_name: str = "Active power" _attr_name: str = "Active power"
_attr_native_unit_of_measurement: str = UnitOfPower.WATT _attr_native_unit_of_measurement: str = UnitOfPower.WATT
@ -284,6 +287,16 @@ class ElectricalMeasurement(Sensor):
return round(value, self._decimals) return round(value, self._decimals)
return round(value) return round(value)
@MULTI_MATCH(
cluster_handler_names=CLUSTER_HANDLER_ELECTRICAL_MEASUREMENT,
stop_on_match_group=CLUSTER_HANDLER_ELECTRICAL_MEASUREMENT,
)
class PolledElectricalMeasurement(ElectricalMeasurement):
"""Polled active power measurement."""
_attr_should_poll = True # BaseZhaEntity defaults to False
async def async_update(self) -> None: async def async_update(self) -> None:
"""Retrieve latest state.""" """Retrieve latest state."""
if not self.available: if not self.available:
@ -299,7 +312,6 @@ class ElectricalMeasurementApparentPower(
SENSOR_ATTR = "apparent_power" SENSOR_ATTR = "apparent_power"
_attr_device_class: SensorDeviceClass = SensorDeviceClass.APPARENT_POWER _attr_device_class: SensorDeviceClass = SensorDeviceClass.APPARENT_POWER
_attr_should_poll = False # Poll indirectly by ElectricalMeasurementSensor
_attr_name: str = "Apparent power" _attr_name: str = "Apparent power"
_attr_native_unit_of_measurement = UnitOfApparentPower.VOLT_AMPERE _attr_native_unit_of_measurement = UnitOfApparentPower.VOLT_AMPERE
_div_mul_prefix = "ac_power" _div_mul_prefix = "ac_power"
@ -311,7 +323,6 @@ class ElectricalMeasurementRMSCurrent(ElectricalMeasurement, id_suffix="rms_curr
SENSOR_ATTR = "rms_current" SENSOR_ATTR = "rms_current"
_attr_device_class: SensorDeviceClass = SensorDeviceClass.CURRENT _attr_device_class: SensorDeviceClass = SensorDeviceClass.CURRENT
_attr_should_poll = False # Poll indirectly by ElectricalMeasurementSensor
_attr_name: str = "RMS current" _attr_name: str = "RMS current"
_attr_native_unit_of_measurement = UnitOfElectricCurrent.AMPERE _attr_native_unit_of_measurement = UnitOfElectricCurrent.AMPERE
_div_mul_prefix = "ac_current" _div_mul_prefix = "ac_current"
@ -323,7 +334,6 @@ class ElectricalMeasurementRMSVoltage(ElectricalMeasurement, id_suffix="rms_volt
SENSOR_ATTR = "rms_voltage" SENSOR_ATTR = "rms_voltage"
_attr_device_class: SensorDeviceClass = SensorDeviceClass.VOLTAGE _attr_device_class: SensorDeviceClass = SensorDeviceClass.VOLTAGE
_attr_should_poll = False # Poll indirectly by ElectricalMeasurementSensor
_attr_name: str = "RMS voltage" _attr_name: str = "RMS voltage"
_attr_native_unit_of_measurement = UnitOfElectricPotential.VOLT _attr_native_unit_of_measurement = UnitOfElectricPotential.VOLT
_div_mul_prefix = "ac_voltage" _div_mul_prefix = "ac_voltage"
@ -335,7 +345,6 @@ class ElectricalMeasurementFrequency(ElectricalMeasurement, id_suffix="ac_freque
SENSOR_ATTR = "ac_frequency" SENSOR_ATTR = "ac_frequency"
_attr_device_class: SensorDeviceClass = SensorDeviceClass.FREQUENCY _attr_device_class: SensorDeviceClass = SensorDeviceClass.FREQUENCY
_attr_should_poll = False # Poll indirectly by ElectricalMeasurementSensor
_attr_name: str = "AC frequency" _attr_name: str = "AC frequency"
_attr_native_unit_of_measurement = UnitOfFrequency.HERTZ _attr_native_unit_of_measurement = UnitOfFrequency.HERTZ
_div_mul_prefix = "ac_frequency" _div_mul_prefix = "ac_frequency"
@ -347,7 +356,6 @@ class ElectricalMeasurementPowerFactor(ElectricalMeasurement, id_suffix="power_f
SENSOR_ATTR = "power_factor" SENSOR_ATTR = "power_factor"
_attr_device_class: SensorDeviceClass = SensorDeviceClass.POWER_FACTOR _attr_device_class: SensorDeviceClass = SensorDeviceClass.POWER_FACTOR
_attr_should_poll = False # Poll indirectly by ElectricalMeasurementSensor
_attr_name: str = "Power factor" _attr_name: str = "Power factor"
_attr_native_unit_of_measurement = PERCENTAGE _attr_native_unit_of_measurement = PERCENTAGE

View file

@ -1,6 +1,6 @@
"""Test ZHA sensor.""" """Test ZHA sensor."""
import math import math
from unittest.mock import patch from unittest.mock import MagicMock, patch
import pytest import pytest
import zigpy.profiles.zha import zigpy.profiles.zha
@ -586,6 +586,10 @@ async def test_temp_uom(
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == uom assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == uom
@patch(
"zigpy.zcl.ClusterPersistingListener",
MagicMock(),
)
async def test_electrical_measurement_init( async def test_electrical_measurement_init(
hass: HomeAssistant, hass: HomeAssistant,
zigpy_device_mock, zigpy_device_mock,
@ -605,7 +609,9 @@ async def test_electrical_measurement_init(
) )
cluster = zigpy_device.endpoints[1].in_clusters[cluster_id] cluster = zigpy_device.endpoints[1].in_clusters[cluster_id]
zha_device = await zha_device_joined(zigpy_device) zha_device = await zha_device_joined(zigpy_device)
entity_id = await find_entity_id(Platform.SENSOR, zha_device, hass) entity_id = await find_entity_id(
Platform.SENSOR, zha_device, hass, qualifier="active_power"
)
# allow traffic to flow through the gateway and devices # allow traffic to flow through the gateway and devices
await async_enable_traffic(hass, [zha_device]) await async_enable_traffic(hass, [zha_device])

View file

@ -195,7 +195,7 @@ DEVICES = [
}, },
("sensor", "00:11:22:33:44:55:66:77-1-2820"): { ("sensor", "00:11:22:33:44:55:66:77-1-2820"): {
DEV_SIG_CLUSTER_HANDLERS: ["electrical_measurement"], DEV_SIG_CLUSTER_HANDLERS: ["electrical_measurement"],
DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurement", DEV_SIG_ENT_MAP_CLASS: "PolledElectricalMeasurement",
DEV_SIG_ENT_MAP_ID: "sensor.centralite_3210_l_active_power", DEV_SIG_ENT_MAP_ID: "sensor.centralite_3210_l_active_power",
}, },
("sensor", "00:11:22:33:44:55:66:77-1-2820-apparent_power"): { ("sensor", "00:11:22:33:44:55:66:77-1-2820-apparent_power"): {
@ -2080,7 +2080,7 @@ DEVICES = [
}, },
("sensor", "00:11:22:33:44:55:66:77-1-2820"): { ("sensor", "00:11:22:33:44:55:66:77-1-2820"): {
DEV_SIG_CLUSTER_HANDLERS: ["electrical_measurement"], DEV_SIG_CLUSTER_HANDLERS: ["electrical_measurement"],
DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurement", DEV_SIG_ENT_MAP_CLASS: "PolledElectricalMeasurement",
DEV_SIG_ENT_MAP_ID: "sensor.lumi_lumi_plug_maus01_active_power", DEV_SIG_ENT_MAP_ID: "sensor.lumi_lumi_plug_maus01_active_power",
}, },
("sensor", "00:11:22:33:44:55:66:77-1-2820-rms_voltage"): { ("sensor", "00:11:22:33:44:55:66:77-1-2820-rms_voltage"): {
@ -2155,7 +2155,7 @@ DEVICES = [
}, },
("sensor", "00:11:22:33:44:55:66:77-1-2820"): { ("sensor", "00:11:22:33:44:55:66:77-1-2820"): {
DEV_SIG_CLUSTER_HANDLERS: ["electrical_measurement"], DEV_SIG_CLUSTER_HANDLERS: ["electrical_measurement"],
DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurement", DEV_SIG_ENT_MAP_CLASS: "PolledElectricalMeasurement",
DEV_SIG_ENT_MAP_ID: "sensor.lumi_lumi_relay_c2acn01_active_power", DEV_SIG_ENT_MAP_ID: "sensor.lumi_lumi_relay_c2acn01_active_power",
}, },
("sensor", "00:11:22:33:44:55:66:77-1-2820-apparent_power"): { ("sensor", "00:11:22:33:44:55:66:77-1-2820-apparent_power"): {
@ -3633,7 +3633,7 @@ DEVICES = [
}, },
("sensor", "00:11:22:33:44:55:66:77-3-2820"): { ("sensor", "00:11:22:33:44:55:66:77-3-2820"): {
DEV_SIG_CLUSTER_HANDLERS: ["electrical_measurement"], DEV_SIG_CLUSTER_HANDLERS: ["electrical_measurement"],
DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurement", DEV_SIG_ENT_MAP_CLASS: "PolledElectricalMeasurement",
DEV_SIG_ENT_MAP_ID: ( DEV_SIG_ENT_MAP_ID: (
"sensor.osram_lightify_rt_tunable_white_active_power" "sensor.osram_lightify_rt_tunable_white_active_power"
), ),
@ -4039,7 +4039,7 @@ DEVICES = [
}, },
("sensor", "00:11:22:33:44:55:66:77-1-2820"): { ("sensor", "00:11:22:33:44:55:66:77-1-2820"): {
DEV_SIG_CLUSTER_HANDLERS: ["electrical_measurement"], DEV_SIG_CLUSTER_HANDLERS: ["electrical_measurement"],
DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurement", DEV_SIG_ENT_MAP_CLASS: "PolledElectricalMeasurement",
DEV_SIG_ENT_MAP_ID: "sensor.securifi_ltd_unk_model_active_power", DEV_SIG_ENT_MAP_ID: "sensor.securifi_ltd_unk_model_active_power",
}, },
("sensor", "00:11:22:33:44:55:66:77-1-2820-apparent_power"): { ("sensor", "00:11:22:33:44:55:66:77-1-2820-apparent_power"): {
@ -4167,7 +4167,7 @@ DEVICES = [
}, },
("sensor", "00:11:22:33:44:55:66:77-1-2820"): { ("sensor", "00:11:22:33:44:55:66:77-1-2820"): {
DEV_SIG_CLUSTER_HANDLERS: ["electrical_measurement"], DEV_SIG_CLUSTER_HANDLERS: ["electrical_measurement"],
DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurement", DEV_SIG_ENT_MAP_CLASS: "PolledElectricalMeasurement",
DEV_SIG_ENT_MAP_ID: "sensor.sercomm_corp_sz_esw01_active_power", DEV_SIG_ENT_MAP_ID: "sensor.sercomm_corp_sz_esw01_active_power",
}, },
("sensor", "00:11:22:33:44:55:66:77-1-2820-apparent_power"): { ("sensor", "00:11:22:33:44:55:66:77-1-2820-apparent_power"): {
@ -4293,7 +4293,7 @@ DEVICES = [
}, },
("sensor", "00:11:22:33:44:55:66:77-1-2820"): { ("sensor", "00:11:22:33:44:55:66:77-1-2820"): {
DEV_SIG_CLUSTER_HANDLERS: ["electrical_measurement"], DEV_SIG_CLUSTER_HANDLERS: ["electrical_measurement"],
DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurement", DEV_SIG_ENT_MAP_CLASS: "PolledElectricalMeasurement",
DEV_SIG_ENT_MAP_ID: "sensor.sinope_technologies_rm3250zb_active_power", DEV_SIG_ENT_MAP_ID: "sensor.sinope_technologies_rm3250zb_active_power",
}, },
("sensor", "00:11:22:33:44:55:66:77-1-2820-apparent_power"): { ("sensor", "00:11:22:33:44:55:66:77-1-2820-apparent_power"): {
@ -4378,7 +4378,7 @@ DEVICES = [
}, },
("sensor", "00:11:22:33:44:55:66:77-1-2820"): { ("sensor", "00:11:22:33:44:55:66:77-1-2820"): {
DEV_SIG_CLUSTER_HANDLERS: ["electrical_measurement"], DEV_SIG_CLUSTER_HANDLERS: ["electrical_measurement"],
DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurement", DEV_SIG_ENT_MAP_CLASS: "PolledElectricalMeasurement",
DEV_SIG_ENT_MAP_ID: "sensor.sinope_technologies_th1123zb_active_power", DEV_SIG_ENT_MAP_ID: "sensor.sinope_technologies_th1123zb_active_power",
}, },
("sensor", "00:11:22:33:44:55:66:77-1-2820-apparent_power"): { ("sensor", "00:11:22:33:44:55:66:77-1-2820-apparent_power"): {
@ -4468,7 +4468,7 @@ DEVICES = [
}, },
("sensor", "00:11:22:33:44:55:66:77-1-2820"): { ("sensor", "00:11:22:33:44:55:66:77-1-2820"): {
DEV_SIG_CLUSTER_HANDLERS: ["electrical_measurement"], DEV_SIG_CLUSTER_HANDLERS: ["electrical_measurement"],
DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurement", DEV_SIG_ENT_MAP_CLASS: "PolledElectricalMeasurement",
DEV_SIG_ENT_MAP_ID: "sensor.sinope_technologies_th1124zb_active_power", DEV_SIG_ENT_MAP_ID: "sensor.sinope_technologies_th1124zb_active_power",
}, },
("sensor", "00:11:22:33:44:55:66:77-1-2820-apparent_power"): { ("sensor", "00:11:22:33:44:55:66:77-1-2820-apparent_power"): {