diff --git a/tests/test_tuya_dimmer.py b/tests/test_tuya_dimmer.py index 7b341d1292..1392ab75e5 100644 --- a/tests/test_tuya_dimmer.py +++ b/tests/test_tuya_dimmer.py @@ -297,3 +297,109 @@ async def test_doubledimmer_state_report(zigpy_device_from_quirk, quirk): assert len(dimmer2_listener.attribute_updates) == 2 assert dimmer2_listener.attribute_updates[1][0] == 0x0000 assert dimmer2_listener.attribute_updates[1][1] == 170 + + +@pytest.mark.parametrize( + "quirk", (zhaquirks.tuya.ts0601_dimmer.TuyaTripleSwitchDimmer,) +) +async def test_triple_command(zigpy_device_from_quirk, quirk): + """Test write cluster attributes for triple switch dimmer.""" + + dimmer_dev = zigpy_device_from_quirk(quirk) + tuya_cluster = dimmer_dev.endpoints[1].tuya_manufacturer + dimmer1_cluster = dimmer_dev.endpoints[1].level + switch2_cluster = dimmer_dev.endpoints[2].on_off + switch3_cluster = dimmer_dev.endpoints[3].on_off + tuya_listener = ClusterListener(tuya_cluster) + + assert len(tuya_listener.cluster_commands) == 0 + assert len(tuya_listener.attribute_updates) == 0 + + with mock.patch.object( + tuya_cluster.endpoint, "request", return_value=foundation.Status.SUCCESS + ) as m1: + rsp = await switch2_cluster.command(0x0001) # turn_on + await wait_for_zigpy_tasks() + + m1.assert_called_with( + cluster=61184, + sequence=1, + data=b"\x01\x01\x00\x00\x01\x07\x01\x00\x01\x01", + command_id=0, + timeout=5, + expect_reply=True, + use_ieee=False, + ask_for_ack=None, + priority=None, + ) + assert rsp.status == foundation.Status.SUCCESS + + rsp = await switch3_cluster.command(0x0001) # turn_on + await wait_for_zigpy_tasks() + + m1.assert_called_with( + cluster=61184, + sequence=2, + data=b"\x01\x02\x00\x00\x02\x0f\x01\x00\x01\x01", + command_id=0, + timeout=5, + expect_reply=True, + use_ieee=False, + ask_for_ack=None, + priority=None, + ) + assert rsp.status == foundation.Status.SUCCESS + + rsp = await dimmer1_cluster.command(0x0000, 225) # move_to_level + await wait_for_zigpy_tasks() + + m1.assert_called_with( + cluster=61184, + sequence=3, + data=b"\x01\x03\x00\x00\x03\x02\x02\x00\x04\x00\x00\x03r", + command_id=0, + timeout=5, + expect_reply=True, + use_ieee=False, + ask_for_ack=None, + priority=None, + ) + assert rsp.status == foundation.Status.SUCCESS + + +@pytest.mark.parametrize( + "quirk", (zhaquirks.tuya.ts0601_dimmer.TuyaTripleSwitchDimmer,) +) +async def test_triple_dim_values(zigpy_device_from_quirk, quirk): + """Test dimming values for triple switch dimmer.""" + + dimmer_dev = zigpy_device_from_quirk(quirk) + + dimmer2_cluster = dimmer_dev.endpoints[2].level + dimmer2_listener = ClusterListener(dimmer2_cluster) + + dimmer3_cluster = dimmer_dev.endpoints[3].level + dimmer3_listener = ClusterListener(dimmer3_cluster) + + tuya_cluster = dimmer_dev.endpoints[1].tuya_manufacturer + + assert len(dimmer2_listener.attribute_updates) == 0 + assert len(dimmer3_listener.attribute_updates) == 0 + + # Test channel 2 dimming + hdr, args = tuya_cluster.deserialize( + b"\tV\x02\x01y\x08\x02\x00\x04\x00\x00\x02\x29" + ) + tuya_cluster.handle_message(hdr, args) + assert len(dimmer2_listener.attribute_updates) == 1 + assert dimmer2_listener.attribute_updates[0][0] == 0x0000 + assert dimmer2_listener.attribute_updates[0][1] == 141 + + # Test channel 3 dimming + hdr, args = tuya_cluster.deserialize( + b"\tV\x02\x01y\x10\x02\x00\x04\x00\x00\x02\xbc" + ) + tuya_cluster.handle_message(hdr, args) + assert len(dimmer3_listener.attribute_updates) == 1 + assert dimmer3_listener.attribute_updates[0][0] == 0x0000 + assert dimmer3_listener.attribute_updates[0][1] == 178 diff --git a/zhaquirks/tuya/ts0601_dimmer.py b/zhaquirks/tuya/ts0601_dimmer.py index eefd78905c..892b5f128c 100644 --- a/zhaquirks/tuya/ts0601_dimmer.py +++ b/zhaquirks/tuya/ts0601_dimmer.py @@ -27,6 +27,7 @@ class TuyaInWallLevelControlNM(NoManufacturerCluster, TuyaInWallLevelControl): # --- DEVICE SUMMARY --- # TuyaSingleSwitchDimmer: 0x00, 0x04, 0x05, 0xEF00; 0x000A, 0x0019 # TuyaDoubleSwitchDimmer: 0x00, 0x04, 0x05, 0xEF00; 0x000A, 0x0019 +# TuyaTripleSwitchDimmer: 0x00, 0x04, 0x05, 0xEF00; 0x000A, 0x0019 # - Dimmer with Green Power Proxy: Endpoint=242 profile=41440 device_type=0x0061, output_clusters: 0x0021 - # TuyaSingleSwitchDimmerGP: 0x00, 0x04, 0x05, 0xEF00; 0x000A, 0x0019 # TuyaDoubleSwitchDimmerGP: 0x00, 0x04, 0x05, 0xEF00; 0x000A, 0x0019 @@ -144,6 +145,68 @@ class TuyaDoubleSwitchDimmer(TuyaDimmerSwitch): } +class TuyaTripleSwitchDimmer(TuyaDimmerSwitch): + """Tuya triple-channel dimmer (TS0601, Zemismart/Moes), non-GP.""" + + signature = { + MODELS_INFO: [ + ("_TZE204_znvwzxkq", "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, + TuyaLevelControlManufCluster.cluster_id, + ], + OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], + }, + }, + } + + replacement = { + ENDPOINTS: { + 1: { + DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, + INPUT_CLUSTERS: [ + Basic.cluster_id, + Groups.cluster_id, + Scenes.cluster_id, + TuyaLevelControlManufCluster, + TuyaOnOff, + TuyaInWallLevelControl, + ], + OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], + }, + 2: { + PROFILE_ID: zha.PROFILE_ID, + DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, + INPUT_CLUSTERS: [ + TuyaOnOff, + TuyaInWallLevelControl, + ], + OUTPUT_CLUSTERS: [], + }, + 3: { + PROFILE_ID: zha.PROFILE_ID, + DEVICE_TYPE: zha.DeviceType.ON_OFF_LIGHT, + INPUT_CLUSTERS: [ + TuyaOnOff, + TuyaInWallLevelControl, + ], + OUTPUT_CLUSTERS: [], + }, + } + } + + class TuyaSingleSwitchDimmerGP(TuyaDimmerSwitch): """Tuya touch switch device."""