summaryrefslogtreecommitdiff
path: root/sds011.lua
blob: a528720136b42017dcc65caca361dc7cb352cadf (plain)
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