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     local url = web_url.."?stype="..url_encode(type).."&sid="..url_encode(id).."¶m="..url_encode(param).."&value="..url_encode(val)
 
 126       url = url:gsub("//","//"..web_user..":"..web_pass.."@",1)
 
 129     local result,code = http.request ({
 
 130       url=url, create=function()
 
 131         local req_sock = socket.tcp()
 
 132         req_sock:settimeout(web_timeout)
 
 137       print("writing record to backlog...")
 
 138       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))
 
 144     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))
 
 153 function storeRecord(id,sensor,param,value) 
 
 155   if not records[id] then
 
 159   records[id]["timestamp"] = os.date("%Y-%m-%dT%H:%M:%S")
 
 161   if not records[id][sensor] then
 
 162     records[id][sensor] = {}
 
 165   records[id][sensor][param] = value
 
 169 function processJson(str)
 
 175   for key,value in pairs(msg) do
 
 177       if key=="model" or key=="device" then
 
 179       elseif key=="id" then
 
 181       elseif key=='time' then
 
 189   if not sensor_id then
 
 190     sensor_id = web_devid
 
 193   if not (sensor_type==nil or sensor_id==nil or sensor_type=='' or sensor_id=='') then
 
 194     if next(sensor)==nil then
 
 195       sensor["command"]="alarm"
 
 198     for k,v in pairs(sensor) do
 
 199       storeRecord(sensor_id,sensor_type,k,v)
 
 200       printLog("Type = "..sensor_type..", ID = "..sensor_id..", Param = "..k..", Value = \""..v.."\"")
 
 201       submitValue(sensor_type,sensor_id,k,v)
 
 203         mqtt_path=string.gsub(mqtt_topic,"{(.-)}", 
 
 206               return mqtt_encode(web_devid)
 
 207             elseif name=="type" then
 
 208               return mqtt_encode(sensor_type)
 
 209             elseif name=="id" then
 
 210               return mqtt_encode(sensor_id)
 
 211             elseif name=="param" then
 
 214               return '{'..name..'}'
 
 217         mqtt_client:connect(mqtt_host,mqtt_port)
 
 218         mqtt_client:publish(mqtt_path,v)
 
 219         mqtt_client:disconnect()
 
 223     printLog("Cannot parse sensor input: "..str)
 
 228 function processLine(str)
 
 231   msg_type=msg[1] or ''
 
 232   msg_body=msg[2] or ''
 
 233   if msg_type=="STATUS" then
 
 234     printLog("Status: "..msg_body)
 
 235   elseif msg_type=="ERROR" then
 
 236     printLog("Error: "..msg_body)  
 
 237   elseif msg_type=="SENSOR" then
 
 238     printLog("SENSOR: "..msg_body)  
 
 239     sens = split(msg_body,",")
 
 243     sensor_id = web_devid
 
 244     for i,rec in ipairs(sens) do
 
 251         elseif key=="ID" then
 
 258     if not (sensor_type==nil or sensor_id==nil or sensor_type=='' or sensor_id=='') then
 
 260       for k,v in pairs(sensor) do
 
 261         storeRecord(sensor_id,sensor_type,k,v)
 
 262         printLog("Type = "..sensor_type..", ID = "..sensor_id..", Param = "..k..", Value = "..v)
 
 263         submitValue(sensor_type,sensor_id,k,v)
 
 265           mqtt_path=string.gsub(mqtt_topic,"{(.-)}", 
 
 269               elseif name=="type" then
 
 271               elseif name=="id" then
 
 273               elseif name=="param" then
 
 276                 return '{'..name..'}'
 
 279           mqtt_client:connect(mqtt_host,mqtt_port)
 
 280           mqtt_client:publish(mqtt_path,v)
 
 281           mqtt_client:disconnect()
 
 285       printLog("Cannot parse sensor input: "..msg_body)
 
 287   elseif msg_type=="ALARM" then
 
 288     printLog("ALARM: "..msg_body)  
 
 289     sens = split(msg_body,",")
 
 293     sensor_id = web_devid
 
 295     for i,rec in ipairs(sens) do
 
 302         elseif key=="ID" then
 
 307     if not (alarm_type==nil or alarm_id==nil or alarm_type=='' or alarm_id=='') then
 
 309         mqtt_path=string.gsub(mqtt_alarm_topic,"{(.-)}", 
 
 313             elseif name=="type" then
 
 315             elseif name=="id" then
 
 318               return '{'..name..'}'
 
 321         mqtt_client:connect(mqtt_host,mqtt_port)
 
 322         mqtt_client:publish(mqtt_path,msg_body)
 
 323         mqtt_client:disconnect()
 
 327           " \""..string.gsub(alarm_type,"\"","\\\"")..
 
 328           "\" \""..string.gsub(alarm_id,"\"","\\\"")..
 
 329           "\" \""..string.gsub(msg_body,"\"","\\\"").."\""
 
 333       printLog("Cannot parse alarm input: "..msg_body)
 
 341 if backlogdb or logdb then
 
 342   local dbdriver = require "luasql.sqlite3"
 
 343   env = assert(dbdriver.sqlite3())
 
 347   if not file_exists(backlogdb) then
 
 349     backlog_con = assert(env:connect(backlogdb))
 
 350     backlog_con:execute("CREATE TABLE queue(time_stamp datetime,sensor_id varchar(16),sensor varchar(16),param varchar(16),value float)")
 
 352     backlog_con = assert(env:connect(backlogdb))
 
 357   if not file_exists(logdb) then
 
 359     log_con = assert(env:connect(logdb))
 
 360     log_con:execute("CREATE TABLE log(time_stamp datetime,sensor_id varchar(16),sensor varchar(16),param varchar(16),value float)")
 
 361     log_con:execute("CREATE INDEX log_idx ON log(sensor_id,sensor,param,time_stamp)")
 
 363     log_con = assert(env:connect(logdb))
 
 368   MQTT = require "mosquitto"
 
 369   mqtt_client = MQTT.new(mqtt_id)
 
 371     mqtt_client:login_set(mqtt_user, mqtt_passwd)
 
 376   serialin=io.open(serial_port,"r")
 
 377 elseif input_file == "-" then
 
 379 elseif input_file then
 
 380   serialin=io.open(input_file,"r")
 
 381 elseif input_exec then
 
 382   serialin=io.popen(input_exec,"r")
 
 384   printLog("No input selected")
 
 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))