Hello everybody,
I’m new on home assistant, I started to work on it end of last year.
My system is working with zigbee’s devices. At the beginning, I installed zigbee2mqtt, but I merged to zha because it’s more stable for my installation and use less memories (the system haos is installed on a raspberry pi 3 b+).
But one device (OWON pc321) is not well recognized.
I took a lot of time to understand quirks. I finally wrote one which is reporting all attributes. But, there’s no any device.
If I install my device without the quirk, 2 entities are discovered.
But with my quirk, no one.
For the moment, I’m using zha toolkit, so I’m able to get attributes values, but it’s not the best.
Here’s my quirk :
import logging
import zigpy.types as t
from zigpy.profiles import zha
from zigpy.quirks import CustomCluster, CustomDevice
from zigpy.zcl.foundation import ZCLAttributeDef, ZCLCommandDef
from zigpy.zcl.clusters.general import (
Basic,
Identify,
)
from zigpy.zcl.clusters.smartenergy import (
Metering,
)
from zhaquirks.const import (
DEVICE_TYPE,
ENDPOINTS,
INPUT_CLUSTERS,
MODELS_INFO,
OUTPUT_CLUSTERS,
PROFILE_ID,
SKIP_CONFIGURATION,
)
from zhaquirks import Bus, LocalDataCluster
_LOGGER = logging.getLogger(__name__)
""" definitions cluster """
class SimpleMetering(CustomCluster):
cluster_id = 0x0702
name = "Owon Simple Metering dbl"
ep_attribute = "simple_metering"
POWER_L = 0x2000
def __init__(self, *args, **kwargs):
"""Init electrical measurement cluster."""
super().__init__(*args, **kwargs)
self.endpoint.device.power_bus.add_listener(self)
def power_reported(self, value):
"""Report consumption."""
self._update_attribute(self.POWER_L, value)
attributes: dict[int, ZCLAttributeDef] = {
0x0000: ZCLAttributeDef("current_summ_delivered", type=t.uint48_t, access="r", mandatory=True),
0x0017: ZCLAttributeDef("Inlet_temperature", type=t.uint24_t, access="r", mandatory=True),
0x0200: ZCLAttributeDef("Status", type=t.bitmap8, access="r", mandatory=True),
0x0300: ZCLAttributeDef("unit_of_measure", type=t.enum8, access="r", mandatory=True),
0x0301: ZCLAttributeDef("multiplier", type=t.uint24_t, access="r", mandatory=True),
0x0302: ZCLAttributeDef("divisor", type=t.uint24_t, access="r", mandatory=True),
0x0303: ZCLAttributeDef("summation_formatting", type=t.bitmap8, access="r", mandatory=True),
0x0304: ZCLAttributeDef("demand_formatting", type=t.bitmap8, access="r", mandatory=True),
0x0306: ZCLAttributeDef("metering_device_type", type=t.bitmap8, access="r", mandatory=True),
0x0400: ZCLAttributeDef("Instantaneous_Demand", type=t.uint24_t, access="rw", mandatory=True),
0x1000: ZCLAttributeDef("report_map", type=t.bitmap8, access="rw", mandatory=True, is_manufacturer_specific=True),
0x2000: ZCLAttributeDef("L1_phase_power", type=t.uint24_t, access="r", mandatory=True, is_manufacturer_specific=True),
0x2001: ZCLAttributeDef("L2_phase_power", type=t.uint24_t, access="r", mandatory=True, is_manufacturer_specific=True),
0x2002: ZCLAttributeDef("L3_phase_power", type=t.uint24_t, access="r", mandatory=True, is_manufacturer_specific=True),
0x2100: ZCLAttributeDef("L1_phase_reactive_power", type=t.uint24_t, access="r", mandatory=True, is_manufacturer_specific=True),
0x2101: ZCLAttributeDef("L2_phase_reactive_power", type=t.uint24_t, access="r", mandatory=True, is_manufacturer_specific=True),
0x2102: ZCLAttributeDef("L3_phase_reactive_power", type=t.uint24_t, access="r", mandatory=True, is_manufacturer_specific=True),
0x2103: ZCLAttributeDef("reactive_power_summation_of_the_3_phases", type=t.uint24_t, access="r", mandatory=True, is_manufacturer_specific=True),
0x3000: ZCLAttributeDef("L1_phase_voltage", type=t.uint24_t, access="r", mandatory=True, is_manufacturer_specific=True),
0x3001: ZCLAttributeDef("L2_phase_voltage", type=t.uint24_t, access="r", mandatory=True, is_manufacturer_specific=True),
0x3002: ZCLAttributeDef("L3_phase_voltage", type=t.uint24_t, access="r", mandatory=True, is_manufacturer_specific=True),
0x3100: ZCLAttributeDef("L1_phase_current", type=t.uint24_t, access="r", mandatory=True, is_manufacturer_specific=True),
0x3101: ZCLAttributeDef("L2_phase_current", type=t.uint24_t, access="r", mandatory=True, is_manufacturer_specific=True),
0x3102: ZCLAttributeDef("L3_phase_current", type=t.uint24_t, access="r", mandatory=True, is_manufacturer_specific=True),
0x3103: ZCLAttributeDef("current_summation_of_the_3_phases", type=t.uint24_t, access="r", mandatory=True, is_manufacturer_specific=True),
0x3104: ZCLAttributeDef("leakage_current", type=t.uint24_t, access="r", mandatory=True, is_manufacturer_specific=True),
0x4000: ZCLAttributeDef("L1_phase_energy_consumption", type=t.uint48_t, access="r", mandatory=True, is_manufacturer_specific=True),
0x4001: ZCLAttributeDef("L2_phase_energy_consumption", type=t.uint48_t, access="r", mandatory=True, is_manufacturer_specific=True),
0x4002: ZCLAttributeDef("L3_phase_energy_consumption", type=t.uint48_t, access="r", mandatory=True, is_manufacturer_specific=True),
0x4100: ZCLAttributeDef("L1_phase_reactive_energy_consumption", type=t.uint48_t, access="r", mandatory=True, is_manufacturer_specific=True),
0x4101: ZCLAttributeDef("L2_phase_reactive_energy_consumption", type=t.uint48_t, access="r", mandatory=True, is_manufacturer_specific=True),
0x4102: ZCLAttributeDef("L3_phase_reactive_energy_consumption", type=t.uint48_t, access="r", mandatory=True, is_manufacturer_specific=True),
0x4103: ZCLAttributeDef("reactive_energy_summation_of_the_3_phases", type=t.uint48_t, access="r", mandatory=True, is_manufacturer_specific=True),
0x5000: ZCLAttributeDef("the_latest_historical_record_time", type=t.uint32_t, access="r", mandatory=True, is_manufacturer_specific=True),
0x5001: ZCLAttributeDef("the_oldest_historical_recorded_time", type=t.uint32_t, access="r", mandatory=True, is_manufacturer_specific=True),
0x5002: ZCLAttributeDef("set_minimum_cycle_for_report", type=t.uint32_t, access="rw", mandatory=True, is_manufacturer_specific=True),
0x5003: ZCLAttributeDef("set_maximum_cycle_for_report", type=t.uint32_t, access="rw", mandatory=True, is_manufacturer_specific=True),
0x5004: ZCLAttributeDef("sent_historical_record_state", type=t.uint8_t, access="r", mandatory=True, is_manufacturer_specific=True),
0x5005: ZCLAttributeDef("frequency", type=t.uint8_t, access="r", mandatory=True, is_manufacturer_specific=True),
0x5006: ZCLAttributeDef("the_accumulative_threshold_of_energy", type=t.uint8_t, access="rw", mandatory=True, is_manufacturer_specific=True),
0x5007: ZCLAttributeDef("report_mode", type=t.uint8_t, access="rw", mandatory=True, is_manufacturer_specific=True),
0x5008: ZCLAttributeDef("Set_Z_percent_change_in_power", type=t.uint8_t, access="rw", mandatory=True, is_manufacturer_specific=True),
}
expose = [
0x2000, 0x2001, 0x2002
]
server_commands: dict[int, ZCLCommandDef] = {
0x20: ZCLCommandDef("get_history_record", {}, is_manufacturer_specific=True),
0x21: ZCLCommandDef("stop_sending_historical_record", {}, is_manufacturer_specific=True),
}
client_commands: dict[int, ZCLCommandDef] = {
0x20: ZCLCommandDef("sent_historical_record", {}, is_manufacturer_specific=True),
}
class ClearMetering(CustomCluster):
cluster_id = 0xFFE0
ep_attribute = "clear_metering"
attributes: dict[int, ZCLAttributeDef] = {}
server_commands: dict[int, ZCLCommandDef] = {
0x00: ZCLCommandDef("clear_measurement_data", {}, is_manufacturer_specific=True),
}
client_commands: dict[int, ZCLCommandDef] = {}
""" nouveau device Owon """
class Owon(CustomDevice):
def __init__(self, *args, **kwargs):
"""Init."""
self.voltage_bus = Bus()
self.consumption_bus = Bus()
self.power_bus = Bus()
super().__init__(*args, **kwargs)
signature = {
#MODELS_INFO: [("Owon", "PC321")],
ENDPOINTS: {
# <SimpleDescriptor endpoint=1 profile=260 device_type=13
# device_version=1
# input_clusters=[0, 3, 1794]
# output_clusters=[3]>
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.CONSUMPTION_AWARENESS_DEVICE,
INPUT_CLUSTERS: [
Basic.cluster_id,
Identify.cluster_id,
Metering.cluster_id,
],
OUTPUT_CLUSTERS: [Identify.cluster_id],
},
},
"manufacturer": "OWON Technology Inc.",
}
replacement = {
#SKIP_CONFIGURATION: True,
ENDPOINTS: {
# <SimpleDescriptor endpoint=1 profile=260 device_type=13
# device_version=1
# input_clusters=[0, 3, 1794]
# output_clusters=[3]>
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.CONSUMPTION_AWARENESS_DEVICE,
INPUT_CLUSTERS: [
Basic.cluster_id,
Identify.cluster_id,
SimpleMetering,
ClearMetering,
],
OUTPUT_CLUSTERS: [Identify.cluster_id],
},
},
}
If someone would have an idea
Thanks