3 local json = require("json")
4 local socket = require("socket")
6 local http = require("socket.http")
10 function getConfig(configname)
14 local uci=require("uci")
15 local cur=uci.cursor()
23 web_url = cur.get(config,"web","url")
24 web_user = cur.get(config,"web","user")
25 web_timeout = cur.get(config,"web","timeout")
26 web_pass = cur.get(config,"web","password")
27 web_devid = cur.get(config,"web","devid")
29 web_iface = cur.get(config,"web","iface")
31 if not web_timeout then
37 command = '/sbin/ifconfig '..web_iface..' | grep \'\\<inet\\>\' | sed -n \'1p\' | tr -s \' \' | cut -d \' \' -f3 | cut -d \':\' -f2'
38 f=io.popen(command,'r')
46 io.input("/sys/class/net/"..web_iface.."/address")
48 io.input("/sys/class/net/eth0/address")
51 local mac = io.read("*line")
52 mac = mac:gsub(":","")
59 logging = cur.get(config,"logging","enabled")
60 touch_file = cur.get(config,"logging","touch_file")
62 backlogdb = cur.get(config,"process","backlogdb")
63 logdb = cur.get(config,"process","logdb")
65 serial_port = cur.get(config,"serial","port")
66 serial_baud = cur.get(config,"serial","baud")
68 input_file = cur.get(config,"input","file")
69 input_exec = cur.get(config,"input","exec")
70 alarm_exec = cur.get(config,"alarm","exec")
74 command = "stty -F "..serial_port.." "..serial_baud
79 mqtt_host = cur.get(config,"mqtt","host")
80 mqtt_port = cur.get(config,"mqtt","port")
81 mqtt_id = cur.get(config,"mqtt","id")
82 mqtt_topic = cur.get(config,"mqtt","topic")
83 mqtt_alarm_topic = cur.get(config,"mqtt","alarm_topic")
85 mqtt_user = cur.get(config,"mqtt","user")
86 mqtt_passwd = cur.get(config,"mqtt","password")
88 if mqtt_host and not mqtt_id then
89 mqtt_id="weather-"..web_devid
92 if mqtt_host and not mqtt_port then
96 if mqtt_host and not mqtt_topic then
97 mqtt_topic = 'weathermon/{dev}/{type}/{id}/{param}'
100 if mqtt_host and not mqtt_alarm_topic then
101 mqtt_alarm_topic = 'alarm/{dev}/{type}/{id}'
104 dump_file = cur.get(config,"process","dump_file")
108 function printLog(str)
109 if logging=="on" then
110 capture("logger -t weathermon "..str)
112 elseif logging=="syslog" then
113 capture("logger -t weathermon "..str)
114 elseif logging=="stdout" then
119 function submitValue(type,id,param,val)
123 if web_url and val then
125 local url = web_url.."?stype="..url_encode(type).."&sid="..url_encode(id).."¶m="..url_encode(param).."&value="..url_encode(val)
128 url = url:gsub("//","//"..web_user..":"..web_pass.."@",1)
131 local result,code = http.request ({
132 url=url, create=function()
133 local req_sock = socket.tcp()
134 req_sock:settimeout(web_timeout)
138 if code ~= 200 and backlog_con then
139 printLog("writing record to backlog...")
140 backlog_con:execute(string.format("INSERT INTO queue(time_stamp,sensor_id,sensor,param,value) VALUES (datetime('now','localtime'),'%s','%s','%s',%f)",id,type,param,val))
146 log_con:execute(string.format("INSERT INTO log(time_stamp,sensor_id,sensor,param,value) VALUES (datetime('now','localtime'),'%s','%s','%s',%f)",id,type,param,val))
155 function storeRecord(id,sensor,param,value)
157 if not records[id] then
161 records[id]["timestamp"] = os.date("%Y-%m-%dT%H:%M:%S")
163 if not records[id][sensor] then
164 records[id][sensor] = {}
167 records[id][sensor][param] = value
171 function processJson(str)
177 for key,value in pairs(msg) do
179 if key=="model" or key=="device" then
181 elseif key=="id" then
183 elseif key=='time' then
191 if not sensor_id then
192 sensor_id = web_devid
195 if not (sensor_type==nil or sensor_id==nil or sensor_type=='' or sensor_id=='') then
196 if next(sensor)==nil then
197 sensor["command"]="alarm"
200 for k,v in pairs(sensor) do
201 storeRecord(sensor_id,sensor_type,k,v)
202 printLog("Type = "..sensor_type..", ID = "..sensor_id..", Param = "..k..", Value = \""..v.."\"")
203 submitValue(sensor_type,sensor_id,k,v)
205 mqtt_path=string.gsub(mqtt_topic,"{(.-)}",
208 return mqtt_encode(web_devid)
209 elseif name=="type" then
210 return mqtt_encode(sensor_type)
211 elseif name=="id" then
212 return mqtt_encode(sensor_id)
213 elseif name=="param" then
216 return '{'..name..'}'
219 mqtt_client:connect(mqtt_host,mqtt_port)
220 mqtt_client:publish(mqtt_path,v)
221 mqtt_client:disconnect()
225 printLog("Cannot parse sensor input: "..str)
230 function processLine(str)
233 msg_type=msg[1] or ''
234 msg_body=msg[2] or ''
235 if msg_type=="STATUS" then
236 printLog("Status: "..msg_body)
237 elseif msg_type=="ERROR" then
238 printLog("Error: "..msg_body)
239 elseif msg_type=="SENSOR" then
240 printLog("SENSOR: "..msg_body)
241 sens = split(msg_body,",")
245 sensor_id = web_devid
246 for i,rec in ipairs(sens) do
253 elseif key=="ID" then
260 if not (sensor_type==nil or sensor_id==nil or sensor_type=='' or sensor_id=='') then
262 for k,v in pairs(sensor) do
263 storeRecord(sensor_id,sensor_type,k,v)
264 printLog("Type = "..sensor_type..", ID = "..sensor_id..", Param = "..k..", Value = "..v)
265 submitValue(sensor_type,sensor_id,k,v)
267 mqtt_path=string.gsub(mqtt_topic,"{(.-)}",
271 elseif name=="type" then
273 elseif name=="id" then
275 elseif name=="param" then
278 return '{'..name..'}'
281 mqtt_client:connect(mqtt_host,mqtt_port)
282 mqtt_client:publish(mqtt_path,v)
283 mqtt_client:disconnect()
287 printLog("Cannot parse sensor input: "..msg_body)
289 elseif msg_type=="ALARM" then
290 printLog("ALARM: "..msg_body)
291 sens = split(msg_body,",")
295 sensor_id = web_devid
297 for i,rec in ipairs(sens) do
304 elseif key=="ID" then
309 if not (alarm_type==nil or alarm_id==nil or alarm_type=='' or alarm_id=='') then
311 mqtt_path=string.gsub(mqtt_alarm_topic,"{(.-)}",
315 elseif name=="type" then
317 elseif name=="id" then
320 return '{'..name..'}'
323 mqtt_client:connect(mqtt_host,mqtt_port)
324 mqtt_client:publish(mqtt_path,msg_body)
325 mqtt_client:disconnect()
329 " \""..string.gsub(alarm_type,"\"","\\\"")..
330 "\" \""..string.gsub(alarm_id,"\"","\\\"")..
331 "\" \""..string.gsub(msg_body,"\"","\\\"").."\""
335 printLog("Cannot parse alarm input: "..msg_body)
343 if backlogdb or logdb then
344 local dbdriver = require "luasql.sqlite3"
345 env = assert(dbdriver.sqlite3())
349 if not file_exists(backlogdb) then
352 backlog_con = assert(env:connect(backlogdb))
353 backlog_con:execute("CREATE TABLE queue(time_stamp datetime,sensor_id varchar(16),sensor varchar(16),param varchar(16),value float)")
357 if not file_exists(logdb) then
360 log_con = assert(env:connect(logdb))
361 log_con:execute("CREATE TABLE log(time_stamp datetime,sensor_id varchar(16),sensor varchar(16),param varchar(16),value float)")
362 log_con:execute("CREATE INDEX log_idx ON log(sensor_id,sensor,param,time_stamp)")
366 MQTT = require "mosquitto"
367 mqtt_client = MQTT.new(mqtt_id)
369 mqtt_client:login_set(mqtt_user, mqtt_passwd)
374 serialin=io.open(serial_port,"r")
375 elseif input_file == "-" then
377 elseif input_file then
378 serialin=io.open(input_file,"r")
379 elseif input_exec then
380 serialin=io.popen(input_exec,"r")
382 printLog("No input selected")
386 serialin:setvbuf('no')
392 line=serialin:read("*l")
400 printLog("Received: "..line)
401 if startswith(line,'{') then
408 local f = io.open(dump_file,"w")
410 io.write(json.encode(records))