3 local json = require("json")
7 function getConfig(configname)
11 local uci=require("uci")
12 local cur=uci.cursor()
20 web_url = cur.get(config,"web","url")
21 web_user = cur.get(config,"web","user")
22 web_timeout = cur.get(config,"web","timeout")
23 web_pass = cur.get(config,"web","password")
25 if not web_timeout then
29 web_devid = get_devid(config)
31 logging = cur.get(config,"logging","enabled")
32 touch_file = cur.get(config,"logging","touch_file")
34 backlogdb = cur.get(config,"process","backlogdb")
35 logdb = cur.get(config,"process","logdb")
37 serial_port = cur.get(config,"serial","port")
38 serial_baud = cur.get(config,"serial","baud")
40 input_file = cur.get(config,"input","file")
41 input_exec = cur.get(config,"input","exec")
42 alarm_exec = cur.get(config,"alarm","exec")
46 command = "stty -F "..serial_port.." "..serial_baud
51 mqtt_host = cur.get(config,"mqtt","host")
52 mqtt_port = cur.get(config,"mqtt","port")
53 mqtt_id = cur.get(config,"mqtt","id")
54 mqtt_topic = cur.get(config,"mqtt","topic")
55 mqtt_alarm_topic = cur.get(config,"mqtt","alarm_topic")
57 mqtt_user = cur.get(config,"mqtt","user")
58 mqtt_passwd = cur.get(config,"mqtt","password")
60 if mqtt_host and not mqtt_id then
61 mqtt_id="weather-"..web_devid
64 if mqtt_host and not mqtt_port then
68 if mqtt_host and not mqtt_topic then
69 mqtt_topic = 'weathermon/{dev}/{type}/{id}/{param}'
72 if mqtt_host and not mqtt_alarm_topic then
73 mqtt_alarm_topic = 'alarm/{dev}/{type}/{id}'
76 dump_file = cur.get(config,"process","dump_file")
80 function printLog(str)
82 capture("logger -t weathermon "..str)
84 elseif logging=="syslog" then
85 capture("logger -t weathermon "..str)
86 elseif logging=="stdout" then
91 function submitValue(type,id,param,val)
95 if web_url and val then
97 local url = web_url.."?stype="..url_encode(type).."&sid="..url_encode(id).."¶m="..url_encode(param).."&value="..url_encode(val)
100 url = url:gsub("//","//"..web_user..":"..web_pass.."@",1)
103 local result,code = http.request ({
104 url=url, create=function()
105 local req_sock = socket.tcp()
106 req_sock:settimeout(web_timeout)
110 if code ~= 200 and backlog_con then
111 printLog("writing record to backlog...")
112 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))
118 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))
123 function storeRecord(id,sensor,param,value)
125 if not records[id] then
129 records[id]["timestamp"] = os.date("%Y-%m-%dT%H:%M:%S")
131 if not records[id][sensor] then
132 records[id][sensor] = {}
135 records[id][sensor][param] = value
139 function processJson(str)
145 for key,value in pairs(msg) do
147 if key=="model" or key=="device" then
149 elseif key=="id" then
151 elseif key=='time' then
159 if not sensor_id then
160 sensor_id = web_devid
163 if not (sensor_type==nil or sensor_id==nil or sensor_type=='' or sensor_id=='') then
164 if next(sensor)==nil then
165 sensor["command"]="alarm"
168 for k,v in pairs(sensor) do
169 storeRecord(sensor_id,sensor_type,k,v)
170 printLog("Type = "..sensor_type..", ID = "..sensor_id..", Param = "..k..", Value = \""..v.."\"")
172 submitValue(sensor_type,sensor_id,k,v)
175 mqtt_path=string.gsub(mqtt_topic,"{(.-)}",
178 return mqtt_encode(web_devid)
179 elseif name=="type" then
180 return mqtt_encode(sensor_type)
181 elseif name=="id" then
182 return mqtt_encode(sensor_id)
183 elseif name=="param" then
186 return '{'..name..'}'
189 if not mqtt_client:socket() then
190 mqtt_client:reconnect()
192 mqtt_client:publish(mqtt_path,v)
197 printLog("Cannot parse sensor input: "..str)
202 function processLine(str)
205 msg_type=msg[1] or ''
206 msg_body=msg[2] or ''
207 if msg_type=="STATUS" then
208 printLog("Status: "..msg_body)
209 elseif msg_type=="ERROR" then
210 printLog("Error: "..msg_body)
211 elseif msg_type=="SENSOR" then
212 printLog("SENSOR: "..msg_body)
213 sens = split(msg_body,",")
217 sensor_id = web_devid
218 for i,rec in ipairs(sens) do
225 elseif key=="ID" then
232 if not (sensor_type==nil or sensor_id==nil or sensor_type=='' or sensor_id=='') then
234 for k,v in pairs(sensor) do
235 storeRecord(sensor_id,sensor_type,k,v)
236 printLog("Type = "..sensor_type..", ID = "..sensor_id..", Param = "..k..", Value = "..v)
238 submitValue(sensor_type,sensor_id,k,v)
241 mqtt_path=string.gsub(mqtt_topic,"{(.-)}",
245 elseif name=="type" then
247 elseif name=="id" then
249 elseif name=="param" then
252 return '{'..name..'}'
255 mqtt_client:publish(mqtt_path,v)
260 printLog("Cannot parse sensor input: "..msg_body)
262 elseif msg_type=="ALARM" then
263 printLog("ALARM: "..msg_body)
264 sens = split(msg_body,",")
268 sensor_id = web_devid
270 for i,rec in ipairs(sens) do
277 elseif key=="ID" then
282 if not (alarm_type==nil or alarm_id==nil or alarm_type=='' or alarm_id=='') then
284 mqtt_path=string.gsub(mqtt_alarm_topic,"{(.-)}",
288 elseif name=="type" then
290 elseif name=="id" then
293 return '{'..name..'}'
296 mqtt_client:publish(mqtt_path,msg_body)
301 " \""..string.gsub(alarm_type,"\"","\\\"")..
302 "\" \""..string.gsub(alarm_id,"\"","\\\"")..
303 "\" \""..string.gsub(msg_body,"\"","\\\"").."\""
307 printLog("Cannot parse alarm input: "..msg_body)
315 if backlogdb or logdb then
316 local dbdriver = require "luasql.sqlite3"
317 env = assert(dbdriver.sqlite3())
321 if not file_exists(backlogdb) then
324 backlog_con = assert(env:connect(backlogdb))
325 backlog_con:execute("CREATE TABLE queue(time_stamp datetime,sensor_id varchar(16),sensor varchar(16),param varchar(16),value float)")
329 if not file_exists(logdb) then
332 log_con = assert(env:connect(logdb))
333 log_con:execute("CREATE TABLE log(time_stamp datetime,sensor_id varchar(16),sensor varchar(16),param varchar(16),value float)")
334 log_con:execute("CREATE INDEX log_idx ON log(sensor_id,sensor,param,time_stamp)")
338 http = require("socket.http")
339 socket = require("socket")
343 MQTT = require "mosquitto"
344 mqtt_client = MQTT.new(mqtt_id)
346 mqtt_client:login_set(mqtt_user, mqtt_passwd)
348 mqtt_client:connect(mqtt_host,mqtt_port)
352 serialin=io.open(serial_port,"r")
353 elseif input_file == "-" then
355 elseif input_file then
356 serialin=io.open(input_file,"r")
357 elseif input_exec then
358 serialin=io.popen(input_exec,"r")
360 printLog("No input selected")
364 serialin:setvbuf('no')
370 line=serialin:read("*l")
378 printLog("Received: "..line)
379 if startswith(line,'{') then
393 local f = io.open(dump_file,"w")
395 io.write(json.encode(records))