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
|
local sds011 = {}
local c_head = 0xaa
local c_tail = 0xab
local c_id = 0xb4
local c_read = 0x00
local c_write = 0x01
local c_report_mode = 0x02
local c_active = 0x00
local c_passive = 0x01
local c_query = 0x04
local c_sleepcmd = 0x06
local c_sleep = 0x00
local c_work = 0x01
local c_workperiod = 0x08
function sds011.finish_cmd(cmd)
cmd = cmd .. string.char(0xff, 0xff)
local checksum = 0
for i = 3, string.len(cmd) do
checksum = (checksum + string.byte(cmd, i)) % 256
end
cmd = cmd .. string.char(checksum, c_tail)
return cmd
end
function sds011.set_report_mode(active)
local cmd = string.char(c_head, c_id, c_report_mode, c_write)
if active then
cmd = cmd .. string.char(c_active)
else
cmd = cmd .. string.char(c_passive)
end
cmd = cmd .. string.char(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
return sds011.finish_cmd(cmd)
end
function sds011.sleep(sleep)
local cmd = string.char(c_head, c_id, c_sleepcmd, c_write)
if sleep then
cmd = cmd .. string.char(c_sleep)
else
cmd = cmd .. string.char(c_work)
end
cmd = cmd .. string.char(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
return sds011.finish_cmd(cmd)
end
function sds011.set_work_period(period)
-- period == 0 : continuous operation, about one measurement per second
-- period > 0 : about one measurement every <period> minutes, fan is turned off in-between
if period < 0 or period > 30 then
return
end
local cmd = string.char(c_head, c_id, c_workperiod, c_write, period)
cmd = cmd .. string.char(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
return sds011.finish_cmd(cmd)
end
function sds011.parse_frame(data)
local header, command, pm25l, pm25h, pm10l, pm10h, id1, id2, sum, tail = struct.unpack("BBBBBBBBBB", data)
if header ~= c_head or command ~= 0xc0 or (pm25l + pm25h + pm10l + pm10h + id1 + id2) % 256 ~= sum or tail ~= c_tail then
return nil
end
pm25 = pm25h * 256 + pm25l
pm10 = pm10h * 256 + pm10l
return pm25 / 10, pm25 % 10, pm10 / 10, pm10 % 10
end
return sds011
|