diff --git a/tests/test_sinope.py b/tests/test_sinope.py index 3dd6a5221b..3f377a858d 100644 --- a/tests/test_sinope.py +++ b/tests/test_sinope.py @@ -101,10 +101,10 @@ def _get_packet_data( @pytest.mark.parametrize( "press_type,button,exp_event", ( - (ButtonAction.Single_off, TURN_OFF, COMMAND_M_INITIAL_PRESS), - (ButtonAction.Single_on, TURN_ON, COMMAND_M_INITIAL_PRESS), - (ButtonAction.Single_release_off, TURN_OFF, COMMAND_M_SHORT_RELEASE), - (ButtonAction.Single_release_on, TURN_ON, COMMAND_M_SHORT_RELEASE), + (ButtonAction.Pressed_off, TURN_OFF, COMMAND_M_INITIAL_PRESS), + (ButtonAction.Pressed_on, TURN_ON, COMMAND_M_INITIAL_PRESS), + (ButtonAction.Released_off, TURN_OFF, COMMAND_M_SHORT_RELEASE), + (ButtonAction.Released_on, TURN_ON, COMMAND_M_SHORT_RELEASE), (ButtonAction.Double_on, TURN_ON, COMMAND_M_MULTI_PRESS_COMPLETE), (ButtonAction.Double_off, TURN_OFF, COMMAND_M_MULTI_PRESS_COMPLETE), (ButtonAction.Long_on, TURN_ON, COMMAND_M_LONG_RELEASE), @@ -135,7 +135,16 @@ class Listener: ), ) data = _get_packet_data(foundation.GeneralCommand.Report_Attributes, attr) - device.handle_message(260, cluster_id, endpoint_id, endpoint_id, data) + + device.packet_received( + t.ZigbeePacket( + profile_id=260, + cluster_id=cluster_id, + src_ep=endpoint_id, + dst_ep=endpoint_id, + data=t.SerializableBytes(data), + ) + ) if exp_event is None: assert cluster_listener.zha_send_event.call_count == 0 @@ -147,6 +156,7 @@ class Listener: "attribute_id": 84, "attribute_name": "action_report", "button": button, + "description": press_type.name, "value": press_type.value, }, ) @@ -172,7 +182,15 @@ class Listener: # read attributes general command data = _get_packet_data(foundation.GeneralCommand.Read_Attributes) - device.handle_message(260, cluster_id, endpoint_id, endpoint_id, data) + device.packet_received( + t.ZigbeePacket( + profile_id=260, + cluster_id=cluster_id, + src_ep=endpoint_id, + dst_ep=endpoint_id, + data=t.SerializableBytes(data), + ) + ) # no ZHA events emitted because we only handle Report_Attributes assert cluster_listener.zha_send_event.call_count == 0 @@ -184,7 +202,15 @@ class Listener: ), # 0x29 = t.int16s ) data = _get_packet_data(foundation.GeneralCommand.Report_Attributes, attr) - device.handle_message(260, cluster_id, endpoint_id, endpoint_id, data) + device.packet_received( + t.ZigbeePacket( + profile_id=260, + cluster_id=cluster_id, + src_ep=endpoint_id, + dst_ep=endpoint_id, + data=t.SerializableBytes(data), + ) + ) # ZHA event emitted because we pass non "action_report" # reports to the base class handler. assert cluster_listener.zha_send_event.call_count == 1 diff --git a/zhaquirks/sinope/__init__.py b/zhaquirks/sinope/__init__.py index 439b283217..ff59f319da 100644 --- a/zhaquirks/sinope/__init__.py +++ b/zhaquirks/sinope/__init__.py @@ -1,6 +1,7 @@ """Module for Sinope quirks implementations.""" from zigpy.quirks import CustomCluster +import zigpy.types as t from zigpy.zcl.clusters.general import DeviceTemperature from zhaquirks.const import ( @@ -16,7 +17,7 @@ COMMAND_M_SHORT_RELEASE, DOUBLE_PRESS, ENDPOINT_ID, - LONG_RELEASE, + LONG_PRESS, SHORT_PRESS, SHORT_RELEASE, TURN_OFF, @@ -28,6 +29,20 @@ SINOPE_MANUFACTURER_CLUSTER_ID = 0xFF01 ATTRIBUTE_ACTION = "action_report" + +class ButtonAction(t.enum8): + """Action_report values.""" + + Pressed_on = 0x01 + Released_on = 0x02 + Long_on = 0x03 + Double_on = 0x04 + Pressed_off = 0x11 + Released_off = 0x12 + Long_off = 0x13 + Double_off = 0x14 + + LIGHT_DEVICE_TRIGGERS = { (SHORT_PRESS, TURN_ON): { ENDPOINT_ID: 1, @@ -37,7 +52,7 @@ ATTRIBUTE_ID: 84, ATTRIBUTE_NAME: ATTRIBUTE_ACTION, BUTTON: TURN_ON, - VALUE: 1, + VALUE: ButtonAction.Pressed_on, }, }, (SHORT_PRESS, TURN_OFF): { @@ -48,7 +63,7 @@ ATTRIBUTE_ID: 84, ATTRIBUTE_NAME: ATTRIBUTE_ACTION, BUTTON: TURN_OFF, - VALUE: 17, + VALUE: ButtonAction.Pressed_off, }, }, (SHORT_RELEASE, TURN_ON): { @@ -59,7 +74,7 @@ ATTRIBUTE_ID: 84, ATTRIBUTE_NAME: ATTRIBUTE_ACTION, BUTTON: TURN_ON, - VALUE: 2, + VALUE: ButtonAction.Released_on, }, }, (SHORT_RELEASE, TURN_OFF): { @@ -70,7 +85,7 @@ ATTRIBUTE_ID: 84, ATTRIBUTE_NAME: ATTRIBUTE_ACTION, BUTTON: TURN_OFF, - VALUE: 18, + VALUE: ButtonAction.Released_off, }, }, (DOUBLE_PRESS, TURN_ON): { @@ -81,7 +96,7 @@ ATTRIBUTE_ID: 84, ATTRIBUTE_NAME: ATTRIBUTE_ACTION, BUTTON: TURN_ON, - VALUE: 4, + VALUE: ButtonAction.Double_on, }, }, (DOUBLE_PRESS, TURN_OFF): { @@ -92,10 +107,10 @@ ATTRIBUTE_ID: 84, ATTRIBUTE_NAME: ATTRIBUTE_ACTION, BUTTON: TURN_OFF, - VALUE: 20, + VALUE: ButtonAction.Double_off, }, }, - (LONG_RELEASE, TURN_ON): { + (LONG_PRESS, TURN_ON): { ENDPOINT_ID: 1, CLUSTER_ID: 65281, COMMAND: COMMAND_M_LONG_RELEASE, @@ -103,10 +118,10 @@ ATTRIBUTE_ID: 84, ATTRIBUTE_NAME: ATTRIBUTE_ACTION, BUTTON: TURN_ON, - VALUE: 3, + VALUE: ButtonAction.Long_on, }, }, - (LONG_RELEASE, TURN_OFF): { + (LONG_PRESS, TURN_OFF): { ENDPOINT_ID: 1, CLUSTER_ID: 65281, COMMAND: COMMAND_M_LONG_RELEASE, @@ -114,7 +129,7 @@ ATTRIBUTE_ID: 84, ATTRIBUTE_NAME: ATTRIBUTE_ACTION, BUTTON: TURN_OFF, - VALUE: 19, + VALUE: ButtonAction.Long_off, }, }, } diff --git a/zhaquirks/sinope/light.py b/zhaquirks/sinope/light.py index 94b7acd729..cb235f252f 100644 --- a/zhaquirks/sinope/light.py +++ b/zhaquirks/sinope/light.py @@ -30,10 +30,12 @@ ATTRIBUTE_ID, ATTRIBUTE_NAME, BUTTON, + COMMAND, COMMAND_M_INITIAL_PRESS, COMMAND_M_LONG_RELEASE, COMMAND_M_MULTI_PRESS_COMPLETE, COMMAND_M_SHORT_RELEASE, + DESCRIPTION, DEVICE_TYPE, ENDPOINTS, INPUT_CLUSTERS, @@ -51,6 +53,7 @@ LIGHT_DEVICE_TRIGGERS, SINOPE, SINOPE_MANUFACTURER_CLUSTER_ID, + ButtonAction, CustomDeviceTemperatureCluster, ) @@ -79,19 +82,6 @@ class DoubleFull(t.enum8): On = 0x01 -class ButtonAction(t.enum8): - """Action_report values.""" - - Single_on = 0x01 - Single_release_on = 0x02 - Long_on = 0x03 - Double_on = 0x04 - Single_off = 0x11 - Single_release_off = 0x12 - Long_off = 0x13 - Double_off = 0x14 - - class SinopeTechnologiesManufacturerCluster(CustomCluster): """SinopeTechnologiesManufacturerCluster manufacturer cluster.""" @@ -163,7 +153,7 @@ class AttributeDefs(foundation.BaseAttributeDefs): server_commands = { 0x54: foundation.ZCLCommandDef( "button_press", - {"command": t.uint8_t}, + {COMMAND: t.uint8_t}, direction=foundation.Direction.Server_to_Client, is_manufacturer_specific=True, ) @@ -197,26 +187,27 @@ def handle_cluster_general_request( hdr, args, dst_addressing=dst_addressing ) - value = attr.value.value + action = self.Action(attr.value.value) - action, button = self._get_command_from_action(self.Action(value)) - if not action or not button: + command, button = self._get_command_from_action(action) + if not command or not button: return event_args = { ATTRIBUTE_ID: 84, ATTRIBUTE_NAME: ATTRIBUTE_ACTION, BUTTON: button, - VALUE: value.value, + DESCRIPTION: action.name, + VALUE: action.value, } self.debug( - "SINOPE ZHA_SEND_EVENT action: '%s' event_args: %s", - self.Action(value), + "SINOPE ZHA_SEND_EVENT command: '%s' event_args: %s", + command, event_args, ) - self.listener_event(ZHA_SEND_EVENT, action, event_args) + self.listener_event(ZHA_SEND_EVENT, command, event_args) def _get_command_from_action( self, action: ButtonAction @@ -224,13 +215,13 @@ def _get_command_from_action( # const lookup = {1: 'up_single', 2: 'up_single_released', 3: 'up_hold', 4: 'up_double', # 17: 'down_single, 18: 'down_single_released', 19: 'down_hold', 20: 'down_double'}; match action: - case self.Action.Single_off: + case self.Action.Pressed_off: return COMMAND_M_INITIAL_PRESS, TURN_OFF - case self.Action.Single_on: + case self.Action.Pressed_on: return COMMAND_M_INITIAL_PRESS, TURN_ON - case self.Action.Single_release_off: + case self.Action.Released_off: return COMMAND_M_SHORT_RELEASE, TURN_OFF - case self.Action.Single_release_on: + case self.Action.Released_on: return COMMAND_M_SHORT_RELEASE, TURN_ON case self.Action.Double_off: return COMMAND_M_MULTI_PRESS_COMPLETE, TURN_OFF