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
722 stars 670 forks source link

[Device Support Request] Please add Support for CO2 sensor in Titan TPZRCO2TH-Z3 #792

Closed B-Hartley closed 3 years ago

B-Hartley commented 3 years ago

Is your feature request related to a problem? Please describe. Please add support for the CO2 measurement feature of the Titan Zigbee 3.0 C02 sensor. I seem to be able to see Humidity and Temperature already. But the battery level doesn't report properly and I don't see the CO2 level at all.

Product Page

Device signature - this can be acquired by removing the device from ZHA and pairing it again from the add devices screen. Be sure to add the entire content of the log panel after pairing the device to a code block below this line.

{
  "node_descriptor": "NodeDescriptor(byte1=2, byte2=64, mac_capability_flags=128, manufacturer_code=4467, maximum_buffer_size=127, maximum_incoming_transfer_size=100, server_mask=11264, maximum_outgoing_transfer_size=100, descriptor_capability_field=0)",
  "endpoints": {
    "1": {
      "profile_id": 260,
      "device_type": "0x0302",
      "in_clusters": [
        "0x0000",
        "0x0001",
        "0x0003",
        "0x0020",
        "0x0402",
        "0x040d"
      ],
      "out_clusters": [
        "0x0019"
      ]
    },
    "2": {
      "profile_id": 260,
      "device_type": "0x0307",
      "in_clusters": [
        "0x0000",
        "0x0001",
        "0x0003",
        "0x0405"
      ],
      "out_clusters": []
    }
  },
  "manufacturer": "Titan Products Ltd",
  "model": "TPZRCO2HT-Z3",
  "class": "zigpy.device.Device"
}

Additional context Add any other context or screenshots about the feature request here.

Endpoint Cluster Attribute Manual Attached

B-Hartley commented 3 years ago

I'm unsure which bits are needed, I think this is the whole pairing / setup sequence.

[0x0000:zdo] ZDO request ZDOCmd.Mgmt_Permit_Joining_req: [60, <Bool.false: 0>]
Device 0xa43a (00:15:8d:00:03:87:7f:49) joined the network
[0xa43a:zdo] ZDO request ZDOCmd.Device_annce: [0xA43A, 00:15:8d:00:03:87:7f:49, 128]
[0xa43a] Requesting 'Node Descriptor'
[0xa43a] Extending timeout for 0x2a request
[0xa43a] Node Descriptor: NodeDescriptor(byte1=2, byte2=64, mac_capability_flags=128, manufacturer_code=4467, maximum_buffer_size=127, maximum_incoming_transfer_size=100, server_mask=11264, maximum_outgoing_transfer_size=100, descriptor_capability_field=0)
[0xa43a] Discovering endpoints
[0xa43a] Extending timeout for 0x2c request
[0xa43a] Discovered endpoints: [1, 2]
[0xa43a:1] Discovering endpoint information
[0xa43a] Extending timeout for 0x2e request
Device 0xa43a (00:15:8d:00:03:87:7f:49) joined the network
Skip initialization for existing device 00:15:8d:00:03:87:7f:49
[0xa43a:zdo] ZDO request ZDOCmd.Device_annce: [0xA43A, 00:15:8d:00:03:87:7f:49, 128]
[0xa43a] Extending timeout for 0x42 request
[0xa43a:1] Discovered endpoint information: SizePrefixedSimpleDescriptor(endpoint=1, profile=260, device_type=770, device_version=1, input_clusters=[0, 1, 3, 1026, 1037, 32], output_clusters=[25])
[0xa43a] Extending timeout for 0x44 request
[0xa43a:1:0x0000] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=68 command_id=Command.Read_Attributes_rsp>
[0xa43a:1] Manufacturer: Titan Products Ltd
[0xa43a:1] Model: TPZRCO2HT-Z3
[0xa43a:2] Discovering endpoint information
[0xa43a] Extending timeout for 0x54 request
[0xa43a:2] Discovered endpoint information: SizePrefixedSimpleDescriptor(endpoint=2, profile=260, device_type=775, device_version=1, input_clusters=[0, 1, 3, 1029], output_clusters=[])
Checking quirks for Titan Products Ltd TPZRCO2HT-Z3 (00:15:8d:00:03:87:7f:49)
device - 0xA43A:00:15:8d:00:03:87:7f:49 entering async_device_initialized - is_new_join: True
device - 0xA43A:00:15:8d:00:03:87:7f:49 has joined the ZHA zigbee network
[0xA43A](TPZRCO2HT-Z3): started configuration
[0xA43A:ZDO](TPZRCO2HT-Z3): 'async_configure' stage succeeded
[0xa43a] Extending timeout for 0x58 request
[0xa43a] Extending timeout for 0x5a request
[0xa43a] Extending timeout for 0x5c request
[0xA43A:1:0x0402]: bound 'temperature' cluster: Status.SUCCESS
[0xa43a] Extending timeout for 0x5e request
[0xA43A:1:0x0001]: bound 'power' cluster: Status.SUCCESS
[0xa43a] Extending timeout for 0x60 request
[0xA43A:1:0x0000]: bound 'basic' cluster: Status.NOT_SUPPORTED
[0xA43A:1:0x0000]: finished channel configuration
[0xa43a] Extending timeout for 0x62 request
[0xa43a:1:0x0402] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=94 command_id=Command.Configure_Reporting_rsp>
[0xA43A:1:0x0402]: reporting 'measured_value' attr on 'temperature' cluster: 30/900/50: Result: '[[ConfigureReportingResponseRecord(status=0)]]'
[0xA43A:1:0x0402]: finished channel configuration
[0xa43a] Extending timeout for 0x64 request
[0xa43a:1:0x0001] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=96 command_id=Command.Configure_Reporting_rsp>
[0xA43A:1:0x0001]: reporting 'battery_voltage' attr on 'power' cluster: 3600/10800/1: Result: '[[ConfigureReportingResponseRecord(status=140, direction=0, attrid=32)]]'
[0xa43a] Extending timeout for 0x66 request
[0xA43A:1:0x0020]: bound 'poll_control' cluster: Status.SUCCESS
[0xa43a] Extending timeout for 0x68 request
[0xA43A:1:0x0019]: bound 'ota' cluster: Status.NOT_SUPPORTED
[0xA43A:1:0x0019]: finished channel configuration
[0xa43a] Extending timeout for 0x6a request
[0xa43a:1:0x0001] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=102 command_id=Command.Configure_Reporting_rsp>
[0xA43A:1:0x0001]: reporting 'battery_percentage_remaining' attr on 'power' cluster: 3600/10800/1: Result: '[[ConfigureReportingResponseRecord(status=134, direction=0, attrid=33)]]'
[0xA43A:1:0x0001]: finished channel configuration
[0xa43a] Extending timeout for 0x6c request
[0xa43a:1:0x0020] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=104 command_id=Command.Write_Attributes_rsp>
[0xA43A:1:0x0020]: 3300.0s check-in interval set: [[WriteAttributesStatusRecord(status=<Status.SUCCESS: 0>)]]
[0xA43A:1:0x0020]: finished channel configuration
[0xA43A:1:0x0402]: 'async_configure' stage succeeded
[0xA43A:1:0x0001]: 'async_configure' stage succeeded
[0xA43A:1:0x0000]: 'async_configure' stage succeeded
[0xA43A:1:0x0020]: 'async_configure' stage succeeded
[0xA43A:1:0x0019]: 'async_configure' stage succeeded
[0xA43A:2:0x0000]: bound 'basic' cluster: Status.NOT_SUPPORTED
[0xA43A:2:0x0000]: finished channel configuration
[0xA43A:2:0x0405]: bound 'humidity' cluster: Status.SUCCESS
[0xa43a] Extending timeout for 0x70 request
[0xa43a:2:0x0405] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=112 command_id=Command.Configure_Reporting_rsp>
[0xA43A:2:0x0405]: reporting 'measured_value' attr on 'humidity' cluster: 30/900/50: Result: '[[ConfigureReportingResponseRecord(status=0)]]'
[0xA43A:2:0x0405]: finished channel configuration
[0xA43A:2:0x0000]: 'async_configure' stage succeeded
[0xA43A:2:0x0405]: 'async_configure' stage succeeded
[0xA43A](TPZRCO2HT-Z3): completed configuration
[0xA43A](TPZRCO2HT-Z3): stored in registry: ZhaDeviceEntry(name='Titan Products Ltd TPZRCO2HT-Z3', ieee='00:15:8d:00:03:87:7f:49', last_seen=1614619030.758866)
[0xa43a] Extending timeout for 0x7e request
[0xa43a:1:0x0003] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=126 command_id=Command.Default_Response>
[0xA43A:1:0x0003]: executed 'trigger_effect' command with args: '(2, 0)' kwargs: '{}' result: [64, <Status.UNSUP_CLUSTER_COMMAND: 129>]
[0xA43A](TPZRCO2HT-Z3): started initialization
[0xA43A:ZDO](TPZRCO2HT-Z3): 'async_initialize' stage succeeded
[0xA43A:1:0x0402]: initializing channel: from_cache: False
[0xa43a] Extending timeout for 0x81 request
[0xA43A:1:0x0001]: initializing channel: from_cache: False
[0xa43a] Extending timeout for 0x83 request
[0xA43A:1:0x0000]: initializing channel: from_cache: False
[0xA43A:1:0x0000]: finished channel configuration
[0xA43A:1:0x0020]: initializing channel: from_cache: False
[0xA43A:1:0x0020]: finished channel configuration
[0xA43A:1:0x0019]: initializing channel: from_cache: False
[0xA43A:1:0x0019]: finished channel configuration
[0xA43A:2:0x0000]: initializing channel: from_cache: False
[0xA43A:2:0x0000]: finished channel configuration
[0xA43A:2:0x0405]: initializing channel: from_cache: False
[0xa43a] Extending timeout for 0x85 request
[0xa43a:1:0x0402] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=129 command_id=Command.Read_Attributes_rsp>
[0xA43A:1:0x0402]: finished channel configuration
[0xa43a] Delivery error for seq # 0x83, on endpoint id 1 cluster 0x0001: message send failure
[0xA43A:1:0x0001]: failed to get attributes '['battery_voltage', 'battery_percentage_remaining']' on 'power' cluster: [0xa43a:1:0x0001]: Message send failure
[0xa43a] Extending timeout for 0x88 request
[0xa43a] Delivery error for seq # 0x85, on endpoint id 2 cluster 0x0405: message send failure
[0xA43A:2:0x0405]: failed to get attributes '['measured_value']' on 'humidity' cluster: [0xa43a:2:0x0405]: Message send failure
[0xA43A:2:0x0405]: finished channel configuration
[0xA43A:2:0x0000]: 'async_initialize' stage succeeded
[0xA43A:2:0x0405]: 'async_initialize' stage succeeded
[0xa43a:1:0x0001] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=136 command_id=Command.Read_Attributes_rsp>
[0xA43A:1:0x0001]: finished channel configuration
[0xA43A:1:0x0402]: 'async_initialize' stage succeeded
[0xA43A:1:0x0001]: 'async_initialize' stage succeeded
[0xA43A:1:0x0000]: 'async_initialize' stage succeeded
[0xA43A:1:0x0020]: 'async_initialize' stage succeeded
[0xA43A:1:0x0019]: 'async_initialize' stage succeeded
[0xA43A](TPZRCO2HT-Z3): power source: Battery or Unknown
[0xA43A](TPZRCO2HT-Z3): completed initialization

I'm going to read through the docs on this site and have a go, but if anyone else can do this, it would be great !

Adminiuga commented 3 years ago

The only non standard cluster is 0x040d cluster. I wonder if that one is the co2 measurement.

B-Hartley commented 3 years ago

Yes it is. It’s linked in the docs as a concentration cluster. In the zigbee spec they use co2 as an example of something that would be stored in a concentration cluster. And that it would built in a structure within that cluster. but doesn’t explain how. as the cluster doesn’t bind I can’t see what it is sending. hoping to experiment with this quirks file sometime tomorrow. But I’m a bit lost at the moment.

I think the battery one must me a bit non standard too as it doesn’t report the battery level properly. That’s not as big a deal.

Adminiuga commented 3 years ago

ah, missed that on the mobile. Kudos to the vendor for providing that information. So this would need a quirk and a modification to the ZHA. For concentration custom cluster would be something like

class GasConcentration(CustomCluster):
    cluster_id = 0x040D
    name = "Gas Concentration Measurement"
    ep_attribute = "gas_concentration"
    vendor_attributes = {
        0x0000: ("measured_value", t.Single),
        0x0001: ("min_measured_value", t.Single),
        0x0002: ("max_measured_value", t.Single),
        0xFFFD: ("cluster_revision", t.uint16_t),
    }
    server_commands = {}
    client_commands = {}

and then a custom device with a replacement for 0x040D cluster_ID using the GacConcentration class. See https://github.com/zigpy/zha-device-handlers#what-the-heck-is-a-quirk for more info

B-Hartley commented 3 years ago

That’s great. I’ll take a look Tomorrow and see if I can understand.

B-Hartley commented 3 years ago

Hi,

Do you know of any similar devices I could look at to figure this out. I kind of follow the logic of what quirks do. But it looks pretty heavy. If I could find a similar device I might have a better chance.

Thanks.

B-Hartley commented 3 years ago

I've raised an issue on Zigpy itself as I'm unsure if the ConcentrationCluster should be added into measurement.py to make products such as this work ?

Is that the right thing to do, or should it just be handled as a quirk ?

Adminiuga commented 3 years ago

No, zigpy only contains standard clusters included in ZCL specification. So unless it was included in ZCL revision 7 it does not belong to zigpy

B-Hartley commented 3 years ago

ok, I've hacked this together.............. I really am shooting in the dark here. I'm unsure what cluster to output my GasConcentration on? Do I need to change it from a Float to something else?

Thanks in advance........

__init__.py

"""Titan quirks."""

TITAN= "Titan Products Ltd"
TPZRC02THZ3.py

"""Device handler for Titan TPZRC02TH-Z3 Environment Sensor."""
from zigpy.profiles import zha
from zigpy.quirks import CustomDevice, CustomCluster
from zigpy.zcl.clusters.general import Basic, Identify, Ota, PollControl
from zigpy.zcl.clusters.measurement import TemperatureMeasurement, RelativeHumidity

from . import TITAN
from ..const import (
    DEVICE_TYPE,
    ENDPOINTS,
    INPUT_CLUSTERS,
    MODELS_INFO,
    OUTPUT_CLUSTERS,
    PROFILE_ID,
)

class GasConcentration(CustomCluster):
    cluster_id = 0x040D
    name = "Gas Concentration Measurement"
    ep_attribute = "gas_concentration"
    vendor_attributes = {
        0x0000: ("measured_value", t.Single),
        0x0001: ("min_measured_value", t.Single),
        0x0002: ("max_measured_value", t.Single),
        0xFFFD: ("cluster_revision", t.uint16_t),
    }
    server_commands = {}
    client_commands = {}

class TPZRC02THZ3(CustomDevice):
    """Custom device representing Bosch TPZRC02TH-Z3 environment sensor."""

    signature = {
        #  <SimpleDescriptor endpoint=1 profile=260 device_type=770
        #  device_version=0
        #  input_clusters=[0, 1, 3, 32, 1026, 1037]
        #  output_clusters=[25]>
        MODELS_INFO: [(TITAN, "TPZRCO2HT-Z3")],
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.xxxxxxxxxx,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    PowerConfigurationCluster.cluster_id,
                    Identify.cluster_id,
                    PollControl.cluster_id,
                    TemperatureMeasurement.cluster_id,
                    RelativeHumidity.cluster_id,
                    GasConcentration.cluster_id,
                ],
                OUTPUT_CLUSTERS: [Ota.cluster_id],
            }
        },
    }

    replacement = {
        ENDPOINTS: {
            1: {
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    PowerConfigurationCluster.cluster_id,
                    Identify.cluster_id,
                    PollControl.cluster_id,
                    TemperatureMeasurement.cluster_id,
                    RelativeHumidity.cluster_id,
                    GasConcentration.cluster_id,
                ],
                OUTPUT_CLUSTERS: [Ota.cluster_id],
            }
        }
    }
B-Hartley commented 3 years ago

No, zigpy only contains standard clusters included in ZCL specification. So unless it was included in ZCL revision 7 it does not belong to zigpy

Thanks. I've closed the issue on Zigpy and I'll see if I can get to the answer through this Quirk issue.

Adminiuga commented 3 years ago

for the signature, the ENDPOINTS key must match the zigbee device signature: For device Types enums, reference https://github.com/zigpy/zigpy/blob/dev/zigpy/profiles/zha.py

    signature = {
        # UPDATE THIS COMMENTS TO MATCH the posted zigbee signature
        #  <SimpleDescriptor endpoint=1 profile=260 device_type=770
        #  device_version=0
        #  input_clusters=[0, 1, 3, 32, 1026, 1037]
        #  output_clusters=[25]>
        MODELS_INFO: [(TITAN, "TPZRCO2HT-Z3")],
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.TEMPERATURE_SENSOR,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    PowerConfigurationCluster.cluster_id,
                    Identify.cluster_id,
                    PollControl.cluster_id,
                    TemperatureMeasurement.cluster_id,
                    GasConcentration.cluster_id,
                ],
                OUTPUT_CLUSTERS: [Ota.cluster_id],
            },
            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.MINI_SPLIT_AC,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    PowerConfigurationCluster.cluster_id,
                    Identify.cluster_id,
                    RelativeHumidity.cluster_id,
                ],
                OUTPUT_CLUSTERS: [],
            }
        },
    }

The replacements, in your case is going to match the signature mostly exactly, with the exception of the gas cluster only. Since you want to replace it with your copy, you have to reference it by the "class" instead of a cluster id:

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.TEMPERATURE_SENSOR,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    PowerConfigurationCluster.cluster_id,
                    Identify.cluster_id,
                    PollControl.cluster_id,
                    TemperatureMeasurement.cluster_id,
                    GasConcentration,
                ],
                OUTPUT_CLUSTERS: [Ota.cluster_id],
            },
            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.MINI_SPLIT_AC,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    PowerConfigurationCluster.cluster_id,
                    Identify.cluster_id,
                    RelativeHumidity.cluster_id,
                ],
                OUTPUT_CLUSTERS: [],
            }
        },
    }
Adminiuga commented 3 years ago

Do I need to change it from a Float to something else?

t.Single is the float type, matching the docs for the cluster. Enable zigpy debug and with your custom quirk, on restart, if everything is configured correctly you should see zigpy finding a quirk for your CO2 sensor. That would be the 1st step.

BTW, where did you get it? link? Dang that thing is expensive. But last I've checked CO2 sensor were expensive. I'd love to know what kind of sensor they've used that it works from a battery.

B-Hartley commented 3 years ago

This is the inside of the sensor. It is running on a lithium battery, so I guess it needs the max power it can get from an AA cell.

sensor

B-Hartley commented 3 years ago

Is the order of this line important.......

        #  input_clusters=[0, 1, 3, 1026, 1037, 32]     

In the log it shows them in this order, rather than in numerical order.

Adminiuga commented 3 years ago

Order is not important. Usually quirks have clusters in numeri orders and constant names following the numeric order.

Thanks for the picture. Looks like this one https://sstsensing.com/product/cozir-lp2-ambient-air-co2-sensor/ Yeah, CO2 sensors seem to draw more power than any other sensors and most of the time have to run continuously and dont't go to low power mode. No chance of running it on C3202 or even an AA battery would not last long

B-Hartley commented 3 years ago

ok, so more stupid questions. I've got the class and the quirk.

I've enabled zigpy debug.

So where do I put the quirk file ?

I'm running....

Version | core-2021.2.3
Installation Type | Home Assistant OS

Thanks very much for your help. I would never have even got this far without you !

B-Hartley commented 3 years ago

Thanks for the picture. Looks like this one https://sstsensing.com/product/cozir-lp2-ambient-air-co2-sensor/

Agreed, it looks exactly like that.

B-Hartley commented 3 years ago

This is the whole file I've got........

TPZRCO2THZ3.py

"""Device handler for Titan TPZRCO2TH-Z3 Environment Sensor."""
from zigpy.profiles import zha
from zigpy.quirks import CustomDevice, CustomCluster
from zigpy.zcl.clusters.general import Basic, Identify, Ota, PollControl
from zigpy.zcl.clusters.measurement import TemperatureMeasurement, RelativeHumidity

from . import TITAN
from ..const import (
    DEVICE_TYPE,
    ENDPOINTS,
    INPUT_CLUSTERS,
    MODELS_INFO,
    OUTPUT_CLUSTERS,
    PROFILE_ID,
)

class GasConcentration(CustomCluster):
    cluster_id = 0x040D
    name = "Gas Concentration Measurement"
    ep_attribute = "gas_concentration"
    vendor_attributes = {
        0x0000: ("measured_value", t.Single),
        0x0001: ("min_measured_value", t.Single),
        0x0002: ("max_measured_value", t.Single),
        0xFFFD: ("cluster_revision", t.uint16_t),
    }
    server_commands = {}
    client_commands = {}

class TPZRCO2THZ3(CustomDevice):
    """Custom device representing Titan TPZRCO2TH-Z3 environment sensor."""

    signature = {
        #  <SimpleDescriptor endpoint=1 profile=260 device_type=770
        #  device_version=1
        #  input_clusters=[0, 1, 3, 32, 1026, 1037]        
        #  output_clusters=[25]>
        MODELS_INFO: [(TITAN, "TPZRCO2HT-Z3")],
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.TEMPERATURE_SENSOR,   
                INPUT_CLUSTERS: [
                    Basic.cluster_id,                    
                    PowerConfigurationCluster.cluster_id,  
                    Identify.cluster_id,                   
                    PollControl.cluster_id,                
                    TemperatureMeasurement.cluster_id,     
                    GasConcentration.cluster_id,                      
                ],
                OUTPUT_CLUSTERS: [Ota.cluster_id],         
            },
            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.MINI_SPLIT_AC, 
                INPUT_CLUSTERS: [
                    Basic.cluster_id,                      
                    PowerConfigurationCluster.cluster_id,  
                    Identify.cluster_id,                   
                    RelativeHumidity.cluster_id,           
                ],
                OUTPUT_CLUSTERS: [],         
            }            
        },
    }

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.TEMPERATURE_SENSOR,   
                INPUT_CLUSTERS: [
                    Basic.cluster_id,                    
                    PowerConfigurationCluster.cluster_id,  
                    Identify.cluster_id,                   
                    PollControl.cluster_id,                
                    TemperatureMeasurement.cluster_id,     
                    GasConcentration,                      
                ],
                OUTPUT_CLUSTERS: [Ota.cluster_id],      
            },
            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.MINI_SPLIT_AC, 
                INPUT_CLUSTERS: [
                    Basic.cluster_id,                      
                    PowerConfigurationCluster.cluster_id,  
                    Identify.cluster_id,                   
                    RelativeHumidity.cluster_id,          
                ],
                OUTPUT_CLUSTERS: [],         
            }            
        },    
    }

and

init.py

"""Titan quirks."""

TITAN = "Titan Products Ltd"
B-Hartley commented 3 years ago

Hang on, I might have found it, let my fight with it for a bit before you give me the answer !

:-)

Adminiuga commented 3 years ago

If running HassOS, try https://github.com/zigpy/zha-device-handlers#testing-quirks-in-development-in-docker-based-install

Usually I just get access to HassOS dev console (not the ssh add-on one), gives you access to the docker. From there inside the home assistant container docker exec -ti homeassistant /bin/bash gives the shell inside the container and the quirks are in 0.113: /usr/local/lib/python3.8/site-packages/zhaquirks/ folder

B-Hartley commented 3 years ago

Thanks, I did it through portainer add-on. I was stumped at first by the fact that home-assistant containers were hidden. I've copied the files over and I'm doing a restart. Can't imagine it will work first time.

Fingers crossed !!

Adminiuga commented 3 years ago

the first step is getting the quirk recognized. Second would require some mods to ZHA

B-Hartley commented 3 years ago

I've run out of home automation time tonight. Will have to get back to this tomorrow.

The suspense !!

B-Hartley commented 3 years ago

Ok, I have progress. But I still can't see the 0x040d cluster being bound. I had to make a few tweaks to the quirk due to syntax errors, or missing imports.

I ended up with..............

"""Device handler for Titan TPZRCO2TH-Z3 Environment Sensor."""
import logging

from zigpy.profiles import zha
from zigpy.quirks import CustomDevice, CustomCluster
from zigpy.zcl.clusters.general import Basic, Identify, Ota, PollControl, PowerConfiguration
from zigpy.zcl.clusters.measurement import TemperatureMeasurement, RelativeHumidity

from zhaquirks import PowerConfigurationCluster
import zigpy.types as t

from zhaquirks.const import (
    DEVICE_TYPE,
    ENDPOINTS,
    INPUT_CLUSTERS,
    MODELS_INFO,
    OUTPUT_CLUSTERS,
    PROFILE_ID,
)

class GasConcentration(CustomCluster):
    cluster_id = 0x040D
    name = "Gas Concentration Measurement"
    ep_attribute = "gas_concentration"
    vendor_attributes = {
        0x0000: ("measured_value", t.Single),
        0x0001: ("min_measured_value", t.Single),
        0x0002: ("max_measured_value", t.Single),
        0xFFFD: ("cluster_revision", t.uint16_t),
    }
    server_commands = {}
    client_commands = {}

_LOGGER = logging.getLogger(__name__)

class TPZRCO2THZ3(CustomDevice):
    """Custom device representing Titan TPZRCO2TH-Z3 environment sensor."""

    signature = {
        MODELS_INFO: [("Titan Products Ltd", "TPZRCO2HT-Z3")],
        ENDPOINTS: {
        #  <SimpleDescriptor endpoint=1 profile=260 device_type=770
        #  device_version=1
        #  input_clusters=[0, 1, 3, 32, 1026, 1037]        
        #  output_clusters=[25]>
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.TEMPERATURE_SENSOR,   
                INPUT_CLUSTERS: [
                    Basic.cluster_id,                    
                    PowerConfigurationCluster.cluster_id,  
                    Identify.cluster_id,                   
                    PollControl.cluster_id,                
                    TemperatureMeasurement.cluster_id,     
                    GasConcentration.cluster_id,                      
                ],
                OUTPUT_CLUSTERS: [Ota.cluster_id],         
            },
        #  <SimpleDescriptor endpoint=2 profile=260, device_type=775
        #  device_version=1
        #  input_clusters=[0, 1, 3, 1029]
        #  output_clusters=[]>
            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.MINI_SPLIT_AC, 
                INPUT_CLUSTERS: [
                    Basic.cluster_id,                      
                    PowerConfigurationCluster.cluster_id,  
                    Identify.cluster_id,                   
                    RelativeHumidity.cluster_id,           
                ],
                OUTPUT_CLUSTERS: [],         
            }            
        },
    }

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.TEMPERATURE_SENSOR,   
                INPUT_CLUSTERS: [
                    Basic.cluster_id,                    
                    PowerConfigurationCluster.cluster_id,  
                    Identify.cluster_id,                   
                    PollControl.cluster_id,                
                    TemperatureMeasurement.cluster_id,     
                    GasConcentration,                      
                ],
                OUTPUT_CLUSTERS: [Ota.cluster_id],      
            },
            2: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.MINI_SPLIT_AC, 
                INPUT_CLUSTERS: [
                    Basic.cluster_id,                      
                    PowerConfigurationCluster.cluster_id,  
                    Identify.cluster_id,                   
                    RelativeHumidity.cluster_id,          
                ],
                OUTPUT_CLUSTERS: [],         
            }            
        },    
    }

The log when I pair the product now says...............


Device 0x1baa   (00:15:8d:00:03:87:7f:49) joined the network
--
[0x1baa:zdo] ZDO request   ZDOCmd.Device_annce: [0x1BAA, 00:15:8d:00:03:87:7f:49, 128]
[0x1baa] Requesting 'Node Descriptor'
[0x1baa] Node Descriptor:   NodeDescriptor(byte1=2, byte2=64, mac_capability_flags=128,   manufacturer_code=4467, maximum_buffer_size=127,   maximum_incoming_transfer_size=100, server_mask=11264,   maximum_outgoing_transfer_size=100, descriptor_capability_field=0)
[0x1baa] Discovering endpoints
[0x1baa] Discovered endpoints: [1, 2]
[0x1baa:1] Discovering endpoint   information
[0x1baa:1] Discovered endpoint   information: SizePrefixedSimpleDescriptor(endpoint=1, profile=260,   device_type=770, device_version=1, input_clusters=[0, 1, 3, 1026, 1037, 32],   output_clusters=[25])
Unknown cluster 1037
[0x1baa:1:0x0000] ZCL deserialize:   <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND   manufacturer_specific=False is_reply=True disable_default_response=True>   manufacturer=None tsn=215 command_id=Command.Read_Attributes_rsp>
[0x1baa:1] Manufacturer: Titan Products   Ltd
[0x1baa:1] Model: TPZRCO2HT-Z3
[0x1baa:2] Discovering endpoint   information
[0x1baa:2] Discovered endpoint   information: SizePrefixedSimpleDescriptor(endpoint=2, profile=260,   device_type=775, device_version=1, input_clusters=[0, 1, 3, 1029],   output_clusters=[])
Checking quirks for Titan Products Ltd   TPZRCO2HT-Z3 (00:15:8d:00:03:87:7f:49)
Considering <class   'zhaquirks.titan.TPZRCO2THZ3.TPZRCO2THZ3'>
Found custom device replacement for   00:15:8d:00:03:87:7f:49: <class   'zhaquirks.titan.TPZRCO2THZ3.TPZRCO2THZ3'>
device - 0x1BAA:00:15:8d:00:03:87:7f:49   entering async_device_initialized - is_new_join: True
device - 0x1BAA:00:15:8d:00:03:87:7f:49   has joined the ZHA zigbee network
[0x1BAA](TPZRCO2HT-Z3): started   configuration
[0x1BAA:ZDO](TPZRCO2HT-Z3):   'async_configure' stage succeeded
[0x1BAA:1:0x0402]: bound 'temperature'   cluster: Status.SUCCESS
[0x1BAA:1:0x0001]: bound 'power' cluster:   Status.SUCCESS
[0x1BAA:1:0x0000]: bound 'basic' cluster:   Status.NOT_SUPPORTED
[0x1BAA:1:0x0000]: finished channel   configuration
[0x1baa:1:0x0402] ZCL deserialize:   <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND   manufacturer_specific=False is_reply=True disable_default_response=True>   manufacturer=None tsn=229 command_id=Command.Configure_Reporting_rsp>
[0x1BAA:1:0x0402]: reporting   'measured_value' attr on 'temperature' cluster: 30/900/50: Result:   '[[ConfigureReportingResponseRecord(status=0)]]'
[0x1BAA:1:0x0402]: finished channel   configuration
[0x1baa:1:0x0001] ZCL deserialize:   <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND   manufacturer_specific=False is_reply=True disable_default_response=True>   manufacturer=None tsn=231 command_id=Command.Configure_Reporting_rsp>
[0x1BAA:1:0x0001]: reporting   'battery_voltage' attr on 'power' cluster: 3600/10800/1: Result:   '[[ConfigureReportingResponseRecord(status=140, direction=0, attrid=32)]]'
[0x1BAA:1:0x0020]: bound 'poll_control'   cluster: Status.SUCCESS
[0x1baa:1:0x0001] ZCL deserialize:   <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND   manufacturer_specific=False is_reply=True disable_default_response=True>   manufacturer=None tsn=237 command_id=Command.Configure_Reporting_rsp>
[0x1BAA:1:0x0001]: reporting   'battery_percentage_remaining' attr on 'power' cluster: 3600/10800/1: Result:   '[[ConfigureReportingResponseRecord(status=134, direction=0, attrid=33)]]'
[0x1BAA:1:0x0001]: finished channel   configuration
[0x1BAA:1:0x0019]: bound 'ota' cluster:   Status.NOT_SUPPORTED
[0x1BAA:1:0x0019]: finished channel   configuration
[0x1baa:1:0x0020] ZCL deserialize:   <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND   manufacturer_specific=False is_reply=True disable_default_response=True>   manufacturer=None tsn=239 command_id=Command.Write_Attributes_rsp>
[0x1BAA:1:0x0020]: 3300.0s check-in   interval set: [[WriteAttributesStatusRecord(status=<Status.SUCCESS:   0>)]]
[0x1BAA:1:0x0020]: finished channel   configuration
[0x1BAA:1:0x0402]: 'async_configure'   stage succeeded
[0x1BAA:1:0x0001]: 'async_configure'   stage succeeded
[0x1BAA:1:0x0000]: 'async_configure'   stage succeeded
[0x1BAA:1:0x0020]: 'async_configure'   stage succeeded
[0x1BAA:1:0x0019]: 'async_configure'   stage succeeded
[0x1BAA:2:0x0000]: bound 'basic' cluster:   Status.NOT_SUPPORTED
[0x1BAA:2:0x0000]: finished channel   configuration
[0x1BAA:2:0x0405]: bound 'humidity'   cluster: Status.SUCCESS
[0x1baa:2:0x0405] ZCL deserialize:   <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND   manufacturer_specific=False is_reply=True disable_default_response=True>   manufacturer=None tsn=245 command_id=Command.Configure_Reporting_rsp>
[0x1BAA:2:0x0405]: reporting   'measured_value' attr on 'humidity' cluster: 30/900/50: Result:   '[[ConfigureReportingResponseRecord(status=0)]]'
[0x1BAA:2:0x0405]: finished channel   configuration
[0x1BAA:2:0x0000]: 'async_configure'   stage succeeded
[0x1BAA:2:0x0405]: 'async_configure'   stage succeeded
[0x1BAA](TPZRCO2HT-Z3): completed   configuration
[0x1BAA](TPZRCO2HT-Z3): stored in   registry: ZhaDeviceEntry(name='Titan Products Ltd TPZRCO2HT-Z3',   ieee='00:15:8d:00:03:87:7f:49', last_seen=1614778648.3336341)
[0x1baa:1:0x0003] ZCL deserialize:   <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND   manufacturer_specific=False is_reply=True disable_default_response=True>   manufacturer=None tsn=249 command_id=Command.Default_Response>
[0x1BAA:1:0x0003]: executed   'trigger_effect' command with args: '(2, 0)' kwargs: '{}' result: [64,   <Status.UNSUP_CLUSTER_COMMAND: 129>]
[0x1BAA](TPZRCO2HT-Z3): started   initialization
[0x1BAA:ZDO](TPZRCO2HT-Z3):   'async_initialize' stage succeeded
[0x1BAA:1:0x0402]: initializing channel:   from_cache: False
[0x1BAA:1:0x0001]: initializing channel:   from_cache: False
[0x1BAA:1:0x0000]: initializing channel:   from_cache: False
[0x1BAA:1:0x0000]: finished channel   configuration
[0x1BAA:1:0x0020]: initializing channel:   from_cache: False
[0x1BAA:1:0x0020]: finished channel   configuration
[0x1BAA:1:0x0019]: initializing channel:   from_cache: False
[0x1BAA:1:0x0019]: finished channel   configuration
[0x1BAA:2:0x0000]: initializing channel:   from_cache: False
[0x1BAA:2:0x0000]: finished channel   configuration
[0x1BAA:2:0x0405]: initializing channel:   from_cache: False
[0x1baa:1:0x0402] ZCL deserialize:   <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND   manufacturer_specific=False is_reply=True disable_default_response=True>   manufacturer=None tsn=255 command_id=Command.Read_Attributes_rsp>
[0x1BAA:1:0x0402]: finished channel   configuration
[0x1baa:1:0x0001] ZCL deserialize:   <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND   manufacturer_specific=False is_reply=True disable_default_response=True>   manufacturer=None tsn=1 command_id=Command.Read_Attributes_rsp>
[0x1baa:2:0x0405] ZCL deserialize:   <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND   manufacturer_specific=False is_reply=True disable_default_response=True>   manufacturer=None tsn=3 command_id=Command.Read_Attributes_rsp>
[0x1BAA:2:0x0405]: finished channel   configuration
[0x1BAA:2:0x0000]: 'async_initialize'   stage succeeded
[0x1BAA:2:0x0405]: 'async_initialize'   stage succeeded
[0x1baa:1:0x0001] ZCL deserialize:   <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND   manufacturer_specific=False is_reply=True disable_default_response=True>   manufacturer=None tsn=7 command_id=Command.Read_Attributes_rsp>
[0x1BAA:1:0x0001]: finished channel   configuration
[0x1BAA:1:0x0402]: 'async_initialize'   stage succeeded
[0x1BAA:1:0x0001]: 'async_initialize'   stage succeeded
[0x1BAA:1:0x0000]: 'async_initialize'   stage succeeded
[0x1BAA:1:0x0020]: 'async_initialize'   stage succeeded
[0x1BAA:1:0x0019]: 'async_initialize'   stage succeeded
[0x1BAA](TPZRCO2HT-Z3): power source:   Battery or Unknown
[0x1BAA](TPZRCO2HT-Z3): completed   initialization

Thoughts ?

Thanks

Adminiuga commented 3 years ago

go to device page, pick the device -> Manage Clusters, Pick GasConcentration and then get value for the "measured_value" attribute. What do you get?

B-Hartley commented 3 years ago

You mean:

integration -> Zigbee -> devices -> titan device. Manage Clusters:

Choose GasConcentration There are no Cluster Attributes to choose?

If I try the same for the Temperature Measurement Cluster, I can get the measured_value.

screenshot-github

Adminiuga commented 3 years ago

Is the drop down empty?

B-Hartley commented 3 years ago

Yes, drop down empty.

Other quirk files say: manufacturer_attributes

Whereas, ours says vendor_attributes

should I change this ?

Adminiuga commented 3 years ago

yes, change it then. It might not check for vendor attrs, if regular attrs are empty

Adminiuga commented 3 years ago

Next step, in docker container you need to patch ZHA. In docker install is in /usr/src/homeassistant: find https://github.com/home-assistant/core/blob/dev/homeassistant/components/zha/core/channels/measurement.py in your docker and make essentially a copy of any channel. Something like

@registries.ZIGBEE_CHANNEL_REGISTRY.register(0x040D)
class GasConcentration(ZigbeeChannel):
    """Gas Concentration measurement channel."""

    REPORT_CONFIG = [
        {
            "attr": "measured_value",
            "config": (REPORT_CONFIG_MIN_INT, REPORT_CONFIG_MAX_INT, 1),
        }
    ]

in "config": (REPORT_CONFIG_MIN_INT, REPORT_CONFIG_MAX_INT, 1) I'm not sure about 1 value. it indicates by how much an attr needs to change in order for it to get reported. Since it is a float, might need something like 0.1 or 0.01 🤷 This part would need some experimentation

then in https://github.com/home-assistant/core/blob/dev/homeassistant/components/zha/sensor.py make a copy of the temp sensor

@STRICT_MATCH(channel_names="gas_concentration")
class GasConcentration(Sensor):
    """Gas Concentration sensor."""

    SENSOR_ATTR = "measured_value"
    _decimals = 5
    _unit = CONCENTRATION_PARTS_PER_MILLION
Adminiuga commented 3 years ago

but first need to get the attribte reading

Adminiuga commented 3 years ago

manufacturer_attributes

Whereas, ours says vendor_attributes

Doh, yeah, it is supposed to be manufacturer_attributes

B-Hartley commented 3 years ago

I've made those edits on a local copy (haven't put onto HA yet). At the moment, the attribute reading is on the drop down, but is returning none. The docs say that CO2 can only be reported every 600 seconds, so I'm going to leave it a while and try again.

Adminiuga commented 3 years ago

enable debug logging, for zigpy and the radio. Either use a config file, or a services call to logger.set_level and monitor for traffic from the device. It might report it even without the configuration, but chances are that you still need to put the ZHA changes in and press "reconfigure device" button so it binds and configures reporting on 0x040d cluster

B-Hartley commented 3 years ago

Can I patch it through custom_components, or do I need to actually change the file in the homeassistant components folder ?

Ok, I added this to measurement.py

@registries.ZIGBEE_CHANNEL_REGISTRY.register(0x040D)
class GasConcentration(ZigbeeChannel):
    """Gas Concentration measurement channel."""

    REPORT_CONFIG = [
        {
            "attr": "measured_value",
            "config": (REPORT_CONFIG_MIN_INT, REPORT_CONFIG_MAX_INT, 1),
        }
    ]

and I added this to sensor.py

@STRICT_MATCH(channel_names="gas_concentration")
class GasConcentration(Sensor):
    """Gas Concentration sensor."""

    SENSOR_ATTR = "measured_value"
    _decimals = 5
    _unit = CONCENTRATION_PARTS_PER_MILLION
Adminiuga commented 3 years ago

you can patch through a custom component, but you do need to copy the entire zha folder content into /config/custom_components/zha

B-Hartley commented 3 years ago

Ok, I've patched those two files in /config/custom_components/zha

I also fixed the quirk file with manufacturer_attributes.

I can ask it to show me the measured_value now, but is shows "None" all the attributes on that cluster show "none" ?

It hasn't bound the cluster.

I see this in the log if it helps........

2021-03-03 14:51:28 DEBUG (MainThread) [zigpy_deconz.api] 'aps_data_indication' response from <DeconzAddress address_mode=ADDRESS_MODE.NWK address=0x36c4>, ep: 1, profile: 0x0104, cluster_id: 0x040d, data: b'1c73111501020086'
2021-03-03 14:55:58 DEBUG (MainThread) [zigpy_deconz.api] 'aps_data_indication' response from <DeconzAddress address_mode=ADDRESS_MODE.NWK address=0x36c4>, ep: 1, profile: 0x0104, cluster_id: 0x040d, data: b'1c73119b01000086'
B-Hartley commented 3 years ago

Should this bit be MIN_INT or should it be float something ?

Adminiuga commented 3 years ago

b'1c73119b01000086' is a "Read_Attribute_Response" with the status of 0x86 -- UNSUPPORTED_ATTRIBUTES 😮

In the quirk, change the manufacturer_attributes to just attributes so it does not try to use the manufacturer id when reading those attributes

B-Hartley commented 3 years ago

Seesms to be a problem with:

CONCENTRATION_PARTS_PER_MILLION

The only one I can find in const.py is:

CONCENTRATION_PARTS_PER_CUBIC_METER

which doesn't seem quite right.

Adminiuga commented 3 years ago

ah, I guess they've added it in the current dev tree only. replace it just with "ppm" string literal

B-Hartley commented 3 years ago

Actually I think I was looking in the wrong place, do I need to import it to use it ?

Adminiuga commented 3 years ago

you do need to import it, yes. But I don't see it in the "master" branch. ATM not even in the beta, only in the dev tree

B-Hartley commented 3 years ago

ok, I had a few issues as I had mistakenly taken the dev branch of zha and put it in custom components. I've taken the correct release branch now. I've put it in literal for now. just starting up to test.

B-Hartley commented 3 years ago

ok, we have a change. querying the measured value now, give nan

I'll give it 10 mins and try again in case it just doesn't have a reading yet.

I've got........

2021-03-03 16:01:42 WARNING (MainThread) [zigpy.zcl] Unknown cluster 1037

which I figure is 0x040d ?

I've also got.........


2021-03-03   16:04:30 DEBUG (MainThread) [zigpy_deconz.uart] Frame received:   0x1cb90012000b0003497f8703008d1500ffca
--
2021-03-03 16:04:30 DEBUG   (MainThread) [zigpy_deconz.uart] Frame received:   0x17b9002a0023002202fdff000217bf00000013000c000017bf497f8703008d15008000afff80e23d00ca
2021-03-03 16:04:30 DEBUG   (MainThread) [zigpy_deconz.api] 'aps_data_indication' response from   <DeconzAddress address_mode=ADDRESS_MODE.NWK address=0xbf17>, ep: 0,   profile: 0x0000, cluster_id: 0x0013, data: b'0017bf497f8703008d150080'
2021-03-03 16:04:34 DEBUG   (MainThread) [zigpy_deconz.zigbee.application] Sending Zigbee request with   tsn 20 under 21 request id, data:   b'14497f8703008d150001200003d0df05ffff2e210001'
2021-03-03 16:04:34 DEBUG   (MainThread) [zigpy_deconz.uart] Send:   0x12cf002c00250015000217bf000000210000160014497f8703008d150001200003d0df05ffff2e2100010200
2021-03-03 16:04:34 DEBUG   (MainThread) [zigpy_deconz.zigbee.application] Sending Zigbee request with   tsn 22 under 23 request id, data:   b'16497f8703008d150001000003d0df05ffff2e210001'
2021-03-03 16:04:34 DEBUG   (MainThread) [zigpy_deconz.zigbee.application] Sending Zigbee request with   tsn 24 under 25 request id, data:   b'18497f8703008d150001020403d0df05ffff2e210001'
2021-03-03 16:04:34 DEBUG   (MainThread) [zigpy_deconz.uart] Send:   0x12d0002c00250017000217bf000000210000160016497f8703008d150001000003d0df05ffff2e2100010200
2021-03-03 16:04:34 DEBUG   (MainThread) [zigpy_deconz.uart] Send:   0x12d1002c00250019000217bf000000210000160018497f8703008d150001020403d0df05ffff2e2100010200
2021-03-03 16:04:41 DEBUG   (MainThread) [zigpy_deconz.uart] Frame received:   0x17d8002a0023002202fdff000217bf00000013000c000317bf497f8703008d15008000afff97e23d00c9
2021-03-03 16:04:41 DEBUG   (MainThread) [zigpy_deconz.api] 'aps_data_indication' response from   <DeconzAddress address_mode=ADDRESS_MODE.NWK address=0xbf17>, ep: 0,   profile: 0x0000, cluster_id: 0x0013, data: b'0317bf497f8703008d150080'
2021-03-03 16:05:09 DEBUG   (MainThread) [zigpy_deconz.zigbee.application] Sending Zigbee request with   tsn 48 under 49 request id, data:   b'30497f8703008d150001010003d0df05ffff2e210001'
2021-03-03 16:05:09 DEBUG   (MainThread) [zigpy_deconz.uart] Send:   0x12fe002c00250031000217bf000000210000160030497f8703008d150001010003d0df05ffff2e2100010200
2021-03-03 16:05:11 DEBUG   (MainThread) [zigpy_deconz.zigbee.application] Sending Zigbee request with   tsn 52 under 53 request id, data:   b'34497f8703008d150001190003d0df05ffff2e210001'
2021-03-03 16:05:11 DEBUG   (MainThread) [zigpy_deconz.uart] Send:   0x1204002c00250035000217bf000000210000160034497f8703008d150001190003d0df05ffff2e2100010200
2021-03-03 16:05:11 DEBUG   (MainThread) [zigpy_deconz.zigbee.application] Sending Zigbee request with   tsn 56 under 57 request id, data:   b'38497f8703008d150002050403d0df05ffff2e210001'
2021-03-03 16:05:11 DEBUG   (MainThread) [zigpy_deconz.uart] Send:   0x120a002c00250039000217bf000000210000160038497f8703008d150002050403d0df05ffff2e2100010200
2021-03-03 16:05:11 DEBUG   (MainThread) [zigpy_deconz.zigbee.application] Sending Zigbee request with   tsn 58 under 59 request id, data:   b'3a497f8703008d150002000003d0df05ffff2e210001'
2021-03-03 16:05:11 DEBUG   (MainThread) [zigpy_deconz.uart] Send:   0x120d002c0025003b000217bf00000021000016003a497f8703008d150002000003d0df05ffff2e2100010200
2021-03-03 16:05:35 INFO   (MainThread) [homeassistant.helpers.entity_registry] Registered new   sensor.zha entity:   sensor.titan_products_ltd_tpzrco2ht_z3_497f8703_temperature
2021-03-03 16:05:35 DEBUG   (MainThread) [homeassistant.core] Bus:Handling <Event   entity_registry_updated[L]: action=create,   entity_id=sensor.titan_products_ltd_tpzrco2ht_z3_497f8703_temperature>
2021-03-03 16:05:35 INFO   (MainThread) [homeassistant.helpers.entity_registry] Registered new   sensor.zha entity: sensor.titan_products_ltd_tpzrco2ht_z3_497f8703_power
2021-03-03 16:05:35 DEBUG   (MainThread) [homeassistant.core] Bus:Handling <Event   entity_registry_updated[L]: action=create,   entity_id=sensor.titan_products_ltd_tpzrco2ht_z3_497f8703_power>
2021-03-03 16:05:35 INFO   (MainThread) [homeassistant.helpers.entity_registry] Registered new   sensor.zha entity: sensor.titan_products_ltd_tpzrco2ht_z3_497f8703_humidity
2021-03-03 16:05:35 DEBUG   (MainThread) [homeassistant.core] Bus:Handling <Event   entity_registry_updated[L]: action=create,   entity_id=sensor.titan_products_ltd_tpzrco2ht_z3_497f8703_humidity>
2021-03-03 16:05:35 DEBUG   (MainThread) [homeassistant.core] Bus:Handling <Event state_changed[L]:   entity_id=sensor.titan_products_ltd_tpzrco2ht_z3_497f8703_temperature,   old_state=None, new_state=<state   sensor.titan_products_ltd_tpzrco2ht_z3_497f8703_temperature=23.0;   unit_of_measurement=°C, friendly_name=Titan Products Ltd TPZRCO2HT-Z3   497f8703 temperature, device_class=temperature @   2021-03-03T16:05:35.970585+00:00>>
2021-03-03 16:05:35 DEBUG   (MainThread) [homeassistant.core] Bus:Handling <Event state_changed[L]:   entity_id=sensor.titan_products_ltd_tpzrco2ht_z3_497f8703_power,   old_state=None, new_state=<state   sensor.titan_products_ltd_tpzrco2ht_z3_497f8703_power=unknown;   battery_size=AA, battery_quantity=1, battery_voltage=3.6,   unit_of_measurement=%, friendly_name=Titan Products Ltd TPZRCO2HT-Z3 497f8703   power, device_class=battery @ 2021-03-03T16:05:35.971371+00:00>>
2021-03-03 16:05:35 DEBUG   (MainThread) [homeassistant.core] Bus:Handling <Event state_changed[L]:   entity_id=sensor.titan_products_ltd_tpzrco2ht_z3_497f8703_humidity,   old_state=None, new_state=<state   sensor.titan_products_ltd_tpzrco2ht_z3_497f8703_humidity=42.7;   unit_of_measurement=%, friendly_name=Titan Products Ltd TPZRCO2HT-Z3 497f8703   humidity, device_class=humidity @ 2021-03-03T16:05:35.972025+00:00>>
2021-03-03 16:06:42 DEBUG   (MainThread) [homeassistant.core] Bus:Handling <Event state_changed[L]:   entity_id=sensor.titan_products_ltd_tpzrco2ht_z3_497f8703_humidity,   old_state=<state   sensor.titan_products_ltd_tpzrco2ht_z3_497f8703_humidity=42.7; unit_of_measurement=%,   friendly_name=Titan Products Ltd TPZRCO2HT-Z3 497f8703 humidity,   device_class=humidity @ 2021-03-03T16:05:35.972025+00:00>,   new_state=<state   sensor.titan_products_ltd_tpzrco2ht_z3_497f8703_humidity=41.4;   unit_of_measurement=%, friendly_name=Titan Products Ltd TPZRCO2HT-Z3 497f8703   humidity, device_class=humidity @ 2021-03-03T16:06:42.568084+00:00>>
Adminiuga commented 3 years ago

Depending on the change in the core, but most of the times you are fine using dev version of zha as a custom component with release version of the core

B-Hartley commented 3 years ago

max measured value returns: 0.0020000000949949026 min measured value returns: 0.0

I guess it's returning the CO2 as a part of the air. And reading up to 2000 ppm

does that make sense ?

Adminiuga commented 3 years ago

2021-03-03 16:01:42 WARNING (MainThread) [zigpy.zcl] Unknown cluster 1037

Check zigbee device signature, if it got the quirk. If you updated the core, then your modifications are gone. post debug log of you reading the measured_value attribue.

Also, post the log lines preceeding the Unknown cluster 1037 message

Adminiuga commented 3 years ago

max measured value returns: 0.0020000000949949026

if 0.0020000000949949026 represents 2000ppm, then may want to set the _multiplier = 1e6 in the sensor, to get readings in ppm. It seems that the measure value is not in parts per million, but parts only?

B-Hartley commented 3 years ago

The quirk is still there. I haven't updated core.

There is very little "zig" related stuff in log before that error.....

2021-03-03 16:01:42 DEBUG (MainThread) [zigpy.appdb] Loading application state from %s
2021-03-03 16:01:42 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event state_changed[L]: entity_id=media_player.lounge_tv_cast, old_state=None, new_state=<state media_player.lounge_tv_cast=unavailable; friendly_name=Lounge TV, supported_features=152461 @ 2021-03-03T16:01:42.265396+00:00>>
2021-03-03 16:01:42 INFO (SyncWorker_6) [pychromecast] Querying device status
2021-03-03 16:01:42 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event state_changed[L]: entity_id=sensor.alarm_log, old_state=None, new_state=<state sensor.alarm_log=unknown; friendly_name=Alarm Log @ 2021-03-03T16:01:42.282513+00:00>>
2021-03-03 16:01:42 WARNING (MainThread) [zigpy.zcl] Unknown cluster 1037

does this log help..........


2021-03-03   16:20:05 DEBUG (MainThread) [zigpy.device] [0xbf17] Extending timeout for   0x4c request
--
2021-03-03 16:20:05 DEBUG   (MainThread) [zigpy_deconz.zigbee.application] Sending Zigbee request with   tsn 76 under 77 request id, data: b'004c000100'
2021-03-03 16:20:05 DEBUG   (MainThread) [zigpy_deconz.api] Command Command.aps_data_request (20, 77, 0,   <DeconzAddressEndpoint address_mode=2 address=0xBF17 endpoint=1>, 260,   1037, 1, b'\x00L\x00\x01\x00', 2, 0)
2021-03-03 16:20:05 DEBUG   (MainThread) [zigpy_deconz.api] APS data request response: [2,   <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE\|2: 34>, 77]
2021-03-03 16:20:07 DEBUG   (MainThread) [zigpy_deconz.api] Device state changed response:   [<DeviceState.128\|APSDE_DATA_REQUEST_SLOTS_AVAILABLE\|APSDE_DATA_CONFIRM\|2:   166>, 0]
2021-03-03 16:20:07 DEBUG   (MainThread) [zigpy_deconz.api] Command Command.aps_data_confirm (0,)
2021-03-03 16:20:07 DEBUG   (MainThread) [zigpy_deconz.api] Device state changed response:   [<DeviceState.128\|APSDE_DATA_REQUEST_SLOTS_AVAILABLE\|APSDE_DATA_INDICATION\|APSDE_DATA_CONFIRM\|2:   174>, 0]
2021-03-03 16:20:07 DEBUG   (MainThread) [zigpy_deconz.api] APS data confirm response for request with id   77: 00
2021-03-03 16:20:07 DEBUG   (MainThread) [zigpy_deconz.api] Request id: 0x4d 'aps_data_confirm' for   <DeconzAddressEndpoint address_mode=ADDRESS_MODE.NWK address=0xbf17   endpoint=1>, status: 0x00
2021-03-03 16:20:07 DEBUG   (MainThread) [zigpy_deconz.api] Command Command.aps_data_indication (1, 1)
2021-03-03 16:20:07 DEBUG   (MainThread) [zigpy_deconz.api] APS data indication response: [34,   <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE\|2: 34>,   <DeconzAddress address_mode=ADDRESS_MODE.NWK address=0x0000>, 1,   <DeconzAddress address_mode=ADDRESS_MODE.NWK address=0xbf17>, 1, 260,   1037, b'\x18L\x01\x01\x00\x009\x00\x00\x00\x00', 0, 175, 255, 128, 228, 61,   0, -52]
2021-03-03 16:20:07 DEBUG   (MainThread) [zigpy.zcl] [0xbf17:1:0x040d] ZCL deserialize: <ZCLHeader   frame_control=<FrameControl frame_type=GLOBAL_COMMAND   manufacturer_specific=False is_reply=True disable_default_response=True>   manufacturer=None tsn=76 command_id=Command.Read_Attributes_rsp>
2021-03-03 16:20:07 DEBUG   (MainThread) [zigpy_deconz.api] 'aps_data_indication' response from   <DeconzAddress address_mode=ADDRESS_MODE.NWK address=0xbf17>, ep: 1,   profile: 0x0104, cluster_id: 0x040d, data: b'184c010100003900000000'
2021-03-03 16:20:10 DEBUG   (MainThread) [zigpy.device] [0xbf17] Extending timeout for 0x4e request
2021-03-03 16:20:10 DEBUG   (MainThread) [zigpy_deconz.zigbee.application] Sending Zigbee request with   tsn 78 under 79 request id, data: b'004e000200'
2021-03-03 16:20:10 DEBUG   (MainThread) [zigpy_deconz.api] Command Command.aps_data_request (20, 79, 0,   <DeconzAddressEndpoint address_mode=2 address=0xBF17 endpoint=1>, 260,   1037, 1, b'\x00N\x00\x02\x00', 2, 0)
2021-03-03 16:20:10 DEBUG   (MainThread) [zigpy_deconz.api] APS data request response: [2,   <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE\|2: 34>, 79]
2021-03-03 16:20:13 DEBUG   (MainThread) [zigpy_deconz.api] Device state changed response:   [<DeviceState.128\|APSDE_DATA_REQUEST_SLOTS_AVAILABLE\|APSDE_DATA_CONFIRM\|2:   166>, 0]
2021-03-03 16:20:13 DEBUG   (MainThread) [zigpy_deconz.api] Device state changed response:   [<DeviceState.128\|APSDE_DATA_REQUEST_SLOTS_AVAILABLE\|APSDE_DATA_INDICATION\|APSDE_DATA_CONFIRM\|2:   174>, 0]
2021-03-03 16:20:13 DEBUG   (MainThread) [zigpy_deconz.api] Command Command.aps_data_confirm (0,)
2021-03-03 16:20:13 DEBUG   (MainThread) [zigpy_deconz.api] APS data confirm response for request with id   79: 00
2021-03-03 16:20:13 DEBUG   (MainThread) [zigpy_deconz.api] Request id: 0x4f 'aps_data_confirm' for   <DeconzAddressEndpoint address_mode=ADDRESS_MODE.NWK address=0xbf17   endpoint=1>, status: 0x00
2021-03-03 16:20:13 DEBUG   (MainThread) [zigpy_deconz.api] Command Command.aps_data_indication (1, 1)
2021-03-03 16:20:13 DEBUG   (MainThread) [zigpy_deconz.api] APS data indication response: [34,   <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE\|2: 34>,   <DeconzAddress address_mode=ADDRESS_MODE.NWK address=0x0000>, 1,   <DeconzAddress address_mode=ADDRESS_MODE.NWK address=0xbf17>, 1, 260,   1037, b'\x18N\x01\x02\x00\x009o\x12\x03;', 0, 175, 255, 138, 228, 61, 0, -52]
2021-03-03 16:20:13 DEBUG   (MainThread) [zigpy.zcl] [0xbf17:1:0x040d] ZCL deserialize: <ZCLHeader   frame_control=<FrameControl frame_type=GLOBAL_COMMAND   manufacturer_specific=False is_reply=True disable_default_response=True>   manufacturer=None tsn=78 command_id=Command.Read_Attributes_rsp>
2021-03-03 16:20:13 DEBUG   (MainThread) [zigpy_deconz.api] 'aps_data_indication' response from   <DeconzAddress address_mode=ADDRESS_MODE.NWK address=0xbf17>, ep: 1,   profile: 0x0104, cluster_id: 0x040d, data: b'184e01020000396f12033b'
2021-03-03 16:20:15 DEBUG   (MainThread) [zigpy.device] [0xbf17] Extending timeout for 0x50 request
2021-03-03 16:20:15 DEBUG   (MainThread) [zigpy_deconz.zigbee.application] Sending Zigbee request with   tsn 80 under 81 request id, data: b'0050000000'
2021-03-03 16:20:15 DEBUG   (MainThread) [zigpy_deconz.api] Command Command.aps_data_request (20, 81, 0,   <DeconzAddressEndpoint address_mode=2 address=0xBF17 endpoint=1>, 260,   1037, 1, b'\x00P\x00\x00\x00', 2, 0)
2021-03-03 16:20:15 DEBUG   (MainThread) [zigpy_deconz.api] APS data request response: [2,   <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE\|2: 34>, 81]
2021-03-03 16:20:18 DEBUG   (MainThread) [zigpy_deconz.zigbee.application] Sending Zigbee request with   tsn 82 under 83 request id, data: b'0052000b05'
2021-03-03 16:20:18 DEBUG   (MainThread) [zigpy_deconz.api] Command Command.aps_data_request (20, 83, 0,   <DeconzAddressEndpoint address_mode=2 address=0x0F66 endpoint=1>, 260,   2820, 1, b'\x00R\x00\x0b\x05', 2, 0)
2021-03-03 16:20:18 DEBUG   (MainThread) [zigpy_deconz.zigbee.application] Sending Zigbee request with   tsn 84 under 85 request id, data: b'0054000b05'
2021-03-03 16:20:18 DEBUG   (MainThread) [zigpy_deconz.api] APS data request response: [2,   <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE\|2: 34>, 83]
2021-03-03 16:20:18 DEBUG   (MainThread) [zigpy_deconz.api] Command Command.aps_data_request (20, 85, 0,   <DeconzAddressEndpoint address_mode=2 address=0x0163 endpoint=1>, 260,   2820, 1, b'\x00T\x00\x0b\x05', 2, 0)
2021-03-03 16:20:18 DEBUG   (MainThread) [zigpy_deconz.api] Device state changed response:   [<DeviceState.128\|APSDE_DATA_REQUEST_SLOTS_AVAILABLE\|APSDE_DATA_CONFIRM\|2:   166>, 0]
2021-03-03 16:20:18 DEBUG   (MainThread) [zigpy_deconz.api] APS data request response: [2,   <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE\|APSDE_DATA_CONFIRM\|2:   38>, 85]
2021-03-03 16:20:18 DEBUG   (MainThread) [zigpy_deconz.api] Command Command.aps_data_confirm (0,)
2021-03-03 16:20:18 DEBUG   (MainThread) [zigpy_deconz.api] APS data confirm response for request with id   83: 00
2021-03-03 16:20:18 DEBUG   (MainThread) [zigpy_deconz.api] Request id: 0x53 'aps_data_confirm' for   <DeconzAddressEndpoint address_mode=ADDRESS_MODE.NWK address=0x0f66   endpoint=1>, status: 0x00
2021-03-03 16:20:18 DEBUG   (MainThread) [zigpy_deconz.api] Device state changed response:   [<DeviceState.128\|APSDE_DATA_REQUEST_SLOTS_AVAILABLE\|APSDE_DATA_CONFIRM\|2:   166>, 0]
2021-03-03 16:20:18 DEBUG   (MainThread) [zigpy_deconz.api] Command Command.aps_data_confirm (0,)
2021-03-03 16:20:18 DEBUG   (MainThread) [zigpy_deconz.api] Device state changed response:   [<DeviceState.128\|APSDE_DATA_REQUEST_SLOTS_AVAILABLE\|APSDE_DATA_INDICATION\|APSDE_DATA_CONFIRM\|2:   174>, 0]
2021-03-03 16:20:18 DEBUG   (MainThread) [zigpy_deconz.api] APS data confirm response for request with id   85: 00
2021-03-03 16:20:18 DEBUG   (MainThread) [zigpy_deconz.api] Request id: 0x55 'aps_data_confirm' for   <DeconzAddressEndpoint address_mode=ADDRESS_MODE.NWK address=0x0163   endpoint=1>, status: 0x00
2021-03-03 16:20:18 DEBUG   (MainThread) [zigpy_deconz.api] Command Command.aps_data_indication (1, 1)
2021-03-03 16:20:18 DEBUG   (MainThread) [zigpy_deconz.api] APS data indication response: [32,   <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE\|2: 34>,   <DeconzAddress address_mode=ADDRESS_MODE.NWK address=0x0000>, 1,   <DeconzAddress address_mode=ADDRESS_MODE.NWK address=0x0163>, 1, 260,   2820, b'\x18T\x01\x0b\x05\x00)\x00\x00', 0, 175, 255, 138, 228, 61, 0, -38]
2021-03-03 16:20:18 DEBUG   (MainThread) [zigpy.zcl] [0x0163:1:0x0b04] ZCL deserialize: <ZCLHeader   frame_control=<FrameControl frame_type=GLOBAL_COMMAND   manufacturer_specific=False is_reply=True disable_default_response=True>   manufacturer=None tsn=84 command_id=Command.Read_Attributes_rsp>
2021-03-03 16:20:18 DEBUG   (MainThread) [zigpy_deconz.api] 'aps_data_indication' response from   <DeconzAddress address_mode=ADDRESS_MODE.NWK address=0x0163>, ep: 1,   profile: 0x0104, cluster_id: 0x0b04, data: b'1854010b0500290000'
2021-03-03 16:20:18 DEBUG   (MainThread) [zigpy_deconz.api] Device state changed response:   [<DeviceState.128\|APSDE_DATA_REQUEST_SLOTS_AVAILABLE\|APSDE_DATA_INDICATION\|2:   170>, 0]
2021-03-03 16:20:18 DEBUG   (MainThread) [zigpy_deconz.api] Command Command.aps_data_indication (1, 1)
2021-03-03 16:20:18 DEBUG   (MainThread) [zigpy_deconz.api] APS data indication response: [32,   <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE\|2: 34>,   <DeconzAddress address_mode=ADDRESS_MODE.NWK address=0x0000>, 1,   <DeconzAddress address_mode=ADDRESS_MODE.NWK address=0x0f66>, 1, 260,   2820, b'\x18R\x01\x0b\x05\x00)\x00\x00', 0, 175, 255, 153, 226, 61, 0, -54]
2021-03-03 16:20:18 DEBUG   (MainThread) [zigpy.zcl] [0x0f66:1:0x0b04] ZCL deserialize: <ZCLHeader   frame_control=<FrameControl frame_type=GLOBAL_COMMAND   manufacturer_specific=False is_reply=True disable_default_response=True>   manufacturer=None tsn=82 command_id=Command.Read_Attributes_rsp>
2021-03-03 16:20:18 DEBUG   (MainThread) [zigpy_deconz.api] 'aps_data_indication' response from   <DeconzAddress address_mode=ADDRESS_MODE.NWK address=0x0f66>, ep: 1,   profile: 0x0104, cluster_id: 0x0b04, data: b'1852010b0500290000'
2021-03-03 16:20:19 DEBUG   (MainThread) [zigpy_deconz.api] Device state changed response:   [<DeviceState.128\|APSDE_DATA_REQUEST_SLOTS_AVAILABLE\|APSDE_DATA_CONFIRM\|2:   166>, 0]
2021-03-03 16:20:19 DEBUG   (MainThread) [zigpy_deconz.api] Command Command.aps_data_confirm (0,)
2021-03-03 16:20:19 DEBUG   (MainThread) [zigpy_deconz.api] Device state changed response:   [<DeviceState.128\|APSDE_DATA_REQUEST_SLOTS_AVAILABLE\|APSDE_DATA_INDICATION\|APSDE_DATA_CONFIRM\|2:   174>, 0]
2021-03-03 16:20:19 DEBUG   (MainThread) [zigpy_deconz.api] APS data confirm response for request with id   81: 00
2021-03-03 16:20:19 DEBUG   (MainThread) [zigpy_deconz.api] Request id: 0x51 'aps_data_confirm' for   <DeconzAddressEndpoint address_mode=ADDRESS_MODE.NWK address=0xbf17   endpoint=1>, status: 0x00
2021-03-03 16:20:19 DEBUG   (MainThread) [zigpy_deconz.api] Command Command.aps_data_indication (1, 1)
2021-03-03 16:20:19 DEBUG   (MainThread) [zigpy_deconz.api] APS data indication response: [34,   <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE\|2: 34>,   <DeconzAddress address_mode=ADDRESS_MODE.NWK address=0x0000>, 1,   <DeconzAddress address_mode=ADDRESS_MODE.NWK address=0xbf17>, 1, 260,   1037, b'\x18P\x01\x00\x00\x009\x00\x00\xc0\x7f', 0, 175, 255, 138, 228, 61,   0, -52]
2021-03-03 16:20:19 DEBUG   (MainThread) [zigpy.zcl] [0xbf17:1:0x040d] ZCL deserialize: <ZCLHeader   frame_control=<FrameControl frame_type=GLOBAL_COMMAND   manufacturer_specific=False is_reply=True disable_default_response=True>   manufacturer=None tsn=80 command_id=Command.Read_Attributes_rsp>
2021-03-03 16:20:19 DEBUG   (MainThread) [zigpy_deconz.api] 'aps_data_indication' response from   <DeconzAddress address_mode=ADDRESS_MODE.NWK address=0xbf17>, ep: 1,   profile: 0x0104, cluster_id: 0x040d, data: b'185001000000390000c07f'
2021-03-03 16:20:19 DEBUG   (MainThread) [zigpy_deconz.api] Device state changed response:   [<DeviceState.128\|APSDE_DATA_REQUEST_SLOTS_AVAILABLE\|APSDE_DATA_INDICATION\|2:   170>, 0]
2021-03-03 16:20:19 DEBUG   (MainThread) [zigpy_deconz.api] Command Command.aps_data_indication (1, 1)
2021-03-03 16:20:19 DEBUG   (MainThread) [zigpy_deconz.api] APS data indication response: [30,   <DeviceState.APSDE_DATA_REQUEST_SLOTS_AVAILABLE\|2: 34>,   <DeconzAddress address_mode=ADDRESS_MODE.NWK address=0x0000>, 1,   <DeconzAddress address_mode=ADDRESS_MODE.NWK address=0x0163>, 1, 260,   0, b'\x18K\n\x01\x00 C', 0, 175, 255, 138, 228, 61, 0, -34]
2021-03-03 16:20:19 DEBUG   (MainThread) [zigpy.zcl] [0x0163:1:0x0000] ZCL deserialize: <ZCLHeader   frame_control=<FrameControl frame_type=GLOBAL_COMMAND   manufacturer_specific=False is_reply=False disable_default_response=True>   manufacturer=None tsn=75 command_id=Command.Report_Attributes>
2021-03-03 16:20:19 DEBUG   (MainThread) [zigpy.zcl] [0x0163:1:0x0000] ZCL request 0x000a:   [[Attribute(attrid=1, value=<TypeValue type=uint8_t, value=67>)]]
2021-03-03 16:20:19 DEBUG   (MainThread) [zigpy.zcl] [0x0163:1:0x0000] Attribute report received:   app_version=67
2021-03-03 16:20:19 DEBUG   (MainThread) [zigpy_deconz.api] 'aps_data_indication' response from   <DeconzAddress address_mode=ADDRESS_MODE.NWK address=0x0163>, ep: 1,   profile: 0x0104, cluster_id: 0x0000, data: b'184b0a01002043'