From 2bc2c4a651a3eb21c3b2aa0fd0e921eba59e4baf Mon Sep 17 00:00:00 2001 From: "David F. Mulcahey" Date: Mon, 1 May 2023 12:32:40 -0400 Subject: [PATCH] Don't poll ZHA electrical measurement sensors unnecessarily (#92330) --- homeassistant/components/zha/sensor.py | 22 +++++++++++++++------- tests/components/zha/test_sensor.py | 10 ++++++++-- tests/components/zha/zha_devices_list.py | 18 +++++++++--------- 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/homeassistant/components/zha/sensor.py b/homeassistant/components/zha/sensor.py index dda9412b56f..52c1f6a5b19 100644 --- a/homeassistant/components/zha/sensor.py +++ b/homeassistant/components/zha/sensor.py @@ -248,13 +248,16 @@ class Battery(Sensor): 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): """Active power measurement.""" SENSOR_ATTR = "active_power" _attr_device_class: SensorDeviceClass = SensorDeviceClass.POWER - _attr_should_poll = True # BaseZhaEntity defaults to False _attr_state_class: SensorStateClass = SensorStateClass.MEASUREMENT _attr_name: str = "Active power" _attr_native_unit_of_measurement: str = UnitOfPower.WATT @@ -284,6 +287,16 @@ class ElectricalMeasurement(Sensor): return round(value, self._decimals) 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: """Retrieve latest state.""" if not self.available: @@ -299,7 +312,6 @@ class ElectricalMeasurementApparentPower( SENSOR_ATTR = "apparent_power" _attr_device_class: SensorDeviceClass = SensorDeviceClass.APPARENT_POWER - _attr_should_poll = False # Poll indirectly by ElectricalMeasurementSensor _attr_name: str = "Apparent power" _attr_native_unit_of_measurement = UnitOfApparentPower.VOLT_AMPERE _div_mul_prefix = "ac_power" @@ -311,7 +323,6 @@ class ElectricalMeasurementRMSCurrent(ElectricalMeasurement, id_suffix="rms_curr SENSOR_ATTR = "rms_current" _attr_device_class: SensorDeviceClass = SensorDeviceClass.CURRENT - _attr_should_poll = False # Poll indirectly by ElectricalMeasurementSensor _attr_name: str = "RMS current" _attr_native_unit_of_measurement = UnitOfElectricCurrent.AMPERE _div_mul_prefix = "ac_current" @@ -323,7 +334,6 @@ class ElectricalMeasurementRMSVoltage(ElectricalMeasurement, id_suffix="rms_volt SENSOR_ATTR = "rms_voltage" _attr_device_class: SensorDeviceClass = SensorDeviceClass.VOLTAGE - _attr_should_poll = False # Poll indirectly by ElectricalMeasurementSensor _attr_name: str = "RMS voltage" _attr_native_unit_of_measurement = UnitOfElectricPotential.VOLT _div_mul_prefix = "ac_voltage" @@ -335,7 +345,6 @@ class ElectricalMeasurementFrequency(ElectricalMeasurement, id_suffix="ac_freque SENSOR_ATTR = "ac_frequency" _attr_device_class: SensorDeviceClass = SensorDeviceClass.FREQUENCY - _attr_should_poll = False # Poll indirectly by ElectricalMeasurementSensor _attr_name: str = "AC frequency" _attr_native_unit_of_measurement = UnitOfFrequency.HERTZ _div_mul_prefix = "ac_frequency" @@ -347,7 +356,6 @@ class ElectricalMeasurementPowerFactor(ElectricalMeasurement, id_suffix="power_f SENSOR_ATTR = "power_factor" _attr_device_class: SensorDeviceClass = SensorDeviceClass.POWER_FACTOR - _attr_should_poll = False # Poll indirectly by ElectricalMeasurementSensor _attr_name: str = "Power factor" _attr_native_unit_of_measurement = PERCENTAGE diff --git a/tests/components/zha/test_sensor.py b/tests/components/zha/test_sensor.py index 4e2d2265178..83799147bbe 100644 --- a/tests/components/zha/test_sensor.py +++ b/tests/components/zha/test_sensor.py @@ -1,6 +1,6 @@ """Test ZHA sensor.""" import math -from unittest.mock import patch +from unittest.mock import MagicMock, patch import pytest import zigpy.profiles.zha @@ -586,6 +586,10 @@ async def test_temp_uom( assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == uom +@patch( + "zigpy.zcl.ClusterPersistingListener", + MagicMock(), +) async def test_electrical_measurement_init( hass: HomeAssistant, zigpy_device_mock, @@ -605,7 +609,9 @@ async def test_electrical_measurement_init( ) cluster = zigpy_device.endpoints[1].in_clusters[cluster_id] 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 await async_enable_traffic(hass, [zha_device]) diff --git a/tests/components/zha/zha_devices_list.py b/tests/components/zha/zha_devices_list.py index a45d02a3aa2..4ccf7323148 100644 --- a/tests/components/zha/zha_devices_list.py +++ b/tests/components/zha/zha_devices_list.py @@ -195,7 +195,7 @@ DEVICES = [ }, ("sensor", "00:11:22:33:44:55:66:77-1-2820"): { 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", }, ("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"): { 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", }, ("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"): { 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", }, ("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"): { DEV_SIG_CLUSTER_HANDLERS: ["electrical_measurement"], - DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurement", + DEV_SIG_ENT_MAP_CLASS: "PolledElectricalMeasurement", DEV_SIG_ENT_MAP_ID: ( "sensor.osram_lightify_rt_tunable_white_active_power" ), @@ -4039,7 +4039,7 @@ DEVICES = [ }, ("sensor", "00:11:22:33:44:55:66:77-1-2820"): { 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", }, ("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"): { 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", }, ("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"): { 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", }, ("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"): { 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", }, ("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"): { 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", }, ("sensor", "00:11:22:33:44:55:66:77-1-2820-apparent_power"): {