Skip to content

Commit 2c4fd66

Browse files
authored
Clean up electrical measurement sensors (#498)
* Clean up electrical measurement sensors * Regenerate diagnostics for changed class names * Move `_attr_max_attribute_name` line for consistency
1 parent 544c5da commit 2c4fd66

File tree

6 files changed

+64
-68
lines changed

6 files changed

+64
-68
lines changed

tests/data/devices/frient-a-s-emizb-151.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,7 +1506,7 @@
15061506
"unique_id": "ab:cd:ef:12:74:0f:89:c3-2-2820-active_power_ph_b",
15071507
"migrate_unique_ids": [],
15081508
"platform": "sensor",
1509-
"class_name": "ElectricalMeasurementRMSActivePowerPhB",
1509+
"class_name": "ElectricalMeasurementActivePowerPhB",
15101510
"translation_key": "active_power_ph_b",
15111511
"device_class": "power",
15121512
"state_class": "measurement",
@@ -1547,7 +1547,7 @@
15471547
"unit": "W"
15481548
},
15491549
"state": {
1550-
"class_name": "ElectricalMeasurementRMSActivePowerPhB",
1550+
"class_name": "ElectricalMeasurementActivePowerPhB",
15511551
"available": true,
15521552
"state": 1274.0,
15531553
"measurement_type": "ACTIVE_MEASUREMENT, PHASE_A_MEASUREMENT, PHASE_B_MEASUREMENT, PHASE_C_MEASUREMENT"
@@ -1559,7 +1559,7 @@
15591559
"unique_id": "ab:cd:ef:12:74:0f:89:c3-2-2820-active_power_ph_c",
15601560
"migrate_unique_ids": [],
15611561
"platform": "sensor",
1562-
"class_name": "ElectricalMeasurementRMSActivePowerPhC",
1562+
"class_name": "ElectricalMeasurementActivePowerPhC",
15631563
"translation_key": "active_power_ph_c",
15641564
"device_class": "power",
15651565
"state_class": "measurement",
@@ -1600,7 +1600,7 @@
16001600
"unit": "W"
16011601
},
16021602
"state": {
1603-
"class_name": "ElectricalMeasurementRMSActivePowerPhC",
1603+
"class_name": "ElectricalMeasurementActivePowerPhC",
16041604
"available": true,
16051605
"state": 29.0,
16061606
"measurement_type": "ACTIVE_MEASUREMENT, PHASE_A_MEASUREMENT, PHASE_B_MEASUREMENT, PHASE_C_MEASUREMENT"

tests/data/devices/ikea-of-sweden-inspelning-smart-plug.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,7 @@
746746
"unique_id": "d4:48:67:ff:fe:13:d6:f8-1-2820",
747747
"migrate_unique_ids": [],
748748
"platform": "sensor",
749-
"class_name": "ElectricalMeasurement",
749+
"class_name": "ReportingElectricalMeasurement",
750750
"translation_key": null,
751751
"device_class": "power",
752752
"state_class": "measurement",
@@ -787,7 +787,7 @@
787787
"unit": "W"
788788
},
789789
"state": {
790-
"class_name": "ElectricalMeasurement",
790+
"class_name": "ReportingElectricalMeasurement",
791791
"available": true,
792792
"state": 0.0,
793793
"measurement_type": "ACTIVE_MEASUREMENT, PHASE_A_MEASUREMENT"

tests/data/devices/innr-sp-234.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -710,7 +710,7 @@
710710
"unique_id": "70:ac:08:ff:fe:ef:c4:b7-1-2820",
711711
"migrate_unique_ids": [],
712712
"platform": "sensor",
713-
"class_name": "ElectricalMeasurement",
713+
"class_name": "ReportingElectricalMeasurement",
714714
"translation_key": null,
715715
"device_class": "power",
716716
"state_class": "measurement",
@@ -751,7 +751,7 @@
751751
"unit": "W"
752752
},
753753
"state": {
754-
"class_name": "ElectricalMeasurement",
754+
"class_name": "ReportingElectricalMeasurement",
755755
"available": true,
756756
"state": 0.0,
757757
"measurement_type": "ACTIVE_MEASUREMENT"

tests/data/devices/inovelli-vzm31-sn.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2631,7 +2631,7 @@
26312631
"unique_id": "ab:cd:ef:12:dc:41:3c:40-1-2820",
26322632
"migrate_unique_ids": [],
26332633
"platform": "sensor",
2634-
"class_name": "ElectricalMeasurement",
2634+
"class_name": "ReportingElectricalMeasurement",
26352635
"translation_key": null,
26362636
"device_class": "power",
26372637
"state_class": "measurement",
@@ -2672,7 +2672,7 @@
26722672
"unit": "W"
26732673
},
26742674
"state": {
2675-
"class_name": "ElectricalMeasurement",
2675+
"class_name": "ReportingElectricalMeasurement",
26762676
"available": true,
26772677
"state": 0.0
26782678
}

tests/data/devices/tze200-ny94onlb-ts0601.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,7 +1015,7 @@
10151015
"unique_id": "ab:cd:ef:12:58:8c:89:ff-1-2820-active_power_ph_b",
10161016
"migrate_unique_ids": [],
10171017
"platform": "sensor",
1018-
"class_name": "ElectricalMeasurementRMSActivePowerPhB",
1018+
"class_name": "ElectricalMeasurementActivePowerPhB",
10191019
"translation_key": "active_power_ph_b",
10201020
"device_class": "power",
10211021
"state_class": "measurement",
@@ -1056,7 +1056,7 @@
10561056
"unit": "W"
10571057
},
10581058
"state": {
1059-
"class_name": "ElectricalMeasurementRMSActivePowerPhB",
1059+
"class_name": "ElectricalMeasurementActivePowerPhB",
10601060
"available": true,
10611061
"state": 266.0
10621062
}
@@ -1067,7 +1067,7 @@
10671067
"unique_id": "ab:cd:ef:12:58:8c:89:ff-1-2820-active_power_ph_c",
10681068
"migrate_unique_ids": [],
10691069
"platform": "sensor",
1070-
"class_name": "ElectricalMeasurementRMSActivePowerPhC",
1070+
"class_name": "ElectricalMeasurementActivePowerPhC",
10711071
"translation_key": "active_power_ph_c",
10721072
"device_class": "power",
10731073
"state_class": "measurement",
@@ -1108,7 +1108,7 @@
11081108
"unit": "W"
11091109
},
11101110
"state": {
1111-
"class_name": "ElectricalMeasurementRMSActivePowerPhC",
1111+
"class_name": "ElectricalMeasurementActivePowerPhC",
11121112
"available": true,
11131113
"state": 70.0
11141114
}

zha/application/platforms/sensor/__init__.py

Lines changed: 50 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -666,14 +666,11 @@ class BaseElectricalMeasurement(PollableSensor):
666666
"""Base class for electrical measurement."""
667667

668668
_use_custom_polling: bool = False
669-
_attribute_name = "active_power"
670669
_attr_suggested_display_precision = 1
671-
_attr_device_class: SensorDeviceClass = SensorDeviceClass.POWER
670+
_attr_max_attribute_name: str | None = None
671+
_divisor_attribute_name: str | None = None
672+
_multiplier_attribute_name: str | None = None
672673
_attr_state_class: SensorStateClass = SensorStateClass.MEASUREMENT
673-
_attr_native_unit_of_measurement: str = UnitOfPower.WATT
674-
_divisor_attribute_name: str | None = "ac_power_divisor"
675-
_multiplier_attribute_name: str | None = "ac_power_multiplier"
676-
_attr_max_attribute_name: str = None
677674

678675
def __init__(
679676
self,
@@ -686,23 +683,17 @@ def __init__(
686683
super().__init__(cluster_handlers, endpoint, device, **kwargs)
687684
self._attr_extra_state_attribute_names: set[str] = {
688685
"measurement_type",
689-
self._max_attribute_name,
686+
self._attr_max_attribute_name, # None values are ignored in HA
690687
}
691688

692-
@property
693-
def _max_attribute_name(self) -> str:
694-
"""Return the max attribute name."""
695-
return self._attr_max_attribute_name or f"{self._attribute_name}_max"
696-
697689
@property
698690
def state(self) -> dict[str, Any]:
699691
"""Return the state for this sensor."""
700692
response = super().state
701693
if self._cluster_handler.measurement_type is not None:
702694
response["measurement_type"] = self._cluster_handler.measurement_type
703695

704-
max_attr_name = self._max_attribute_name
705-
if not hasattr(self._cluster_handler.cluster.AttributeDefs, max_attr_name):
696+
if (max_attr_name := self._attr_max_attribute_name) is None:
706697
return response
707698

708699
if (max_v := self._cluster_handler.cluster.get(max_attr_name)) is not None:
@@ -733,13 +724,27 @@ def _divisor(self, value: int | float | None) -> None:
733724
raise AttributeError("Cannot set divisor directly")
734725

735726

727+
# this entity will be created by ReportingEM or PolledEM class below
728+
class ElectricalMeasurementActivePower(BaseElectricalMeasurement):
729+
"""Active power phase measurement."""
730+
731+
_attribute_name = "active_power"
732+
# no unique id suffix for backwards compatibility
733+
# no translation key due to device class
734+
_attr_max_attribute_name = "active_power_max"
735+
_divisor_attribute_name = "ac_power_divisor"
736+
_multiplier_attribute_name = "ac_power_multiplier"
737+
_attr_device_class: SensorDeviceClass = SensorDeviceClass.POWER
738+
_attr_native_unit_of_measurement: str = UnitOfPower.WATT
739+
740+
736741
@MULTI_MATCH(
737742
cluster_handler_names=CLUSTER_HANDLER_ELECTRICAL_MEASUREMENT,
738743
stop_on_match_group=CLUSTER_HANDLER_ELECTRICAL_MEASUREMENT,
739744
models={"VZM31-SN", "SP 234", "outletv4", "INSPELNING Smart plug"},
740745
)
741-
class ElectricalMeasurement(BaseElectricalMeasurement):
742-
"""Active power measurement."""
746+
class ReportingElectricalMeasurement(ElectricalMeasurementActivePower):
747+
"""Unpolled active power measurement."""
743748

744749
pass
745750

@@ -748,71 +753,67 @@ class ElectricalMeasurement(BaseElectricalMeasurement):
748753
cluster_handler_names=CLUSTER_HANDLER_ELECTRICAL_MEASUREMENT,
749754
stop_on_match_group=CLUSTER_HANDLER_ELECTRICAL_MEASUREMENT,
750755
)
751-
class PolledElectricalMeasurement(BaseElectricalMeasurement):
752-
"""Polled active power measurement."""
756+
class PolledElectricalMeasurement(ElectricalMeasurementActivePower):
757+
"""Polled active power measurement that polls all relevant EM attributes."""
753758

754759
_use_custom_polling: bool = True
755760

756761

757762
@MULTI_MATCH(cluster_handler_names=CLUSTER_HANDLER_ELECTRICAL_MEASUREMENT)
758-
class ElectricalMeasurementRMSActivePowerPhB(PolledElectricalMeasurement):
759-
"""RMS active power phase B measurement."""
763+
class ElectricalMeasurementActivePowerPhB(ElectricalMeasurementActivePower):
764+
"""Active power phase B measurement."""
760765

761766
_attribute_name = "active_power_ph_b"
762767
_unique_id_suffix = "active_power_ph_b"
763768
_attr_translation_key: str = "active_power_ph_b"
764-
_use_custom_polling = False # Poll indirectly by ElectricalMeasurementSensor
765-
_skip_creation_if_no_attr_cache = True
766769
_attr_max_attribute_name = "active_power_max_ph_b"
770+
_skip_creation_if_no_attr_cache = True
767771

768772

769773
@MULTI_MATCH(cluster_handler_names=CLUSTER_HANDLER_ELECTRICAL_MEASUREMENT)
770-
class ElectricalMeasurementRMSActivePowerPhC(PolledElectricalMeasurement):
771-
"""RMS active power phase C measurement."""
774+
class ElectricalMeasurementActivePowerPhC(ElectricalMeasurementActivePower):
775+
"""Active power phase C measurement."""
772776

773777
_attribute_name = "active_power_ph_c"
774778
_unique_id_suffix = "active_power_ph_c"
775779
_attr_translation_key: str = "active_power_ph_c"
776-
_use_custom_polling = False # Poll indirectly by ElectricalMeasurementSensor
777-
_skip_creation_if_no_attr_cache = True
778780
_attr_max_attribute_name = "active_power_max_ph_c"
781+
_skip_creation_if_no_attr_cache = True
779782

780783

781784
@MULTI_MATCH(cluster_handler_names=CLUSTER_HANDLER_ELECTRICAL_MEASUREMENT)
782-
class ElectricalMeasurementTotalActivePower(PolledElectricalMeasurement):
785+
class ElectricalMeasurementTotalActivePower(ElectricalMeasurementActivePower):
783786
"""Total active power measurement."""
784787

785788
_attribute_name = "total_active_power"
786789
_unique_id_suffix = "total_active_power"
787790
_attr_translation_key: str = "total_active_power"
788-
_use_custom_polling = False # Poll indirectly by ElectricalMeasurementSensor
789791
_skip_creation_if_no_attr_cache = True
790792

791793

792794
@MULTI_MATCH(cluster_handler_names=CLUSTER_HANDLER_ELECTRICAL_MEASUREMENT)
793-
class ElectricalMeasurementApparentPower(PolledElectricalMeasurement):
795+
class ElectricalMeasurementApparentPower(BaseElectricalMeasurement):
794796
"""Apparent power measurement."""
795797

796798
_attribute_name = "apparent_power"
797799
_unique_id_suffix = "apparent_power"
798-
_use_custom_polling = False # Poll indirectly by ElectricalMeasurementSensor
799-
_attr_device_class: SensorDeviceClass = SensorDeviceClass.APPARENT_POWER
800-
_attr_native_unit_of_measurement = UnitOfApparentPower.VOLT_AMPERE
801800
_divisor_attribute_name = "ac_power_divisor"
802801
_multiplier_attribute_name = "ac_power_multiplier"
802+
_attr_device_class: SensorDeviceClass = SensorDeviceClass.APPARENT_POWER
803+
_attr_native_unit_of_measurement = UnitOfApparentPower.VOLT_AMPERE
803804

804805

805806
@MULTI_MATCH(cluster_handler_names=CLUSTER_HANDLER_ELECTRICAL_MEASUREMENT)
806-
class ElectricalMeasurementRMSCurrent(PolledElectricalMeasurement):
807+
class ElectricalMeasurementRMSCurrent(BaseElectricalMeasurement):
807808
"""RMS current measurement."""
808809

809810
_attribute_name = "rms_current"
810811
_unique_id_suffix = "rms_current"
811-
_use_custom_polling = False # Poll indirectly by ElectricalMeasurementSensor
812-
_attr_device_class: SensorDeviceClass = SensorDeviceClass.CURRENT
813-
_attr_native_unit_of_measurement = UnitOfElectricCurrent.AMPERE
812+
_attr_max_attribute_name = "rms_current_max"
814813
_divisor_attribute_name = "ac_current_divisor"
815814
_multiplier_attribute_name = "ac_current_multiplier"
815+
_attr_device_class: SensorDeviceClass = SensorDeviceClass.CURRENT
816+
_attr_native_unit_of_measurement = UnitOfElectricCurrent.AMPERE
816817

817818

818819
@MULTI_MATCH(cluster_handler_names=CLUSTER_HANDLER_ELECTRICAL_MEASUREMENT)
@@ -822,8 +823,8 @@ class ElectricalMeasurementRMSCurrentPhB(ElectricalMeasurementRMSCurrent):
822823
_attribute_name = "rms_current_ph_b"
823824
_unique_id_suffix = "rms_current_ph_b"
824825
_attr_translation_key: str = "rms_current_ph_b"
825-
_skip_creation_if_no_attr_cache = True
826826
_attr_max_attribute_name: str = "rms_current_max_ph_b"
827+
_skip_creation_if_no_attr_cache = True
827828

828829

829830
@MULTI_MATCH(cluster_handler_names=CLUSTER_HANDLER_ELECTRICAL_MEASUREMENT)
@@ -833,21 +834,21 @@ class ElectricalMeasurementRMSCurrentPhC(ElectricalMeasurementRMSCurrent):
833834
_attribute_name: str = "rms_current_ph_c"
834835
_unique_id_suffix: str = "rms_current_ph_c"
835836
_attr_translation_key: str = "rms_current_ph_c"
836-
_skip_creation_if_no_attr_cache = True
837837
_attr_max_attribute_name: str = "rms_current_max_ph_c"
838+
_skip_creation_if_no_attr_cache = True
838839

839840

840841
@MULTI_MATCH(cluster_handler_names=CLUSTER_HANDLER_ELECTRICAL_MEASUREMENT)
841-
class ElectricalMeasurementRMSVoltage(PolledElectricalMeasurement):
842+
class ElectricalMeasurementRMSVoltage(BaseElectricalMeasurement):
842843
"""RMS Voltage measurement."""
843844

844845
_attribute_name = "rms_voltage"
845846
_unique_id_suffix = "rms_voltage"
846-
_use_custom_polling = False # Poll indirectly by ElectricalMeasurementSensor
847-
_attr_device_class: SensorDeviceClass = SensorDeviceClass.VOLTAGE
848-
_attr_native_unit_of_measurement = UnitOfElectricPotential.VOLT
847+
_attr_max_attribute_name = "rms_voltage_max"
849848
_divisor_attribute_name = "ac_voltage_divisor"
850849
_multiplier_attribute_name = "ac_voltage_multiplier"
850+
_attr_device_class: SensorDeviceClass = SensorDeviceClass.VOLTAGE
851+
_attr_native_unit_of_measurement = UnitOfElectricPotential.VOLT
851852

852853

853854
@MULTI_MATCH(cluster_handler_names=CLUSTER_HANDLER_ELECTRICAL_MEASUREMENT)
@@ -857,8 +858,8 @@ class ElectricalMeasurementRMSVoltagePhB(ElectricalMeasurementRMSVoltage):
857858
_attribute_name = "rms_voltage_ph_b"
858859
_unique_id_suffix = "rms_voltage_ph_b"
859860
_attr_translation_key: str = "rms_voltage_ph_b"
860-
_skip_creation_if_no_attr_cache = True
861861
_attr_max_attribute_name = "rms_voltage_max_ph_b"
862+
_skip_creation_if_no_attr_cache = True
862863

863864

864865
@MULTI_MATCH(cluster_handler_names=CLUSTER_HANDLER_ELECTRICAL_MEASUREMENT)
@@ -868,35 +869,32 @@ class ElectricalMeasurementRMSVoltagePhC(ElectricalMeasurementRMSVoltage):
868869
_attribute_name = "rms_voltage_ph_c"
869870
_unique_id_suffix = "rms_voltage_ph_c"
870871
_attr_translation_key: str = "rms_voltage_ph_c"
871-
_skip_creation_if_no_attr_cache = True
872872
_attr_max_attribute_name = "rms_voltage_max_ph_c"
873+
_skip_creation_if_no_attr_cache = True
873874

874875

875876
@MULTI_MATCH(cluster_handler_names=CLUSTER_HANDLER_ELECTRICAL_MEASUREMENT)
876-
class ElectricalMeasurementFrequency(PolledElectricalMeasurement):
877+
class ElectricalMeasurementFrequency(BaseElectricalMeasurement):
877878
"""Frequency measurement."""
878879

879880
_attribute_name = "ac_frequency"
880881
_unique_id_suffix = "ac_frequency"
881-
_use_custom_polling = False # Poll indirectly by ElectricalMeasurementSensor
882-
_attr_device_class: SensorDeviceClass = SensorDeviceClass.FREQUENCY
883882
_attr_translation_key: str = "ac_frequency"
884-
_attr_native_unit_of_measurement = UnitOfFrequency.HERTZ
883+
_attr_max_attribute_name = "ac_frequency_max"
885884
_divisor_attribute_name = "ac_frequency_divisor"
886885
_multiplier_attribute_name = "ac_frequency_multiplier"
886+
_attr_device_class: SensorDeviceClass = SensorDeviceClass.FREQUENCY
887+
_attr_native_unit_of_measurement = UnitOfFrequency.HERTZ
887888

888889

889890
@MULTI_MATCH(cluster_handler_names=CLUSTER_HANDLER_ELECTRICAL_MEASUREMENT)
890-
class ElectricalMeasurementPowerFactor(PolledElectricalMeasurement):
891+
class ElectricalMeasurementPowerFactor(BaseElectricalMeasurement):
891892
"""Power Factor measurement."""
892893

893894
_attribute_name = "power_factor"
894895
_unique_id_suffix = "power_factor"
895-
_use_custom_polling = False # Poll indirectly by ElectricalMeasurementSensor
896896
_attr_device_class: SensorDeviceClass = SensorDeviceClass.POWER_FACTOR
897897
_attr_native_unit_of_measurement = PERCENTAGE
898-
_divisor_attribute_name = None
899-
_multiplier_attribute_name = None
900898

901899

902900
@MULTI_MATCH(cluster_handler_names=CLUSTER_HANDLER_ELECTRICAL_MEASUREMENT)
@@ -907,7 +905,6 @@ class ElectricalMeasurementPowerFactorPhB(ElectricalMeasurementPowerFactor):
907905
_unique_id_suffix = "power_factor_ph_b"
908906
_attr_translation_key: str = "power_factor_ph_b"
909907
_skip_creation_if_no_attr_cache = True
910-
_attr_max_attribute_name = "power_factor_max_ph_b"
911908

912909

913910
@MULTI_MATCH(cluster_handler_names=CLUSTER_HANDLER_ELECTRICAL_MEASUREMENT)
@@ -918,7 +915,6 @@ class ElectricalMeasurementPowerFactorPhC(ElectricalMeasurementPowerFactor):
918915
_unique_id_suffix = "power_factor_ph_c"
919916
_attr_translation_key: str = "power_factor_ph_c"
920917
_skip_creation_if_no_attr_cache = True
921-
_attr_max_attribute_name = "power_factor_max_ph_c"
922918

923919

924920
@MULTI_MATCH(

0 commit comments

Comments
 (0)