zigpy / zha-device-handlers

ZHA device handlers bridge the functionality gap created when manufacturers deviate from the ZCL specification, handling deviations and exceptions by parsing custom messages to and from Zigbee devices.
Apache License 2.0
683 stars 636 forks source link

[Device Support Request] Bituo Technik SPM01-D2TZ-U01 Energy meter #2958

Open fbalesse opened 5 months ago

fbalesse commented 5 months ago

Problem description

Device is correctly added to Home Assistant and sensors appears after a reboot. The issue is Power value (in W) on Home Assistant is divised by 1000 with 1 digit precision. Regarding the cluster, the value is ok, but a dividor is set to 1000 when multiplicator is set to 1.

Solution description

I tried to write my first Quirks, by if i don't use LocalDataCluster, the sensors don't change, and if i use it, the sensors keep the 0 value. I don't understand why.

Screenshots/Video

No response

Device signature

Device signature signature = { # "node_descriptor": "NodeDescriptor(logical_type=, complex_descriptor_available=0, # user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=, # mac_capability_flags=, # manufacturer_code=4098, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, # maximum_outgoing_transfer_size=82, descriptor_capability_field=, # *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=False, # *is_full_function_device=True, *is_mains_powered=True, *is_receiver_on_when_idle=True, *is_router=True, # *is_security_capable=False)", # device_version=1 # input_clusters=[0x0000, 0x0003, 0x0702, 0x0b04, 0x0b05] # output_clusters=[0x0003, 0x0019] MODELS_INFO: [ ("BITUO TECHNIK", "SPM01X001"), ], ENDPOINTS: { # 1: { PROFILE_ID: 0x0104, DEVICE_TYPE: 0x0501, INPUT_CLUSTERS: [ Basic.cluster_id, Identify.cluster_id, Metering.cluster_id, ElectricalMeasurement.cluster_id, Diagnostic.cluster_id, ], OUTPUT_CLUSTERS: [Identify.cluster_id, Ota.cluster_id], } }, }

Diagnostic information

No response

Logs

No response

Custom quirk

Custom quirk ```python """Bituo Din Power Meter.""" from zigpy.profiles import zha from zigpy.quirks import CustomDevice import zigpy.types as t from zigpy.zcl.clusters.general import Basic, Ota, Scenes, Identify from zigpy.zcl.clusters.homeautomation import ElectricalMeasurement, Diagnostic from zigpy.zcl.clusters.smartenergy import Metering from zhaquirks import Bus, LocalDataCluster from zhaquirks.const import ( DEVICE_TYPE, ENDPOINTS, INPUT_CLUSTERS, MODELS_INFO, OUTPUT_CLUSTERS, PROFILE_ID, ) class PowerMeasurement(LocalDataCluster, ElectricalMeasurement): """Custom class for power, voltage and current measurement.""" cluster_id = ElectricalMeasurement.cluster_id POWER_ID = 0x050B VOLTAGE_ID = 0x0505 CURRENT_ID = 0x0508 REACTIVE_POWER_ID = 0x050E AC_FREQUENCY_ID = 0x0300 TOTAL_REACTIVE_POWER_ID = 0x0305 TOTAL_POWER_ID = 0x0304 POWER_FACTOR_ID = 0x0510 AC_CURRENT_MULTIPLIER = 0x0602 AC_CURRENT_DIVISOR = 0x0603 AC_FREQUENCY_MULTIPLIER = 0x0400 AC_FREQUENCY_DIVISOR = 0x0401 AC_POWER_MULTIPLIER = 0x0604 AC_POWER_DIVISOR = 0x0605 _CONSTANT_ATTRIBUTES = { AC_POWER_MULTIPLIER: 1000, AC_POWER_DIVISOR: 1000, } def voltage_reported(self, value): """Voltage reported.""" self._update_attribute(self.VOLTAGE_ID, value) def power_reported(self, value): """Power reported.""" self._update_attribute(self.POWER_ID, value * self.AC_POWER_MULTIPLIER) def power_factor_reported(self, value): """Power Factor reported.""" self._update_attribute(self.POWER_FACTOR_ID, value) def reactive_power_reported(self, value): """Reactive Power reported.""" self._update_attribute(self.REACTIVE_POWER_ID, value * self.AC_POWER_MULTIPLIER) def current_reported(self, value): """Ampers reported.""" self._update_attribute(self.CURRENT_ID, value) def frequency_reported(self, value): """AC Frequency reported.""" self._update_attribute(self.AC_FREQUENCY_ID, value) def reactive_energy_reported(self, value): """Summation Reactive Energy reported.""" self._update_attribute(self.TOTAL_REACTIVE_POWER_ID, value) class BituoPowerMeter(CustomDevice): signature = { # "node_descriptor": "NodeDescriptor(logical_type=, complex_descriptor_available=0, # user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=, # mac_capability_flags=, # manufacturer_code=4098, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, # maximum_outgoing_transfer_size=82, descriptor_capability_field=, # *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=False, # *is_full_function_device=True, *is_mains_powered=True, *is_receiver_on_when_idle=True, *is_router=True, # *is_security_capable=False)", # device_version=1 # input_clusters=[0x0000, 0x0003, 0x0702, 0x0b04, 0x0b05] # output_clusters=[0x0003, 0x0019] MODELS_INFO: [ ("BITUO TECHNIK", "SPM01X001"), ], ENDPOINTS: { # 1: { PROFILE_ID: 0x0104, DEVICE_TYPE: 0x0501, INPUT_CLUSTERS: [ Basic.cluster_id, Identify.cluster_id, Metering.cluster_id, ElectricalMeasurement.cluster_id, Diagnostic.cluster_id, ], OUTPUT_CLUSTERS: [Identify.cluster_id, Ota.cluster_id], } }, } replacement = { ENDPOINTS: { 1: { PROFILE_ID: zha.PROFILE_ID, DEVICE_TYPE: zha.DeviceType.SMART_PLUG, INPUT_CLUSTERS: [ Basic.cluster_id, Identify.cluster_id, Metering.cluster_id, PowerMeasurement, Diagnostic.cluster_id, ], OUTPUT_CLUSTERS: [Identify.cluster_id, Ota.cluster_id], } } } ```

Additional information

No response

romainrossi commented 4 months ago

Same issue here : with this device, the current, voltage and energy meter are ok, but the power values are way too small (apparent power seems to be incorrectly divided by 1000). I also tried to write a quirk file, but without success.