This repository has been archived by the owner on Apr 20, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 177
/
command.py
258 lines (198 loc) · 7.15 KB
/
command.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
import midea.crc8 as crc8
VERSION = '0.1.7'
class base_command:
def __init__(self, device_type=0xAC):
# More magic numbers. I'm sure each of these have a purpose, but none of it is documented in english. I might make an effort to google translate the SDK
self.data = bytearray([
0xaa, 0x23, 0xAC, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x02, 0x40, 0x81, 0x00, 0xff, 0x03, 0xff,
0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0xcc
])
self.data[0x02] = device_type
def finalize(self):
# Add the CRC8
self.data[0x1d] = crc8.calculate(self.data[16:])
# Set the length of the command data
self.data[0x01] = len(self.data)
return self.data
class set_command(base_command):
def __init__(self, device_type):
base_command.__init__(self, device_type)
@property
def audible_feedback(self):
return self.data[0x0b] & 0x42
@audible_feedback.setter
def audible_feedback(self, feedback_anabled: bool):
self.data[0x0b] &= ~ 0x42 # Clear the audible bits
self.data[0x0b] |= 0x42 if feedback_anabled else 0
@property
def power_state(self):
return self.data[0x0b] & 0x01
@power_state.setter
def power_state(self, state: bool):
self.data[0x0b] &= ~ 0x01 # Clear the power bit
self.data[0x0b] |= 0x01 if state else 0
@property
def target_temperature(self):
return self.data[0x0c] & 0x1f
@target_temperature.setter
def target_temperature(self, temperature_celsius: int):
self.data[0x0c] &= ~ 0x1f # Clear the temperature bits
self.data[0x0c] |= (temperature_celsius & 0xf) | (
(temperature_celsius << 4) & 0x10)
@property
def operational_mode(self):
return (self.data[0x0c] & 0xe0) >> 5
@operational_mode.setter
def operational_mode(self, mode: int):
self.data[0x0c] &= ~ 0xe0 # Clear the mode bit
self.data[0x0c] |= (mode << 5) & 0xe0
@property
def fan_speed(self):
return self.data[0x0d]
@fan_speed.setter
def fan_speed(self, speed: int):
self.data[0x0d] = speed
@property
def eco_mode(self):
return self.data[0x13] > 0
@eco_mode.setter
def eco_mode(self, eco_mode_enabled: bool):
self.data[0x13] = 0xFF if eco_mode_enabled else 0
@property
def swing_mode(self):
return self.data[0x11]
@swing_mode.setter
def swing_mode(self, mode: int):
self.data[0x11] &= ~ 0x0f # Clear the mode bit
self.data[0x11] |= mode & 0x0f
@property
def turbo_mode(self):
return self.data[0x14] > 0
@turbo_mode.setter
def turbo_mode(self, turbo_mode_enabled: bool):
self.data[0x14] = 0x02 if turbo_mode_enabled else 0
class appliance_response:
def __init__(self, data: bytearray):
# The response data from the appliance includes a packet header which we don't want
self.data = data[0x32:]
if(__debug__):
print("Appliance response data: {}".format(self.data.hex()))
# Byte 0x01
@property
def power_state(self):
return (self.data[0x01] & 0x1) > 0
@property
def imode_resume(self):
return (self.data[0x01] & 0x4) > 0
@property
def timer_mode(self):
return (self.data[0x01] & 0x10) > 0
@property
def appliance_error(self):
return (self.data[0x01] & 0x80) > 0
# Byte 0x02
@property
def target_temperature(self):
return (self.data[0x02] & 0xf) + 16
@property
def operational_mode(self):
return (self.data[0x02] & 0xe0) >> 5
# Byte 0x03
@property
def fan_speed(self):
return self.data[0x03] & 0x7f
# Byte 0x04 + 0x06
@property
def on_timer(self):
on_timer_value = self.data[0x04]
on_timer_minutes = self.data[0x06]
return {
'status': ((on_timer_value & 0x80) >> 7) > 0,
'hour': (on_timer_value & 0x7c) >> 2,
'minutes': (on_timer_value & 0x3) | ((on_timer_minutes & 0xf0) >> 4)
}
# Byte 0x05 + 0x06
@property
def off_timer(self):
off_timer_value = self.data[0x05]
off_timer_minutes = self.data[0x06]
return {
'status': ((off_timer_value & 0x80) >> 7) > 0,
'hour': (off_timer_value & 0x7c) >> 2,
'minutes': (off_timer_value & 0x3) | (off_timer_minutes & 0xf)
}
# Byte 0x07
@property
def swing_mode(self):
return self.data[0x07] & 0x0f
# Byte 0x08
@property
def cozy_sleep(self):
return self.data[0x08] & 0x03
@property
def save(self): # This needs a better name, dunno what it actually means
return (self.data[0x08] & 0x08) > 0
@property
def low_frequency_fan(self):
return (self.data[0x08] & 0x10) > 0
@property
def super_fan(self):
return (self.data[0x08] & 0x20) > 0
@property
def feel_own(self): # This needs a better name, dunno what it actually means
return (self.data[0x08] & 0x80) > 0
# Byte 0x09
@property
def child_sleep_mode(self):
return (self.data[0x09] & 0x01) > 0
@property
def exchange_air(self):
return (self.data[0x09] & 0x02) > 0
@property
def dry_clean(self): # This needs a better name, dunno what it actually means
return (self.data[0x09] & 0x04) > 0
@property
def aux_heat(self):
return (self.data[0x09] & 0x08) > 0
@property
def eco_mode(self):
return (self.data[0x09] & 0x10) > 0
@property
def clean_up(self): # This needs a better name, dunno what it actually means
return (self.data[0x09] & 0x20) > 0
@property
def temp_unit(self): # This needs a better name, dunno what it actually means
return (self.data[0x09] & 0x80) > 0
# Byte 0x0a
@property
def sleep_function(self):
return (self.data[0x0a] & 0x01) > 0
@property
def turbo_mode(self):
return (self.data[0x0a] & 0x02) > 0
@property
def catch_cold(self): # This needs a better name, dunno what it actually means
return (self.data[0x0a] & 0x08) > 0
@property
def night_light(self): # This needs a better name, dunno what it actually means
return (self.data[0x0a] & 0x10) > 0
@property
def peak_elec(self): # This needs a better name, dunno what it actually means
return (self.data[0x0a] & 0x20) > 0
@property
def natural_fan(self): # This needs a better name, dunno what it actually means
return (self.data[0x0a] & 0x40) > 0
# Byte 0x0b
@property
def indoor_temperature(self):
return (self.data[0x0b] - 50) / 2.0
# Byte 0x0c
@property
def outdoor_temperature(self):
return (self.data[0x0c] - 50) / 2.0
# Byte 0x0d
@property
def humidity(self):
return (self.data[0x0d] & 0x7f)