Repository: mill1000/midea-msmart
Pull request #137 (2024-07-10 02:59:26)

Supress warning from unknown and unsupported capabilities
This warning comes up every now and then in user logs. Totally harmless but I think it does cause some distress to new users.

https://github.com/mill1000/midea-ac-py/issues/81


Patch:
diff --git a/msmart/device/AC/command.py b/msmart/device/AC/command.py
index cf3a44c..028d00f 100644
--- a/msmart/device/AC/command.py
+++ b/msmart/device/AC/command.py
@@ -34,6 +34,7 @@ class CapabilityId(IntEnum):
     WIND_ON_ME = 0x0032
     WIND_OFF_ME = 0x0033
     SELF_CLEAN = 0x0039  # AKA Active Clean
+    _UNKNOWN = 0x0040  # Unknown ID from various logs
     ONE_KEY_NO_WIND_ON_ME = 0x0042
     BREEZE_CONTROL = 0x0043  # AKA "FA No Wind Sense"
     RATE_SELECT = 0x0048
@@ -511,6 +512,7 @@ class CapabilitiesResponse(Response):
             # CapabilityId.TEMPERATURES too complex to be handled here
             CapabilityId.WIND_OFF_ME:  reader("wind_off_me", get_value(1)),
             CapabilityId.WIND_ON_ME:  reader("wind_on_me", get_value(1)),
+            # CapabilityId._UNKNOWN is a special case
         }
 
         count = payload[1]
@@ -574,8 +576,13 @@ class CapabilitiesResponse(Response):
                 self._capabilities["decimals"] = (
                     caps[9] if size > 6 else caps[2]) != 0
 
+            elif capability_id == CapabilityId._UNKNOWN:
+                # Supress warnings from unknown capability
+                _LOGGER.debug(
+                    "Ignored unknown capability. ID: 0x%04X, Size: %d.", capability_id, size)
+
             else:
-                _LOGGER.warning(
+                _LOGGER.info(
                     "Unsupported capability. ID: 0x%04X, Size: %d.", capability_id, size)
 
             # Advanced to next capability


Test patch:
diff --git a/msmart/device/AC/test_command.py b/msmart/device/AC/test_command.py
index c0ee681..9261a39 100644
--- a/msmart/device/AC/test_command.py
+++ b/msmart/device/AC/test_command.py
@@ -347,12 +347,13 @@ class TestCapabilitiesResponse(_TestResponseBase):
             "aa3dac00000000000203b50a12020101180001001402010115020101160201001a020101100201011f020100250207203c203c203c00400001000100c83a")
 
         # Test case includes an unknown capability 0x40 that generates a warning
-        with self.assertLogs("msmart") as log:
+        with self.assertLogs("msmart", logging.DEBUG) as log:
             resp = self._test_build_response(TEST_CAPABILITIES_RESPONSE)
             resp = cast(CapabilitiesResponse, resp)
 
-            # Check warning is generated for ID 0x0040
-            self.assertRegex(log.output[0], "Unknown capability. ID: 0x0040")
+            # Check debug message is generated for ID 0x0040
+            self.assertRegex("\n".join(log.output),
+                             "Ignored unknown capability. ID: 0x0040")
 
         EXPECTED_RAW_CAPABILITIES = {
             "eco_mode": True, "eco_mode_2": False, "silky_cool": False,
@@ -473,13 +474,14 @@ class TestCapabilitiesResponse(_TestResponseBase):
         TEST_CAPABILITIES_RESPONSE = bytes.fromhex(
             "aa3dac00000000000303b50a12020101430001011402010115020101160201001a020101100201011f020103250207203c203c203c05400001000100c805")
 
-        # Test case includes an unknown capability 0x40 that generates a warning
-        with self.assertLogs("msmart") as log:
+        # Test case includes an unknown capability 0x40 that generates a log
+        with self.assertLogs("msmart", logging.DEBUG) as log:
             resp = self._test_build_response(TEST_CAPABILITIES_RESPONSE)
             resp = cast(CapabilitiesResponse, resp)
 
-            # Check warning is generated for ID 0x0040
-            self.assertRegex(log.output[0], "Unknown capability. ID: 0x0040")
+            # Check debug message is generated for ID 0x0040
+            self.assertRegex("\n".join(log.output),
+                             "Ignored unknown capability. ID: 0x0040")
 
         EXPECTED_RAW_CAPABILITIES = {
             "eco_mode": True, "eco_mode_2": False,