diff --git a/msmart/device/AC/command.py b/msmart/device/AC/command.py index b9e8df32..5a4d46ea 100644 --- a/msmart/device/AC/command.py +++ b/msmart/device/AC/command.py @@ -618,6 +618,13 @@ def decode_temp(d: int) -> Optional[float]: self.display_on = (payload[14] != 0x70) + # Decode additional temperature resolution + if self.indoor_temperature: + self.indoor_temperature += (payload[15] & 0xF) / 10 + + if self.outdoor_temperature: + self.outdoor_temperature += (payload[15] >> 4) / 10 + # TODO dudanov/MideaUART humidity set point in byte 19, mask 0x7F # TODO Some payloads are shorter than expected. Unsure what, when or why diff --git a/msmart/device/AC/test_command.py b/msmart/device/AC/test_command.py index 9ffcec3f..160ac3cb 100644 --- a/msmart/device/AC/test_command.py +++ b/msmart/device/AC/test_command.py @@ -42,6 +42,7 @@ def _test_response(self, msg) -> StateResponse: return cast(StateResponse, resp) def test_message_checksum(self) -> None: + # https://github.com/mill1000/midea-ac-py/issues/11#issuecomment-1650647625 # V3 state response with checksum as CRC, and shorter than expected TEST_MESSAGE_CHECKSUM_AS_CRC = bytes.fromhex( "aa1eac00000000000003c0004b1e7f7f000000000069630000000000000d33") @@ -89,6 +90,70 @@ def test_message_v3(self) -> None: self.assertEqual(resp.indoor_temperature, 21.0) self.assertEqual(resp.outdoor_temperature, 28.5) + def test_message_additional_precision(self) -> None: + """Test decoding of temperatures with higher precision.""" + # Messages with additional temperature precision bits + TEST_MESSAGES = { + # https://github.com/mill1000/midea-msmart/issues/89#issuecomment-1783316836 + (24.0, 25.1, 10.0): bytes.fromhex( + "aa23ac00000000000203c00188647f7f000000000063450c0056190000000000000497c3"), + # https://github.com/mill1000/midea-msmart/issues/89#issuecomment-1782352164 + (24.0, 27.0, 10.2): bytes.fromhex( + "aa23ac00000000000203c00188647f7f000000000067450c00750000000000000001a3b0"), + (24.0, 25.0, 10.0): bytes.fromhex( + "aa23ac00000000000203c00188647f7f000080000064450c00501d00000000000001508e"), + } + + for targets, message in TEST_MESSAGES.items(): + # Create response from the message + resp = self._test_response(message) + + # Assert response is a state response + self.assertEqual(type(resp), StateResponse) + + # Suppress type errors + resp = cast(StateResponse, resp) + + target, indoor, outdoor = targets + + self.assertEqual(resp.target_temperature, target) + self.assertEqual(resp.indoor_temperature, indoor) + self.assertEqual(resp.outdoor_temperature, outdoor) + + # Raw responses with additional temperature precision bits + TEST_RESPONSES = { + # https://github.com/mill1000/midea-ac-py/issues/39#issuecomment-1729884851 + # Corrected target values from user reported values + (16.0, 23.2, 18.4): bytes.fromhex("c00181667f7f003c00000060560400420000000000000048"), + (16.5, 23.4, 18.4): bytes.fromhex("c00191667f7f003c00000060560400440000000000000049"), + (17.0, 24.1, 18.3): bytes.fromhex("c00181667f7f003c0000006156050036000000000000004a"), + (17.5, 24.3, 18.2): bytes.fromhex("c00191667f7f003c0000006156050028000000000000004b"), + (18.0, 24.3, 18.2): bytes.fromhex("c00182667f7f003c0000006156060028000000000000004c"), + (18.5, 24.3, 18.2): bytes.fromhex("c00192667f7f003c0000006156060028000000000000004d"), + (19.0, 24.3, 18.2): bytes.fromhex("c00183667f7f003c0000006156070028000000000000004e"), + (19.5, 24.0, 19.0): bytes.fromhex("c00193667f7f003c00000061570700550000000000000050"), + } + + for targets, payload in TEST_RESPONSES.items(): + # Create response + with memoryview(payload) as mv_payload: + resp = StateResponse(mv_payload) + + # Assert that it exists + self.assertIsNotNone(resp) + + # Assert response is a state response + self.assertEqual(type(resp), StateResponse) + + # Suppress type errors + resp = cast(StateResponse, resp) + + target, indoor, outdoor = targets + + self.assertEqual(resp.target_temperature, target) + self.assertEqual(resp.indoor_temperature, indoor) + self.assertEqual(resp.outdoor_temperature, outdoor) + def test_target_temperature(self) -> None: """Test decoding of target temperature from a variety of state responses.""" TEST_PAYLOADS = {