homebridge-midea-platform 1.2.7-beta.3 → 1.2.8-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1227 @@
1
+ ----除湿机协议解析
2
+ ----author: tong.li
3
+ ----date : 2017/7/13
4
+
5
+
6
+ local JSON = require "cjson"
7
+
8
+ -----------------JSON相关key值变量-----------------
9
+ local keyT = {}
10
+ --版本号
11
+ keyT["KEY_VERSION"]="version"
12
+ --电源
13
+ keyT["KEY_POWER"] = "power"
14
+ --风速
15
+ keyT["KEY_WIND_SPEED"] = "wind_speed"
16
+ --模式
17
+ keyT["KEY_MODE"] = "mode"
18
+ --湿度
19
+ keyT["KEY_HUMIDITY"] = "humidity"
20
+ --水箱状态(只读)
21
+ keyT["KEY_TANK_STATUS"] = "tank_status"
22
+ --当前湿度(只读)
23
+ keyT["KEY_CURRENT_HUMIDITY"] = "cur_humidity"
24
+ --定时开
25
+ keyT["KEY_TIME_ON"] = "power_on_timer"
26
+ --定时关
27
+ keyT["KEY_TIME_OFF"] = "power_off_timer"
28
+ --定时关时间
29
+ keyT["KEY_CLOSE_TIME"] = "power_off_time_value"
30
+ --定时开时间
31
+ keyT["KEY_OPEN_TIME"] = "power_on_time_value"
32
+ --水满档位
33
+ keyT["KEY_WATER_FULL_LEVEL"] = "water_full_level"
34
+ --水满时间
35
+ keyT["KEY_WATER_FULL_TIME"] = "water_full_time"
36
+ --负离子
37
+ keyT["KEY_ANION"] = "anion"
38
+ --滤网
39
+ keyT["KEY_FILTER_VALUE"] = "filter_value"
40
+ --水泵
41
+ keyT["KEY_WATER_PUMP"] = "water_pump"
42
+ --水泵有效
43
+ keyT["KEY_WATER_PUMP_ENABLE"] = "water_pump_enable"
44
+ --灯光
45
+ keyT["KEY_LIGHT"] = "light"
46
+ --净化
47
+ keyT["KEY_PURIFIER"] = "purifier"
48
+
49
+ ----------------JSON相关value值变量----------------
50
+ local keyV = {}
51
+ --版本号
52
+ keyV["VALUE_VERSION"] = 18
53
+ --功能开
54
+ keyV["VALUE_FUNCTION_ON"] = "on"
55
+ --功能关
56
+ keyV["VALUE_FUNCTION_OFF"] = "off"
57
+ --无效
58
+ keyV["VALUE_MODE_INVALID"] = "invalid"
59
+ --设定除湿
60
+ keyV["VALUE_MODE_SET"] = "set"
61
+ --智能除湿
62
+ keyV["VALUE_MODE_AUTO"] = "auto"
63
+ --连续除湿
64
+ keyV["VALUE_MODE_CONTINUITY"] = "continuity"
65
+ --干衣除湿
66
+ keyV["VALUE_MODE_DRY_CLOTHES"] = "dry_clothes"
67
+ --干鞋模式
68
+ keyV["VALUE_MODE_DRY_SHOES"] = "dry_shoes"
69
+ --送风模式
70
+ keyV["VALUE_MODE_FAN"] = "fan"
71
+ --ECO模式
72
+ keyV["VALUE_MODE_ECO"] = "eco"
73
+
74
+ -----------------二进制相关属性变量----------------
75
+ local keyB = {}
76
+ --设备
77
+ keyB["BYTE_DEVICE_TYPE"] = 0xA1
78
+ --控制请求
79
+ keyB["BYTE_CONTROL_REQUEST"] = 0x02
80
+ --查询请求
81
+ keyB["BYTE_QUERY_REQUEST"] = 0x03
82
+ --协议头
83
+ keyB["BYTE_PROTOCOL_HEAD"] = 0xAA
84
+ --协议头长度
85
+ keyB["BYTE_PROTOCOL_LENGTH"] = 0x0A
86
+ --电源开
87
+ keyB["BYTE_POWER_ON"] = 0x01
88
+ --电源关
89
+ keyB["BYTE_POWER_OFF"] = 0x00
90
+ --无效模式
91
+ keyB["BYTE_MODE_INVALID"] = 0x00
92
+ --设置模式
93
+ keyB["BYTE_MODE_SET"] = 0x01
94
+ --连续除湿模式
95
+ keyB["BYTE_MODE_CONTINUITY"] = 0x02
96
+ --自动除湿模式
97
+ keyB["BYTE_MODE_AUTO"] = 0x03
98
+ --干衣模式
99
+ keyB["BYTE_MODE_DRY_CLOTH"] = 0x04
100
+ --干鞋模式
101
+ keyB["BYTE_MODE_DRY_SHOES"] = 0x05
102
+ --送风模式
103
+ keyB["BYTE_MODE_FAN"] = 0x08
104
+ --ECO模式
105
+ keyB["BYTE_MODE_ECO"] = 0x09
106
+ --蜂鸣器开
107
+ keyB["BYTE_BUZZER_ON"] = 0x40
108
+ --蜂鸣器关
109
+ keyB["BYTE_BUZZER_OFF"] = 0x00
110
+ --定时关(开)
111
+ keyB["BYTE_CLOSE_TIMER_SWITCH_ON"] = 0x80
112
+ --定时关(关)
113
+ keyB["BYTE_CLOSE_TIMER_SWITCH_OFF"] = 0x7F
114
+ --定时开(开)
115
+ keyB["BYTE_START_TIMER_SWITCH_ON"] = 0x80
116
+ --定时开(关)
117
+ keyB["BYTE_START_TIMER_SWITCH_OFF"] = 0x7F
118
+ --负离子开
119
+ keyB["BYTE_ANION_ON"] = 0x40
120
+ --负离子关
121
+ keyB["BYTE_ANION_OFF"] = 0x00
122
+
123
+
124
+ -------------------定义属性变量--------------------
125
+ local keyP = {}
126
+ local dataType = 0
127
+
128
+ --水箱状态
129
+ keyP["tankStatusValue"] = 0
130
+ keyP["closeTimerSwitch"] = 0
131
+ keyP["openTimerSwitch"] = 0
132
+ keyP["closeTime"] = 0
133
+ keyP["openTime"] = 0
134
+ keyP["swingUDValue"] = 0
135
+ keyP["waterLevelValue"] = 0
136
+ keyP["waterTimeValue"] = 0
137
+ keyP["filterValue"] = 0
138
+ keyP["waterPumpValue"] = 0
139
+ keyP["waterPumpEnableValue"] = 0
140
+ keyP["isB5query"] = 0
141
+ keyP["filter_flag"] = 0
142
+ keyP["lightValue"] = 0
143
+ --净化
144
+ keyP["purifier"] = 0
145
+
146
+ local function init_keyP()
147
+ keyP["b5_auto_dry"] = nil
148
+ keyP["b5_dry_clothes_mode"] = nil
149
+ keyP["b5_anion"] = nil
150
+ keyP["b5_filter_value"] = nil
151
+ keyP["b5_water_full_level"] = nil
152
+ keyP["b5_water_pump"] = nil
153
+ keyP["b5_wind_speed"] = nil
154
+ keyP["b5_light"] = nil
155
+ keyP["b5_mode"] = nil
156
+ keyP["b5_wind_swing_ud"] = nil
157
+ keyP["b5_purifier"] = nil
158
+ keyP["b5_eco"] = nil
159
+ keyP["b5_self_clean"] = nil
160
+ keyP["b5_sound"] = nil
161
+ keyP["filter_flag"] = 0
162
+ keyP["propertyNumber"] = 0
163
+ keyP["self_clean"] = nil
164
+ keyP["light"] = nil
165
+ keyP["sound"] = nil
166
+ --电源
167
+ keyP["powerValue"] = nil
168
+ --模式
169
+ keyP["modeValue"] = nil
170
+ --负离子
171
+ keyP["anionValue"] = nil
172
+ --风速
173
+ keyP["windSpeedValue"] = nil
174
+ --湿度
175
+ keyP["humidityValue"] = nil
176
+ --当前湿度
177
+ keyP["curHumidityValue"] = nil
178
+ --故障代码
179
+ keyP["errorCodeValue"] = nil
180
+
181
+ --自清洁
182
+ keyP["self_clean"] = nil
183
+ keyP["tankStatusValue"] = nil
184
+ keyP["closeTimerSwitch"] = nil
185
+ keyP["openTimerSwitch"] = nil
186
+ keyP["closeTime"] = nil
187
+ keyP["openTime"] = nil
188
+ keyP["swingUDValue"] = nil
189
+ keyP["waterLevelValue"] = nil
190
+ keyP["waterTimeValue"] = nil
191
+ keyP["filterValue"] = nil
192
+ keyP["waterPumpValue"] = nil
193
+ keyP["waterPumpEnableValue"] = nil
194
+ keyP["lightValue"] = nil
195
+ --净化
196
+ keyP["purifier"] = nil
197
+ end
198
+
199
+ init_keyP()
200
+
201
+ --检查取值是否超过边界
202
+ local function checkBoundary(data, min, max)
203
+ if (not data) then
204
+ data = 0
205
+ end
206
+
207
+ data = tonumber(data)
208
+
209
+ if ((data >= min) and (data <= max)) then
210
+ return data
211
+ else
212
+ if (data < min) then
213
+ return min
214
+ else
215
+ return max
216
+ end
217
+ end
218
+ end
219
+
220
+
221
+ -----------根据电控协议不同,需要改变的函数-------------
222
+ --根据 json 修改属性变量
223
+ local function jsonToModel(stateJson,controlJson)
224
+ local oldState = stateJson
225
+ local controlCmd = controlJson
226
+
227
+ --电源
228
+ local temValue = oldState[keyT["KEY_POWER"]]
229
+ if (controlCmd[keyT["KEY_POWER"]] ~= nil) then
230
+ temValue = controlCmd[keyT["KEY_POWER"]]
231
+ end
232
+
233
+ if(temValue == keyV["VALUE_FUNCTION_ON"]) then
234
+ keyP["powerValue"] = keyB["BYTE_POWER_ON"]
235
+ keyP["openTimerSwitch"] = keyB["BYTE_START_TIMER_SWITCH_OFF"]
236
+ keyP["closeTimerSwitch"] = keyB["BYTE_CLOSE_TIMER_SWITCH_OFF"]
237
+ else
238
+ keyP["powerValue"] = keyB["BYTE_POWER_OFF"]
239
+ keyP["openTimerSwitch"] = keyB["BYTE_START_TIMER_SWITCH_OFF"]
240
+ keyP["closeTimerSwitch"] = keyB["BYTE_CLOSE_TIMER_SWITCH_OFF"]
241
+ end
242
+
243
+ --风速
244
+ temValue = oldState[keyT["KEY_WIND_SPEED"]]
245
+ if (controlCmd[keyT["KEY_WIND_SPEED"]] ~= nil) then
246
+ temValue = controlCmd[keyT["KEY_WIND_SPEED"]]
247
+ end
248
+ keyP["windSpeedValue"] = checkBoundary(temValue, 1, 102)
249
+
250
+ --湿度
251
+ temValue = oldState[keyT["KEY_HUMIDITY"]]
252
+ if (controlCmd[keyT["KEY_HUMIDITY"]] ~= nil) then
253
+ temValue = controlCmd[keyT["KEY_HUMIDITY"]]
254
+ end
255
+ keyP["humidityValue"] = checkBoundary(temValue, 0, 99)
256
+ --银离子
257
+ temValue = oldState[keyT["KEY_ANION"]]
258
+ if (controlCmd[keyT["KEY_ANION"]] ~= nil) then
259
+ temValue = controlCmd[keyT["KEY_ANION"]]
260
+ end
261
+
262
+ if(temValue == keyV["VALUE_FUNCTION_ON"]) then
263
+ keyP["anionValue"] = keyB["BYTE_ANION_ON"]
264
+ else
265
+ keyP["anionValue"] = keyB["BYTE_ANION_OFF"]
266
+ end
267
+ --模式
268
+ temValue = oldState[keyT["KEY_MODE"]]
269
+ if (controlCmd[keyT["KEY_MODE"]] ~= nil) then
270
+ temValue = controlCmd[keyT["KEY_MODE"]]
271
+ end
272
+ --DG3下发自动除湿时,实际电控组包为设定除湿
273
+ if (temValue == keyV["VALUE_MODE_SET"]) then
274
+ keyP["modeValue"] = keyB["BYTE_MODE_SET"]
275
+ elseif (temValue == keyV["VALUE_MODE_AUTO"]) then
276
+ keyP["modeValue"] = keyB["BYTE_MODE_AUTO"]
277
+ elseif (temValue == keyV["VALUE_MODE_CONTINUITY"]) then
278
+ keyP["modeValue"] = keyB["BYTE_MODE_CONTINUITY"]
279
+ elseif (temValue == keyV["VALUE_MODE_DRY_CLOTHES"]) then
280
+ keyP["modeValue"] = keyB["BYTE_MODE_DRY_CLOTH"]
281
+ --keyP["windSpeedValue"] = 80
282
+ elseif (temValue == keyV["VALUE_MODE_DRY_SHOES"]) then
283
+ keyP["modeValue"] = keyB["BYTE_MODE_DRY_SHOES"]
284
+ --keyP["windSpeedValue"] = 80
285
+ elseif (temValue == keyV["VALUE_MODE_FAN"]) then
286
+ keyP["modeValue"] = keyB["BYTE_MODE_FAN"]
287
+ elseif (temValue == keyV["VALUE_MODE_ECO"]) then
288
+ keyP["modeValue"] = keyB["BYTE_MODE_ECO"]
289
+ end
290
+
291
+ --上下扫风
292
+ keyP["swingUDValue"] = oldState["wind_swing_ud"]
293
+ if(oldState["wind_swing_ud"] == keyV["VALUE_FUNCTION_ON"]) then
294
+ keyP["swingUDValue"] = 0x01
295
+ elseif (oldState["wind_swing_ud"] == keyV["VALUE_FUNCTION_OFF"]) then
296
+ keyP["swingUDValue"] = 0x00
297
+ end
298
+ if (controlCmd["wind_swing_ud"] == keyV["VALUE_FUNCTION_ON"]) then
299
+ keyP["swingUDValue"] = 0x01
300
+ elseif (controlCmd["wind_swing_ud"] == keyV["VALUE_FUNCTION_OFF"]) then
301
+ keyP["swingUDValue"] = 0x00
302
+ end
303
+
304
+ --定时开
305
+ if (oldState[keyT["KEY_TIME_ON"]] == keyV["VALUE_FUNCTION_ON"]) then
306
+ keyP["openTimerSwitch"] = keyB["BYTE_START_TIMER_SWITCH_ON"]
307
+ elseif (oldState[keyT["KEY_TIME_ON"]] == keyV["VALUE_FUNCTION_OFF"]) then
308
+ keyP["openTimerSwitch"] = keyB["BYTE_START_TIMER_SWITCH_OFF"]
309
+ end
310
+ if (controlCmd[keyT["KEY_TIME_ON"]] == keyV["VALUE_FUNCTION_ON"]) then
311
+ keyP["openTimerSwitch"] = keyB["BYTE_START_TIMER_SWITCH_ON"]
312
+ elseif (controlCmd[keyT["KEY_TIME_ON"]] == keyV["VALUE_FUNCTION_OFF"]) then
313
+ keyP["openTimerSwitch"] = keyB["BYTE_START_TIMER_SWITCH_OFF"]
314
+ end
315
+
316
+ --定时关
317
+ if (oldState[keyT["KEY_TIME_OFF"]] == keyV["VALUE_FUNCTION_ON"]) then
318
+ keyP["closeTimerSwitch"] = keyB["BYTE_CLOSE_TIMER_SWITCH_ON"]
319
+ elseif (oldState[keyT["KEY_TIME_OFF"]] == keyV["VALUE_FUNCTION_OFF"]) then
320
+ keyP["closeTimerSwitch"] = keyB["BYTE_CLOSE_TIMER_SWITCH_OFF"]
321
+ end
322
+ if (controlCmd[keyT["KEY_TIME_OFF"]] == keyV["VALUE_FUNCTION_ON"]) then
323
+ keyP["closeTimerSwitch"] = keyB["BYTE_CLOSE_TIMER_SWITCH_ON"]
324
+ elseif (controlCmd[keyT["KEY_TIME_OFF"]] == keyV["VALUE_FUNCTION_OFF"]) then
325
+ keyP["closeTimerSwitch"] = keyB["BYTE_CLOSE_TIMER_SWITCH_OFF"]
326
+ end
327
+
328
+ --定时关机时间
329
+ keyP["closeTime"] =oldState[keyT["KEY_CLOSE_TIME"]]
330
+ if (controlCmd[keyT["KEY_CLOSE_TIME"]] ~= nil) then
331
+ keyP["closeTime"] = controlCmd[keyT["KEY_CLOSE_TIME"]]
332
+ end
333
+
334
+ --定时开机时间
335
+ keyP["openTime"] =oldState[keyT["KEY_OPEN_TIME"]]
336
+ if (controlCmd[keyT["KEY_OPEN_TIME"]] ~= nil) then
337
+ keyP["openTime"] = controlCmd[keyT["KEY_OPEN_TIME"]]
338
+ end
339
+ --水满档位
340
+ keyP["waterLevelValue"] =oldState[keyT["KEY_WATER_FULL_LEVEL"]]
341
+ if (controlCmd[keyT["KEY_WATER_FULL_LEVEL"]] ~= nil) then
342
+ keyP["waterLevelValue"] = controlCmd[keyT["KEY_WATER_FULL_LEVEL"]]
343
+ end
344
+ --水满时间
345
+ keyP["waterTimeValue"] =oldState[keyT["KEY_WATER_FULL_TIME"]]
346
+ if (controlCmd[keyT["KEY_WATER_FULL_TIME"]] ~= nil) then
347
+ keyP["waterTimeValue"] = controlCmd[keyT["KEY_WATER_FULL_TIME"]]
348
+ end
349
+ --滤网
350
+ temValue = oldState[keyT["KEY_FILTER_VALUE"]]
351
+ if (controlCmd[keyT["KEY_FILTER_VALUE"]] ~= nil) then
352
+ temValue = controlCmd[keyT["KEY_FILTER_VALUE"]]
353
+ keyP["filter_flag"] = 1
354
+ end
355
+
356
+ if(temValue == keyV["VALUE_FUNCTION_ON"]) then
357
+ keyP["filterValue"] = 0x80
358
+ else
359
+ keyP["filterValue"] = 0x00
360
+ end
361
+ --水泵
362
+ temValue = oldState[keyT["KEY_WATER_PUMP"]]
363
+ if (controlCmd[keyT["KEY_WATER_PUMP"]] ~= nil) then
364
+ temValue = controlCmd[keyT["KEY_WATER_PUMP"]]
365
+ end
366
+
367
+ if(temValue == keyV["VALUE_FUNCTION_ON"]) then
368
+ keyP["waterPumpValue"] = 0x08
369
+ else
370
+ keyP["waterPumpValue"] = 0x00
371
+ end
372
+ --滤网
373
+ temValue = oldState[keyT["KEY_WATER_PUMP_ENABLE"]]
374
+ if (controlCmd[keyT["KEY_WATER_PUMP_ENABLE"]] ~= nil) then
375
+ temValue = controlCmd[keyT["KEY_WATER_PUMP_ENABLE"]]
376
+ end
377
+ --灯光
378
+ if (controlCmd[keyT["KEY_LIGHT"]] ~= nil) then
379
+ keyP["propertyNumber"] = keyP["propertyNumber"] + 1
380
+ keyP["light"] = controlCmd[keyT["KEY_LIGHT"]]
381
+ end
382
+
383
+ --自清洁
384
+ if (controlCmd["self_clean"] ~= nil) then
385
+ keyP["propertyNumber"] = keyP["propertyNumber"] + 1
386
+ keyP["self_clean"] = controlCmd["self_clean"]
387
+ end
388
+
389
+ --声音
390
+ if (controlCmd["sound"] ~= nil) then
391
+ keyP["propertyNumber"] = keyP["propertyNumber"] + 1
392
+ keyP["sound"] = controlCmd["sound"]
393
+ end
394
+
395
+ if(temValue == keyV["VALUE_FUNCTION_ON"]) then
396
+ keyP["waterPumpEnableValue"] = 0x10
397
+ else
398
+ keyP["waterPumpEnableValue"] = 0x00
399
+ end
400
+ --净化
401
+ temValue = oldState[keyT["KEY_PURIFIER"]]
402
+ if (controlCmd[keyT["KEY_PURIFIER"]] ~= nil) then
403
+ temValue = controlCmd[keyT["KEY_PURIFIER"]]
404
+ end
405
+
406
+ if(temValue == keyV["VALUE_FUNCTION_ON"]) then
407
+ keyP["purifier"] = 0x01
408
+ else
409
+ keyP["purifier"] = 0x00
410
+ end
411
+ end
412
+
413
+ --根据 bin 修改属性变量
414
+ local function binToModel(binData)
415
+ if (#binData == 0) then
416
+ print("3333333")
417
+ return nil
418
+ end
419
+
420
+ local messageBytes = binData
421
+
422
+ if (dataType == 0x03 and messageBytes[0] == 0xB5) then
423
+ keyP["propertyNumber"] = messageBytes[1]
424
+ local cursor = 2
425
+ for i = 1, keyP["propertyNumber"] do
426
+ if (messageBytes[cursor + 0] == 0x20 and messageBytes[cursor + 1] == 0x02) then
427
+ keyP["b5_dry_clothes_mode"] = messageBytes[cursor + 3]
428
+ cursor = cursor + 4
429
+ end
430
+ if (messageBytes[cursor + 0] == 0x1F and messageBytes[cursor + 1] == 0x02) then
431
+ keyP["b5_auto_dry"] = messageBytes[cursor + 3]
432
+ cursor = cursor + 4
433
+ end
434
+ if (messageBytes[cursor + 0] == 0x10 and messageBytes[cursor + 1] == 0x02) then
435
+ keyP["b5_wind_speed"] = messageBytes[cursor + 3]
436
+ cursor = cursor + 4
437
+ end
438
+ if (messageBytes[cursor + 0] == 0x1E and messageBytes[cursor + 1] == 0x02) then
439
+ keyP["b5_anion"] = messageBytes[cursor + 3]
440
+ cursor = cursor + 4
441
+ end
442
+ if (messageBytes[cursor + 0] == 0x17 and messageBytes[cursor + 1] == 0x02) then
443
+ keyP["b5_filter_value"] = messageBytes[cursor + 3]
444
+ cursor = cursor + 4
445
+ end
446
+ if (messageBytes[cursor + 0] == 0x1D and messageBytes[cursor + 1] == 0x02) then
447
+ keyP["b5_water_pump"] = messageBytes[cursor + 3]
448
+ cursor = cursor + 4
449
+ end
450
+ if (messageBytes[cursor + 0] == 0x2D and messageBytes[cursor + 1] == 0x02) then
451
+ keyP["b5_water_full_level"] = messageBytes[cursor + 3]
452
+ cursor = cursor + 4
453
+ end
454
+ if (messageBytes[cursor + 0] == 0x14 and messageBytes[cursor + 1] == 0x02) then
455
+ keyP["b5_mode"] = messageBytes[cursor + 3]
456
+ cursor = cursor + 4
457
+ end
458
+ if (messageBytes[cursor + 0] == 0x24 and messageBytes[cursor + 1] == 0x02) then
459
+ keyP["b5_light"] = messageBytes[cursor + 3]
460
+ cursor = cursor + 4
461
+ end
462
+ if (messageBytes[cursor + 0] == 0x15 and messageBytes[cursor + 1] == 0x02) then
463
+ keyP["b5_wind_swing_ud"] = messageBytes[cursor + 3]
464
+ cursor = cursor + 4
465
+ end
466
+ if (messageBytes[cursor + 0] == 0x54 and messageBytes[cursor + 1] == 0x02) then
467
+ keyP["b5_purifier"] = messageBytes[cursor + 3]
468
+ cursor = cursor + 4
469
+ end
470
+ if (messageBytes[cursor + 0] == 0x12 and messageBytes[cursor + 1] == 0x02) then
471
+ keyP["b5_eco"] = messageBytes[cursor + 3]
472
+ cursor = cursor + 4
473
+ end
474
+ if (messageBytes[cursor + 0] == 0x39 and messageBytes[cursor + 1] == 0x00) then
475
+ keyP["b5_self_clean"] = messageBytes[cursor + 3]
476
+ cursor = cursor + 4
477
+ end
478
+ if (messageBytes[cursor + 0] == 0x2C and messageBytes[cursor + 1] == 0x02) then
479
+ keyP["b5_sound"] = messageBytes[cursor + 3]
480
+ cursor = cursor + 4
481
+ end
482
+ end
483
+ elseif(dataType == 0x05 and messageBytes[0] == 0xB5)then
484
+ keyP["propertyNumber"] = messageBytes[1]
485
+ local cursor = 2
486
+ for i = 1, keyP["propertyNumber"] do
487
+ if (messageBytes[cursor + 0] == 0x39 and messageBytes[cursor + 1] == 0x00) then
488
+ keyP["self_clean"] = messageBytes[cursor + 3]
489
+ cursor = cursor + 4
490
+ end
491
+ if (messageBytes[cursor + 0] == 0x2C and messageBytes[cursor + 1] == 0x02) then
492
+ keyP["sound"] = messageBytes[cursor + 3]
493
+ cursor = cursor + 4
494
+ end
495
+ if (messageBytes[cursor + 0] == 0x5B and messageBytes[cursor + 1] == 0x00) then
496
+ keyP["light"] = messageBytes[cursor + 3]
497
+ cursor = cursor + 4
498
+ end
499
+ end
500
+ elseif(messageBytes[0] == 0xB1 or messageBytes[0] == 0xB0) then
501
+ keyP["propertyNumber"] = messageBytes[1]
502
+ local cursor = 2
503
+ for i = 1, keyP["propertyNumber"] do
504
+ if (messageBytes[cursor + 0] == 0x5B and messageBytes[cursor + 1] == 0x00) then
505
+ keyP["light"] = messageBytes[cursor + 4]
506
+ cursor = cursor + 5
507
+ end
508
+ if (messageBytes[cursor + 0] == 0x39 and messageBytes[cursor + 1] == 0x00) then
509
+ keyP["self_clean"] = messageBytes[cursor + 4]
510
+ cursor = cursor + 5
511
+ end
512
+ if (messageBytes[cursor + 0] == 0x2C and messageBytes[cursor + 1] == 0x02) then
513
+ keyP["sound"] = messageBytes[cursor + 4]
514
+ cursor = cursor + 5
515
+ end
516
+ end
517
+
518
+ else
519
+ keyP["powerValue"] = bit.band(messageBytes[1], 0x01)
520
+ keyP["modeValue"] = bit.band(messageBytes[2], 0x0F)
521
+ keyP["windSpeedValue"] =bit.band(messageBytes[3], 0x7F)
522
+ keyP["anionValue"] = bit.band(messageBytes[9], 0x40)
523
+ keyP["filterValue"] = bit.band(messageBytes[9], 0x80)
524
+ keyP["waterPumpValue"] = bit.rshift(bit.band(messageBytes[9], 0x08), 3)
525
+ keyP["waterPumpEnableValue"] = bit.rshift(bit.band(messageBytes[9], 0x10), 4)
526
+
527
+ if (bit.band(messageBytes[4], keyB["BYTE_START_TIMER_SWITCH_ON"]) == keyB["BYTE_START_TIMER_SWITCH_ON"]) then
528
+ keyP["openTimerSwitch"] = keyB["BYTE_START_TIMER_SWITCH_ON"]
529
+ else
530
+ keyP["openTimerSwitch"] = keyB["BYTE_START_TIMER_SWITCH_OFF"]
531
+ end
532
+ if (bit.band(messageBytes[5], keyB["BYTE_CLOSE_TIMER_SWITCH_ON"]) == keyB["BYTE_CLOSE_TIMER_SWITCH_ON"]) then
533
+ keyP["closeTimerSwitch"] = keyB["BYTE_CLOSE_TIMER_SWITCH_ON"]
534
+ else
535
+ keyP["closeTimerSwitch"] = keyB["BYTE_CLOSE_TIMER_SWITCH_OFF"]
536
+ end
537
+ local closeHour = bit.rshift(bit.band(messageBytes[5], 0x7F), 2)
538
+ local closeStepMintues = bit.band(messageBytes[5], 0x03)
539
+ local closeMin = 15 - bit.band(messageBytes[6], 0x0f)
540
+ keyP["closeTime"] = closeHour * 60 + closeStepMintues * 15 + closeMin
541
+ local openHour = bit.rshift(bit.band(messageBytes[4], 0x7F), 2)
542
+ local openStepMintues = bit.band(messageBytes[4], 0x03)
543
+ local openMin = 15 - bit.rshift(bit.band(messageBytes[6], 0xf0),4)
544
+ keyP["openTime"] = openHour * 60 + openStepMintues * 15 + openMin
545
+
546
+ keyP["humidityValue"] = messageBytes[7]
547
+ if (keyP["humidityValue"] < 35) then
548
+ keyP["humidityValue"] = 35
549
+ end
550
+ keyP["waterTimeValue"] = bit.bor(bit.lshift(messageBytes[14],8),messageBytes[13])
551
+ keyP["waterLevelValue"] = messageBytes[15]
552
+ keyP["curHumidityValue"] = messageBytes[16]
553
+ keyP["tankStatusValue"] = messageBytes[10]
554
+ keyP["swingUDValue"] = bit.rshift(bit.band(messageBytes[19], 0x20), 5)
555
+ keyP["errorCodeValue"] = messageBytes[21]
556
+ if(#binData >= 23) then
557
+ keyP["purifier"] = bit.band(messageBytes[23], 0x01)
558
+ end
559
+ end
560
+
561
+
562
+ end
563
+
564
+
565
+ ---------------公共的函数---------------
566
+ --打印 table 表
567
+ local function print_lua_table(lua_table, indent)
568
+ indent = indent or 0
569
+
570
+ for k, v in pairs(lua_table) do
571
+ if type(k) == "string" then
572
+ k = string.format("%q", k)
573
+ end
574
+
575
+ local szSuffix = ""
576
+
577
+ if type(v) == "table" then
578
+ szSuffix = "{"
579
+ end
580
+
581
+ local szPrefix = string.rep(" ", indent)
582
+ formatting = szPrefix.."["..k.."]".." = "..szSuffix
583
+
584
+ if type(v) == "table" then
585
+ print(formatting)
586
+
587
+ print_lua_table(v, indent + 1)
588
+
589
+ print(szPrefix.."},")
590
+ else
591
+ local szValue = ""
592
+
593
+ if type(v) == "string" then
594
+ szValue = string.format("%q", v)
595
+ else
596
+ szValue = tostring(v)
597
+ end
598
+
599
+ print(formatting..szValue..",")
600
+ end
601
+ end
602
+ end
603
+
604
+
605
+ --table 转 string
606
+ local function table2string(cmd)
607
+ local ret = ""
608
+ local i
609
+
610
+ for i = 1, #cmd do
611
+ ret = ret..string.char(cmd[i])
612
+ end
613
+
614
+ return ret
615
+ end
616
+
617
+ --十六进制 string 转 table
618
+ local function string2table(hexstr)
619
+ local tb = {}
620
+ local i = 1
621
+ local j = 1
622
+
623
+ for i = 1, #hexstr - 1, 2 do
624
+ local doublebytestr = string.sub(hexstr, i, i + 1)
625
+ tb[j] = tonumber(doublebytestr, 16)
626
+ j = j + 1
627
+ end
628
+
629
+ return tb
630
+ end
631
+
632
+ --十六进制 string 输出
633
+ local function string2hexstring(str)
634
+ local ret = ""
635
+
636
+ for i = 1, #str do
637
+ ret = ret .. string.format("%02x", str:byte(i))
638
+ end
639
+
640
+ return ret
641
+ end
642
+
643
+ --table 转 json
644
+ local function encode(cmd)
645
+ local tb
646
+
647
+ if JSON == nil then
648
+ JSON = require "cjson"
649
+ end
650
+
651
+ tb = JSON.encode(cmd)
652
+
653
+ return tb
654
+ end
655
+
656
+ --json 转 table
657
+ local function decode(cmd)
658
+ local tb
659
+
660
+ if JSON == nil then
661
+ JSON = require "cjson"
662
+ end
663
+
664
+ tb = JSON.decode(cmd)
665
+
666
+ return tb
667
+ end
668
+
669
+ local function splitStrByChar(str,sepChar)
670
+ local splitList = {}
671
+ local pattern = '[^'..sepChar..']+'
672
+ string.gsub(str, pattern, function(w) table.insert(splitList, w) end )
673
+ return splitList
674
+ end
675
+
676
+ local function values (t)
677
+ local i = 0
678
+ return function() i = i + 1; return t[i] end
679
+ end
680
+
681
+ --sum校验
682
+ local function makeSum(tmpbuf, start_pos, end_pos)
683
+ local resVal = 0
684
+
685
+ for si = start_pos, end_pos do
686
+ resVal = resVal + tmpbuf[si]
687
+
688
+ if resVal > 0xff then
689
+ resVal = bit.band(resVal, 0xff)
690
+ end
691
+ end
692
+
693
+ resVal = 255 - resVal + 1
694
+
695
+ return resVal
696
+ end
697
+
698
+ --CRC表
699
+ local crc8_854_table =
700
+ {
701
+ 0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
702
+ 157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
703
+ 35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
704
+ 190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
705
+ 70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
706
+ 219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
707
+ 101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
708
+ 248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
709
+ 140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
710
+ 17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
711
+ 175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
712
+ 50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
713
+ 202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
714
+ 87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
715
+ 233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
716
+ 116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53
717
+ }
718
+
719
+ --CRC校验
720
+ local function crc8_854(dataBuf, start_pos, end_pos)
721
+ local crc = 0
722
+
723
+ for si = start_pos, end_pos do
724
+ crc = crc8_854_table[bit.band(bit.bxor(crc, dataBuf[si]), 0xFF) + 1]
725
+ end
726
+
727
+ return crc
728
+ end
729
+
730
+
731
+ --二进制转json
732
+ function dataToJson(jsonCmd)
733
+ init_keyP()
734
+ if (not jsonCmd) then
735
+ print("444444")
736
+ return nil
737
+ end
738
+
739
+ local json = decode(jsonCmd)
740
+ local deviceinfo = json["deviceinfo"]
741
+ local deviceSubType = deviceinfo["deviceSubType"]
742
+
743
+
744
+ --根据设备子类型来处理协议差异
745
+ if (deviceSubType == 1) then
746
+
747
+ end
748
+
749
+ local binData = json["msg"]["data"]
750
+ local info = {}
751
+ local msgBytes = {}
752
+ local bodyBytes = {}
753
+ local msgLength = 0
754
+ local bodyLength = 0
755
+
756
+ info = string2table(binData)
757
+
758
+ dataType=info[10]
759
+ if((dataType ~= 0x02) and (dataType ~= 0x03) and (dataType ~= 0x04) and (dataType ~= 0x05))then
760
+ return nil
761
+ end
762
+
763
+ for i = 1, #info do
764
+ msgBytes[i - 1] = info[i]
765
+ end
766
+
767
+ msgLength = msgBytes[1]
768
+ bodyLength = msgLength - keyB["BYTE_PROTOCOL_LENGTH"] - 1
769
+
770
+ --streams["b5_next_frame"] = info[msgLength - 2]
771
+
772
+ --检验 sum 判断消息格式是否正确
773
+ local sumRes = makeSum(msgBytes, 1, msgLength - 1)
774
+ if (sumRes ~= msgBytes[msgLength]) then
775
+ return nil
776
+ end
777
+
778
+ --获取 body 部分
779
+ for i = 0, bodyLength do
780
+ bodyBytes[i] = msgBytes[i + keyB["BYTE_PROTOCOL_LENGTH"]]
781
+ end
782
+
783
+ --检验 crc 判断消息格式是否正确
784
+ local crcRes = crc8_854(bodyBytes, 0, bodyLength - 1)
785
+ if (crcRes ~= bodyBytes[bodyLength]) then
786
+ return nil
787
+ end
788
+
789
+ --将二进制状态解析为属性值
790
+ binToModel(bodyBytes)
791
+
792
+ --将属性值转换为最终 table
793
+ local streams = {}
794
+
795
+ --版本
796
+ streams[keyT["KEY_VERSION"]]=keyV["VALUE_VERSION"]
797
+ streams["sub_type"]=2
798
+
799
+ if (keyP["propertyNumber"] == 0) then
800
+ --处理常规协议
801
+ --电源
802
+ if (keyP["powerValue"] == keyB["BYTE_POWER_ON"]) then
803
+ streams[keyT["KEY_POWER"]] = keyV["VALUE_FUNCTION_ON"]
804
+ elseif (keyP["powerValue"] == keyB["BYTE_POWER_OFF"]) then
805
+ streams[keyT["KEY_POWER"]] = keyV["VALUE_FUNCTION_OFF"]
806
+ end
807
+
808
+ --模式
809
+ if (keyP["modeValue"] == keyB["BYTE_MODE_SET"]) then
810
+ streams[keyT["KEY_MODE"]] = keyV["VALUE_MODE_SET"]
811
+ elseif (keyP["modeValue"] == keyB["BYTE_MODE_AUTO"]) then
812
+ streams[keyT["KEY_MODE"]] = keyV["VALUE_MODE_AUTO"]
813
+ elseif (keyP["modeValue"] == keyB["BYTE_MODE_CONTINUITY"]) then
814
+ streams[keyT["KEY_MODE"]] = keyV["VALUE_MODE_CONTINUITY"]
815
+ elseif (keyP["modeValue"] == keyB["BYTE_MODE_DRY_CLOTH"]) then
816
+ streams[keyT["KEY_MODE"]] = keyV["VALUE_MODE_DRY_CLOTHES"]
817
+ elseif (keyP["modeValue"] == keyB["BYTE_MODE_DRY_SHOES"]) then
818
+ streams[keyT["KEY_MODE"]] = keyV["VALUE_MODE_DRY_SHOES"]
819
+ elseif (keyP["modeValue"] == keyB["BYTE_MODE_FAN"]) then
820
+ streams[keyT["KEY_MODE"]] = keyV["VALUE_MODE_FAN"]
821
+ elseif (keyP["modeValue"] == keyB["BYTE_MODE_ECO"]) then
822
+ streams[keyT["KEY_MODE"]] = keyV["VALUE_MODE_ECO"]
823
+ end
824
+
825
+ --档位
826
+ streams[keyT["KEY_WIND_SPEED"]] = keyP["windSpeedValue"]
827
+ streams[keyT["KEY_HUMIDITY"]] = keyP["humidityValue"]
828
+ streams[keyT["KEY_CURRENT_HUMIDITY"]] = keyP["curHumidityValue"]
829
+ streams[keyT["KEY_TANK_STATUS"]] = keyP["tankStatusValue"]
830
+
831
+ --上下扫风
832
+ if (keyP["swingUDValue"] == 0x01) then
833
+ streams["wind_swing_ud"] = keyV["VALUE_FUNCTION_ON"]
834
+ elseif (keyP["swingUDValue"] == 0x00) then
835
+ streams["wind_swing_ud"] = keyV["VALUE_FUNCTION_OFF"]
836
+ end
837
+
838
+ --定时开
839
+ if (keyP["openTimerSwitch"] == keyB["BYTE_START_TIMER_SWITCH_ON"]) then
840
+ streams[keyT["KEY_TIME_ON"]] = keyV["VALUE_FUNCTION_ON"]
841
+ elseif (keyP["openTimerSwitch"] == keyB["BYTE_START_TIMER_SWITCH_OFF"]) then
842
+ streams[keyT["KEY_TIME_ON"]] = keyV["VALUE_FUNCTION_OFF"]
843
+ end
844
+
845
+ --定时关
846
+ if (keyP["closeTimerSwitch"] == keyB["BYTE_CLOSE_TIMER_SWITCH_ON"]) then
847
+ streams[keyT["KEY_TIME_OFF"]] = keyV["VALUE_FUNCTION_ON"]
848
+ elseif (keyP["closeTimerSwitch"] == keyB["BYTE_CLOSE_TIMER_SWITCH_OFF"]) then
849
+ streams[keyT["KEY_TIME_OFF"]] = keyV["VALUE_FUNCTION_OFF"]
850
+ end
851
+
852
+ --定时关机时间
853
+ if (keyP["closeTimerSwitch"] == keyB["BYTE_CLOSE_TIMER_SWITCH_OFF"]) then
854
+ streams[keyT["KEY_CLOSE_TIME"]] = 0
855
+ else
856
+ streams[keyT["KEY_CLOSE_TIME"]] = keyP["closeTime"]
857
+ end
858
+
859
+ --定时开机时间
860
+ if (keyP["openTimerSwitch"] == keyB["BYTE_START_TIMER_SWITCH_OFF"]) then
861
+ streams[keyT["KEY_OPEN_TIME"]] = 0
862
+ else
863
+ streams[keyT["KEY_OPEN_TIME"]] = keyP["openTime"]
864
+ end
865
+ --银离子
866
+ if (keyP["anionValue"] == keyB["BYTE_ANION_ON"]) then
867
+ streams[keyT["KEY_ANION"]] = keyV["VALUE_FUNCTION_ON"]
868
+ elseif (keyP["anionValue"] == keyB["BYTE_ANION_OFF"]) then
869
+ streams[keyT["KEY_ANION"]] = keyV["VALUE_FUNCTION_OFF"]
870
+ end
871
+ --滤网
872
+ if (keyP["filterValue"] == 0x80) then
873
+ streams[keyT["KEY_FILTER_VALUE"]] = keyV["VALUE_FUNCTION_ON"]
874
+ elseif (keyP["filterValue"] == 0x00) then
875
+ streams[keyT["KEY_FILTER_VALUE"]] = keyV["VALUE_FUNCTION_OFF"]
876
+ end
877
+ --水泵
878
+ streams[keyT["KEY_WATER_PUMP"]] = keyP["waterPumpValue"]
879
+ if(keyP["waterPumpValue"] == 0x08 or keyP["waterPumpValue"] == 0x01) then
880
+ streams[keyT["KEY_WATER_PUMP"]] = 1
881
+ else
882
+ streams[keyT["KEY_WATER_PUMP"]] = 0
883
+ end
884
+ --净化
885
+ streams[keyT["KEY_PURIFIER"]] = keyP["purifier"]
886
+ if(keyP["purifier"] == 0x01) then
887
+ streams[keyT["KEY_PURIFIER"]] = "on"
888
+ else
889
+ streams[keyT["KEY_PURIFIER"]] = "off"
890
+ end
891
+ --水泵有效
892
+ streams[keyT["KEY_WATER_PUMP_ENABLE"]] = keyP["waterPumpEnableValue"]
893
+ if(keyP["waterPumpEnableValue"] == 0x10 or keyP["waterPumpEnableValue"] == 0x01) then
894
+ streams[keyT["KEY_WATER_PUMP_ENABLE"]] = 1
895
+ else
896
+ streams[keyT["KEY_WATER_PUMP_ENABLE"]] = 0
897
+ end
898
+ --水满档位
899
+ streams[keyT["KEY_WATER_FULL_LEVEL"]] = keyP["waterLevelValue"]
900
+ --水满时间
901
+ streams[keyT["KEY_WATER_FULL_TIME"]] = keyP["waterTimeValue"]
902
+ if(keyP["errorCodeValue"] ~= nil) then
903
+ streams["error_code"] = keyP["errorCodeValue"]
904
+ end
905
+ else
906
+ if(keyP["b5_dry_clothes_mode"] ~= nil) then
907
+ streams["b5_dry_clothes_mode"] = keyP["b5_dry_clothes_mode"]
908
+ end
909
+ if(keyP["b5_auto_dry"] ~= nil) then
910
+ streams["b5_auto_dry"] = keyP["b5_auto_dry"]
911
+ end
912
+ if(keyP["b5_wind_speed"] ~= nil) then
913
+ streams["b5_wind_speed"] = keyP["b5_wind_speed"]
914
+ end
915
+ if(keyP["b5_anion"] ~= nil) then
916
+ streams["b5_anion"] = keyP["b5_anion"]
917
+ end
918
+ if(keyP["b5_filter_value"] ~= nil) then
919
+ streams["b5_filter_value"] = keyP["b5_filter_value"]
920
+ end
921
+ if(keyP["b5_water_pump"] ~= nil) then
922
+ streams["b5_water_pump"] = keyP["b5_water_pump"]
923
+ end
924
+ if(keyP["b5_water_full_level"] ~= nil) then
925
+ streams["b5_water_full_level"] = keyP["b5_water_full_level"]
926
+ end
927
+ if(keyP["light"] ~= nil) then
928
+ streams["light"] = keyP["light"]
929
+ end
930
+ if(keyP["b5_light"] ~= nil) then
931
+ streams["b5_light"] = keyP["b5_light"]
932
+ end
933
+ if(keyP["b5_mode"] ~= nil) then
934
+ streams["b5_mode"] = keyP["b5_mode"]
935
+ end
936
+ if(keyP["b5_wind_swing_ud"] ~= nil) then
937
+ streams["b5_wind_swing_ud"] = keyP["b5_wind_swing_ud"]
938
+ end
939
+ if(keyP["b5_purifier"] ~= nil) then
940
+ streams["b5_purifier"] = keyP["b5_purifier"]
941
+ end
942
+ if(keyP["b5_eco"] ~= nil) then
943
+ streams["b5_eco"] = keyP["b5_eco"]
944
+ end
945
+ if(keyP["self_clean"] ~= nil) then
946
+ streams["self_clean"] = keyP["self_clean"]
947
+ end
948
+ if(keyP["b5_self_clean"] ~= nil) then
949
+ streams["b5_self_clean"] = keyP["b5_self_clean"]
950
+ end
951
+ if(keyP["sound"] ~= nil) then
952
+ streams["sound"] = keyP["sound"]
953
+ end
954
+ if(keyP["b5_sound"] ~= nil) then
955
+ streams["b5_sound"] = keyP["b5_sound"]
956
+ end
957
+ end
958
+
959
+ local retTable = {}
960
+ retTable["status"] = streams
961
+
962
+ local ret = encode(retTable)
963
+ return ret
964
+ end
965
+
966
+
967
+ --json转二进制,可传入原状态
968
+ function jsonToData(jsonCmd)
969
+ if (#jsonCmd == 0) then
970
+ print("222222")
971
+ return nil
972
+ end
973
+
974
+ local json = decode(jsonCmd)
975
+ local deviceSubType = json["deviceinfo"]["deviceSubType"]
976
+
977
+ --根据设备子类型来处理协议差异
978
+ if (deviceSubType == 1) then
979
+
980
+ end
981
+
982
+ local query = json["query"]
983
+ local control = json["control"]
984
+ local status = json["status"]
985
+
986
+ local bodyLength = 0
987
+ local b5BodyLength = 0
988
+
989
+ local bodyBytes = {}
990
+ local b5Body = {}
991
+
992
+ --当前是查询指令,构造固定的二进制即可
993
+ if (query) then
994
+ --构造消息 body 部分
995
+ local queryType = nil
996
+ if (type(query) == "table") then
997
+ queryType = query["query_type"]
998
+ end
999
+ if (queryType == "all_first_frame") then
1000
+ keyP["isB5query"] = 1
1001
+ b5BodyLength = 15
1002
+ for i = 0, b5BodyLength - 1 do
1003
+ b5Body[i] = 0
1004
+ end
1005
+ b5Body[1] = 0xaa
1006
+ b5Body[2] = 0x0e
1007
+ b5Body[3] = 0xa1
1008
+ b5Body[4] = 0x00
1009
+ b5Body[5] = 0x00
1010
+ b5Body[6] = 0x00
1011
+ b5Body[7] = 0x00
1012
+ b5Body[8] = 0x00
1013
+ b5Body[9] = 0x03
1014
+ b5Body[10] = 0x03
1015
+ b5Body[11] = 0xb5
1016
+ b5Body[12] = 0x01
1017
+ b5Body[13] = 0x11
1018
+ b5Body[14] = 0x8e
1019
+ b5Body[15] = 0xf6
1020
+ elseif (queryType == "all_second_frame") then
1021
+ keyP["isB5query"] = 1
1022
+ b5BodyLength = 16
1023
+ for i = 0, b5BodyLength do
1024
+ b5Body[i] = 0
1025
+ end
1026
+ b5Body[1] = 0xaa
1027
+ b5Body[2] = 0x0f
1028
+ b5Body[3] = 0xa1
1029
+ b5Body[4] = 0x00
1030
+ b5Body[5] = 0x00
1031
+ b5Body[6] = 0x00
1032
+ b5Body[7] = 0x00
1033
+ b5Body[8] = 0x00
1034
+ b5Body[9] = 0x03
1035
+ b5Body[10] = 0x03
1036
+ b5Body[11] = 0xb5
1037
+ b5Body[12] = 0x01
1038
+ b5Body[13] = 0x01
1039
+ b5Body[14] = 0x01
1040
+ b5Body[15] = 0x21
1041
+ --b5Body[16] = 0x66
1042
+ b5Body[15] = crc8_854(b5Body, 0, 15)
1043
+ elseif(queryType == nil) then
1044
+ for i = 0, 21 do
1045
+ bodyBytes[i] = 0
1046
+ end
1047
+ bodyBytes[0] = 0x41
1048
+ bodyBytes[1] = 0x81
1049
+ bodyBytes[3] = 0xFF
1050
+
1051
+ math.randomseed(os.time())
1052
+ bodyBytes[20] = math.random(0, 100)
1053
+ bodyBytes[21] = crc8_854(bodyBytes, 0, 20)
1054
+
1055
+
1056
+ else
1057
+ bodyBytes[0] = 0xB1
1058
+ local propertyNum = 0
1059
+
1060
+ local queryList = {}
1061
+ if (string.match(queryType,",")==",") then
1062
+ queryList = splitStrByChar(queryType,",")
1063
+ else
1064
+ table.insert(queryList, queryType)
1065
+ end
1066
+ for v in values(queryList) do
1067
+ queryType = v
1068
+ if (queryType == "light") then
1069
+ bodyBytes[1 + propertyNum * 2 + 1] = 0x5B
1070
+ bodyBytes[1 + propertyNum * 2 + 2] = 0x00
1071
+ propertyNum = propertyNum + 1
1072
+ end
1073
+ if (queryType == "self_clean") then
1074
+ bodyBytes[1 + propertyNum * 2 + 1] = 0x39
1075
+ bodyBytes[1 + propertyNum * 2 + 2] = 0x00
1076
+ propertyNum = propertyNum + 1
1077
+ end
1078
+ if (queryType == "sound") then
1079
+ bodyBytes[1 + propertyNum * 2 + 1] = 0x2C
1080
+ bodyBytes[1 + propertyNum * 2 + 2] = 0x02
1081
+ propertyNum = propertyNum + 1
1082
+ end
1083
+ end
1084
+ bodyBytes[1] = propertyNum
1085
+ bodyBytes[1 + propertyNum * 2 + 1] = math.random(0, 100)
1086
+ bodyBytes[1 + propertyNum * 2 + 2] = crc8_854(bodyBytes, 0, 1 + propertyNum * 2 + 1)
1087
+ end
1088
+
1089
+ --当前是控制指令
1090
+ elseif (control) then
1091
+ keyP["light"] = nil
1092
+ keyP["self_clean"] = nil
1093
+ keyP["sound"] = nil
1094
+ keyP["propertyNumber"] = 0
1095
+ --先将原始状态转换为属性
1096
+ if (control and status) then
1097
+ jsonToModel(status,control)
1098
+ end
1099
+ if(keyP["propertyNumber"] > 0) then
1100
+ bodyBytes[0] = 0xB0
1101
+ bodyBytes[1] = keyP["propertyNumber"]
1102
+ local cursor = 2
1103
+ if(keyP["light"] ~= nil) then
1104
+ bodyBytes[cursor + 0] = 0x5B
1105
+ bodyBytes[cursor + 1] = 0x00
1106
+ bodyBytes[cursor + 2] = 0x01
1107
+ bodyBytes[cursor + 3] = keyP["light"]
1108
+ cursor = cursor + 4
1109
+ end
1110
+ if(keyP["self_clean"] ~= nil) then
1111
+ bodyBytes[cursor + 0] = 0x39
1112
+ bodyBytes[cursor + 1] = 0x00
1113
+ bodyBytes[cursor + 2] = 0x01
1114
+ bodyBytes[cursor + 3] = keyP["self_clean"]
1115
+ cursor = cursor + 4
1116
+ end
1117
+ if(keyP["sound"] ~= nil) then
1118
+ bodyBytes[cursor + 0] = 0x2C
1119
+ bodyBytes[cursor + 1] = 0x02
1120
+ bodyBytes[cursor + 2] = 0x01
1121
+ bodyBytes[cursor + 3] = keyP["sound"]
1122
+ cursor = cursor + 4
1123
+ end
1124
+
1125
+ bodyBytes[cursor] = math.random(0, 100)
1126
+ bodyBytes[cursor + 1] = crc8_854(bodyBytes, 0, cursor)
1127
+
1128
+ else
1129
+ --构造消息 body 部分
1130
+ for i = 0, 22 do
1131
+ bodyBytes[i] = 0
1132
+ end
1133
+ bodyBytes[0] = 0x48
1134
+ bodyBytes[1] = bit.bor(keyP["powerValue"], keyB["BYTE_BUZZER_ON"])
1135
+ bodyBytes[1] = bit.bor(bodyBytes[1], 0x02)
1136
+ bodyBytes[2] = keyP["modeValue"]
1137
+ bodyBytes[3] = keyP["windSpeedValue"]
1138
+ if(keyP["filter_flag"] == 0) then
1139
+ keyP["filterValue"] = 0x00
1140
+ end
1141
+ bodyBytes[9] = bit.bor(bit.bor(bit.bor(keyP["anionValue"] ,keyP["filterValue"] ),keyP["waterPumpValue"] ),keyP["waterPumpEnableValue"])
1142
+ if (keyP["closeTime"] == nil) then
1143
+ keyP["closeTime"] = 0
1144
+ end
1145
+ local closeHour = math.floor(keyP["closeTime"] / 60)
1146
+ local closeStepMintues = math.floor((keyP["closeTime"] % 60) / 15)
1147
+ local closeMin = math.floor(((keyP["closeTime"] % 60) % 15))
1148
+ if (keyP["openTime"] == nil) then
1149
+ keyP["openTime"] = 0
1150
+ end
1151
+ local openHour = math.floor(keyP["openTime"] / 60)
1152
+ local openStepMintues = math.floor((keyP["openTime"] % 60) / 15)
1153
+ local openMin = math.floor(((keyP["openTime"] % 60) % 15))
1154
+ if (keyP["openTimerSwitch"] == keyB["BYTE_START_TIMER_SWITCH_ON"]) then
1155
+ bodyBytes[4] = bit.bor(bit.bor(keyP["openTimerSwitch"] , bit.lshift(openHour, 2)), openStepMintues)
1156
+ bodyBytes[6] = bit.bor(bodyBytes[6], bit.lshift((15 - openMin), 4))
1157
+ bodyBytes[3] = bit.bor(bodyBytes[3], 0x80)
1158
+ elseif (keyP["openTimerSwitch"] == keyB["BYTE_START_TIMER_SWITCH_OFF"] ) then
1159
+ bodyBytes[4] = 0x7F
1160
+ bodyBytes[3] = bit.bor(bodyBytes[3], 0x80)
1161
+ end
1162
+ if (keyP["closeTimerSwitch"] == keyB["BYTE_CLOSE_TIMER_SWITCH_ON"]) then
1163
+ bodyBytes[5] = bit.bor(bit.bor(keyP["closeTimerSwitch"] , bit.lshift(closeHour, 2)), closeStepMintues)
1164
+ bodyBytes[6] = bit.bor(bodyBytes[6], (15 - closeMin))
1165
+ bodyBytes[3] = bit.bor(bodyBytes[3], 0x80)
1166
+ elseif (keyP["closeTimerSwitch"] == keyB["BYTE_CLOSE_TIMER_SWITCH_OFF"]) then
1167
+ bodyBytes[5] = 0x7F
1168
+ bodyBytes[3] = bit.bor(bodyBytes[3], 0x80)
1169
+ end
1170
+ --bodyBytes[6] = bit.bor(bit.lshift((15 - openMin), 4), (15 - closeMin))
1171
+
1172
+ bodyBytes[7] = keyP["humidityValue"]
1173
+ bodyBytes[10] = bit.bor(bit.lshift(keyP["swingUDValue"] ,3), bodyBytes[10])
1174
+ bodyBytes[13] = keyP["waterLevelValue"]
1175
+ bodyBytes[14] = keyP["purifier"]
1176
+ bodyBytes[21] = math.random(0, 100)
1177
+ bodyBytes[22] = crc8_854(bodyBytes, 0, 21)
1178
+ end
1179
+
1180
+ end
1181
+
1182
+
1183
+ --lua table 索引从 1 开始,因此此处要重新转换一次
1184
+ --local bodyBytes = {}
1185
+ local infoM = {}
1186
+
1187
+ --for i = 1, msgLength + 1 do
1188
+ --bodyBytes[i] = msgBytes[i - 1]
1189
+ --end
1190
+ if(keyP["isB5query"] == 0) then
1191
+ bodyLength = #bodyBytes
1192
+ local msgLength = bodyLength + keyB["BYTE_PROTOCOL_LENGTH"] + 1
1193
+ local msgBytes = {}
1194
+ for i = 0, msgLength do
1195
+ msgBytes[i] = 0
1196
+ end
1197
+ --构造消息部分
1198
+ msgBytes[0] = keyB["BYTE_PROTOCOL_HEAD"]
1199
+ msgBytes[1] = bodyLength + keyB["BYTE_PROTOCOL_LENGTH"] + 1
1200
+ msgBytes[2] = keyB["BYTE_DEVICE_TYPE"]
1201
+ if(query)then
1202
+ msgBytes[9] = 0x03
1203
+ elseif(control) then
1204
+ msgBytes[9] = 0x02
1205
+ end
1206
+
1207
+ for i = 0, bodyLength do
1208
+ msgBytes[i + keyB["BYTE_PROTOCOL_LENGTH"]] = bodyBytes[i]
1209
+ end
1210
+
1211
+ msgBytes[msgLength] = makeSum(msgBytes, 1, msgLength - 1)
1212
+ for i = 1, msgLength + 1 do
1213
+ infoM[i] = msgBytes[i - 1]
1214
+ end
1215
+ else
1216
+ for i = 1, b5BodyLength + 1 do
1217
+ infoM[i] = b5Body[i]
1218
+ end
1219
+ keyP["isB5query"] = 0
1220
+ end
1221
+ --table 转换成 string 之后返回
1222
+ --local ret = table2string(bodyBytes)
1223
+ local ret = table2string(infoM)
1224
+ ret = string2hexstring(ret)
1225
+
1226
+ return ret
1227
+ end