async def test_report_values_psbzs(zigpy_device_from_quirk, quirk): """Test receiving attributes from PARKSIDE water valve.""" water_valve_dev = zigpy_device_from_quirk(quirk) tuya_cluster = water_valve_dev.endpoints[1].tuya_manufacturer tuya_listener = ClusterListener(tuya_cluster) assert len(tuya_listener.cluster_commands) == 0 assert len(tuya_listener.attribute_updates) == 0 frames = ( b"\x09\x5D\x02\x00\x4C\x06\x02\x00\x04\x00\x00\x00\x04", # time left 4min b"\x09\x5D\x02\x00\x4C\x06\x02\x00\x04\x00\x00\x02\x57", # time left max 599min b"\x09\x56\x02\x00\x21\x6C\x01\x00\x01\x01", # frost lock active b"\x09\x56\x02\x00\x21\x6C\x01\x00\x01\x00", # frost lock inactive ) for frame in frames: hdr, args = tuya_cluster.deserialize(frame) tuya_cluster.handle_message(hdr, args) assert len(tuya_listener.attribute_updates) == 4 assert tuya_listener.attribute_updates[0][0] == 0xEF12 assert tuya_listener.attribute_updates[0][1] == 4 assert tuya_listener.attribute_updates[1][0] == 0xEF12 assert tuya_listener.attribute_updates[1][1] == 599 assert tuya_listener.attribute_updates[2][0] == 0xEF13 assert tuya_listener.attribute_updates[2][1] == 0 # frost lock state is inverted assert tuya_listener.attribute_updates[3][0] == 0xEF13 assert tuya_listener.attribute_updates[3][1] == 1 # frost lock state is inverted
async def test_motion(zigpy_device_from_quirk, quirk): """Test tuya motion sensor.""" motion_dev = zigpy_device_from_quirk(quirk) motion_cluster = motion_dev.endpoints[1].ias_zone motion_listener = ClusterListener(motion_cluster) tuya_cluster = motion_dev.endpoints[1].tuya_manufacturer # send motion on Tuya manufacturer specific cluster hdr, args = tuya_cluster.deserialize(ZCL_TUYA_MOTION) with mock.patch.object(motion_cluster, "reset_s", 0): tuya_cluster.handle_message(hdr, args) assert len(motion_listener.cluster_commands) == 1 assert len(motion_listener.attribute_updates) == 1 assert motion_listener.cluster_commands[0][1] == ZONE_STATE assert motion_listener.cluster_commands[0][2][0] == ON await asyncio.gather(asyncio.sleep(0), asyncio.sleep(0), asyncio.sleep(0)) assert len(motion_listener.cluster_commands) == 2 assert motion_listener.cluster_commands[1][1] == ZONE_STATE assert motion_listener.cluster_commands[1][2][0] == OFF
async def test_tuya_receive_attribute(zigpy_device_from_quirk, quirk): """Test conversion of tuya commands to attributes.""" test_dev = zigpy_device_from_quirk(quirk) tuya_cluster = test_dev.endpoints[1].tuya_manufacturer listener = ClusterListener(tuya_cluster) hdr, args = tuya_cluster.deserialize(ZCL_TUYA_ATTRIBUTE_617_TO_179) tuya_cluster.handle_message(hdr, args) assert len(listener.attribute_updates) == 1 assert listener.attribute_updates[0][0] == 617 assert listener.attribute_updates[0][1] == 179
async def test_konke_motion(zigpy_device_from_quirk, quirk): """Test konke motion sensor.""" motion_dev = zigpy_device_from_quirk(quirk) motion_cluster = motion_dev.endpoints[1].ias_zone motion_listener = ClusterListener(motion_cluster) occupancy_cluster = motion_dev.endpoints[1].occupancy occupancy_listener = ClusterListener(occupancy_cluster) p1 = mock.patch.object(motion_cluster, "reset_s", 0) p2 = mock.patch.object(occupancy_cluster, "reset_s", 0) # send motion on IAS zone command hdr, args = motion_cluster.deserialize(ZCL_IAS_MOTION_COMMAND) with p1, p2: motion_cluster.handle_message(hdr, args) assert len(motion_listener.cluster_commands) == 1 assert len(motion_listener.attribute_updates) == 0 assert motion_listener.cluster_commands[0][1] == ZONE_STATE assert motion_listener.cluster_commands[0][2][0] == ON assert len(occupancy_listener.cluster_commands) == 0 assert len(occupancy_listener.attribute_updates) == 1 assert occupancy_listener.attribute_updates[0][0] == 0x0000 assert occupancy_listener.attribute_updates[0][1] == 1 await asyncio.sleep(0.1) assert len(motion_listener.cluster_commands) == 2 assert motion_listener.cluster_commands[1][1] == ZONE_STATE assert motion_listener.cluster_commands[1][2][0] == OFF assert len(occupancy_listener.cluster_commands) == 0 assert len(occupancy_listener.attribute_updates) == 2 assert occupancy_listener.attribute_updates[1][0] == 0x0000 assert occupancy_listener.attribute_updates[1][1] == 0
async def test_siren_state_report(zigpy_device_from_quirk, quirk): """Test tuya siren standard state reporting from incoming commands.""" siren_dev = zigpy_device_from_quirk(quirk) tuya_cluster = siren_dev.endpoints[1].tuya_manufacturer temp_listener = ClusterListener(siren_dev.endpoints[1].temperature) humid_listener = ClusterListener(siren_dev.endpoints[1].humidity) switch_listener = ClusterListener(siren_dev.endpoints[1].on_off) frames = ( ZCL_TUYA_SIREN_TEMPERATURE, ZCL_TUYA_SIREN_HUMIDITY, ZCL_TUYA_SIREN_ON, ZCL_TUYA_SIREN_OFF, ) for frame in frames: hdr, args = tuya_cluster.deserialize(frame) tuya_cluster.handle_message(hdr, args) assert len(temp_listener.cluster_commands) == 0 assert len(temp_listener.attribute_updates) == 1 assert temp_listener.attribute_updates[0][0] == 0x0000 assert temp_listener.attribute_updates[0][1] == 1790 assert len(humid_listener.cluster_commands) == 0 assert len(humid_listener.attribute_updates) == 1 assert humid_listener.attribute_updates[0][0] == 0x0000 assert humid_listener.attribute_updates[0][1] == 8500 assert len(switch_listener.cluster_commands) == 0 assert len(switch_listener.attribute_updates) == 2 assert switch_listener.attribute_updates[0][0] == 0x0000 assert switch_listener.attribute_updates[0][1] == ON assert switch_listener.attribute_updates[1][0] == 0x0000 assert switch_listener.attribute_updates[1][1] == OFF
async def test_doubledimmer_state_report(zigpy_device_from_quirk, quirk): """Test tuya double switch.""" TUYA_EP2_DIMM_1 = b"\tV\x02\x01y\x08\x02\x00\x04\x00\x00\x02\xc5" TUYA_EP2_DIMM_2 = b"\tW\x02\x01z\x08\x02\x00\x04\x00\x00\x02\x9e" dimmer_dev = zigpy_device_from_quirk(quirk) dimmer1_cluster = dimmer_dev.endpoints[1].level dimmer1_listener = ClusterListener(dimmer1_cluster) dimmer2_cluster = dimmer_dev.endpoints[2].level dimmer2_listener = ClusterListener(dimmer2_cluster) tuya_cluster = dimmer_dev.endpoints[1].tuya_manufacturer assert len(dimmer1_listener.cluster_commands) == 0 assert len(dimmer1_listener.attribute_updates) == 0 assert len(dimmer2_listener.cluster_commands) == 0 assert len(dimmer2_listener.attribute_updates) == 0 # events from channel 2 updates only EP 2 hdr, args = tuya_cluster.deserialize(TUYA_EP2_DIMM_1) tuya_cluster.handle_message(hdr, args) assert len(dimmer1_listener.attribute_updates) == 0 assert len(dimmer2_listener.attribute_updates) == 1 assert dimmer2_listener.attribute_updates[0][0] == 0x0000 assert dimmer2_listener.attribute_updates[0][1] == 180 # events from channel 1 updates only EP 1 hdr, args = tuya_cluster.deserialize(TUYA_EP2_DIMM_2) tuya_cluster.handle_message(hdr, args) assert len(dimmer1_listener.attribute_updates) == 0 assert len(dimmer2_listener.attribute_updates) == 2 assert dimmer2_listener.attribute_updates[1][0] == 0x0000 assert dimmer2_listener.attribute_updates[1][1] == 170
async def test_valve_state_report(zigpy_device_from_quirk, quirk): """Test thermostatic valves standard reporting from incoming commands.""" valve_dev = zigpy_device_from_quirk(quirk) tuya_cluster = valve_dev.endpoints[1].tuya_manufacturer thermostat_listener = ClusterListener(valve_dev.endpoints[1].thermostat) frames = ( ZCL_TUYA_VALVE_TEMPERATURE, ZCL_TUYA_VALVE_TARGET_TEMP, ZCL_TUYA_VALVE_OFF, ZCL_TUYA_VALVE_SCHEDULE, ZCL_TUYA_VALVE_MANUAL, ) for frame in frames: hdr, args = tuya_cluster.deserialize(frame) tuya_cluster.handle_message(hdr, args) assert len(thermostat_listener.cluster_commands) == 0 assert len(thermostat_listener.attribute_updates) == 13 assert thermostat_listener.attribute_updates[0][0] == 0x0000 # TEMP assert thermostat_listener.attribute_updates[0][1] == 1790 assert thermostat_listener.attribute_updates[1][0] == 0x0012 # TARGET assert thermostat_listener.attribute_updates[1][1] == 500 assert thermostat_listener.attribute_updates[2][0] == 0x001C # OFF assert thermostat_listener.attribute_updates[2][1] == 0x00 assert thermostat_listener.attribute_updates[3][0] == 0x001E assert thermostat_listener.attribute_updates[3][1] == 0x00 assert thermostat_listener.attribute_updates[4][0] == 0x0029 assert thermostat_listener.attribute_updates[4][1] == 0x00 assert thermostat_listener.attribute_updates[5][0] == 0x001C # SCHEDULE assert thermostat_listener.attribute_updates[5][1] == 0x04 assert thermostat_listener.attribute_updates[6][0] == 0x0025 assert thermostat_listener.attribute_updates[6][1] == 0x01 assert thermostat_listener.attribute_updates[7][0] == 0x001E assert thermostat_listener.attribute_updates[7][1] == 0x04 assert thermostat_listener.attribute_updates[8][0] == 0x0029 assert thermostat_listener.attribute_updates[8][1] == 0x01 assert thermostat_listener.attribute_updates[9][0] == 0x001C # MANUAL assert thermostat_listener.attribute_updates[9][1] == 0x04 assert thermostat_listener.attribute_updates[10][0] == 0x0025 assert thermostat_listener.attribute_updates[10][1] == 0x00 assert thermostat_listener.attribute_updates[11][0] == 0x001E assert thermostat_listener.attribute_updates[11][1] == 0x04 assert thermostat_listener.attribute_updates[12][0] == 0x0029 assert thermostat_listener.attribute_updates[12][1] == 0x01
async def test_eheating_state_report(zigpy_device_from_quirk, quirk): """Test thermostatic valves standard reporting from incoming commands.""" electric_dev = zigpy_device_from_quirk(quirk) tuya_cluster = electric_dev.endpoints[1].tuya_manufacturer thermostat_listener = ClusterListener(electric_dev.endpoints[1].thermostat) frames = (ZCL_TUYA_EHEAT_TEMPERATURE, ZCL_TUYA_EHEAT_TARGET_TEMP) for frame in frames: hdr, args = tuya_cluster.deserialize(frame) tuya_cluster.handle_message(hdr, args) assert len(thermostat_listener.cluster_commands) == 0 assert len(thermostat_listener.attribute_updates) == 2 assert thermostat_listener.attribute_updates[0][0] == 0x0000 # TEMP assert thermostat_listener.attribute_updates[0][1] == 1790 assert thermostat_listener.attribute_updates[1][0] == 0x0012 # TARGET assert thermostat_listener.attribute_updates[1][1] == 2100
async def test_singleswitch_state_report(zigpy_device_from_quirk, quirk): """Test tuya single switch.""" switch_dev = zigpy_device_from_quirk(quirk) switch_cluster = switch_dev.endpoints[1].on_off switch_listener = ClusterListener(switch_cluster) tuya_cluster = switch_dev.endpoints[1].tuya_manufacturer hdr, args = tuya_cluster.deserialize(ZCL_TUYA_SWITCH_ON) tuya_cluster.handle_message(hdr, args) hdr, args = tuya_cluster.deserialize(ZCL_TUYA_SWITCH_OFF) tuya_cluster.handle_message(hdr, args) assert len(switch_listener.cluster_commands) == 0 assert len(switch_listener.attribute_updates) == 2 assert switch_listener.attribute_updates[0][0] == 0x0000 assert switch_listener.attribute_updates[0][1] == ON assert switch_listener.attribute_updates[1][0] == 0x0000 assert switch_listener.attribute_updates[1][1] == OFF
async def test_tuya_version(zigpy_device_from_quirk, quirk): """Test TUYA_MCU_VERSION_RSP messages.""" tuya_device = zigpy_device_from_quirk(quirk) tuya_cluster = tuya_device.endpoints[1].tuya_manufacturer cluster_listener = ClusterListener(tuya_cluster) assert len(cluster_listener.attribute_updates) == 0 # simulate a TUYA_MCU_VERSION_RSP message hdr, args = tuya_cluster.deserialize(ZCL_TUYA_VERSION_RSP) assert hdr.command_id == TUYA_MCU_VERSION_RSP tuya_cluster.handle_message(hdr, args) assert len(cluster_listener.attribute_updates) == 1 assert cluster_listener.attribute_updates[0][0] == ATTR_MCU_VERSION assert cluster_listener.attribute_updates[0][1] == "2.0.2" # read 'mcu_version' from cluster's attributes succ, fail = await tuya_cluster.read_attributes(("mcu_version",)) assert succ["mcu_version"] == "2.0.2"
async def test_command(zigpy_device_from_quirk, quirk): """Test write cluster attributes.""" 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 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: status = await switch2_cluster.command(0x0001) m1.assert_called_with( 61184, 2, b"\x01\x02\x00\x00\x01\x07\x01\x00\x01\x01", expect_reply=True, command_id=0, ) assert status == foundation.Status.SUCCESS status = await dimmer1_cluster.command(0x0000, 225) m1.assert_called_with( 61184, 4, b"\x01\x04\x00\x00\x03\x02\x02\x00\x04\x00\x00\x03r", expect_reply=True, command_id=0, ) assert status == foundation.Status.SUCCESS
async def test_command_psbzs(zigpy_device_from_quirk, quirk): """Test executing cluster commands for PARKSIDE water valve.""" water_valve_dev = zigpy_device_from_quirk(quirk) tuya_cluster = water_valve_dev.endpoints[1].tuya_manufacturer switch_cluster = water_valve_dev.endpoints[1].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 switch_cluster.command(0x0001) m1.assert_called_with( 61184, 2, b"\x01\x02\x00\x00\x01\x01\x01\x00\x01\x01", expect_reply=True, command_id=0, ) assert rsp.status == foundation.Status.SUCCESS
async def test_moes(zigpy_device_from_quirk, quirk): """Test thermostatic valve outgoing commands.""" valve_dev = zigpy_device_from_quirk(quirk) tuya_cluster = valve_dev.endpoints[1].tuya_manufacturer thermostat_cluster = valve_dev.endpoints[1].thermostat onoff_cluster = valve_dev.endpoints[1].on_off thermostat_ui_cluster = valve_dev.endpoints[1].thermostat_ui thermostat_listener = ClusterListener(valve_dev.endpoints[1].thermostat) onoff_listener = ClusterListener(valve_dev.endpoints[1].on_off) frames = ( ZCL_TUYA_VALVE_TEMPERATURE, ZCL_TUYA_VALVE_WINDOW_DETECTION, ZCL_TUYA_VALVE_WORKDAY_SCHEDULE, ZCL_TUYA_VALVE_WEEKEND_SCHEDULE, ZCL_TUYA_VALVE_OFF, ZCL_TUYA_VALVE_SCHEDULE, ZCL_TUYA_VALVE_MANUAL, ZCL_TUYA_VALVE_COMFORT, ZCL_TUYA_VALVE_ECO, ZCL_TUYA_VALVE_BOOST, ZCL_TUYA_VALVE_COMPLEX, ZCL_TUYA_VALVE_STATE_50, ) for frame in frames: hdr, args = tuya_cluster.deserialize(frame) tuya_cluster.handle_message(hdr, args) assert len(thermostat_listener.cluster_commands) == 0 assert len(thermostat_listener.attribute_updates) == 61 assert thermostat_listener.attribute_updates[0][0] == 0x0000 assert thermostat_listener.attribute_updates[0][1] == 1790 assert thermostat_listener.attribute_updates[1][0] == 0x4110 assert thermostat_listener.attribute_updates[1][1] == 6 assert thermostat_listener.attribute_updates[2][0] == 0x4111 assert thermostat_listener.attribute_updates[2][1] == 0 assert thermostat_listener.attribute_updates[3][0] == 0x4112 assert thermostat_listener.attribute_updates[3][1] == 2000 assert thermostat_listener.attribute_updates[4][0] == 0x4120 assert thermostat_listener.attribute_updates[4][1] == 8 assert thermostat_listener.attribute_updates[5][0] == 0x4121 assert thermostat_listener.attribute_updates[5][1] == 0 assert thermostat_listener.attribute_updates[6][0] == 0x4122 assert thermostat_listener.attribute_updates[6][1] == 1500 assert thermostat_listener.attribute_updates[7][0] == 0x4130 assert thermostat_listener.attribute_updates[7][1] == 11 assert thermostat_listener.attribute_updates[8][0] == 0x4131 assert thermostat_listener.attribute_updates[8][1] == 30 assert thermostat_listener.attribute_updates[9][0] == 0x4132 assert thermostat_listener.attribute_updates[9][1] == 1500 assert thermostat_listener.attribute_updates[10][0] == 0x4140 assert thermostat_listener.attribute_updates[10][1] == 12 assert thermostat_listener.attribute_updates[11][0] == 0x4141 assert thermostat_listener.attribute_updates[11][1] == 30 assert thermostat_listener.attribute_updates[12][0] == 0x4142 assert thermostat_listener.attribute_updates[12][1] == 1500 assert thermostat_listener.attribute_updates[13][0] == 0x4150 assert thermostat_listener.attribute_updates[13][1] == 17 assert thermostat_listener.attribute_updates[14][0] == 0x4151 assert thermostat_listener.attribute_updates[14][1] == 30 assert thermostat_listener.attribute_updates[15][0] == 0x4152 assert thermostat_listener.attribute_updates[15][1] == 2000 assert thermostat_listener.attribute_updates[16][0] == 0x4160 assert thermostat_listener.attribute_updates[16][1] == 22 assert thermostat_listener.attribute_updates[17][0] == 0x4161 assert thermostat_listener.attribute_updates[17][1] == 0 assert thermostat_listener.attribute_updates[18][0] == 0x4162 assert thermostat_listener.attribute_updates[18][1] == 1500 assert thermostat_listener.attribute_updates[19][0] == 0x4210 assert thermostat_listener.attribute_updates[19][1] == 6 assert thermostat_listener.attribute_updates[20][0] == 0x4211 assert thermostat_listener.attribute_updates[20][1] == 0 assert thermostat_listener.attribute_updates[21][0] == 0x4212 assert thermostat_listener.attribute_updates[21][1] == 2000 assert thermostat_listener.attribute_updates[22][0] == 0x4220 assert thermostat_listener.attribute_updates[22][1] == 8 assert thermostat_listener.attribute_updates[23][0] == 0x4221 assert thermostat_listener.attribute_updates[23][1] == 0 assert thermostat_listener.attribute_updates[24][0] == 0x4222 assert thermostat_listener.attribute_updates[24][1] == 1500 assert thermostat_listener.attribute_updates[25][0] == 0x4230 assert thermostat_listener.attribute_updates[25][1] == 11 assert thermostat_listener.attribute_updates[26][0] == 0x4231 assert thermostat_listener.attribute_updates[26][1] == 30 assert thermostat_listener.attribute_updates[27][0] == 0x4232 assert thermostat_listener.attribute_updates[27][1] == 1500 assert thermostat_listener.attribute_updates[28][0] == 0x4240 assert thermostat_listener.attribute_updates[28][1] == 12 assert thermostat_listener.attribute_updates[29][0] == 0x4241 assert thermostat_listener.attribute_updates[29][1] == 30 assert thermostat_listener.attribute_updates[30][0] == 0x4242 assert thermostat_listener.attribute_updates[30][1] == 1500 assert thermostat_listener.attribute_updates[31][0] == 0x4250 assert thermostat_listener.attribute_updates[31][1] == 17 assert thermostat_listener.attribute_updates[32][0] == 0x4251 assert thermostat_listener.attribute_updates[32][1] == 30 assert thermostat_listener.attribute_updates[33][0] == 0x4252 assert thermostat_listener.attribute_updates[33][1] == 2000 assert thermostat_listener.attribute_updates[34][0] == 0x4260 assert thermostat_listener.attribute_updates[34][1] == 22 assert thermostat_listener.attribute_updates[35][0] == 0x4261 assert thermostat_listener.attribute_updates[35][1] == 0 assert thermostat_listener.attribute_updates[36][0] == 0x4262 assert thermostat_listener.attribute_updates[36][1] == 1500 assert thermostat_listener.attribute_updates[37][0] == 0x4002 assert thermostat_listener.attribute_updates[37][1] == 0 assert thermostat_listener.attribute_updates[38][0] == 0x0025 assert thermostat_listener.attribute_updates[38][1] == 0 assert thermostat_listener.attribute_updates[39][0] == 0x0002 assert thermostat_listener.attribute_updates[39][1] == 0 assert thermostat_listener.attribute_updates[40][0] == 0x4002 assert thermostat_listener.attribute_updates[40][1] == 1 assert thermostat_listener.attribute_updates[41][0] == 0x0025 assert thermostat_listener.attribute_updates[41][1] == 1 assert thermostat_listener.attribute_updates[42][0] == 0x0002 assert thermostat_listener.attribute_updates[42][1] == 1 assert thermostat_listener.attribute_updates[43][0] == 0x4002 assert thermostat_listener.attribute_updates[43][1] == 2 assert thermostat_listener.attribute_updates[44][0] == 0x0025 assert thermostat_listener.attribute_updates[44][1] == 0 assert thermostat_listener.attribute_updates[45][0] == 0x0002 assert thermostat_listener.attribute_updates[45][1] == 1 assert thermostat_listener.attribute_updates[46][0] == 0x4002 assert thermostat_listener.attribute_updates[46][1] == 3 assert thermostat_listener.attribute_updates[47][0] == 0x0025 assert thermostat_listener.attribute_updates[47][1] == 0 assert thermostat_listener.attribute_updates[48][0] == 0x0002 assert thermostat_listener.attribute_updates[48][1] == 1 assert thermostat_listener.attribute_updates[49][0] == 0x4002 assert thermostat_listener.attribute_updates[49][1] == 4 assert thermostat_listener.attribute_updates[50][0] == 0x0025 assert thermostat_listener.attribute_updates[50][1] == 4 assert thermostat_listener.attribute_updates[51][0] == 0x0002 assert thermostat_listener.attribute_updates[51][1] == 1 assert thermostat_listener.attribute_updates[52][0] == 0x4002 assert thermostat_listener.attribute_updates[52][1] == 5 assert thermostat_listener.attribute_updates[53][0] == 0x0025 assert thermostat_listener.attribute_updates[53][1] == 0 assert thermostat_listener.attribute_updates[54][0] == 0x0002 assert thermostat_listener.attribute_updates[54][1] == 1 assert thermostat_listener.attribute_updates[55][0] == 0x4002 assert thermostat_listener.attribute_updates[55][1] == 6 assert thermostat_listener.attribute_updates[56][0] == 0x0025 assert thermostat_listener.attribute_updates[56][1] == 0 assert thermostat_listener.attribute_updates[57][0] == 0x0002 assert thermostat_listener.attribute_updates[57][1] == 1 assert thermostat_listener.attribute_updates[58][0] == 0x4004 assert thermostat_listener.attribute_updates[58][1] == 50 assert thermostat_listener.attribute_updates[59][0] == 0x001E assert thermostat_listener.attribute_updates[59][1] == 4 assert thermostat_listener.attribute_updates[60][0] == 0x0029 assert thermostat_listener.attribute_updates[60][1] == 1 assert len(onoff_listener.cluster_commands) == 0 assert len(onoff_listener.attribute_updates) == 3 assert onoff_listener.attribute_updates[0][0] == 0x6001 assert onoff_listener.attribute_updates[0][1] == 5 assert onoff_listener.attribute_updates[1][0] == 0x6000 assert onoff_listener.attribute_updates[1][1] == 1600 assert onoff_listener.attribute_updates[2][0] == 0x0000 # TARGET assert onoff_listener.attribute_updates[2][1] == 1 thermostat_ui_listener = ClusterListener(valve_dev.endpoints[1].thermostat_ui) power_listener = ClusterListener(valve_dev.endpoints[1].power) frames = ( ZCL_TUYA_VALVE_CHILD_LOCK_ON, ZCL_TUYA_VALVE_AUTO_LOCK_ON, ZCL_TUYA_VALVE_BATTERY_LOW, ) for frame in frames: hdr, args = tuya_cluster.deserialize(frame) tuya_cluster.handle_message(hdr, args) assert len(thermostat_ui_listener.cluster_commands) == 0 assert len(thermostat_ui_listener.attribute_updates) == 2 assert thermostat_ui_listener.attribute_updates[0][0] == 0x0001 assert thermostat_ui_listener.attribute_updates[0][1] == 1 assert thermostat_ui_listener.attribute_updates[1][0] == 0x5000 assert thermostat_ui_listener.attribute_updates[1][1] == 1 assert len(power_listener.cluster_commands) == 0 assert len(power_listener.attribute_updates) == 1 assert power_listener.attribute_updates[0][0] == 0x0021 assert power_listener.attribute_updates[0][1] == 10 async def async_success(*args, **kwargs): return foundation.Status.SUCCESS with mock.patch.object( tuya_cluster.endpoint, "request", side_effect=async_success ) as m1: status = await thermostat_cluster.write_attributes( { "occupied_heating_setpoint": 2500, } ) m1.assert_called_with( 61184, 1, b"\x01\x01\x00\x00\x01\x02\x02\x00\x04\x00\x00\x00\xfa", expect_reply=False, command_id=0, ) assert status == (foundation.Status.SUCCESS,) status = await thermostat_cluster.write_attributes( { "operation_preset": 0x00, } ) m1.assert_called_with( 61184, 2, b"\x01\x02\x00\x00\x02\x04\x04\x00\x01\x00", expect_reply=False, command_id=0, ) assert status == (foundation.Status.SUCCESS,) status = await thermostat_cluster.write_attributes( { "operation_preset": 0x02, } ) m1.assert_called_with( 61184, 3, b"\x01\x03\x00\x00\x03\x04\x04\x00\x01\x02", expect_reply=False, command_id=0, ) assert status == (foundation.Status.SUCCESS,) # simulate a target temp update so that relative changes can work hdr, args = tuya_cluster.deserialize(ZCL_TUYA_VALVE_TARGET_TEMP) tuya_cluster.handle_message(hdr, args) status = await thermostat_cluster.command(0x0000, 0x00, 20) m1.assert_called_with( 61184, 4, b"\x01\x04\x00\x00\x04\x02\x02\x00\x04\x00\x00\x00F", expect_reply=False, command_id=0, ) assert status == (foundation.Status.SUCCESS,) status = await onoff_cluster.write_attributes( { "on_off": 0x00, "window_detection_timeout_minutes": 0x02, "window_detection_temperature": 2000, } ) m1.assert_called_with( 61184, 5, b"\x01\x05\x00\x00\x05\x68\x00\x00\x03\x00\x14\x02", expect_reply=False, command_id=0, ) assert status == (foundation.Status.SUCCESS,) status = await thermostat_cluster.write_attributes( { "occupancy": 0x00, } ) m1.assert_called_with( 61184, 6, b"\x01\x06\x00\x00\x06\x04\x04\x00\x01\x00", expect_reply=False, command_id=0, ) assert status == (foundation.Status.SUCCESS,) status = await thermostat_cluster.write_attributes( { "occupancy": 0x01, "programing_oper_mode": 0x00, } ) m1.assert_called_with( 61184, 7, b"\x01\x07\x00\x00\x07\x04\x04\x00\x01\x02", expect_reply=False, command_id=0, ) assert status == (foundation.Status.SUCCESS,) status = await thermostat_cluster.write_attributes( { "programing_oper_mode": 0x01, } ) m1.assert_called_with( 61184, 8, b"\x01\x08\x00\x00\x08\x04\x04\x00\x01\x01", expect_reply=False, command_id=0, ) assert status == (foundation.Status.SUCCESS,) status = await thermostat_cluster.write_attributes( { "programing_oper_mode": 0x04, } ) m1.assert_called_with( 61184, 9, b"\x01\x09\x00\x00\x09\x04\x04\x00\x01\x04", expect_reply=False, command_id=0, ) assert status == (foundation.Status.SUCCESS,) status = await thermostat_cluster.write_attributes( { "workday_schedule_1_temperature": 1700, } ) m1.assert_called_with( 61184, 10, b"\x01\x0A\x00\x00\x0A\x70\x00\x00\x12\x06\x00\x11\x08\x00\x0F\x0B\x1E\x0F\x0C\x1E\x0F\x11\x1E\x14\x16\x00\x0F", expect_reply=False, command_id=0, ) assert status == (foundation.Status.SUCCESS,) status = await thermostat_cluster.write_attributes( { "workday_schedule_1_minute": 45, } ) m1.assert_called_with( 61184, 11, b"\x01\x0B\x00\x00\x0B\x70\x00\x00\x12\x06\x2D\x14\x08\x00\x0F\x0B\x1E\x0F\x0C\x1E\x0F\x11\x1E\x14\x16\x00\x0F", expect_reply=False, command_id=0, ) assert status == (foundation.Status.SUCCESS,) status = await thermostat_cluster.write_attributes( { "workday_schedule_1_hour": 5, } ) m1.assert_called_with( 61184, 12, b"\x01\x0C\x00\x00\x0C\x70\x00\x00\x12\x05\x00\x14\x08\x00\x0F\x0B\x1E\x0F\x0C\x1E\x0F\x11\x1E\x14\x16\x00\x0F", expect_reply=False, command_id=0, ) assert status == (foundation.Status.SUCCESS,) status = await thermostat_cluster.write_attributes( { "weekend_schedule_1_temperature": 1700, } ) m1.assert_called_with( 61184, 13, b"\x01\x0D\x00\x00\x0D\x71\x00\x00\x12\x06\x00\x11\x08\x00\x0F\x0B\x1E\x0F\x0C\x1E\x0F\x11\x1E\x14\x16\x00\x0F", expect_reply=False, command_id=0, ) assert status == (foundation.Status.SUCCESS,) status = await thermostat_cluster.write_attributes( { "weekend_schedule_1_minute": 45, } ) m1.assert_called_with( 61184, 14, b"\x01\x0E\x00\x00\x0E\x71\x00\x00\x12\x06\x2D\x14\x08\x00\x0F\x0B\x1E\x0F\x0C\x1E\x0F\x11\x1E\x14\x16\x00\x0F", expect_reply=False, command_id=0, ) assert status == (foundation.Status.SUCCESS,) status = await thermostat_cluster.write_attributes( { "weekend_schedule_1_hour": 5, } ) m1.assert_called_with( 61184, 15, b"\x01\x0F\x00\x00\x0F\x71\x00\x00\x12\x05\x00\x14\x08\x00\x0F\x0B\x1E\x0F\x0C\x1E\x0F\x11\x1E\x14\x16\x00\x0F", expect_reply=False, command_id=0, ) assert status == (foundation.Status.SUCCESS,) status = await thermostat_cluster.write_attributes( { "system_mode": 0x01, } ) m1.assert_called_with( 61184, 16, b"\x01\x10\x00\x00\x10\x04\x04\x00\x01\x06", expect_reply=False, command_id=0, ) assert status == (foundation.Status.SUCCESS,) status = await thermostat_ui_cluster.write_attributes( { "auto_lock": 0x00, } ) m1.assert_called_with( 61184, 17, b"\x01\x11\x00\x00\x11\x74\x01\x00\x01\x00", expect_reply=False, command_id=0, ) assert status == (foundation.Status.SUCCESS,) status = await onoff_cluster.command(0x0000) m1.assert_called_with( 61184, 18, b"\x01\x12\x00\x00\x12\x68\x00\x00\x03\x00\x10\x05", expect_reply=False, command_id=0, ) assert status == (foundation.Status.SUCCESS,) status = await onoff_cluster.command(0x0001) m1.assert_called_with( 61184, 19, b"\x01\x13\x00\x00\x13\x68\x00\x00\x03\x01\x10\x05", expect_reply=False, command_id=0, ) assert status == (foundation.Status.SUCCESS,) status = await onoff_cluster.command(0x0002) m1.assert_called_with( 61184, 20, b"\x01\x14\x00\x00\x14\x68\x00\x00\x03\x00\x10\x05", expect_reply=False, command_id=0, ) assert status == (foundation.Status.SUCCESS,) status = await onoff_cluster.write_attributes({}) assert status == (foundation.Status.SUCCESS,) status = await thermostat_cluster.command(0x0002) assert status == foundation.Status.UNSUP_CLUSTER_COMMAND status = await onoff_cluster.command(0x0009) assert status == foundation.Status.UNSUP_CLUSTER_COMMAND origdatetime = datetime.datetime datetime.datetime = NewDatetime hdr, args = tuya_cluster.deserialize(ZCL_TUYA_SET_TIME_REQUEST) tuya_cluster.handle_message(hdr, args) m1.assert_called_with( 61184, 21, b"\x01\x15\x24\x00\x08\x00\x00\x1C\x20\x00\x00\x0E\x10", expect_reply=False, command_id=0x0024, ) datetime.datetime = origdatetime
async def test_dim_values(zigpy_device_from_quirk, quirk): """Test dimming values.""" dimmer_dev = zigpy_device_from_quirk(quirk) dimmer2_cluster = dimmer_dev.endpoints[2].level dimmer2_listener = ClusterListener(dimmer2_cluster) tuya_cluster = dimmer_dev.endpoints[1].tuya_manufacturer assert len(dimmer2_listener.cluster_commands) == 0 assert len(dimmer2_listener.attribute_updates) == 0 # payload=553 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 succ, fail = await dimmer2_cluster.read_attributes(("current_level", )) assert succ["current_level"] == 141 # payload=700 hdr, args = tuya_cluster.deserialize( b"\tV\x02\x01y\x08\x02\x00\x04\x00\x00\x02\xbc") tuya_cluster.handle_message(hdr, args) succ, fail = await dimmer2_cluster.read_attributes(("current_level", )) assert succ["current_level"] == 178 # payload=982 hdr, args = tuya_cluster.deserialize( b"\tV\x02\x01y\x08\x02\x00\x04\x00\x00\x03\xd6") tuya_cluster.handle_message(hdr, args) succ, fail = await dimmer2_cluster.read_attributes(("current_level", )) assert succ["current_level"] == 250 # payload=657 hdr, args = tuya_cluster.deserialize( b"\tV\x02\x01y\x08\x02\x00\x04\x00\x00\x02\x91") tuya_cluster.handle_message(hdr, args) succ, fail = await dimmer2_cluster.read_attributes(("current_level", )) assert succ["current_level"] == 167 # payload=400 hdr, args = tuya_cluster.deserialize( b"\tV\x02\x01y\x08\x02\x00\x04\x00\x00\x01\x90") tuya_cluster.handle_message(hdr, args) succ, fail = await dimmer2_cluster.read_attributes(("current_level", )) assert succ["current_level"] == 102 # payload=149 hdr, args = tuya_cluster.deserialize( b"\tV\x02\x01y\x08\x02\x00\x04\x00\x00\x00\x95") tuya_cluster.handle_message(hdr, args) succ, fail = await dimmer2_cluster.read_attributes(("current_level", )) assert succ["current_level"] == 37 # payload=339 hdr, args = tuya_cluster.deserialize( b"\tV\x02\x01y\x08\x02\x00\x04\x00\x00\x01\x53") tuya_cluster.handle_message(hdr, args) succ, fail = await dimmer2_cluster.read_attributes(("current_level", )) assert succ["current_level"] == 86