|
| 1 | +"""Midea local AD message.""" |
| 2 | + |
| 3 | +from midealocal.const import DeviceType |
| 4 | +from midealocal.crc8 import calculate |
| 5 | +from midealocal.message import ( |
| 6 | + ListTypes, |
| 7 | + MessageBody, |
| 8 | + MessageRequest, |
| 9 | + MessageResponse, |
| 10 | + MessageType, |
| 11 | +) |
| 12 | + |
| 13 | +MAX_MSG_SERIAL_NUM = 254 |
| 14 | + |
| 15 | + |
| 16 | +class MessageADBase(MessageRequest): |
| 17 | + """AD message base.""" |
| 18 | + |
| 19 | + _message_serial = 0 |
| 20 | + |
| 21 | + def __init__( |
| 22 | + self, |
| 23 | + protocol_version: int, |
| 24 | + message_type: MessageType, |
| 25 | + body_type: ListTypes, |
| 26 | + ) -> None: |
| 27 | + """Initialize AD message base.""" |
| 28 | + super().__init__( |
| 29 | + device_type=DeviceType.AD, |
| 30 | + protocol_version=protocol_version, |
| 31 | + message_type=message_type, |
| 32 | + body_type=body_type, |
| 33 | + ) |
| 34 | + MessageADBase._message_serial += 1 |
| 35 | + if MessageADBase._message_serial >= MAX_MSG_SERIAL_NUM: |
| 36 | + MessageADBase._message_serial = 1 |
| 37 | + self._message_id = MessageADBase._message_serial |
| 38 | + |
| 39 | + @property |
| 40 | + def _body(self) -> bytearray: |
| 41 | + raise NotImplementedError |
| 42 | + |
| 43 | + @property |
| 44 | + def body(self) -> bytearray: |
| 45 | + """AD message base body.""" |
| 46 | + body = bytearray([self.body_type]) + self._body + bytearray([self._message_id]) |
| 47 | + body.append(calculate(body)) |
| 48 | + return body |
| 49 | + |
| 50 | + |
| 51 | +class Message21Query(MessageADBase): |
| 52 | + """AD X21 message query.""" |
| 53 | + |
| 54 | + def __init__(self, protocol_version: int) -> None: |
| 55 | + """Initialize AD X21 message query.""" |
| 56 | + super().__init__( |
| 57 | + protocol_version=protocol_version, |
| 58 | + message_type=MessageType.query, |
| 59 | + body_type=ListTypes.X21, |
| 60 | + ) |
| 61 | + |
| 62 | + @property |
| 63 | + def _body(self) -> bytearray: |
| 64 | + return bytearray( |
| 65 | + [ |
| 66 | + 0x01, |
| 67 | + ], |
| 68 | + ) |
| 69 | + |
| 70 | + |
| 71 | +class Message31Query(MessageADBase): |
| 72 | + """AD X31 message query.""" |
| 73 | + |
| 74 | + def __init__(self, protocol_version: int) -> None: |
| 75 | + """Initialize AD X31 message query.""" |
| 76 | + super().__init__( |
| 77 | + protocol_version=protocol_version, |
| 78 | + message_type=MessageType.query, |
| 79 | + body_type=ListTypes.X31, |
| 80 | + ) |
| 81 | + |
| 82 | + @property |
| 83 | + def _body(self) -> bytearray: |
| 84 | + return bytearray( |
| 85 | + [ |
| 86 | + 0x01, |
| 87 | + ], |
| 88 | + ) |
| 89 | + |
| 90 | + |
| 91 | +class X31MessageBody(MessageBody): |
| 92 | + """AD X31 message general body.""" |
| 93 | + |
| 94 | + def __init__(self, body: bytearray) -> None: |
| 95 | + """Initialize AD X31 message general body.""" |
| 96 | + super().__init__(body) |
| 97 | + self.screen_status = body[2] > 0 if body[2] != ListTypes.FF else None |
| 98 | + self.led_status = body[3] > 0 if body[3] != ListTypes.FF else None |
| 99 | + self.arofene_link = body[4] > 0 if body[4] != ListTypes.FF else None |
| 100 | + self.header_exist = body[5] > 0 if body[5] != ListTypes.FF else None |
| 101 | + self.radar_exist = body[6] > 0 if body[6] != ListTypes.FF else None |
| 102 | + self.header_led_status = body[7] > 0 if body[7] != ListTypes.FF else None |
| 103 | + self.temperature_raw = ( |
| 104 | + (body[8] << 8) + body[9] if body[8] != ListTypes.FF else None |
| 105 | + ) |
| 106 | + self.humidity_raw = ( |
| 107 | + (body[10] << 8) + body[11] if body[10] != ListTypes.FF else None |
| 108 | + ) |
| 109 | + self.temperature_compensate = ( |
| 110 | + (body[12] << 8) + body[13] if body[1] > ListTypes.X0D else None |
| 111 | + ) |
| 112 | + self.humidity_compensate = ( |
| 113 | + (body[14] << 8) + body[15] if body[1] > ListTypes.X0D else None |
| 114 | + ) |
| 115 | + |
| 116 | + |
| 117 | +class X21MessageBody(MessageBody): |
| 118 | + """AD X21 message general body.""" |
| 119 | + |
| 120 | + def __init__(self, body: bytearray) -> None: |
| 121 | + """Initialize AD X21 message general body.""" |
| 122 | + super().__init__(body) |
| 123 | + self.portable_sense = body[2] > 0 |
| 124 | + self.night_mode = body[3] > 0 |
| 125 | + self.screen_extinction_timeout = body[4] if (body[4] != ListTypes.FF) else None |
| 126 | + |
| 127 | + |
| 128 | +class ADNotifyMessageBody(MessageBody): |
| 129 | + """AD message notify body.""" |
| 130 | + |
| 131 | + def __init__(self, body: bytearray) -> None: |
| 132 | + """Initialize AD message notify body.""" |
| 133 | + super().__init__(body) |
| 134 | + if body[1] == 0x01: |
| 135 | + self.temperature = ( |
| 136 | + ((((body[3] << 8) + body[4]) - 65535) - 1) / 100 |
| 137 | + if body[3] >= ListTypes.X80 # >= 128 |
| 138 | + else ((body[3] << 8) + body[4]) / 100 |
| 139 | + ) |
| 140 | + self.humidity = ( |
| 141 | + ((body[5] << 8) + body[6]) / 100 if body[5] != ListTypes.FF else None |
| 142 | + ) |
| 143 | + self.tvoc = ((body[7] << 8) + body[8]) if body[7] != ListTypes.FF else None |
| 144 | + self.pm25 = ((body[9] << 8) + body[10]) if body[9] != ListTypes.FF else None |
| 145 | + self.co2 = ( |
| 146 | + ((body[11] << 8) + body[12]) if body[11] != ListTypes.FF else None |
| 147 | + ) |
| 148 | + self.hcho = ( |
| 149 | + ((body[13] << 8) + body[14]) / 0.1 if body[13] != ListTypes.FF else None |
| 150 | + ) |
| 151 | + self.arofene_link = ( |
| 152 | + ((body[16] & 0x01) > 0) if body[16] != ListTypes.FF else None |
| 153 | + ) |
| 154 | + self.radar_exist = ( |
| 155 | + ((body[16] & 0x02) > 0) if body[16] != ListTypes.FF else None |
| 156 | + ) |
| 157 | + elif body[1] == ListTypes.X04: |
| 158 | + if body[3] == ListTypes.X01: |
| 159 | + self.presets_function = body[4] == 0x01 |
| 160 | + elif body[3] == ListTypes.X02: |
| 161 | + self.fall_asleep_status = body[4] == 0x01 |
| 162 | + |
| 163 | + |
| 164 | +class MessageADResponse(MessageResponse): |
| 165 | + """AD message response.""" |
| 166 | + |
| 167 | + def __init__(self, message: bytes) -> None: |
| 168 | + """Initialize AD message response.""" |
| 169 | + super().__init__(bytearray(message)) |
| 170 | + |
| 171 | + if self._body_type == ListTypes.X11: |
| 172 | + self.set_body(ADNotifyMessageBody(super().body)) |
| 173 | + elif self._body_type == ListTypes.X21: |
| 174 | + self.set_body(X21MessageBody(super().body)) |
| 175 | + elif self._body_type == ListTypes.X31: |
| 176 | + self.set_body(X31MessageBody(super().body)) |
| 177 | + self.set_attr() |
0 commit comments