From 45983533158eabed09e0943520bb573cb1722d03 Mon Sep 17 00:00:00 2001 From: Robin Dupont Date: Fri, 19 Nov 2021 01:43:08 +0100 Subject: [PATCH] Add apparent_power for ZHA ElectricalMeasurement (#59857) * Add apparent_power for ZHA ElectricalMeasurement * Add apparent_power to REPORT_CONFIG * update device list with apparent_power attribute * update test decorators for apparent_power * remove comments * Add test for apparent_power in test_sensor --- .../zha/core/channels/homeautomation.py | 1 + homeassistant/components/zha/sensor.py | 18 +++++ tests/components/zha/test_channels.py | 1 + tests/components/zha/test_sensor.py | 51 +++++++++++--- tests/components/zha/zha_devices_list.py | 67 +++++++++++++++++++ 5 files changed, 129 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/zha/core/channels/homeautomation.py b/homeassistant/components/zha/core/channels/homeautomation.py index 89a9d51395e..5c3ef3a0f6c 100644 --- a/homeassistant/components/zha/core/channels/homeautomation.py +++ b/homeassistant/components/zha/core/channels/homeautomation.py @@ -65,6 +65,7 @@ class ElectricalMeasurementChannel(ZigbeeChannel): REPORT_CONFIG = ( {"attr": "active_power", "config": REPORT_CONFIG_OP}, {"attr": "active_power_max", "config": REPORT_CONFIG_DEFAULT}, + {"attr": "apparent_power", "config": REPORT_CONFIG_OP}, {"attr": "rms_current", "config": REPORT_CONFIG_OP}, {"attr": "rms_current_max", "config": REPORT_CONFIG_DEFAULT}, {"attr": "rms_voltage", "config": REPORT_CONFIG_OP}, diff --git a/homeassistant/components/zha/sensor.py b/homeassistant/components/zha/sensor.py index 365a7d8084f..d5df223ffb0 100644 --- a/homeassistant/components/zha/sensor.py +++ b/homeassistant/components/zha/sensor.py @@ -38,6 +38,7 @@ from homeassistant.const import ( ENTITY_CATEGORY_DIAGNOSTIC, LIGHT_LUX, PERCENTAGE, + POWER_VOLT_AMPERE, POWER_WATT, PRESSURE_HPA, TEMP_CELSIUS, @@ -313,6 +314,23 @@ class ElectricalMeasurement(Sensor): await super().async_update() +@MULTI_MATCH(channel_names=CHANNEL_ELECTRICAL_MEASUREMENT) +class ElectricalMeasurementApparentPower( + ElectricalMeasurement, id_suffix="apparent_power" +): + """Apparent power measurement.""" + + SENSOR_ATTR = "apparent_power" + _device_class = DEVICE_CLASS_POWER + _unit = POWER_VOLT_AMPERE + _div_mul_prefix = "ac_power" + + @property + def should_poll(self) -> bool: + """Poll indirectly by ElectricalMeasurementSensor.""" + return False + + @MULTI_MATCH(channel_names=CHANNEL_ELECTRICAL_MEASUREMENT) class ElectricalMeasurementRMSCurrent(ElectricalMeasurement, id_suffix="rms_current"): """RMS current measurement.""" diff --git a/tests/components/zha/test_channels.py b/tests/components/zha/test_channels.py index e2543181a1a..f4ec40fcb15 100644 --- a/tests/components/zha/test_channels.py +++ b/tests/components/zha/test_channels.py @@ -158,6 +158,7 @@ async def poll_control_device(zha_device_restored, zigpy_device_mock): { "active_power", "active_power_max", + "apparent_power", "rms_current", "rms_current_max", "rms_voltage", diff --git a/tests/components/zha/test_sensor.py b/tests/components/zha/test_sensor.py index 918876fe448..af4bb082b03 100644 --- a/tests/components/zha/test_sensor.py +++ b/tests/components/zha/test_sensor.py @@ -23,6 +23,7 @@ from homeassistant.const import ( ENERGY_KILO_WATT_HOUR, LIGHT_LUX, PERCENTAGE, + POWER_VOLT_AMPERE, POWER_WATT, PRESSURE_HPA, STATE_UNAVAILABLE, @@ -174,6 +175,24 @@ async def async_test_electrical_measurement(hass, cluster, entity_id): assert hass.states.get(entity_id).attributes["active_power_max"] == "8.8" +async def async_test_em_apparent_power(hass, cluster, entity_id): + """Test electrical measurement Apparent Power sensor.""" + # update divisor cached value + await send_attributes_report(hass, cluster, {"ac_power_divisor": 1}) + await send_attributes_report(hass, cluster, {0: 1, 0x050F: 100, 10: 1000}) + assert_state(hass, entity_id, "100", POWER_VOLT_AMPERE) + + await send_attributes_report(hass, cluster, {0: 1, 0x050F: 99, 10: 1000}) + assert_state(hass, entity_id, "99", POWER_VOLT_AMPERE) + + await send_attributes_report(hass, cluster, {"ac_power_divisor": 10}) + await send_attributes_report(hass, cluster, {0: 1, 0x050F: 1000, 10: 5000}) + assert_state(hass, entity_id, "100", POWER_VOLT_AMPERE) + + await send_attributes_report(hass, cluster, {0: 1, 0x050F: 99, 10: 5000}) + assert_state(hass, entity_id, "9.9", POWER_VOLT_AMPERE) + + async def async_test_em_rms_current(hass, cluster, entity_id): """Test electrical measurement RMS Current sensor.""" @@ -290,25 +309,33 @@ async def async_test_powerconfiguration(hass, cluster, entity_id): homeautomation.ElectricalMeasurement.cluster_id, "electrical_measurement", async_test_electrical_measurement, - 6, + 7, {"ac_power_divisor": 1000, "ac_power_multiplier": 1}, - {"rms_current", "rms_voltage"}, + {"apparent_power", "rms_current", "rms_voltage"}, + ), + ( + homeautomation.ElectricalMeasurement.cluster_id, + "electrical_measurement_apparent_power", + async_test_em_apparent_power, + 7, + {"ac_power_divisor": 1000, "ac_power_multiplier": 1}, + {"active_power", "rms_current", "rms_voltage"}, ), ( homeautomation.ElectricalMeasurement.cluster_id, "electrical_measurement_rms_current", async_test_em_rms_current, - 6, + 7, {"ac_current_divisor": 1000, "ac_current_multiplier": 1}, - {"active_power", "rms_voltage"}, + {"active_power", "apparent_power", "rms_voltage"}, ), ( homeautomation.ElectricalMeasurement.cluster_id, "electrical_measurement_rms_voltage", async_test_em_rms_voltage, - 6, + 7, {"ac_voltage_divisor": 10, "ac_voltage_multiplier": 1}, - {"active_power", "rms_current"}, + {"active_power", "apparent_power", "rms_current"}, ), ( general.PowerConfiguration.cluster_id, @@ -561,18 +588,22 @@ async def test_electrical_measurement_init( ( ( homeautomation.ElectricalMeasurement.cluster_id, - {"rms_voltage", "rms_current"}, + {"apparent_power", "rms_voltage", "rms_current"}, {"electrical_measurement"}, { + "electrical_measurement_apparent_power", "electrical_measurement_rms_voltage", "electrical_measurement_rms_current", }, ), ( homeautomation.ElectricalMeasurement.cluster_id, - {"rms_current"}, + {"apparent_power", "rms_current"}, {"electrical_measurement_rms_voltage", "electrical_measurement"}, - {"electrical_measurement_rms_current"}, + { + "electrical_measurement_apparent_power", + "electrical_measurement_rms_current", + }, ), ( homeautomation.ElectricalMeasurement.cluster_id, @@ -580,6 +611,7 @@ async def test_electrical_measurement_init( { "electrical_measurement_rms_voltage", "electrical_measurement", + "electrical_measurement_apparent_power", "electrical_measurement_rms_current", }, set(), @@ -853,6 +885,7 @@ async def test_elec_measurement_skip_unsupported_attribute( all_attrs = { "active_power", "active_power_max", + "apparent_power", "rms_current", "rms_current_max", "rms_voltage", diff --git a/tests/components/zha/zha_devices_list.py b/tests/components/zha/zha_devices_list.py index 2ef2e578dce..41d4b0d1bee 100644 --- a/tests/components/zha/zha_devices_list.py +++ b/tests/components/zha/zha_devices_list.py @@ -117,6 +117,8 @@ DEVICES = [ }, DEV_SIG_ENTITIES: [ "sensor.centralite_3210_l_77665544_electrical_measurement", + "sensor.centralite_3210_l_77665544_electrical_measurement_apparent_power", + "sensor.centralite_3210_l_77665544_electrical_measurement_apparent_power", "sensor.centralite_3210_l_77665544_electrical_measurement_rms_current", "sensor.centralite_3210_l_77665544_electrical_measurement_rms_voltage", "sensor.centralite_3210_l_77665544_smartenergy_metering", @@ -144,6 +146,11 @@ DEVICES = [ DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurement", DEV_SIG_ENT_MAP_ID: "sensor.centralite_3210_l_77665544_electrical_measurement", }, + ("sensor", "00:11:22:33:44:55:66:77-1-2820-apparent_power"): { + DEV_SIG_CHANNELS: ["electrical_measurement"], + DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurementApparentPower", + DEV_SIG_ENT_MAP_ID: "sensor.centralite_3210_l_77665544_electrical_measurement_apparent_power", + }, ("sensor", "00:11:22:33:44:55:66:77-1-2820-rms_current"): { DEV_SIG_CHANNELS: ["electrical_measurement"], DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurementRMSCurrent", @@ -1448,6 +1455,7 @@ DEVICES = [ "sensor.lumi_lumi_plug_maus01_77665544_analog_input", "sensor.lumi_lumi_plug_maus01_77665544_analog_input_2", "sensor.lumi_lumi_plug_maus01_77665544_electrical_measurement", + "sensor.lumi_lumi_plug_maus01_77665544_electrical_measurement_apparent_power", "sensor.lumi_lumi_plug_maus01_77665544_electrical_measurement_rms_current", "sensor.lumi_lumi_plug_maus01_77665544_electrical_measurement_rms_voltage", "switch.lumi_lumi_plug_maus01_77665544_on_off", @@ -1473,6 +1481,11 @@ DEVICES = [ DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurement", DEV_SIG_ENT_MAP_ID: "sensor.lumi_lumi_plug_maus01_77665544_electrical_measurement", }, + ("sensor", "00:11:22:33:44:55:66:77-1-2820-apparent_power"): { + DEV_SIG_CHANNELS: ["electrical_measurement"], + DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurementApparentPower", + DEV_SIG_ENT_MAP_ID: "sensor.lumi_lumi_plug_maus01_77665544_electrical_measurement_apparent_power", + }, ("sensor", "00:11:22:33:44:55:66:77-1-2820-rms_current"): { DEV_SIG_CHANNELS: ["electrical_measurement"], DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurementRMSCurrent", @@ -1517,6 +1530,7 @@ DEVICES = [ "light.lumi_lumi_relay_c2acn01_77665544_on_off", "light.lumi_lumi_relay_c2acn01_77665544_on_off_2", "sensor.lumi_lumi_relay_c2acn01_77665544_electrical_measurement", + "sensor.lumi_lumi_relay_c2acn01_77665544_electrical_measurement_apparent_power", "sensor.lumi_lumi_relay_c2acn01_77665544_electrical_measurement_rms_current", "sensor.lumi_lumi_relay_c2acn01_77665544_electrical_measurement_rms_voltage", ], @@ -1531,6 +1545,11 @@ DEVICES = [ DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurement", DEV_SIG_ENT_MAP_ID: "sensor.lumi_lumi_relay_c2acn01_77665544_electrical_measurement", }, + ("sensor", "00:11:22:33:44:55:66:77-1-2820-apparent_power"): { + DEV_SIG_CHANNELS: ["electrical_measurement"], + DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurementApparentPower", + DEV_SIG_ENT_MAP_ID: "sensor.lumi_lumi_relay_c2acn01_77665544_electrical_measurement_apparent_power", + }, ("sensor", "00:11:22:33:44:55:66:77-1-2820-rms_current"): { DEV_SIG_CHANNELS: ["electrical_measurement"], DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurementRMSCurrent", @@ -2602,6 +2621,7 @@ DEVICES = [ DEV_SIG_ENTITIES: [ "light.osram_lightify_rt_tunable_white_77665544_level_light_color_on_off", "sensor.osram_lightify_rt_tunable_white_77665544_electrical_measurement", + "sensor.osram_lightify_rt_tunable_white_77665544_electrical_measurement_apparent_power", "sensor.osram_lightify_rt_tunable_white_77665544_electrical_measurement_rms_current", "sensor.osram_lightify_rt_tunable_white_77665544_electrical_measurement_rms_voltage", ], @@ -2616,6 +2636,11 @@ DEVICES = [ DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurement", DEV_SIG_ENT_MAP_ID: "sensor.osram_lightify_rt_tunable_white_77665544_electrical_measurement", }, + ("sensor", "00:11:22:33:44:55:66:77-3-2820-apparent_power"): { + DEV_SIG_CHANNELS: ["electrical_measurement"], + DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurementApparentPower", + DEV_SIG_ENT_MAP_ID: "sensor.osram_lightify_rt_tunable_white_77665544_electrical_measurement_apparent_power", + }, ("sensor", "00:11:22:33:44:55:66:77-3-2820-rms_current"): { DEV_SIG_CHANNELS: ["electrical_measurement"], DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurementRMSCurrent", @@ -2646,6 +2671,7 @@ DEVICES = [ }, DEV_SIG_ENTITIES: [ "sensor.osram_plug_01_77665544_electrical_measurement", + "sensor.osram_plug_01_77665544_electrical_measurement_apparent_power", "sensor.osram_plug_01_77665544_electrical_measurement_rms_current", "sensor.osram_plug_01_77665544_electrical_measurement_rms_voltage", "switch.osram_plug_01_77665544_on_off", @@ -2661,6 +2687,11 @@ DEVICES = [ DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurement", DEV_SIG_ENT_MAP_ID: "sensor.osram_plug_01_77665544_electrical_measurement", }, + ("sensor", "00:11:22:33:44:55:66:77-3-2820-apparent_power"): { + DEV_SIG_CHANNELS: ["electrical_measurement"], + DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurementApparentPower", + DEV_SIG_ENT_MAP_ID: "sensor.osram_plug_01_77665544_electrical_measurement_apparent_power", + }, ("sensor", "00:11:22:33:44:55:66:77-3-2820-rms_current"): { DEV_SIG_CHANNELS: ["electrical_measurement"], DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurementRMSCurrent", @@ -2930,6 +2961,7 @@ DEVICES = [ }, DEV_SIG_ENTITIES: [ "sensor.securifi_ltd_unk_model_77665544_electrical_measurement", + "sensor.securifi_ltd_unk_model_77665544_electrical_measurement_apparent_power", "sensor.securifi_ltd_unk_model_77665544_electrical_measurement_rms_current", "sensor.securifi_ltd_unk_model_77665544_electrical_measurement_rms_voltage", "switch.securifi_ltd_unk_model_77665544_on_off", @@ -2945,6 +2977,11 @@ DEVICES = [ DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurement", DEV_SIG_ENT_MAP_ID: "sensor.securifi_ltd_unk_model_77665544_electrical_measurement", }, + ("sensor", "00:11:22:33:44:55:66:77-1-2820-apparent_power"): { + DEV_SIG_CHANNELS: ["electrical_measurement"], + DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurementApparentPower", + DEV_SIG_ENT_MAP_ID: "sensor.securifi_ltd_unk_model_77665544_electrical_measurement_apparent_power", + }, ("sensor", "00:11:22:33:44:55:66:77-1-2820-rms_current"): { DEV_SIG_CHANNELS: ["electrical_measurement"], DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurementRMSCurrent", @@ -3020,6 +3057,7 @@ DEVICES = [ DEV_SIG_ENTITIES: [ "light.sercomm_corp_sz_esw01_77665544_on_off", "sensor.sercomm_corp_sz_esw01_77665544_electrical_measurement", + "sensor.sercomm_corp_sz_esw01_77665544_electrical_measurement_apparent_power", "sensor.sercomm_corp_sz_esw01_77665544_electrical_measurement_rms_current", "sensor.sercomm_corp_sz_esw01_77665544_electrical_measurement_rms_voltage", "sensor.sercomm_corp_sz_esw01_77665544_smartenergy_metering", @@ -3046,6 +3084,11 @@ DEVICES = [ DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurement", DEV_SIG_ENT_MAP_ID: "sensor.sercomm_corp_sz_esw01_77665544_electrical_measurement", }, + ("sensor", "00:11:22:33:44:55:66:77-1-2820-apparent_power"): { + DEV_SIG_CHANNELS: ["electrical_measurement"], + DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurementApparentPower", + DEV_SIG_ENT_MAP_ID: "sensor.sercomm_corp_sz_esw01_77665544_electrical_measurement_apparent_power", + }, ("sensor", "00:11:22:33:44:55:66:77-1-2820-rms_current"): { DEV_SIG_CHANNELS: ["electrical_measurement"], DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurementRMSCurrent", @@ -3119,6 +3162,7 @@ DEVICES = [ }, DEV_SIG_ENTITIES: [ "sensor.sinope_technologies_rm3250zb_77665544_electrical_measurement", + "sensor.sinope_technologies_rm3250zb_77665544_electrical_measurement_apparent_power", "sensor.sinope_technologies_rm3250zb_77665544_electrical_measurement_rms_current", "sensor.sinope_technologies_rm3250zb_77665544_electrical_measurement_rms_voltage", "switch.sinope_technologies_rm3250zb_77665544_on_off", @@ -3134,6 +3178,11 @@ DEVICES = [ DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurement", DEV_SIG_ENT_MAP_ID: "sensor.sinope_technologies_rm3250zb_77665544_electrical_measurement", }, + ("sensor", "00:11:22:33:44:55:66:77-1-2820-apparent_power"): { + DEV_SIG_CHANNELS: ["electrical_measurement"], + DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurementApparentPower", + DEV_SIG_ENT_MAP_ID: "sensor.sinope_technologies_rm3250zb_77665544_electrical_measurement_apparent_power", + }, ("sensor", "00:11:22:33:44:55:66:77-1-2820-rms_current"): { DEV_SIG_CHANNELS: ["electrical_measurement"], DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurementRMSCurrent", @@ -3171,6 +3220,7 @@ DEVICES = [ DEV_SIG_ENTITIES: [ "climate.sinope_technologies_th1123zb_77665544_thermostat", "sensor.sinope_technologies_th1123zb_77665544_electrical_measurement", + "sensor.sinope_technologies_th1123zb_77665544_electrical_measurement_apparent_power", "sensor.sinope_technologies_th1123zb_77665544_electrical_measurement_rms_current", "sensor.sinope_technologies_th1123zb_77665544_electrical_measurement_rms_voltage", "sensor.sinope_technologies_th1123zb_77665544_temperature", @@ -3192,6 +3242,11 @@ DEVICES = [ DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurement", DEV_SIG_ENT_MAP_ID: "sensor.sinope_technologies_th1123zb_77665544_electrical_measurement", }, + ("sensor", "00:11:22:33:44:55:66:77-1-2820-apparent_power"): { + DEV_SIG_CHANNELS: ["electrical_measurement"], + DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurementApparentPower", + DEV_SIG_ENT_MAP_ID: "sensor.sinope_technologies_th1123zb_77665544_electrical_measurement_apparent_power", + }, ("sensor", "00:11:22:33:44:55:66:77-1-2820-rms_current"): { DEV_SIG_CHANNELS: ["electrical_measurement"], DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurementRMSCurrent", @@ -3234,6 +3289,7 @@ DEVICES = [ }, DEV_SIG_ENTITIES: [ "sensor.sinope_technologies_th1124zb_77665544_electrical_measurement", + "sensor.sinope_technologies_th1124zb_77665544_electrical_measurement_apparent_power", "sensor.sinope_technologies_th1124zb_77665544_electrical_measurement_rms_current", "sensor.sinope_technologies_th1124zb_77665544_electrical_measurement_rms_voltage", "sensor.sinope_technologies_th1124zb_77665544_temperature", @@ -3261,6 +3317,11 @@ DEVICES = [ DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurement", DEV_SIG_ENT_MAP_ID: "sensor.sinope_technologies_th1124zb_77665544_electrical_measurement", }, + ("sensor", "00:11:22:33:44:55:66:77-1-2820-apparent_power"): { + DEV_SIG_CHANNELS: ["electrical_measurement"], + DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurementApparentPower", + DEV_SIG_ENT_MAP_ID: "sensor.sinope_technologies_th1124zb_77665544_electrical_measurement_apparent_power", + }, ("sensor", "00:11:22:33:44:55:66:77-1-2820-rms_current"): { DEV_SIG_CHANNELS: ["electrical_measurement"], DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurementRMSCurrent", @@ -3291,6 +3352,7 @@ DEVICES = [ }, DEV_SIG_ENTITIES: [ "sensor.smartthings_outletv4_77665544_electrical_measurement", + "sensor.smartthings_outletv4_77665544_electrical_measurement_apparent_power", "sensor.smartthings_outletv4_77665544_electrical_measurement_rms_current", "sensor.smartthings_outletv4_77665544_electrical_measurement_rms_voltage", "switch.smartthings_outletv4_77665544_on_off", @@ -3306,6 +3368,11 @@ DEVICES = [ DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurement", DEV_SIG_ENT_MAP_ID: "sensor.smartthings_outletv4_77665544_electrical_measurement", }, + ("sensor", "00:11:22:33:44:55:66:77-1-2820-apparent_power"): { + DEV_SIG_CHANNELS: ["electrical_measurement"], + DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurementApparentPower", + DEV_SIG_ENT_MAP_ID: "sensor.smartthings_outletv4_77665544_electrical_measurement_apparent_power", + }, ("sensor", "00:11:22:33:44:55:66:77-1-2820-rms_current"): { DEV_SIG_CHANNELS: ["electrical_measurement"], DEV_SIG_ENT_MAP_CLASS: "ElectricalMeasurementRMSCurrent",