forked from tenderlove/esp8266aq
-
Notifications
You must be signed in to change notification settings - Fork 0
/
client.rb
66 lines (51 loc) · 1.93 KB
/
client.rb
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
# Sample program for listening to AQ / Temp / RH information.
#
# The server that runs on the ESP8266 broadcasts data via UDP on port 9000.
# This program just listens for that data and decodes it
require "socket"
require "ipaddr"
require "json"
MULTICAST_ADDR = "224.0.0.1"
BIND_ADDR = "0.0.0.0"
PORT = 9000
AQ = Struct.new(:pm1_0_standard, :pm2_5_standard, :pm10_standard,
:pm1_0_env, :pm2_5_env,
:concentration_unit,
# These fields are "number of particles beyond N um
# per 0.1L of air". These numbers are multiplied by
# 10, so 03um == "number of particles beyond 0.3um
# in 0.1L of air"
:particle_03um, :particle_05um, :particle_10um,
:particle_25um, :particle_50um, :particle_100um)
TempRH = Struct.new(:temp, :rh)
class Combined
attr_reader :time, :mac, :record_id, :aq, :temprh
def initialize time, mac, record_id, aq, temprh
@time = time
@mac = mac
@record_id = record_id
@aq = aq
@temprh = temprh
end
end
if_addr = Socket.getifaddrs.find { |s| s.addr.ipv4? && !s.addr.ipv4_loopback? }
p if_addr.addr.ip_address
socket = UDPSocket.new
membership = IPAddr.new(MULTICAST_ADDR).hton + IPAddr.new(BIND_ADDR).hton
socket.setsockopt(:IPPROTO_IP, :IP_ADD_MEMBERSHIP, membership)
socket.setsockopt(:IPPROTO_IP, :IP_MULTICAST_TTL, 1)
socket.setsockopt(:SOL_SOCKET, :SO_REUSEPORT, 1)
socket.bind(BIND_ADDR, PORT)
loop do
m, _ = socket.recvfrom(2000)
record = JSON.load(m)
data = record["aq"].unpack("m0").first
unpack = data.unpack('CCnn14')
crc = 0x42 + 0x4d + 28 + data.bytes.drop(4).first(26).inject(:+)
unless crc != unpack.last
aq = AQ.new(*unpack.drop(3).first(12))
temprh = TempRH.new(record["temperature"] / 100.0, record["humidity"] / 100.0)
rec = Combined.new(Time.now.utc, record["mac"], record["record_id"], aq, temprh)
p rec
end
end