Repository: mill1000/midea-msmart
Pull request #117 (2024-03-15 20:48:06)

Only update swing angles when response field is not none
When parsing PropertiesResponses, only update the device state with fields from the message that are not None.

This should fix repeated logs of 
```
Unknown <enum 'SwingAngle'>: None
```
which were originally noticed in https://github.com/mill1000/midea-ac-py/issues/101#issuecomment-1999156216


Patch:
diff --git a/msmart/device/AC/device.py b/msmart/device/AC/device.py
index d92d923..c238251 100644
--- a/msmart/device/AC/device.py
+++ b/msmart/device/AC/device.py
@@ -153,14 +153,15 @@ class AirConditioner(Device):
 
         elif isinstance(res, PropertiesResponse):
 
-            self._horizontal_swing_angle = cast(
-                AirConditioner.SwingAngle,
-                AirConditioner.SwingAngle.get_from_value(
-                    res.swing_horizontal_angle))
-            self._vertical_swing_angle = cast(
-                AirConditioner.SwingAngle,
-                AirConditioner.SwingAngle.get_from_value(
-                    res.swing_vertical_angle))
+            if res.swing_horizontal_angle:
+                self._horizontal_swing_angle = cast(
+                    AirConditioner.SwingAngle,
+                    AirConditioner.SwingAngle.get_from_value(res.swing_horizontal_angle))
+
+            if res.swing_vertical_angle:
+                self._vertical_swing_angle = cast(
+                    AirConditioner.SwingAngle,
+                    AirConditioner.SwingAngle.get_from_value(res.swing_vertical_angle))
 
     def _update_capabilities(self, res: CapabilitiesResponse) -> None:
         # Build list of supported operation modes


Test patch:
diff --git a/msmart/device/AC/test_command.py b/msmart/device/AC/test_command.py
index a78c175..74807ec 100644
--- a/msmart/device/AC/test_command.py
+++ b/msmart/device/AC/test_command.py
@@ -682,6 +682,7 @@ class TestPropertiesResponse(_TestResponseBase):
 
         # Check state
         self.assertEqual(resp.swing_vertical_angle, 0)
+        self.assertIsNone(resp.swing_horizontal_angle)
 
 
 if __name__ == "__main__":
diff --git a/msmart/device/AC/test_device.py b/msmart/device/AC/test_device.py
index 41578de..22606af 100644
--- a/msmart/device/AC/test_device.py
+++ b/msmart/device/AC/test_device.py
@@ -184,6 +184,33 @@ class TestUpdateStateFromResponse(unittest.TestCase):
         self.assertEqual(device.horizontal_swing_angle, AC.SwingAngle.POS_3)
         self.assertEqual(device.vertical_swing_angle, AC.SwingAngle.OFF)
 
+    def test_properties_missing_field(self) -> None:
+        """Test parsing of PropertiesResponse that only contains some properties."""
+        # https://github.com/mill1000/midea-msmart/issues/97#issuecomment-1949495900
+        TEST_RESPONSE = bytes.fromhex(
+            "aa13ac00000000000303b1010a0000013200c884")
+
+        # Create a dummy device
+        device = AC(0, 0, 0)
+
+        # Set some properties
+        device.horizontal_swing_angle = AC.SwingAngle.POS_5
+        device.vertical_swing_angle = AC.SwingAngle.POS_5
+
+        # Construct and assert response
+        resp = Response.construct(TEST_RESPONSE)
+        self.assertIsNotNone(resp)
+        self.assertEqual(type(resp), PropertiesResponse)
+
+        # Process response
+        device._process_state_response(resp)
+
+        # Assert that only the properties in the response are updated
+        self.assertEqual(device.horizontal_swing_angle, AC.SwingAngle.POS_3)
+
+        # Assert other properties are untouched
+        self.assertEqual(device.vertical_swing_angle, AC.SwingAngle.POS_5)
+
 
 class TestSendCommand(unittest.IsolatedAsyncioTestCase):