diff --git a/setup.cfg b/setup.cfg index 06d223c765..82feb7412f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -66,6 +66,22 @@ error_summary = True install_types = True non_interactive = True +disable_error_code = + arg-type, + assignment, + attr-defined, + call-arg, + dict-item, + index, + misc, + no-any-return, + no-untyped-call, + no-untyped-def, + override, + return-value, + union-attr, + var-annotated + [pydocstyle] ignore = D202, diff --git a/setup.py b/setup.py index ae52f0fa05..a25dfc0e73 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ from setuptools import find_packages, setup -VERSION = "0.0.69" +VERSION = "0.0.70" setup( diff --git a/tests/test_quirks.py b/tests/test_quirks.py index 446ad08259..54da84ec33 100644 --- a/tests/test_quirks.py +++ b/tests/test_quirks.py @@ -1,6 +1,7 @@ """General quirk tests.""" from __future__ import annotations +import importlib from pathlib import Path from unittest import mock @@ -508,3 +509,11 @@ def test_zigpy_custom_cluster_pollution() -> None: raise RuntimeError( f"Custom clusters must subclass `CustomCluster`: {non_zigpy_clusters}" ) + + +@pytest.mark.parametrize("module_name", {q.__module__ for q in ALL_QUIRK_CLASSES}) +def test_no_module_level_device_automation_triggers(module_name: str) -> None: + """Ensure no quirk module has a module-level `device_automation_triggers` dict.""" + + mod = importlib.import_module(module_name) + assert not hasattr(mod, "device_automation_triggers") diff --git a/tests/test_tuya.py b/tests/test_tuya.py index 4d74f5a35c..5f82375418 100644 --- a/tests/test_tuya.py +++ b/tests/test_tuya.py @@ -236,7 +236,7 @@ async def test_singleswitch_requests(zigpy_device_from_quirk, quirk): tuya_cluster.endpoint, "request", return_value=foundation.Status.SUCCESS ) as m1: - status = await switch_cluster.command(0x0000) + rsp = await switch_cluster.command(0x0000) m1.assert_called_with( 61184, 2, @@ -244,9 +244,9 @@ async def test_singleswitch_requests(zigpy_device_from_quirk, quirk): expect_reply=True, command_id=0, ) - assert status == 0 + assert rsp.status == 0 - status = await switch_cluster.command(0x0001) + rsp = await switch_cluster.command(0x0001) m1.assert_called_with( 61184, 4, @@ -254,10 +254,10 @@ async def test_singleswitch_requests(zigpy_device_from_quirk, quirk): expect_reply=True, command_id=0, ) - assert status == 0 + assert rsp.status == 0 - status = await switch_cluster.command(0x0002) - assert status == foundation.Status.UNSUP_CLUSTER_COMMAND + rsp = await switch_cluster.command(0x0002) + assert rsp.status == foundation.Status.UNSUP_CLUSTER_COMMAND def test_ts0121_signature(assert_signature_matches_quirk): diff --git a/tests/test_tuya_dimmer.py b/tests/test_tuya_dimmer.py index d5d5f4f648..de8e2205bb 100644 --- a/tests/test_tuya_dimmer.py +++ b/tests/test_tuya_dimmer.py @@ -30,7 +30,7 @@ async def test_command(zigpy_device_from_quirk, quirk): with mock.patch.object( tuya_cluster.endpoint, "request", return_value=foundation.Status.SUCCESS ) as m1: - status = await switch2_cluster.command(0x0001) + rsp = await switch2_cluster.command(0x0001) m1.assert_called_with( 61184, @@ -39,9 +39,9 @@ async def test_command(zigpy_device_from_quirk, quirk): expect_reply=True, command_id=0, ) - assert status == foundation.Status.SUCCESS + assert rsp.status == foundation.Status.SUCCESS - status = await dimmer1_cluster.command(0x0000, 225) + rsp = await dimmer1_cluster.command(0x0000, 225) m1.assert_called_with( 61184, @@ -50,7 +50,7 @@ async def test_command(zigpy_device_from_quirk, quirk): expect_reply=True, command_id=0, ) - assert status == foundation.Status.SUCCESS + assert rsp.status == foundation.Status.SUCCESS @pytest.mark.parametrize( diff --git a/tests/test_tuya_mcu.py b/tests/test_tuya_mcu.py index 74d15000bf..747f873160 100644 --- a/tests/test_tuya_mcu.py +++ b/tests/test_tuya_mcu.py @@ -85,17 +85,17 @@ async def test_tuya_methods(zigpy_device_from_quirk, quirk): m1.assert_not_called() result_3 = await dimmer2_cluster.command(0x0006) - assert result_3 == foundation.Status.UNSUP_CLUSTER_COMMAND + assert result_3.status == foundation.Status.UNSUP_CLUSTER_COMMAND with mock.patch.object(tuya_cluster, "tuya_mcu_command") as m1: - status = await switch1_cluster.command(0x0001) + rsp = await switch1_cluster.command(0x0001) m1.assert_called_once_with(tcd_switch1_on) - assert status == foundation.Status.SUCCESS + assert rsp.status == foundation.Status.SUCCESS - status = await switch1_cluster.command(0x0004) + rsp = await switch1_cluster.command(0x0004) m1.assert_called_once_with(tcd_switch1_on) # no extra calls - assert status == foundation.Status.UNSUP_CLUSTER_COMMAND + assert rsp.status == foundation.Status.UNSUP_CLUSTER_COMMAND async def test_tuya_mcu_classes(): diff --git a/zhaquirks/const.py b/zhaquirks/const.py index 8ab72f9c66..7888f20b97 100644 --- a/zhaquirks/const.py +++ b/zhaquirks/const.py @@ -57,6 +57,7 @@ COMMAND_STEP_SATURATION = "step_saturation" COMMAND_STOP = "stop" COMMAND_STOP_MOVE_STEP = "stop_move_step" +COMMAND_STOP_ON_OFF = "stop_with_on_off" COMMAND_TILT = "Tilt" COMMAND_TOGGLE = "toggle" COMMAND_TRIPLE = "triple" diff --git a/zhaquirks/ikea/dimmer.py b/zhaquirks/ikea/dimmer.py index e336245683..719b603c14 100644 --- a/zhaquirks/ikea/dimmer.py +++ b/zhaquirks/ikea/dimmer.py @@ -88,18 +88,17 @@ class IkeaDimmer(CustomDevice): } } - -device_automation_triggers = { - (ROTATED, RIGHT): { - COMMAND: COMMAND_MOVE, - CLUSTER_ID: 8, - ENDPOINT_ID: 1, - ARGS: [0, 195], - }, - (ROTATED, LEFT): { - COMMAND: COMMAND_MOVE, - CLUSTER_ID: 8, - ENDPOINT_ID: 1, - ARGS: [1, 195], - }, -} + device_automation_triggers = { + (ROTATED, RIGHT): { + COMMAND: COMMAND_MOVE, + CLUSTER_ID: 8, + ENDPOINT_ID: 1, + ARGS: [0, 195], + }, + (ROTATED, LEFT): { + COMMAND: COMMAND_MOVE, + CLUSTER_ID: 8, + ENDPOINT_ID: 1, + ARGS: [1, 195], + }, + } diff --git a/zhaquirks/ikea/fourbtnremote.py b/zhaquirks/ikea/fourbtnremote.py index 1735d79dfd..018c7181d1 100644 --- a/zhaquirks/ikea/fourbtnremote.py +++ b/zhaquirks/ikea/fourbtnremote.py @@ -22,7 +22,7 @@ COMMAND_OFF, COMMAND_ON, COMMAND_PRESS, - COMMAND_STOP, + COMMAND_STOP_ON_OFF, DEVICE_TYPE, DIM_DOWN, DIM_UP, @@ -110,7 +110,11 @@ class IkeaTradfriRemote(CustomDevice): ENDPOINT_ID: 1, ARGS: [0, 83], }, - (LONG_RELEASE, DIM_UP): {COMMAND: COMMAND_STOP, CLUSTER_ID: 8, ENDPOINT_ID: 1}, + (LONG_RELEASE, DIM_UP): { + COMMAND: COMMAND_STOP_ON_OFF, + CLUSTER_ID: 8, + ENDPOINT_ID: 1, + }, (SHORT_PRESS, TURN_OFF): {COMMAND: COMMAND_OFF, CLUSTER_ID: 6, ENDPOINT_ID: 1}, (LONG_PRESS, DIM_DOWN): { COMMAND: COMMAND_MOVE, @@ -119,7 +123,7 @@ class IkeaTradfriRemote(CustomDevice): ARGS: [1, 83], }, (LONG_RELEASE, DIM_DOWN): { - COMMAND: COMMAND_STOP, + COMMAND: COMMAND_STOP_ON_OFF, CLUSTER_ID: 8, ENDPOINT_ID: 1, }, diff --git a/zhaquirks/ikea/shortcutbtn.py b/zhaquirks/ikea/shortcutbtn.py index 1a184bc907..c6790f1ee5 100644 --- a/zhaquirks/ikea/shortcutbtn.py +++ b/zhaquirks/ikea/shortcutbtn.py @@ -22,7 +22,7 @@ COMMAND_MOVE_ON_OFF, COMMAND_OFF, COMMAND_ON, - COMMAND_STOP, + COMMAND_STOP_ON_OFF, DEVICE_TYPE, DIM_UP, DOUBLE_PRESS, @@ -100,6 +100,82 @@ class IkeaTradfriShortcutBtn(CustomDevice): } } + device_automation_triggers = { + (SHORT_PRESS, TURN_ON): {COMMAND: COMMAND_ON, CLUSTER_ID: 6, ENDPOINT_ID: 1}, + (DOUBLE_PRESS, TURN_ON): {COMMAND: COMMAND_OFF, CLUSTER_ID: 6, ENDPOINT_ID: 1}, + (LONG_PRESS, DIM_UP): { + COMMAND: COMMAND_MOVE_ON_OFF, + CLUSTER_ID: 8, + ENDPOINT_ID: 1, + ARGS: [0, 83], + }, + (LONG_RELEASE, DIM_UP): { + COMMAND: COMMAND_STOP_ON_OFF, + CLUSTER_ID: 8, + ENDPOINT_ID: 1, + }, + } + + +class IkeaTradfriShortcutBtn2(CustomDevice): + """Custom device representing IKEA of Sweden TRADFRI shortcut button with IKEA cluster.""" + + signature = { + # + MODELS_INFO: [(IKEA, "TRADFRI SHORTCUT Button")], + ENDPOINTS: { + 1: { + PROFILE_ID: zha.PROFILE_ID, + DEVICE_TYPE: zha.DeviceType.NON_COLOR_CONTROLLER, + INPUT_CLUSTERS: [ + Basic.cluster_id, + PowerConfiguration.cluster_id, + Identify.cluster_id, + Alarms.cluster_id, + PollControl.cluster_id, + LightLink.cluster_id, + 0xFC7C, # IKEA Cluster + ], + OUTPUT_CLUSTERS: [ + Identify.cluster_id, + Groups.cluster_id, + OnOff.cluster_id, + LevelControl.cluster_id, + Ota.cluster_id, + LightLink.cluster_id, + ], + } + }, + } + + replacement = { + ENDPOINTS: { + 1: { + PROFILE_ID: zha.PROFILE_ID, + DEVICE_TYPE: zha.DeviceType.NON_COLOR_CONTROLLER, + INPUT_CLUSTERS: [ + Basic.cluster_id, + PowerConfiguration1CRCluster, + Identify.cluster_id, + Alarms.cluster_id, + PollControl.cluster_id, + LightLinkCluster, + ], + OUTPUT_CLUSTERS: [ + Identify.cluster_id, + Groups.cluster_id, + OnOff.cluster_id, + LevelControl.cluster_id, + Ota.cluster_id, + LightLink.cluster_id, + ], + } + } + } + device_automation_triggers = { (SHORT_PRESS, TURN_ON): {COMMAND: COMMAND_ON, CLUSTER_ID: 6, ENDPOINT_ID: 1}, (DOUBLE_PRESS, TURN_ON): {COMMAND: COMMAND_OFF, CLUSTER_ID: 6, ENDPOINT_ID: 1}, diff --git a/zhaquirks/ikea/twobtnremote.py b/zhaquirks/ikea/twobtnremote.py index 6e81a7f6b3..dae1767e83 100644 --- a/zhaquirks/ikea/twobtnremote.py +++ b/zhaquirks/ikea/twobtnremote.py @@ -24,6 +24,7 @@ COMMAND_OFF, COMMAND_ON, COMMAND_STOP, + COMMAND_STOP_ON_OFF, DEVICE_TYPE, DIM_DOWN, DIM_UP, @@ -115,7 +116,7 @@ class IkeaTradfriRemote2Btn(CustomDevice): ARGS: [0, 83], }, (LONG_RELEASE, DIM_UP): { - COMMAND: COMMAND_STOP, + COMMAND: COMMAND_STOP_ON_OFF, CLUSTER_ID: 8, ENDPOINT_ID: 1, }, diff --git a/zhaquirks/osram/switchmini.py b/zhaquirks/osram/switchmini.py index a6802f9d4a..7bd24ffef5 100644 --- a/zhaquirks/osram/switchmini.py +++ b/zhaquirks/osram/switchmini.py @@ -26,6 +26,7 @@ COMMAND_OFF, COMMAND_ON, COMMAND_STOP, + COMMAND_STOP_ON_OFF, DEVICE_TYPE, ENDPOINT_ID, ENDPOINTS, @@ -118,7 +119,7 @@ class OsramSwitchMini(CustomDevice): device_automation_triggers = { (SHORT_PRESS, BUTTON_1): {COMMAND: COMMAND_ON, ENDPOINT_ID: 1}, (LONG_PRESS, BUTTON_1): {COMMAND: COMMAND_MOVE_ON_OFF, ENDPOINT_ID: 1}, - (LONG_RELEASE, BUTTON_1): {COMMAND: COMMAND_STOP, ENDPOINT_ID: 1}, + (LONG_RELEASE, BUTTON_1): {COMMAND: COMMAND_STOP_ON_OFF, ENDPOINT_ID: 1}, (SHORT_PRESS, BUTTON_2): { COMMAND: COMMAND_MOVE_TO_LEVEL_ON_OFF, ENDPOINT_ID: 3, diff --git a/zhaquirks/tuya/__init__.py b/zhaquirks/tuya/__init__.py index 31cd2c311f..8038e1e377 100644 --- a/zhaquirks/tuya/__init__.py +++ b/zhaquirks/tuya/__init__.py @@ -670,11 +670,17 @@ async def command( """Implement thermostat commands.""" if command_id != 0x0000: - return [command_id, foundation.Status.UNSUP_CLUSTER_COMMAND] + return foundation.GENERAL_COMMANDS[ + foundation.GeneralCommand.Default_Response + ].schema( + command_id=command_id, status=foundation.Status.UNSUP_CLUSTER_COMMAND + ) mode, offset = args if mode not in (self.SetpointMode.Heat, self.SetpointMode.Both): - return [command_id, foundation.Status.INVALID_VALUE] + return foundation.GENERAL_COMMANDS[ + foundation.GeneralCommand.Default_Response + ].schema(command_id=command_id, status=foundation.Status.INVALID_VALUE) attrid = self.attributes_by_name["occupied_heating_setpoint"].id @@ -689,7 +695,9 @@ async def command( {"occupied_heating_setpoint": current + offset * 10}, manufacturer=manufacturer, ) - return [command_id, res[0].status] + return foundation.GENERAL_COMMANDS[ + foundation.GeneralCommand.Default_Response + ].schema(command_id=command_id, status=res[0].status) class TuyaUserInterfaceCluster(LocalDataCluster, UserInterface): @@ -840,6 +848,7 @@ class TuyaZBOnOffAttributeCluster(CustomCluster, OnOff): """Tuya Zigbee On Off cluster with extra attributes.""" attributes = OnOff.attributes.copy() + attributes.update({0x8000: ("child_lock", t.Bool)}) attributes.update({0x8001: ("backlight_mode", SwitchBackLight)}) attributes.update({0x8002: ("power_on_state", PowerOnState)}) attributes.update({0x8004: ("switch_mode", SwitchMode)}) diff --git a/zhaquirks/tuya/mcu/__init__.py b/zhaquirks/tuya/mcu/__init__.py index 8890f66f79..68a5322840 100644 --- a/zhaquirks/tuya/mcu/__init__.py +++ b/zhaquirks/tuya/mcu/__init__.py @@ -294,10 +294,14 @@ async def command( TUYA_MCU_COMMAND, cluster_data, ) - return foundation.Status.SUCCESS + return foundation.GENERAL_COMMANDS[ + foundation.GeneralCommand.Default_Response + ].schema(command_id=command_id, status=foundation.Status.SUCCESS) self.warning("Unsupported command_id: %s", command_id) - return foundation.Status.UNSUP_CLUSTER_COMMAND + return foundation.GENERAL_COMMANDS[ + foundation.GeneralCommand.Default_Response + ].schema(command_id=command_id, status=foundation.Status.UNSUP_CLUSTER_COMMAND) class TuyaOnOffManufCluster(TuyaMCUCluster): @@ -406,10 +410,14 @@ async def command( TUYA_MCU_COMMAND, cluster_data, ) - return foundation.Status.SUCCESS + return foundation.GENERAL_COMMANDS[ + foundation.GeneralCommand.Default_Response + ].schema(command_id=command_id, status=foundation.Status.SUCCESS) self.warning("Unsupported command_id: %s", command_id) - return foundation.Status.UNSUP_CLUSTER_COMMAND + return foundation.GENERAL_COMMANDS[ + foundation.GeneralCommand.Default_Response + ].schema(command_id=command_id, status=foundation.Status.UNSUP_CLUSTER_COMMAND) class TuyaInWallLevelControl(TuyaAttributesCluster, TuyaLevelControl): diff --git a/zhaquirks/tuya/ts011f_plug.py b/zhaquirks/tuya/ts011f_plug.py index ef1aaaef12..7cfc117b14 100644 --- a/zhaquirks/tuya/ts011f_plug.py +++ b/zhaquirks/tuya/ts011f_plug.py @@ -24,6 +24,7 @@ PROFILE_ID, ) from zhaquirks.tuya import ( + TuyaNewManufCluster, TuyaZBE000Cluster, TuyaZBElectricalMeasurement, TuyaZBExternalSwitchTypeCluster, @@ -440,3 +441,161 @@ class Plug_4AC_2USB(CustomDevice): }, }, } + + +class Plug_TZ3210_2AC(CustomDevice): + """TS0011F 2 outlet plug.""" + + signature = { + MODEL: "TS011F", + ENDPOINTS: { + # + 1: { + PROFILE_ID: zha.PROFILE_ID, + DEVICE_TYPE: zha.DeviceType.SMART_PLUG, + INPUT_CLUSTERS: [ + Basic.cluster_id, + Identify.cluster_id, + Groups.cluster_id, + Scenes.cluster_id, + OnOff.cluster_id, + Metering.cluster_id, + ElectricalMeasurement.cluster_id, + TuyaNewManufCluster.cluster_id, + ], + OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], + }, + # + 2: { + PROFILE_ID: zha.PROFILE_ID, + DEVICE_TYPE: zha.DeviceType.SMART_PLUG, + INPUT_CLUSTERS: [ + Identify.cluster_id, + Groups.cluster_id, + Scenes.cluster_id, + OnOff.cluster_id, + TuyaNewManufCluster.cluster_id, + ], + OUTPUT_CLUSTERS: [], + }, + # + 242: { + PROFILE_ID: 41440, + DEVICE_TYPE: 97, + INPUT_CLUSTERS: [], + OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id], + }, + }, + } + + replacement = { + ENDPOINTS: { + 1: { + PROFILE_ID: zha.PROFILE_ID, + DEVICE_TYPE: zha.DeviceType.SMART_PLUG, + INPUT_CLUSTERS: [ + Basic.cluster_id, + Identify.cluster_id, + Groups.cluster_id, + Scenes.cluster_id, + OnOff.cluster_id, + TuyaZBMeteringCluster, + TuyaZBElectricalMeasurement, + TuyaNewManufCluster, + ], + OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], + }, + 2: { + PROFILE_ID: zha.PROFILE_ID, + DEVICE_TYPE: zha.DeviceType.SMART_PLUG, + INPUT_CLUSTERS: [ + Identify.cluster_id, + Groups.cluster_id, + Scenes.cluster_id, + OnOff.cluster_id, + TuyaNewManufCluster, + ], + OUTPUT_CLUSTERS: [], + }, + 242: { + PROFILE_ID: 41440, + DEVICE_TYPE: 97, + INPUT_CLUSTERS: [], + OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id], + }, + }, + } + + +class Plug_TZ3210_1AC(CustomDevice): + """TS0011F 1 outlet plug.""" + + signature = { + MODEL: "TS011F", + ENDPOINTS: { + # + 1: { + PROFILE_ID: zha.PROFILE_ID, + DEVICE_TYPE: zha.DeviceType.ON_OFF_PLUG_IN_UNIT, + INPUT_CLUSTERS: [ + Basic.cluster_id, + Identify.cluster_id, + Groups.cluster_id, + Scenes.cluster_id, + OnOff.cluster_id, + Metering.cluster_id, + ElectricalMeasurement.cluster_id, + TuyaNewManufCluster.cluster_id, + ], + OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], + }, + # + 242: { + PROFILE_ID: 41440, + DEVICE_TYPE: 97, + INPUT_CLUSTERS: [], + OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id], + }, + }, + } + + replacement = { + ENDPOINTS: { + 1: { + PROFILE_ID: zha.PROFILE_ID, + DEVICE_TYPE: zha.DeviceType.ON_OFF_PLUG_IN_UNIT, + INPUT_CLUSTERS: [ + Basic.cluster_id, + Identify.cluster_id, + Groups.cluster_id, + Scenes.cluster_id, + OnOff.cluster_id, + TuyaZBMeteringCluster, + TuyaZBElectricalMeasurement, + TuyaNewManufCluster, + ], + OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id], + }, + 242: { + PROFILE_ID: 41440, + DEVICE_TYPE: 97, + INPUT_CLUSTERS: [], + OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id], + }, + }, + } diff --git a/zhaquirks/tuya/ts0601_siren.py b/zhaquirks/tuya/ts0601_siren.py index 666ea44b62..b8c9196e1b 100644 --- a/zhaquirks/tuya/ts0601_siren.py +++ b/zhaquirks/tuya/ts0601_siren.py @@ -150,9 +150,13 @@ async def command( (res,) = await self.endpoint.tuya_manufacturer.write_attributes( {TUYA_ALARM_ATTR: command_id}, manufacturer=manufacturer ) - return [command_id, res[0].status] + return foundation.GENERAL_COMMANDS[ + foundation.GeneralCommand.Default_Response + ].schema(command_id=command_id, status=res[0].status) - return [command_id, foundation.Status.UNSUP_CLUSTER_COMMAND] + return foundation.GENERAL_COMMANDS[ + foundation.GeneralCommand.Default_Response + ].schema(command_id=command_id, status=foundation.Status.UNSUP_CLUSTER_COMMAND) class TuyaTemperatureMeasurement(LocalDataCluster, TemperatureMeasurement): @@ -270,7 +274,9 @@ class TuyaMCUSiren(OnOff, TuyaAttributesCluster): async def write_attributes(self, attributes, manufacturer=None): """Overwrite to force manufacturer code.""" - return await super().write_attributes(attributes, manufacturer="") + return await super().write_attributes( + attributes, manufacturer=foundation.ZCLHeader.NO_MANUFACTURER_ID + ) async def command( self, @@ -289,16 +295,20 @@ async def command( cluster_attr="on_off", attr_value=command_id, expect_reply=expect_reply, - manufacturer="", + manufacturer=foundation.ZCLHeader.NO_MANUFACTURER_ID, ) self.endpoint.device.command_bus.listener_event( TUYA_MCU_COMMAND, cluster_data, ) - return foundation.Status.SUCCESS + return foundation.GENERAL_COMMANDS[ + foundation.GeneralCommand.Default_Response + ].schema(command_id=command_id, status=foundation.Status.SUCCESS) self.warning("Unsupported command_id: %s", command_id) - return foundation.Status.UNSUP_CLUSTER_COMMAND + return foundation.GENERAL_COMMANDS[ + foundation.GeneralCommand.Default_Response + ].schema(command_id=command_id, status=foundation.Status.UNSUP_CLUSTER_COMMAND) class NeoSirenManufCluster(TuyaMCUCluster): diff --git a/zhaquirks/tuya/ts0601_trv.py b/zhaquirks/tuya/ts0601_trv.py index 6e0a9139da..4bccb24b75 100644 --- a/zhaquirks/tuya/ts0601_trv.py +++ b/zhaquirks/tuya/ts0601_trv.py @@ -885,16 +885,22 @@ async def command( try: value = success[attrid] except KeyError: - return foundation.Status.FAILURE + return foundation.GENERAL_COMMANDS[ + foundation.GeneralCommand.Default_Response + ].schema(command_id=command_id, status=foundation.Status.FAILURE) value = not value (res,) = await self.write_attributes( {"on_off": value}, manufacturer=manufacturer, ) - return [command_id, res[0].status] + return foundation.GENERAL_COMMANDS[ + foundation.GeneralCommand.Default_Response + ].schema(command_id=command_id, status=res[0].status) - return [command_id, foundation.Status.UNSUP_CLUSTER_COMMAND] + return foundation.GENERAL_COMMANDS[ + foundation.GeneralCommand.Default_Response + ].schema(command_id=command_id, status=foundation.Status.UNSUP_CLUSTER_COMMAND) ZONNSMART_MODE_ATTR = ( @@ -1262,16 +1268,22 @@ async def command( try: value = success[attrid] except KeyError: - return foundation.Status.FAILURE + return foundation.GENERAL_COMMANDS[ + foundation.GeneralCommand.Default_Response + ].schema(command_id=command_id, status=foundation.Status.FAILURE) value = not value _LOGGER.debug("CALLING WRITE FROM COMMAND") (res,) = await self.write_attributes( {"on_off": value}, manufacturer=manufacturer, ) - return [command_id, res[0].status] + return foundation.GENERAL_COMMANDS[ + foundation.GeneralCommand.Default_Response + ].schema(command_id=command_id, status=res[0].status) - return [command_id, foundation.Status.UNSUP_CLUSTER_COMMAND] + return foundation.GENERAL_COMMANDS[ + foundation.GeneralCommand.Default_Response + ].schema(command_id=command_id, status=foundation.Status.UNSUP_CLUSTER_COMMAND) class ZONNSMARTBoost(ZONNSMARTHelperOnOff): diff --git a/zhaquirks/waxman/leaksmart.py b/zhaquirks/waxman/leaksmart.py index 989ac89a05..2bcb0865f5 100644 --- a/zhaquirks/waxman/leaksmart.py +++ b/zhaquirks/waxman/leaksmart.py @@ -47,8 +47,7 @@ def __init__(self, *args, **kwargs): async def bind(self): """Bind cluster.""" - result = await self.endpoint.device.app_cluster.bind() - return result + return await self.endpoint.device.app_cluster.bind() async def write_attributes(self, attributes, manufacturer=None): """Ignore write_attributes.""" diff --git a/zhaquirks/xbee/__init__.py b/zhaquirks/xbee/__init__.py index 3da2439f01..bd3d80d11e 100644 --- a/zhaquirks/xbee/__init__.py +++ b/zhaquirks/xbee/__init__.py @@ -488,7 +488,11 @@ async def command( self._endpoint.device.endpoints[232].out_clusters[ LevelControl.cluster_id ].handle_cluster_request(hdr, value) - return 0, foundation.Status.SUCCESS + + # XXX: Is command_id=0x00 correct? + return foundation.GENERAL_COMMANDS[ + foundation.GeneralCommand.Default_Response + ].schema(command_id=0x00, status=foundation.Status.SUCCESS) class XBeeRemoteATResponse(LocalDataCluster): diff --git a/zhaquirks/xiaomi/__init__.py b/zhaquirks/xiaomi/__init__.py index b04b385b6d..ce48026c82 100644 --- a/zhaquirks/xiaomi/__init__.py +++ b/zhaquirks/xiaomi/__init__.py @@ -120,7 +120,7 @@ class XiaomiCluster(CustomCluster): def _iter_parse_attr_report( self, data: bytes - ) -> Iterator[foundation.Attribute, bytes]: + ) -> Iterator[tuple[foundation.Attribute, bytes]]: """Yield all interpretations of the first attribute in an Xiaomi report.""" # Peek at the attribute report diff --git a/zhaquirks/xiaomi/aqara/roller_curtain_e1.py b/zhaquirks/xiaomi/aqara/roller_curtain_e1.py index 2604745eab..e1fda70cb2 100644 --- a/zhaquirks/xiaomi/aqara/roller_curtain_e1.py +++ b/zhaquirks/xiaomi/aqara/roller_curtain_e1.py @@ -114,22 +114,30 @@ async def command( (res,) = await self.endpoint.multistate_output.write_attributes( {"present_value": 1} ) - return res[0].status + return foundation.GENERAL_COMMANDS[ + foundation.GeneralCommand.Default_Response + ].schema(command_id=command_id, status=res[0].status) if command_id == DOWN_CLOSE: (res,) = await self.endpoint.multistate_output.write_attributes( {"present_value": 0} ) - return res[0].status + return foundation.GENERAL_COMMANDS[ + foundation.GeneralCommand.Default_Response + ].schema(command_id=command_id, status=res[0].status) if command_id == GO_TO_LIFT_PERCENTAGE: (res,) = await self.endpoint.analog_output.write_attributes( {"present_value": (100 - args[0])} ) - return res[0].status + return foundation.GENERAL_COMMANDS[ + foundation.GeneralCommand.Default_Response + ].schema(command_id=command_id, status=res[0].status) if command_id == STOP: (res,) = await self.endpoint.multistate_output.write_attributes( {"present_value": 2} ) - return res[0].status + return foundation.GENERAL_COMMANDS[ + foundation.GeneralCommand.Default_Response + ].schema(command_id=command_id, status=res[0].status) class MultistateOutputRollerE1(CustomCluster, MultistateOutput):