1
1
"""Tests for TuyaQuirkBuilder."""
2
2
3
+ import datetime
3
4
from unittest import mock
4
5
5
6
import pytest
9
10
from zigpy .zcl import foundation
10
11
from zigpy .zcl .clusters .general import Basic , BatterySize
11
12
12
- from tests .common import ClusterListener , wait_for_zigpy_tasks
13
+ from tests .common import ClusterListener , MockDatetime , wait_for_zigpy_tasks
13
14
import zhaquirks
14
15
from zhaquirks .tuya import (
15
16
TUYA_QUERY_DATA ,
17
+ TUYA_SET_TIME ,
16
18
TuyaPowerConfigurationCluster ,
17
19
TuyaPowerConfigurationCluster2AAA ,
18
20
)
23
25
TuyaIasContact ,
24
26
TuyaIasFire ,
25
27
TuyaIasGas ,
28
+ TuyaIlluminance ,
26
29
TuyaPM25Concentration ,
27
30
TuyaQuirkBuilder ,
28
31
TuyaRelativeHumidity ,
29
32
TuyaSoilMoisture ,
30
33
TuyaTemperatureMeasurement ,
31
- TuyaValveWaterConsumed ,
34
+ TuyaValveWaterConsumedNoInstDemand ,
32
35
)
33
36
from zhaquirks .tuya .mcu import TuyaMCUCluster , TuyaOnOffNM
37
+ from zhaquirks .tuya .tuya_sensor import NoManufTimeTuyaMCUCluster
38
+
39
+ ZCL_TUYA_SET_TIME = b"\x09 \x12 \x24 \x0d \x00 "
34
40
35
41
zhaquirks .setup ()
36
42
39
45
"method_name,attr_name,exp_class" ,
40
46
[
41
47
("tuya_battery" , "power" , TuyaPowerConfigurationCluster ),
42
- ("tuya_metering" , "smartenergy_metering" , TuyaValveWaterConsumed ),
48
+ ("tuya_metering" , "smartenergy_metering" , TuyaValveWaterConsumedNoInstDemand ),
43
49
("tuya_onoff" , "on_off" , TuyaOnOffNM ),
44
50
("tuya_soil_moisture" , "soil_moisture" , TuyaSoilMoisture ),
45
51
("tuya_temperature" , "temperature" , TuyaTemperatureMeasurement ),
55
61
TuyaFormaldehydeConcentration ,
56
62
),
57
63
("tuya_gas" , "ias_zone" , TuyaIasGas ),
64
+ ("tuya_illuminance" , "illuminance" , TuyaIlluminance ),
58
65
],
59
66
)
60
67
async def test_convenience_methods (device_mock , method_name , attr_name , exp_class ):
@@ -140,6 +147,9 @@ class TestEnum(t.enum8):
140
147
A = 0x00
141
148
B = 0x01
142
149
150
+ class ModTuyaMCUCluster (TuyaMCUCluster ):
151
+ """Modified Cluster."""
152
+
143
153
entry = (
144
154
TuyaQuirkBuilder (device_mock .manufacturer , device_mock .model , registry = registry )
145
155
.tuya_battery (dp_id = 1 )
@@ -178,7 +188,7 @@ class TestEnum(t.enum8):
178
188
fallback_name = "Test enum" ,
179
189
)
180
190
.skip_configuration ()
181
- .add_to_registry ()
191
+ .add_to_registry (replacement_cluster = ModTuyaMCUCluster )
182
192
)
183
193
184
194
# coverage for overridden __eq__ method
@@ -195,6 +205,7 @@ class TestEnum(t.enum8):
195
205
assert isinstance (ep .basic , Basic )
196
206
197
207
assert ep .tuya_manufacturer is not None
208
+ assert isinstance (ep .tuya_manufacturer , ModTuyaMCUCluster )
198
209
assert isinstance (ep .tuya_manufacturer , TuyaMCUCluster )
199
210
200
211
tuya_cluster = ep .tuya_manufacturer
@@ -303,3 +314,49 @@ async def test_tuya_spell(device_mock, read_attr_spell, data_query_spell):
303
314
messages += 1
304
315
305
316
request_mock .reset_mock ()
317
+
318
+
319
+ async def test_tuya_mcu_set_time (device_mock ):
320
+ """Test TuyaQuirkBuilder replacement cluster, set_time requests (0x24) messages for MCU devices."""
321
+
322
+ registry = DeviceRegistry ()
323
+
324
+ (
325
+ TuyaQuirkBuilder (device_mock .manufacturer , device_mock .model , registry = registry )
326
+ .tuya_battery (dp_id = 1 )
327
+ .skip_configuration ()
328
+ .add_to_registry (replacement_cluster = NoManufTimeTuyaMCUCluster )
329
+ )
330
+
331
+ quirked = registry .get_device (device_mock )
332
+ assert isinstance (quirked , CustomDeviceV2 )
333
+ assert quirked in registry
334
+
335
+ ep = quirked .endpoints [1 ]
336
+
337
+ assert not ep .tuya_manufacturer ._is_manuf_specific
338
+ assert not ep .tuya_manufacturer .server_commands [
339
+ TUYA_SET_TIME
340
+ ].is_manufacturer_specific
341
+
342
+ # Mock datetime
343
+ origdatetime = datetime .datetime
344
+ datetime .datetime = MockDatetime
345
+
346
+ # simulate a SET_TIME message
347
+ hdr , args = ep .tuya_manufacturer .deserialize (ZCL_TUYA_SET_TIME )
348
+ assert hdr .command_id == TUYA_SET_TIME
349
+
350
+ with mock .patch .object (
351
+ ep .tuya_manufacturer ._endpoint ,
352
+ "request" ,
353
+ return_value = foundation .Status .SUCCESS ,
354
+ ) as m1 :
355
+ ep .tuya_manufacturer .handle_message (hdr , args )
356
+ await wait_for_zigpy_tasks ()
357
+
358
+ res_hdr = foundation .ZCLHeader .deserialize (m1 .await_args [1 ]["data" ])
359
+ assert not res_hdr [0 ].manufacturer
360
+ assert not res_hdr [0 ].frame_control .is_manufacturer_specific
361
+
362
+ datetime .datetime = origdatetime # restore datetime
0 commit comments