Open Nelevit opened 1 year ago
Can you attach the logs with the quirk applied? Logs from quirk would be more descriptive. Also, with the quirk applied, catch the logs from the device powerup (when wires are connected). Tuya devices usually reports its status and give to us some DPs information. Any link to vendor site or device capabilities?
@javicalle Thanks a lot for your reply!
Sorry it takes me so long to post those logs. I can't reproduce loading the quirk now :/
Would you please help to figure it out?
Here is a link to device page on AliExpress
Thanks in advance! Nestor
Take the ts0601_motion.py
version from here:
https://github.com/zigpy/zha-device-handlers/raw/release/0.0.74/zhaquirks/tuya/ts0601_motion.py
Add your model, save changes and restart HA.
Check here to enable the debug logs:
@javicalle Thanks for your help :)
Its alive! :D
I've experimented with it and 2 classes were able to load:
Single entity - human presence sensor which works ok
txt files files contain logs while resetting.
Hope it helps, Nestor
Hi, @TheJulianJES I've noticed you tagged a custom quirk but can't find it 😕 Could you please help? Would be happy to test it out and report back. Thanks in advance, Nestor
I think the label just concerns adding _TZE204_dtzziy1e
to the existing MmwRadarMotion cluster. That's what I did and it does work for the basic function of detecting occupancy and illuminance, but I can't control the relay or the parameters that should make the relay switch.
Does anybody know where to get started on this? There is some information available from another project: https://github.com/Koenkk/zigbee-herdsman-converters/issues/5930
@JeroenVanOort I did quirk for it's brother _TZE204_clrdrnya, it's same options device. But it probably will not really usable for you as I running zha as component and exposed all options/target distance sensor in it's bundles. Anyway it contains all datapoints so at least you will be able to change values of options via Mange ZigBee device.
But add your signature 1st
Thank you very much!
Have you been able to get the relay working? For me, the relay never switches, neither automatic nor manual. Maybe my unit is just broken, but I don't know.
Yes @JeroenVanOort , it is working.
I have the full UI due to custom changes I did in ZHA, with default ZHA you will not see controls but you can try to do it manually from the device page via the Manage Zigbee device.
Open Manage Zigbee device and select MmwRadarV3ManufCluster Select breaker_mode attribute and write 0 to it (it will set the device to Standart mode with the ability to manipulate relay) then select the breaker_status attribute and write 0 to set it off or 1 to set it on (polarity depends on one more attribute breaker_polarity but I am not sure if it is implemented in your device)
I tried with the attached zip file by replacing the device info, but I only have occupancy showed, does someone know how to correct it and have the .py file that fit the _TZE204_dtzziy1e ?
Working fine with the following:
import math
from typing import Dict
from zigpy.profiles import zgp, zha
from zigpy.quirks import CustomDevice
import zigpy.types as t
from zigpy.zcl.clusters.general import (
AnalogInput,
AnalogOutput,
Basic,
GreenPowerProxy,
Groups,
Ota,
Scenes,
Time,
)
from zigpy.zcl.clusters.measurement import IlluminanceMeasurement, OccupancySensing
from zhaquirks.const import (
DEVICE_TYPE,
ENDPOINTS,
INPUT_CLUSTERS,
MODELS_INFO,
OUTPUT_CLUSTERS,
PROFILE_ID,
)
from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster, TuyaNewManufCluster
from zhaquirks.tuya.mcu import (
DPToAttributeMapping,
TuyaAttributesCluster,
TuyaMCUCluster,
)
ZONE_TYPE = 0x0001
class TuyaMmwRadarSelfTest(t.enum8):
"""Mmw radar self test values."""
TESTING = 0
TEST_SUCCESS = 1
TEST_FAILURE = 2
OTHER = 3
COMM_FAULT = 4
RADAR_FAULT = 5
class TuyaOccupancySensing(OccupancySensing, TuyaLocalCluster):
"""Tuya local OccupancySensing cluster."""
class TuyaAnalogInput(AnalogInput, TuyaLocalCluster):
"""Tuya local AnalogInput cluster."""
class TuyaIlluminanceMeasurement(IlluminanceMeasurement, TuyaLocalCluster):
"""Tuya local IlluminanceMeasurement cluster."""
class TuyaMmwRadarSensitivity(TuyaAttributesCluster, AnalogOutput):
"""AnalogOutput cluster for sensitivity."""
def __init__(self, *args, **kwargs):
"""Init."""
super().__init__(*args, **kwargs)
self._update_attribute(self.attributes_by_name["description"].id, "Sensitivity")
self._update_attribute(self.attributes_by_name["min_present_value"].id, 1)
self._update_attribute(self.attributes_by_name["max_present_value"].id, 9)
self._update_attribute(self.attributes_by_name["resolution"].id, 1)
class TuyaMmwRadarMinRange(TuyaAttributesCluster, AnalogOutput):
"""AnalogOutput cluster for min range."""
def __init__(self, *args, **kwargs):
"""Init."""
super().__init__(*args, **kwargs)
self._update_attribute(self.attributes_by_name["description"].id, "Min range")
self._update_attribute(self.attributes_by_name["min_present_value"].id, 0)
self._update_attribute(self.attributes_by_name["max_present_value"].id, 950)
self._update_attribute(self.attributes_by_name["resolution"].id, 10)
self._update_attribute(
self.attributes_by_name["engineering_units"].id, 118
) # 31: meters
class TuyaMmwRadarMaxRange(TuyaAttributesCluster, AnalogOutput):
"""AnalogOutput cluster for max range."""
def __init__(self, *args, **kwargs):
"""Init."""
super().__init__(*args, **kwargs)
self._update_attribute(self.attributes_by_name["description"].id, "Max range")
self._update_attribute(self.attributes_by_name["min_present_value"].id, 10)
self._update_attribute(self.attributes_by_name["max_present_value"].id, 950)
self._update_attribute(self.attributes_by_name["resolution"].id, 10)
self._update_attribute(
self.attributes_by_name["engineering_units"].id, 118
) # 31: meters
class TuyaMmwRadarDetectionDelay(TuyaAttributesCluster, AnalogOutput):
"""AnalogOutput cluster for detection delay."""
def __init__(self, *args, **kwargs):
"""Init."""
super().__init__(*args, **kwargs)
self._update_attribute(
self.attributes_by_name["description"].id, "Detection delay"
)
self._update_attribute(self.attributes_by_name["min_present_value"].id, 000)
self._update_attribute(self.attributes_by_name["max_present_value"].id, 20000)
self._update_attribute(self.attributes_by_name["resolution"].id, 100)
self._update_attribute(
self.attributes_by_name["engineering_units"].id, 159
) # 73: seconds
class TuyaMmwRadarFadingTime(TuyaAttributesCluster, AnalogOutput):
"""AnalogOutput cluster for fading time."""
def __init__(self, *args, **kwargs):
"""Init."""
super().__init__(*args, **kwargs)
self._update_attribute(self.attributes_by_name["description"].id, "Fading time")
self._update_attribute(self.attributes_by_name["min_present_value"].id, 2000)
self._update_attribute(self.attributes_by_name["max_present_value"].id, 200000)
self._update_attribute(self.attributes_by_name["resolution"].id, 1000)
self._update_attribute(
self.attributes_by_name["engineering_units"].id, 159
) # 73: seconds
class TuyaMmwRadarTargetDistance(TuyaAttributesCluster, AnalogInput):
"""AnalogInput cluster for target distance."""
def __init__(self, *args, **kwargs):
"""Init."""
super().__init__(*args, **kwargs)
self._update_attribute(
self.attributes_by_name["description"].id, "Target distance"
)
self._update_attribute(
self.attributes_by_name["engineering_units"].id, 31
) # 31: meters
class TuyaMmwRadarClusterBase(NoManufacturerCluster, TuyaMCUCluster):
"""Mmw radar cluster, base class."""
attributes = TuyaMCUCluster.attributes.copy()
attributes.update(
{
# ramdom attribute IDs
0xEF01: ("occupancy", t.uint32_t, True),
0xEF02: ("sensitivity", t.uint32_t, True),
0xEF03: ("min_range", t.uint32_t, True),
0xEF04: ("max_range", t.uint32_t, True),
0xEF06: ("self_test", TuyaMmwRadarSelfTest, True),
0xEF09: ("target_distance", t.uint32_t, True),
0xEF65: ("detection_delay", t.uint32_t, True),
0xEF66: ("fading_time", t.uint32_t, True),
0xEF67: ("cli", t.CharacterString, True),
0xEF68: ("illuminance", t.uint32_t, True),
}
)
class TuyaMmwRadarClusterVariant1(TuyaMmwRadarClusterBase):
"""Mmw radar cluster, variant 1."""
dp_to_attribute: Dict[int, DPToAttributeMapping] = {
1: DPToAttributeMapping(
TuyaOccupancySensing.ep_attribute,
"occupancy",
),
2: DPToAttributeMapping(
TuyaMmwRadarSensitivity.ep_attribute,
"present_value",
),
3: DPToAttributeMapping(
TuyaMmwRadarMinRange.ep_attribute,
"present_value",
endpoint_id=2,
),
4: DPToAttributeMapping(
TuyaMmwRadarMaxRange.ep_attribute,
"present_value",
endpoint_id=3,
),
6: DPToAttributeMapping(
TuyaMCUCluster.ep_attribute,
"self_test",
),
9: DPToAttributeMapping(
TuyaMmwRadarTargetDistance.ep_attribute,
"present_value",
lambda x: x / 100,
),
101: DPToAttributeMapping(
TuyaMmwRadarDetectionDelay.ep_attribute,
"present_value",
converter=lambda x: x * 100,
dp_converter=lambda x: x // 100,
endpoint_id=4,
),
102: DPToAttributeMapping(
TuyaMmwRadarFadingTime.ep_attribute,
"present_value",
converter=lambda x: x * 100,
dp_converter=lambda x: x // 100,
endpoint_id=5,
),
103: DPToAttributeMapping(
TuyaMCUCluster.ep_attribute,
"cli",
),
104: DPToAttributeMapping(
TuyaIlluminanceMeasurement.ep_attribute,
"measured_value",
converter=lambda x: int(math.log10(x) * 10000 + 1) if x > 0 else int(0),
),
}
data_point_handlers = {
1: "_dp_2_attr_update",
2: "_dp_2_attr_update",
3: "_dp_2_attr_update",
4: "_dp_2_attr_update",
6: "_dp_2_attr_update",
9: "_dp_2_attr_update",
101: "_dp_2_attr_update",
102: "_dp_2_attr_update",
103: "_dp_2_attr_update",
104: "_dp_2_attr_update",
}
class TuyaMmwRadarOccupancyVariant1(CustomDevice):
"""Millimeter wave occupancy sensor, variant 1."""
signature = {
# endpoint=1, profile=260, device_type=81, device_version=1,
# input_clusters=[0, 4, 5, 61184], output_clusters=[25, 10]
MODELS_INFO: [
("_TZE204_dtzziy1e", "TS0601"),
],
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
INPUT_CLUSTERS: [
Basic.cluster_id,
Groups.cluster_id,
Scenes.cluster_id,
TuyaNewManufCluster.cluster_id,
],
OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
},
},
}
replacement = {
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.OCCUPANCY_SENSOR,
INPUT_CLUSTERS: [
Basic.cluster_id,
Groups.cluster_id,
Scenes.cluster_id,
TuyaMmwRadarClusterVariant1,
TuyaIlluminanceMeasurement,
TuyaOccupancySensing,
TuyaMmwRadarTargetDistance,
TuyaMmwRadarSensitivity,
],
OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
},
2: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
INPUT_CLUSTERS: [
TuyaMmwRadarMinRange,
],
OUTPUT_CLUSTERS: [],
},
3: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
INPUT_CLUSTERS: [
TuyaMmwRadarMaxRange,
],
OUTPUT_CLUSTERS: [],
},
4: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
INPUT_CLUSTERS: [
TuyaMmwRadarDetectionDelay,
],
OUTPUT_CLUSTERS: [],
},
5: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
INPUT_CLUSTERS: [
TuyaMmwRadarFadingTime,
],
OUTPUT_CLUSTERS: [],
},
}
}
class TuyaMmwRadarOccupancyVariant1GPP(CustomDevice):
"""Millimeter wave occupancy sensor, variant 1 with GPP."""
signature = {
# endpoint=1, profile=260, device_type=81, device_version=1,
# input_clusters=[0, 4, 5, 61184], output_clusters=[25, 10])
MODELS_INFO: [
("_TZE204_dtzziy1e", "TS0601"),
],
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
INPUT_CLUSTERS: [
Basic.cluster_id,
Groups.cluster_id,
Scenes.cluster_id,
TuyaNewManufCluster.cluster_id,
],
OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
},
242: {
# <SimpleDescriptor endpoint=242 profile=41440 device_type=97
# input_clusters=[]
# output_clusters=[33]
PROFILE_ID: zgp.PROFILE_ID,
DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
INPUT_CLUSTERS: [],
OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
},
},
}
replacement = {
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.OCCUPANCY_SENSOR,
INPUT_CLUSTERS: [
Basic.cluster_id,
Groups.cluster_id,
Scenes.cluster_id,
TuyaMmwRadarClusterVariant1,
TuyaIlluminanceMeasurement,
TuyaOccupancySensing,
TuyaMmwRadarTargetDistance,
TuyaMmwRadarSensitivity,
],
OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
},
2: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
INPUT_CLUSTERS: [
TuyaMmwRadarMinRange,
],
OUTPUT_CLUSTERS: [],
},
3: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
INPUT_CLUSTERS: [
TuyaMmwRadarMaxRange,
],
OUTPUT_CLUSTERS: [],
},
4: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
INPUT_CLUSTERS: [
TuyaMmwRadarDetectionDelay,
],
OUTPUT_CLUSTERS: [],
},
5: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
INPUT_CLUSTERS: [
TuyaMmwRadarFadingTime,
],
OUTPUT_CLUSTERS: [],
},
242: {
PROFILE_ID: zgp.PROFILE_ID,
DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
INPUT_CLUSTERS: [],
OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
},
}
}
class TuyaMmwRadarClusterVariant2(TuyaMmwRadarClusterBase):
"""Tuya MMW radar cluster, variant 2."""
dp_to_attribute: Dict[int, DPToAttributeMapping] = {
103: DPToAttributeMapping(
TuyaMCUCluster.ep_attribute,
"cli",
),
104: DPToAttributeMapping(
TuyaIlluminanceMeasurement.ep_attribute,
"measured_value",
converter=lambda x: int(math.log10(x) * 10000 + 1) if x > 0 else int(0),
),
105: DPToAttributeMapping(
TuyaOccupancySensing.ep_attribute,
"occupancy",
),
106: DPToAttributeMapping(
TuyaMmwRadarSensitivity.ep_attribute,
"present_value",
),
107: DPToAttributeMapping(
TuyaMmwRadarMaxRange.ep_attribute,
"present_value",
endpoint_id=3,
),
108: DPToAttributeMapping(
TuyaMmwRadarMinRange.ep_attribute,
"present_value",
endpoint_id=2,
),
109: DPToAttributeMapping(
TuyaMmwRadarTargetDistance.ep_attribute,
"present_value",
),
110: DPToAttributeMapping(
TuyaMmwRadarFadingTime.ep_attribute,
"present_value",
converter=lambda x: x * 100,
dp_converter=lambda x: x // 100,
endpoint_id=5,
),
111: DPToAttributeMapping(
TuyaMmwRadarDetectionDelay.ep_attribute,
"present_value",
converter=lambda x: x * 100,
dp_converter=lambda x: x // 100,
endpoint_id=4,
),
}
data_point_handlers = {
103: "_dp_2_attr_update",
104: "_dp_2_attr_update",
105: "_dp_2_attr_update",
106: "_dp_2_attr_update",
107: "_dp_2_attr_update",
108: "_dp_2_attr_update",
109: "_dp_2_attr_update",
110: "_dp_2_attr_update",
111: "_dp_2_attr_update",
}
class TuyaMmwRadarOccupancyVariant2(CustomDevice):
"""Millimeter wave occupancy sensor, variant 2."""
signature = {
# endpoint=1, profile=260, device_type=81, device_version=1,
# input_clusters=[0, 4, 5, 61184], output_clusters=[25, 10])
MODELS_INFO: [
("_TZE204_dtzziy1e", "TS0601"),
],
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
INPUT_CLUSTERS: [
Basic.cluster_id,
Groups.cluster_id,
Scenes.cluster_id,
TuyaNewManufCluster.cluster_id,
],
OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
},
242: {
# <SimpleDescriptor endpoint=242 profile=41440 device_type=97
# input_clusters=[]
# output_clusters=[33]
PROFILE_ID: zgp.PROFILE_ID,
DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
INPUT_CLUSTERS: [],
OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
},
},
}
replacement = {
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.OCCUPANCY_SENSOR,
INPUT_CLUSTERS: [
Basic.cluster_id,
Groups.cluster_id,
Scenes.cluster_id,
TuyaMmwRadarClusterVariant2,
TuyaIlluminanceMeasurement,
TuyaOccupancySensing,
TuyaMmwRadarTargetDistance,
TuyaMmwRadarSensitivity,
],
OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
},
2: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
INPUT_CLUSTERS: [
TuyaMmwRadarMinRange,
],
OUTPUT_CLUSTERS: [],
},
3: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
INPUT_CLUSTERS: [
TuyaMmwRadarMaxRange,
],
OUTPUT_CLUSTERS: [],
},
4: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
INPUT_CLUSTERS: [
TuyaMmwRadarDetectionDelay,
],
OUTPUT_CLUSTERS: [],
},
5: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
INPUT_CLUSTERS: [
TuyaMmwRadarFadingTime,
],
OUTPUT_CLUSTERS: [],
},
242: {
PROFILE_ID: zgp.PROFILE_ID,
DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
INPUT_CLUSTERS: [],
OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
},
}
}
Thanks a lot, it's work fine with my TS060 _TZE204_clrdrnya, but I don't understand why i don't see the radar target distance in my sensors so i see in the advanced parameters
could you explain why ? And you, you can see the radar target distance
I tried with the attached zip file by replacing the device info, but I only have occupancy showed, does someone know how to correct it and have the .py file that fit the _TZE204_dtzziy1e ?
@RiRomain Do you see more than Illuminance and Occupancy in ZHA?
I only see illuminance and occupancy, but didn't think that the sensor can handle anything more (appart from the settings). And I didn't use the zip, but the code in the comment.
Wow nice, GUI controls woohoo! :) I tried it and it works!
My detectors are picking up movements of neighbors so for me the entry controls are essential. Currently, Entry Sensitivity and Entry Distance Indentation are sadly missing in the quirk update. I currently have no time nor knowledge (yet :) ) to adjust your quirk, so I will revert back and keep an eye out for possible updates in this thread.
Thanks for sharing your quirk @RiRomain !
Hi @evgenln ,
I have _TZE204_clrdrnya. I load the quirk ts0601_presence.py.txt but I only get the presence and iluminance but not the Controls to adjust the parametres.
Do you know what could be the issue?
Many thanks!
Sometimes it helps to reload the ZHA integration, just in case you have not tried this. You can also try to remove the devices and add them again. I had the same problem and this fixed things for me.
thanks @tommetje for your quick answer.
Unfortunally I followed your instructions several times with no results. Any other idea?
Many thanks!
PD: just to say I have the last firmware version
thanks @tommetje for your quick answer.
Unfortunally I followed your instructions several times with no results. Any other idea?
Many thanks!
I updated the existing quirk, after this I did not see the changes.
From what I remember, I also tried removing removing the affected devices + removing the quirk folder + HA restart + ZHA reload. After this I added the folder of the updated quirk and gave it a different name, again HA restart + adding devices again + ZHA reload (if needed) .
Not sure if all the steps are needed but this is what I tried. Eventually I got the updated quirk working.
thks @tommetje,
I'll try to play more the weekend!
Best,
Hello, I have a _TZE204_sbyx0lm6 (the 5.8G version as opposed to the 2.4G) and have tried all quirks above, changing the device specs in the code, and only randomly gotten only the illuminance and presence to work. I am not a coder so can't unfortunately contribute to this, but would really appreciate if somebody could continue developing this quirk further. Many thanks!
I have a _TZE204_clrdrnya device and with @RiRomain python script, I get the occupancy to work fine ... Yeah! Thank you.
But
Luminance is not working, and neither Ota nor Time are working. Then there is the the question of the relay.
According to @LuisAlbertoFB in this thead it is possible to get it all working. I tried a few things, but so far no luck... Anyone has a clue on how to port this?
Hi all, I got it to work on _TZE204_clrdrnya using the quirk shared in the zip file above. however, the illuminance figures are not within the expected range. e.g, I am currently in a room, in a cloudy day; would expect to have something between 15 to 30 lx but instead, it shows 1,522lx. Anyone else has the same problem?
Was there any luck getting the relay to work?
I got it working for _TZE204_dtzziy1e with the code from @RiRomain's comment. The illuminance value does not show up at first, i have to restart HA every time i add a new device of this type, then it shows up. Anyone working on the missing values and relay?
Same. I get following controls and Occupancy Sensor. No lux.
Detection Delay Fading Time Max Range Min Range Sensitivity
Firmware Update is also visible
Relay isn't exposed and doesn't align to Occupancy. That all I really need.
I got everything working except the relay. In my case, I don't use the relay function.
Can this be added to ZHA. This ZHA quirks prevent me from updating to 2024.08 ->. Many of my automations at home use these devices to function.
"""Tuya mmw radar occupancy sensor."""
import math from typing import Dict
from zigpy.profiles import zgp, zha from zigpy.quirks import CustomDevice import zigpy.types as t from zigpy.zcl.clusters.general import ( AnalogInput, AnalogOutput, Basic, GreenPowerProxy, Groups, Ota, Scenes, Time, ) from zigpy.zcl.clusters.measurement import IlluminanceMeasurement, OccupancySensing
from zhaquirks.const import ( DEVICE_TYPE, ENDPOINTS, INPUT_CLUSTERS, MODELS_INFO, OUTPUT_CLUSTERS, PROFILE_ID, ) from zhaquirks.tuya import NoManufacturerCluster, TuyaLocalCluster, TuyaNewManufCluster from zhaquirks.tuya.mcu import ( DPToAttributeMapping, TuyaAttributesCluster, TuyaMCUCluster, )
ZONE_TYPE = 0x0001
class TuyaMmwRadarSelfTest(t.enum8): """Mmw radar self test values."""
TESTING = 0
TEST_SUCCESS = 1
TEST_FAILURE = 2
OTHER = 3
COMM_FAULT = 4
RADAR_FAULT = 5
class TuyaOccupancySensing(OccupancySensing, TuyaLocalCluster): """Tuya local OccupancySensing cluster."""
class TuyaAnalogInput(AnalogInput, TuyaLocalCluster): """Tuya local AnalogInput cluster."""
class TuyaIlluminanceMeasurement(IlluminanceMeasurement, TuyaLocalCluster): """Tuya local IlluminanceMeasurement cluster."""
class TuyaMmwRadarSensitivity(TuyaAttributesCluster, AnalogOutput): """AnalogOutput cluster for sensitivity."""
def __init__(self, *args, **kwargs):
"""Init."""
super().__init__(*args, **kwargs)
self._update_attribute(self.attributes_by_name["description"].id, "Sensitivity")
self._update_attribute(self.attributes_by_name["min_present_value"].id, 1)
self._update_attribute(self.attributes_by_name["max_present_value"].id, 9)
self._update_attribute(self.attributes_by_name["resolution"].id, 1)
class TuyaMmwRadarMinRange(TuyaAttributesCluster, AnalogOutput): """AnalogOutput cluster for min range."""
def __init__(self, *args, **kwargs):
"""Init."""
super().__init__(*args, **kwargs)
self._update_attribute(self.attributes_by_name["description"].id, "Min range")
self._update_attribute(self.attributes_by_name["min_present_value"].id, 0)
self._update_attribute(self.attributes_by_name["max_present_value"].id, 950)
self._update_attribute(self.attributes_by_name["resolution"].id, 10)
self._update_attribute(
self.attributes_by_name["engineering_units"].id, 118
) # 31: meters
class TuyaMmwRadarMaxRange(TuyaAttributesCluster, AnalogOutput): """AnalogOutput cluster for max range."""
def __init__(self, *args, **kwargs):
"""Init."""
super().__init__(*args, **kwargs)
self._update_attribute(self.attributes_by_name["description"].id, "Max range")
self._update_attribute(self.attributes_by_name["min_present_value"].id, 10)
self._update_attribute(self.attributes_by_name["max_present_value"].id, 950)
self._update_attribute(self.attributes_by_name["resolution"].id, 10)
self._update_attribute(
self.attributes_by_name["engineering_units"].id, 118
) # 31: meters
class TuyaMmwRadarDetectionDelay(TuyaAttributesCluster, AnalogOutput): """AnalogOutput cluster for detection delay."""
def __init__(self, *args, **kwargs):
"""Init."""
super().__init__(*args, **kwargs)
self._update_attribute(
self.attributes_by_name["description"].id, "Detection delay"
)
self._update_attribute(self.attributes_by_name["min_present_value"].id, 000)
self._update_attribute(self.attributes_by_name["max_present_value"].id, 20000)
self._update_attribute(self.attributes_by_name["resolution"].id, 100)
self._update_attribute(
self.attributes_by_name["engineering_units"].id, 159
) # 73: seconds
class TuyaMmwRadarFadingTime(TuyaAttributesCluster, AnalogOutput): """AnalogOutput cluster for fading time."""
def __init__(self, *args, **kwargs):
"""Init."""
super().__init__(*args, **kwargs)
self._update_attribute(self.attributes_by_name["description"].id, "Fading time")
self._update_attribute(self.attributes_by_name["min_present_value"].id, 2000)
self._update_attribute(self.attributes_by_name["max_present_value"].id, 200000)
self._update_attribute(self.attributes_by_name["resolution"].id, 1000)
self._update_attribute(
self.attributes_by_name["engineering_units"].id, 159
) # 73: seconds
class TuyaMmwRadarTargetDistance(TuyaAttributesCluster, AnalogInput): """AnalogInput cluster for target distance."""
def __init__(self, *args, **kwargs):
"""Init."""
super().__init__(*args, **kwargs)
self._update_attribute(
self.attributes_by_name["description"].id, "Target distance"
)
self._update_attribute(
self.attributes_by_name["engineering_units"].id, 31
) # 31: meters
class TuyaMmwRadarClusterBase(NoManufacturerCluster, TuyaMCUCluster): """Mmw radar cluster, base class."""
attributes = TuyaMCUCluster.attributes.copy()
attributes.update(
{
# ramdom attribute IDs
0xEF01: ("occupancy", t.uint32_t, True),
0xEF02: ("sensitivity", t.uint32_t, True),
0xEF03: ("min_range", t.uint32_t, True),
0xEF04: ("max_range", t.uint32_t, True),
0xEF06: ("self_test", TuyaMmwRadarSelfTest, True),
0xEF09: ("target_distance", t.uint32_t, True),
0xEF65: ("detection_delay", t.uint32_t, True),
0xEF66: ("fading_time", t.uint32_t, True),
0xEF67: ("cli", t.CharacterString, True),
0xEF68: ("illuminance", t.uint32_t, True),
}
)
class TuyaMmwRadarClusterVariant1(TuyaMmwRadarClusterBase): """Mmw radar cluster, variant 1."""
dp_to_attribute: Dict[int, DPToAttributeMapping] = {
1: DPToAttributeMapping(
TuyaOccupancySensing.ep_attribute,
"occupancy",
),
2: DPToAttributeMapping(
TuyaMmwRadarSensitivity.ep_attribute,
"present_value",
),
3: DPToAttributeMapping(
TuyaMmwRadarMinRange.ep_attribute,
"present_value",
endpoint_id=2,
),
4: DPToAttributeMapping(
TuyaMmwRadarMaxRange.ep_attribute,
"present_value",
endpoint_id=3,
),
6: DPToAttributeMapping(
TuyaMCUCluster.ep_attribute,
"self_test",
),
9: DPToAttributeMapping(
TuyaMmwRadarTargetDistance.ep_attribute,
"present_value",
lambda x: x / 100,
),
101: DPToAttributeMapping(
TuyaMmwRadarDetectionDelay.ep_attribute,
"present_value",
converter=lambda x: x * 100,
dp_converter=lambda x: x // 100,
endpoint_id=4,
),
102: DPToAttributeMapping(
TuyaMmwRadarFadingTime.ep_attribute,
"present_value",
converter=lambda x: x * 100,
dp_converter=lambda x: x // 100,
endpoint_id=5,
),
103: DPToAttributeMapping(
TuyaMCUCluster.ep_attribute,
"cli",
),
104: DPToAttributeMapping(
TuyaIlluminanceMeasurement.ep_attribute,
"measured_value",
converter=lambda x: int(math.log10(x) * 10000 + 1) if x > 0 else int(0),
),
}
data_point_handlers = {
1: "_dp_2_attr_update",
2: "_dp_2_attr_update",
3: "_dp_2_attr_update",
4: "_dp_2_attr_update",
6: "_dp_2_attr_update",
9: "_dp_2_attr_update",
101: "_dp_2_attr_update",
102: "_dp_2_attr_update",
103: "_dp_2_attr_update",
104: "_dp_2_attr_update",
}
class TuyaMmwRadarOccupancyVariant1(CustomDevice): """Millimeter wave occupancy sensor, variant 1."""
signature = {
# endpoint=1, profile=260, device_type=81, device_version=1,
# input_clusters=[0, 4, 5, 61184], output_clusters=[25, 10]
MODELS_INFO: [
("_TZE200_ar0slwnd", "TS0601"),
("_TZE200_sfiy5tfs", "TS0601"),
("_TZE200_mrf6vtua", "TS0601"),
("_TZE200_ztc6ggyl", "TS0601"),
("_TZE204_ztc6ggyl", "TS0601"),
("_TZE200_wukb7rhc", "TS0601"),
("_TZE204_qasjif9e", "TS0601"),
("_TZE204_dtzziy1e", "TS0601"),
],
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
INPUT_CLUSTERS: [
Basic.cluster_id,
Groups.cluster_id,
Scenes.cluster_id,
TuyaNewManufCluster.cluster_id,
],
OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
},
},
}
replacement = {
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.OCCUPANCY_SENSOR,
INPUT_CLUSTERS: [
Basic.cluster_id,
Groups.cluster_id,
Scenes.cluster_id,
TuyaMmwRadarClusterVariant1,
TuyaIlluminanceMeasurement,
TuyaOccupancySensing,
TuyaMmwRadarTargetDistance,
TuyaMmwRadarSensitivity,
],
OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
},
2: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
INPUT_CLUSTERS: [
TuyaMmwRadarMinRange,
],
OUTPUT_CLUSTERS: [],
},
3: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
INPUT_CLUSTERS: [
TuyaMmwRadarMaxRange,
],
OUTPUT_CLUSTERS: [],
},
4: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
INPUT_CLUSTERS: [
TuyaMmwRadarDetectionDelay,
],
OUTPUT_CLUSTERS: [],
},
5: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
INPUT_CLUSTERS: [
TuyaMmwRadarFadingTime,
],
OUTPUT_CLUSTERS: [],
},
}
}
class TuyaMmwRadarOccupancyVariant1GPP(CustomDevice): """Millimeter wave occupancy sensor, variant 1 with GPP."""
signature = {
# endpoint=1, profile=260, device_type=81, device_version=1,
# input_clusters=[0, 4, 5, 61184], output_clusters=[25, 10])
MODELS_INFO: [
("_TZE200_ar0slwnd", "TS0601"),
("_TZE200_sfiy5tfs", "TS0601"),
("_TZE200_mrf6vtua", "TS0601"),
("_TZE204_qasjif9e", "TS0601"),
],
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
INPUT_CLUSTERS: [
Basic.cluster_id,
Groups.cluster_id,
Scenes.cluster_id,
TuyaNewManufCluster.cluster_id,
],
OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
},
242: {
# <SimpleDescriptor endpoint=242 profile=41440 device_type=97
# input_clusters=[]
# output_clusters=[33]
PROFILE_ID: zgp.PROFILE_ID,
DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
INPUT_CLUSTERS: [],
OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
},
},
}
replacement = {
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.OCCUPANCY_SENSOR,
INPUT_CLUSTERS: [
Basic.cluster_id,
Groups.cluster_id,
Scenes.cluster_id,
TuyaMmwRadarClusterVariant1,
TuyaIlluminanceMeasurement,
TuyaOccupancySensing,
TuyaMmwRadarTargetDistance,
TuyaMmwRadarSensitivity,
],
OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
},
2: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
INPUT_CLUSTERS: [
TuyaMmwRadarMinRange,
],
OUTPUT_CLUSTERS: [],
},
3: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
INPUT_CLUSTERS: [
TuyaMmwRadarMaxRange,
],
OUTPUT_CLUSTERS: [],
},
4: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
INPUT_CLUSTERS: [
TuyaMmwRadarDetectionDelay,
],
OUTPUT_CLUSTERS: [],
},
5: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
INPUT_CLUSTERS: [
TuyaMmwRadarFadingTime,
],
OUTPUT_CLUSTERS: [],
},
242: {
PROFILE_ID: zgp.PROFILE_ID,
DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
INPUT_CLUSTERS: [],
OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
},
}
}
class TuyaMmwRadarClusterVariant2(TuyaMmwRadarClusterBase): """Tuya MMW radar cluster, variant 2."""
dp_to_attribute: Dict[int, DPToAttributeMapping] = {
103: DPToAttributeMapping(
TuyaMCUCluster.ep_attribute,
"cli",
),
104: DPToAttributeMapping(
TuyaIlluminanceMeasurement.ep_attribute,
"measured_value",
converter=lambda x: int(math.log10(x) * 10000 + 1) if x > 0 else int(0),
),
105: DPToAttributeMapping(
TuyaOccupancySensing.ep_attribute,
"occupancy",
),
106: DPToAttributeMapping(
TuyaMmwRadarSensitivity.ep_attribute,
"present_value",
),
107: DPToAttributeMapping(
TuyaMmwRadarMaxRange.ep_attribute,
"present_value",
endpoint_id=3,
),
108: DPToAttributeMapping(
TuyaMmwRadarMinRange.ep_attribute,
"present_value",
endpoint_id=2,
),
109: DPToAttributeMapping(
TuyaMmwRadarTargetDistance.ep_attribute,
"present_value",
),
110: DPToAttributeMapping(
TuyaMmwRadarFadingTime.ep_attribute,
"present_value",
converter=lambda x: x * 100,
dp_converter=lambda x: x // 100,
endpoint_id=5,
),
111: DPToAttributeMapping(
TuyaMmwRadarDetectionDelay.ep_attribute,
"present_value",
converter=lambda x: x * 100,
dp_converter=lambda x: x // 100,
endpoint_id=4,
),
}
data_point_handlers = {
103: "_dp_2_attr_update",
104: "_dp_2_attr_update",
105: "_dp_2_attr_update",
106: "_dp_2_attr_update",
107: "_dp_2_attr_update",
108: "_dp_2_attr_update",
109: "_dp_2_attr_update",
110: "_dp_2_attr_update",
111: "_dp_2_attr_update",
}
class TuyaMmwRadarOccupancyVariant2(CustomDevice): """Millimeter wave occupancy sensor, variant 2."""
signature = {
# endpoint=1, profile=260, device_type=81, device_version=1,
# input_clusters=[0, 4, 5, 61184], output_clusters=[25, 10])
MODELS_INFO: [
("_TZE204_sxm7l9xa", "TS0601"),
("_TZE204_bmdsp6bs", "TS0601"),
],
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
INPUT_CLUSTERS: [
Basic.cluster_id,
Groups.cluster_id,
Scenes.cluster_id,
TuyaNewManufCluster.cluster_id,
],
OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
},
242: {
# <SimpleDescriptor endpoint=242 profile=41440 device_type=97
# input_clusters=[]
# output_clusters=[33]
PROFILE_ID: zgp.PROFILE_ID,
DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
INPUT_CLUSTERS: [],
OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
},
},
}
replacement = {
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.OCCUPANCY_SENSOR,
INPUT_CLUSTERS: [
Basic.cluster_id,
Groups.cluster_id,
Scenes.cluster_id,
TuyaMmwRadarClusterVariant2,
TuyaIlluminanceMeasurement,
TuyaOccupancySensing,
TuyaMmwRadarTargetDistance,
TuyaMmwRadarSensitivity,
],
OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
},
2: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
INPUT_CLUSTERS: [
TuyaMmwRadarMinRange,
],
OUTPUT_CLUSTERS: [],
},
3: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
INPUT_CLUSTERS: [
TuyaMmwRadarMaxRange,
],
OUTPUT_CLUSTERS: [],
},
4: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
INPUT_CLUSTERS: [
TuyaMmwRadarDetectionDelay,
],
OUTPUT_CLUSTERS: [],
},
5: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.COMBINED_INTERFACE,
INPUT_CLUSTERS: [
TuyaMmwRadarFadingTime,
],
OUTPUT_CLUSTERS: [],
},
242: {
PROFILE_ID: zgp.PROFILE_ID,
DEVICE_TYPE: zgp.DeviceType.PROXY_BASIC,
INPUT_CLUSTERS: [],
OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
},
}
}
Thank you for this @nnae06 . Tried to copy paste this into a new customised quirk, and then reinstalled the device. It still insists on picking up the original zhaquirks.tuya.ts0601_motion.MmwRadarMotionGPP instead of the customised one. Can anybody help explaining how I make the custom quirk override the default one? Any specific file naming convention to be followed? The hardware specs correspond to what is in the customised quirk so this should not be the issue. And all my other customised device quirks work well.
I will post a finished file later in the day. Maybe can help.
ts0601_radar.zip Added support for TS0601 by _TZE204_sbyx0lm6. Occupancy and Lux but no relay.
Attempted to update latest quirk with the full DP's from zigbee2mqtt herdsmen (link)
More experimenting is required as I don't fully understand quirks, but posting this as it might help someone else.
tuyaDatapoints: [
[1, 'presence', tuya.valueConverter.trueFalse1],
[2, 'radar_sensitivity', tuya.valueConverter.raw],
[3, 'shield_range', tuya.valueConverter.divideBy100],
[4, 'detection_range', tuya.valueConverter.divideBy100],
[6, 'equipment_status', tuya.valueConverter.raw],
[9, 'target_distance', tuya.valueConverter.divideBy100],
[101, 'entry_filter_time', tuya.valueConverter.divideBy10],
[102, 'departure_delay', tuya.valueConverter.raw],
[103, 'cline', tuya.valueConverter.raw],
[104, 'illuminance_lux', tuya.valueConverter.divideBy10],
[105, 'entry_sensitivity', tuya.valueConverter.raw],
[106, 'entry_distance_indentation', tuya.valueConverter.divideBy100],
[107, 'breaker_mode', tuya.valueConverterBasic.lookup({'standard': tuya.enum(0), 'local': tuya.enum(1)})],
[108, 'breaker_status', tuya.valueConverterBasic.lookup({'OFF': tuya.enum(0), 'ON': tuya.enum(1)})],
[109, 'status_indication', tuya.valueConverterBasic.lookup({'OFF': tuya.enum(0), 'ON': tuya.enum(1)})],
[110, 'illuminance_threshold', tuya.valueConverter.divideBy10],
[111, 'breaker_polarity', tuya.valueConverterBasic.lookup({'NC': tuya.enum(0), 'NO': tuya.enum(1)})],
[112, 'block_time', tuya.valueConverter.divideBy10],
[113, 'parameter_setting_result', tuya.valueConverter.raw],
[114, 'factory_parameters', tuya.valueConverter.raw],
[115, 'sensor', tuya.valueConverterBasic.lookup({
'on': tuya.enum(0), 'off': tuya.enum(1), 'occupied': tuya.enum(2), 'unoccupied': tuya.enum(3)})],
[116, 'distance_report', tuya.valueConverterBasic.lookup({
'off': tuya.enum(0),
'on': tuya.enum(1)
Thanks a lot! Could you please add a TS0601 "_TZE204_iaeejhvf" to TuyaMmwRadarOccupancyVariant1GPP. I have added it locally and it show up as I would think it is supposed to by the quirk.
Looking forward to see if the breaker part of device can get solved as well. zha-10bd056a4de4cbece683ed97f85638a7-_TZE204_iaeejhvf TS0601-dac28b9c161b2bebc10f7ebf01608fb2.json
One more improvement suggestion (I would love to contribute more actively but have yet not passed the threshold of understanding the quirks and how to debug/try/error/improve).
Currently the number-sliders for the device settings show up as "Controls" in the device in Home Assistant, I think they would be better placed under "Configuration". The small benefit that I see of that is that they would then not show up in the default dashboard in Home Assistant. (You likely don't want to change those on a daily basis).
Yes, I can make them hidden to achieve the same so no major issue, but just a proposal :-)
Problem description
When adding to ZHA only device exists, no entities.
Solution description
Device is added with all related entities (sensor, switch). If possible add sensitivity controls.
Screenshots/Video
Screenshots/Video
![image](https://github.com/zigpy/zha-device-handlers/assets/52739692/1d5d8980-36d6-4a1b-8e0c-26707c44a7d3) ![PXL_20230704_132845009 – копія](https://github.com/zigpy/zha-device-handlers/assets/52739692/c90b5162-4668-442f-86d2-8979c6950455) ![PXL_20230704_132751715 – копія](https://github.com/zigpy/zha-device-handlers/assets/52739692/4a89b312-eaf7-4451-915a-437f1db39590) ![PXL_20230704_132816177 – копія](https://github.com/zigpy/zha-device-handlers/assets/52739692/8c63919d-8ea9-4562-9e66-a5fa712aab20) ![PXL_20230704_132827544 – копія](https://github.com/zigpy/zha-device-handlers/assets/52739692/6c36e044-db57-4401-b296-eb1c5a3badf6) ![PXL_20230704_132838648 – копія](https://github.com/zigpy/zha-device-handlers/assets/52739692/1d39b2b1-4a29-4b56-b648-2987297b833d)Device signature
Device signature
```json { "node_descriptor": "NodeDescriptor(logical_type=Diagnostic information
Diagnostic information
```json { "home_assistant": { "installation_type": "Home Assistant OS", "version": "2023.6.3", "dev": false, "hassio": true, "virtualenv": false, "python_version": "3.11.4", "docker": true, "arch": "x86_64", "timezone": "Europe/Kiev", "os_name": "Linux", "os_version": "6.1.34", "supervisor": "2023.06.4", "host_os": "Home Assistant OS 10.3", "docker_version": "23.0.6", "chassis": "vm", "run_as_root": true }, "custom_components": { "scheduler": { "version": "v0.0.0", "requirements": [] }, "hacs": { "version": "1.32.1", "requirements": [ "aiogithubapi>=22.10.1" ] } }, "integration_manifest": { "domain": "zha", "name": "Zigbee Home Automation", "after_dependencies": [ "onboarding", "usb" ], "codeowners": [ "@dmulcahey", "@adminiuga", "@puddly" ], "config_flow": true, "dependencies": [ "file_upload" ], "documentation": "https://www.home-assistant.io/integrations/zha", "iot_class": "local_polling", "loggers": [ "aiosqlite", "bellows", "crccheck", "pure_pcapy3", "zhaquirks", "zigpy", "zigpy_deconz", "zigpy_xbee", "zigpy_zigate", "zigpy_znp" ], "requirements": [ "bellows==0.35.5", "pyserial==3.5", "pyserial-asyncio==0.6", "zha-quirks==0.0.100", "zigpy-deconz==0.21.0", "zigpy==0.55.0", "zigpy-xbee==0.18.0", "zigpy-zigate==0.11.0", "zigpy-znp==0.11.1" ], "usb": [ { "vid": "10C4", "pid": "EA60", "description": "*2652*", "known_devices": [ "slae.sh cc2652rb stick" ] }, { "vid": "1A86", "pid": "55D4", "description": "*sonoff*plus*", "known_devices": [ "sonoff zigbee dongle plus v2" ] }, { "vid": "10C4", "pid": "EA60", "description": "*sonoff*plus*", "known_devices": [ "sonoff zigbee dongle plus" ] }, { "vid": "10C4", "pid": "EA60", "description": "*tubeszb*", "known_devices": [ "TubesZB Coordinator" ] }, { "vid": "1A86", "pid": "7523", "description": "*tubeszb*", "known_devices": [ "TubesZB Coordinator" ] }, { "vid": "1A86", "pid": "7523", "description": "*zigstar*", "known_devices": [ "ZigStar Coordinators" ] }, { "vid": "1CF1", "pid": "0030", "description": "*conbee*", "known_devices": [ "Conbee II" ] }, { "vid": "10C4", "pid": "8A2A", "description": "*zigbee*", "known_devices": [ "Nortek HUSBZB-1" ] }, { "vid": "0403", "pid": "6015", "description": "*zigate*", "known_devices": [ "ZiGate+" ] }, { "vid": "10C4", "pid": "EA60", "description": "*zigate*", "known_devices": [ "ZiGate" ] }, { "vid": "10C4", "pid": "8B34", "description": "*bv 2010/10*", "known_devices": [ "Bitron Video AV2010/10" ] } ], "zeroconf": [ { "type": "_esphomelib._tcp.local.", "name": "tube*" }, { "type": "_zigate-zigbee-gateway._tcp.local.", "name": "*zigate*" }, { "type": "_zigstar_gw._tcp.local.", "name": "*zigstar*" }, { "type": "_slzb-06._tcp.local.", "name": "slzb-06*" } ], "is_built_in": true }, "data": { "ieee": "**REDACTED**", "nwk": 20130, "manufacturer": "_TZE204_dtzziy1e", "model": "TS0601", "name": "_TZE204_dtzziy1e TS0601", "quirk_applied": false, "quirk_class": "zigpy.device.Device", "manufacturer_code": 4098, "power_source": "Mains", "lqi": 120, "rssi": -70, "last_seen": "2023-07-04T17:06:49", "available": true, "device_type": "Router", "signature": { "node_descriptor": "NodeDescriptor(logical_type=Logs
Logs
```python Logger: zigpy.zcl Source: runner.py:179 First occurred: 4:33:38 PM (126 occurrences) Last logged: 4:54:38 PM [0x4EA2:1:0xef00] Unknown cluster command 2 b'\x00G\t\x02\x00\x04\x00\x00\x00\x00' [0x4EA2:1:0xef00] Unknown cluster command 2 b'\x00H\x01\x04\x00\x01\x01' [0x4EA2:1:0xef00] Unknown cluster command 2 b'\x00I\t\x02\x00\x04\x00\x00\x01o' [0x4EA2:1:0xef00] Unknown cluster command 2 b'\x00J\t\x02\x00\x04\x00\x00\x00\x00' [0x4EA2:1:0xef00] Unknown cluster command 2 b'\x00K\x01\x04\x00\x01\x00' ```Additional information
Successfully loaded a custom ts0601_motion.py quirk (with additional MODELS INFO in MmwRadarMotion(CustomDevice) class) but it exposes only one binary sensor and relay isn't clicking when detected/clear.
Also as you can see on the board photo it has a IR led. Why is it there? Would it be possible to use it?