@@ -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