Repository: mill1000/midea-msmart (python)

Issue:
Ignore "capability" responses (0xB5) with a frame type of 0x05
Originally noticed in the debug log from this post.

> [midea_msmart.debug_3.log](https://github.com/mill1000/midea-ac-py/files/15209814/midea_msmart.debug_3.log)

_Originally posted by @v1k70rk4 in https://github.com/mill1000/midea-ac-py/issues/122#issuecomment-2094145935_

The log contains the following bit of interest
```
2024-05-04 15:11:14.231 DEBUG (MainThread) [msmart.lan] Received response from 192.168.1.60:6444: aa12ac00000000000205b50110060101bda808
...
2024-05-04 15:11:14.373 DEBUG (MainThread) [msmart.device.AC.command] Capabilities response payload: b50110060101bd
2024-05-04 15:11:14.374 WARNING (MainThread) [msmart.device.AC.command] Unknown capability. ID: 0x 610, Size: 1.
2024-05-04 15:11:14.374 DEBUG (MainThread) [msmart.device.AC.command] Raw capabilities: {}
...
2024-05-04 15:11:14.374 DEBUG (MainThread) [msmart.device.AC.device] Ignored unknown response from 192.168.1.60:6444: b50110060101bd
```

The response was ignored, but we should have never processed it as a capabilities response. Based on the Lua, it looks like some special case property response, but the ID 0x610 is not handled by the Lua.

The log contains additional entries with known property IDs.
```
2024-05-04 15:11:59.388 DEBUG (MainThread) [msmart.device.AC.command] Capabilities response payload: b50310060101090001010a000101dc
2024-05-04 15:11:59.389 WARNING (MainThread) [msmart.device.AC.command] Unknown capability. ID: 0x 610, Size: 1.
2024-05-04 15:11:59.389 DEBUG (MainThread) [msmart.device.AC.command] Raw capabilities: {'swing_vertical_angle': True, 'swing_horizontal_angle': True}
2024-05-04 15:11:59.390 DEBUG (MainThread) [msmart.device.AC.device] Ignored unknown response from 192.168.1.60:6444: b50310060101090001010a000101dc
```

Likely this message is some kind of property update notification.

Pull request:
Ignore "capability" responses with unexpected frame type.
Close #122 

Add test case to ensure 0xB5 responses with different frame types are ignored.

Patch:
diff --git a/msmart/device/AC/command.py b/msmart/device/AC/command.py
index 80b616a..7944dea 100644
--- a/msmart/device/AC/command.py
+++ b/msmart/device/AC/command.py
@@ -356,10 +356,12 @@ class Response():
             Frame.validate(frame_mv)
 
             # Fetch the appropriate response class from the ID
+            frame_type = frame_mv[9]
             response_id = frame_mv[10]
             if response_id == ResponseId.STATE:
                 response_class = StateResponse
-            elif response_id == ResponseId.CAPABILITIES:
+            elif response_id == ResponseId.CAPABILITIES and frame_type == FrameType.QUERY:
+                # Some devices have unsolicited "capabilities" responses with a frame type of 0x5
                 response_class = CapabilitiesResponse
             elif response_id in [ResponseId.PROPERTIES, ResponseId.PROPERTIES_ACK]:
                 response_class = PropertiesResponse


Test patch:
diff --git a/msmart/device/AC/test_command.py b/msmart/device/AC/test_command.py
index cc171e9..11e963a 100644
--- a/msmart/device/AC/test_command.py
+++ b/msmart/device/AC/test_command.py
@@ -662,6 +662,17 @@ class TestPropertiesResponse(_TestResponseBase):
         self.assertEqual(resp.get_property(PropertyId.SWING_LR_ANGLE), 50)
         self.assertEqual(resp.get_property(PropertyId.SWING_UD_ANGLE), 0)
 
+    def test_properties_notify(self) -> None:
+        """Test ignore property notifications."""
+        # https://github.com/mill1000/midea-msmart/issues/122
+        TEST_RESPONSE = bytes.fromhex(
+            "aa1aac00000000000205b50310060101090001010a000101dcbcb4")
+
+        resp = self._test_build_response(TEST_RESPONSE)
+
+        # Assert response is generic
+        self.assertEqual(type(resp), Response)
+
 
 class TestResponseConstruct(_TestResponseBase):
     """Test construction of responses from raw data."""