Skip to content

Commit 8e38cd9

Browse files
Convert Tuya motion quirks to v2, add _TZE200_ya4ft0w4 (#3612)
Co-authored-by: TheJulianJES <[email protected]>
1 parent d116e37 commit 8e38cd9

File tree

3 files changed

+227
-504
lines changed

3 files changed

+227
-504
lines changed

tests/test_tuya.py

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
"""Tests for Tuya quirks."""
22

3-
import asyncio
43
import base64
54
import datetime
65
import struct
@@ -26,7 +25,6 @@
2625
ON,
2726
OUTPUT_CLUSTERS,
2827
PROFILE_ID,
29-
ZONE_STATUS_CHANGE_COMMAND,
3028
)
3129
from zhaquirks.tuya import Data, TuyaManufClusterAttributes, TuyaNewManufCluster
3230
import zhaquirks.tuya.sm0202_motion
@@ -54,7 +52,6 @@
5452
ZCL_TUYA_BUTTON_2_SINGLE_PRESS = b"\tN\x06\x01\x1f\x02\x04\x00\x01\x00"
5553
ZCL_TUYA_BUTTON_2_DOUBLE_PRESS = b"\tj\x06\x03\x10\x02\x04\x00\x01\x01"
5654
ZCL_TUYA_BUTTON_2_LONG_PRESS = b"\tl\x06\x03\x12\x02\x04\x00\x01\x02"
57-
ZCL_TUYA_MOTION = b"\tL\x01\x00\x05\x03\x04\x00\x01\x02"
5855
ZCL_TUYA_SWITCH_ON = b"\tQ\x02\x006\x01\x01\x00\x01\x01"
5956
ZCL_TUYA_SWITCH_OFF = b"\tQ\x02\x006\x01\x01\x00\x01\x00"
6057
ZCL_TUYA_ATTRIBUTE_617_TO_179 = b"\tp\x02\x00\x02i\x02\x00\x04\x00\x00\x00\xb3"
@@ -100,33 +97,6 @@
10097
ZCL_TUYA_EHEAT_TARGET_TEMP = b"\t3\x01\x03\x05\x10\x02\x00\x04\x00\x00\x00\x15"
10198

10299

103-
@pytest.mark.parametrize("quirk", (zhaquirks.tuya.ts0601_motion.TuyaMotion,))
104-
async def test_motion(zigpy_device_from_quirk, quirk):
105-
"""Test tuya motion sensor."""
106-
107-
motion_dev = zigpy_device_from_quirk(quirk)
108-
109-
motion_cluster = motion_dev.endpoints[1].ias_zone
110-
motion_listener = ClusterListener(motion_cluster)
111-
112-
tuya_cluster = motion_dev.endpoints[1].tuya_manufacturer
113-
114-
# send motion on Tuya manufacturer specific cluster
115-
hdr, args = tuya_cluster.deserialize(ZCL_TUYA_MOTION)
116-
with mock.patch.object(motion_cluster, "reset_s", 0):
117-
tuya_cluster.handle_message(hdr, args)
118-
119-
assert len(motion_listener.cluster_commands) == 1
120-
assert motion_listener.cluster_commands[0][1] == ZONE_STATUS_CHANGE_COMMAND
121-
assert motion_listener.cluster_commands[0][2][0] == ON
122-
123-
await asyncio.gather(asyncio.sleep(0), asyncio.sleep(0), asyncio.sleep(0))
124-
125-
assert len(motion_listener.cluster_commands) == 2
126-
assert motion_listener.cluster_commands[1][1] == ZONE_STATUS_CHANGE_COMMAND
127-
assert motion_listener.cluster_commands[1][2][0] == OFF
128-
129-
130100
@pytest.mark.parametrize("quirk", (zhaquirks.tuya.ts0601_switch.TuyaSingleSwitchTI,))
131101
async def test_singleswitch_state_report(zigpy_device_from_quirk, quirk):
132102
"""Test tuya single switch."""
@@ -1628,25 +1598,6 @@ def test_ts0601_valve_signature(assert_signature_matches_quirk):
16281598
assert_signature_matches_quirk(zhaquirks.tuya.ts0601_valve.TuyaValve, signature)
16291599

16301600

1631-
def test_ts0601_motion_signature(assert_signature_matches_quirk):
1632-
"""Test TS0601 motion by TreatLife remote signature is matched to its quirk."""
1633-
signature = {
1634-
"node_descriptor": "NodeDescriptor(logical_type=<LogicalType.EndDevice: 2>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress: 128>, manufacturer_code=4417, maximum_buffer_size=66, maximum_incoming_transfer_size=66, server_mask=10752, maximum_outgoing_transfer_size=66, descriptor_capability_field=<DescriptorCapability.NONE: 0>, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=True, *is_full_function_device=False, *is_mains_powered=False, *is_receiver_on_when_idle=False, *is_router=False, *is_security_capable=False)",
1635-
"endpoints": {
1636-
"1": {
1637-
"profile_id": 260,
1638-
"device_type": "0x0051",
1639-
"in_clusters": ["0x0000", "0x0004", "0x0005", "0xef00"],
1640-
"out_clusters": ["0x000a", "0x0019"],
1641-
}
1642-
},
1643-
"manufacturer": "_TZE200_ppuj1vem",
1644-
"model": "TS0601",
1645-
"class": "zigpy.device.Device",
1646-
}
1647-
assert_signature_matches_quirk(zhaquirks.tuya.ts0601_motion.NeoMotion, signature)
1648-
1649-
16501601
def test_multiple_attributes_report():
16511602
"""Test a multi attribute report from Tuya device."""
16521603

tests/test_tuya_motion.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
"""Tests for Tuya quirks."""
2+
3+
import pytest
4+
from zigpy.zcl import foundation
5+
from zigpy.zcl.clusters.measurement import OccupancySensing
6+
7+
from tests.common import ClusterListener
8+
import zhaquirks
9+
import zhaquirks.tuya
10+
from zhaquirks.tuya.mcu import TuyaMCUCluster
11+
12+
ZCL_TUYA_MOTION = b"\tL\x01\x00\x05\x01\x01\x00\x01\x01" # DP 1
13+
ZCL_TUYA_MOTION_V2 = b"\tL\x01\x00\x05\x65\x01\x00\x01\x01" # DP 101
14+
ZCL_TUYA_MOTION_V3 = b"\tL\x01\x00\x05\x03\x04\x00\x01\x02" # DP 3, enum
15+
16+
17+
zhaquirks.setup()
18+
19+
20+
@pytest.mark.parametrize(
21+
"model,manuf,occ_msg",
22+
[
23+
("_TZE200_ya4ft0w4", "TS0601", ZCL_TUYA_MOTION),
24+
("_TZE200_7hfcudw5", "TS0601", ZCL_TUYA_MOTION_V2),
25+
("_TZE200_ppuj1vem", "TS0601", ZCL_TUYA_MOTION_V2),
26+
("_TZE200_ar0slwnd", "TS0601", ZCL_TUYA_MOTION),
27+
("_TZE200_mrf6vtua", "TS0601", ZCL_TUYA_MOTION),
28+
("_TZE200_sfiy5tfs", "TS0601", ZCL_TUYA_MOTION),
29+
("_TZE204_sooucan5", "TS0601", ZCL_TUYA_MOTION),
30+
("_TZE200_wukb7rhc", "TS0601", ZCL_TUYA_MOTION),
31+
("_TZE204_qasjif9e", "TS0601", ZCL_TUYA_MOTION),
32+
("_TZE200_ztc6ggyl", "TS0601", ZCL_TUYA_MOTION),
33+
("_TZE204_ztc6ggyl", "TS0601", ZCL_TUYA_MOTION),
34+
("_TZE204_ztqnh5cg", "TS0601", ZCL_TUYA_MOTION),
35+
("_TYST11_i5j6ifxj", "5j6ifxj", ZCL_TUYA_MOTION_V3),
36+
("_TYST11_7hfcudw5", "hfcudw5", ZCL_TUYA_MOTION_V3),
37+
],
38+
)
39+
async def test_tuya_motion_quirk(zigpy_device_from_v2_quirk, model, manuf, occ_msg):
40+
"""Test Tuya Motion Quirks."""
41+
quirked_device = zigpy_device_from_v2_quirk(model, manuf)
42+
ep = quirked_device.endpoints[1]
43+
44+
assert ep.tuya_manufacturer is not None
45+
assert isinstance(ep.tuya_manufacturer, TuyaMCUCluster)
46+
47+
assert ep.occupancy is not None
48+
assert isinstance(ep.occupancy, OccupancySensing)
49+
50+
occupancy_listener = ClusterListener(ep.occupancy)
51+
52+
hdr, data = ep.tuya_manufacturer.deserialize(occ_msg)
53+
status = ep.tuya_manufacturer.handle_get_data(data.data)
54+
55+
assert status == foundation.Status.SUCCESS
56+
57+
zcl_occupancy_id = OccupancySensing.AttributeDefs.occupancy.id
58+
59+
assert len(occupancy_listener.attribute_updates) == 1
60+
assert occupancy_listener.attribute_updates[0][0] == zcl_occupancy_id
61+
assert (
62+
occupancy_listener.attribute_updates[0][1]
63+
== OccupancySensing.Occupancy.Occupied
64+
)

0 commit comments

Comments
 (0)