+++ /dev/null
-#!/usr/bin/lua
-
-json = require("json")
-socket = require("socket")
-
-function startswith(String,Start)
- if String then
- return string.sub(String,1,string.len(Start))==Start
- else
- return False
- end
-end
-
-function url_encode(str)
- if (str) then
- str = string.gsub (str, "\n", "\r\n")
- str = string.gsub (str, "([^%w %-%_%.%~])",
- function (c) return string.format ("%%%02X", string.byte(c)) end)
- str = string.gsub (str, " ", "+")
- end
- return str
-end
-
-function capture(cmd, raw)
- local f = assert(io.popen(cmd, 'r'))
- local s = assert(f:read('*a'))
- f:close()
- if raw then return s end
- s = string.gsub(s, '^%s+', '')
- s = string.gsub(s, '%s+$', '')
- s = string.gsub(s, '[\n\r]+', ' ')
- return s
-end
-
-function mqtt_encode(str)
- if (str) then
- str = string.gsub (str, "\n", "")
- str = string.gsub (str, "/", "-")
- end
- return str
-end
-
-function getConfig(configname)
-
- local uci=require("uci")
- local cur=uci.cursor()
- local config
- if configname then
- config=configname
- else
- config="weathermon"
- end
-
- web_url = cur.get(config,"web","url")
- web_user = cur.get(config,"web","user")
- web_pass = cur.get(config,"web","password")
- web_devid = cur.get(config,"web","devid")
-
- web_iface = cur.get(config,"web","iface")
-
- if web_iface then
-
- command = '/sbin/ifconfig '..web_iface..' | grep \'\\<inet\\>\' | sed -n \'1p\' | tr -s \' \' | cut -d \' \' -f3 | cut -d \':\' -f2'
- f=io.popen(command,'r')
- ip_addr=f:read()
-
- end
-
- if not web_devid then
-
- if web_iface then
- io.input("/sys/class/net/"..web_iface.."/address")
- else
- io.input("/sys/class/net/eth0/address")
- end
-
- mac = io.read("*line")
- mac = mac:gsub(":","")
- mac = mac:upper()
-
- web_devid = mac
-
- end
-
- logging = cur.get(config,"logging","enabled")
- touch_file = cur.get(config,"logging","touch_file")
-
- serial_port = cur.get(config,"serial","port")
- serial_baud = cur.get(config,"serial","baud")
-
- input_file = cur.get(config,"input","file")
- input_exec = cur.get(config,"input","exec")
- alarm_exec = cur.get(config,"alarm","exec")
-
- if serial_port then
-
- command = "stty -F "..serial_port.." "..serial_baud
- capture(command)
-
- end
-
- mqtt_host = cur.get(config,"mqtt","host")
- mqtt_port = cur.get(config,"mqtt","port")
- mqtt_id = cur.get(config,"mqtt","id")
- mqtt_topic = cur.get(config,"mqtt","topic")
- mqtt_alarm_topic = cur.get(config,"mqtt","alarm_topic")
-
- mqtt_user = cur.get(config,"mqtt","user")
- mqtt_passwd = cur.get(config,"mqtt","password")
-
- if mqtt_host and not mqtt_id then
- mqtt_id="weather-"..web_devid
- end
-
- if mqtt_host and not mqtt_port then
- mqtt_port = 1883
- end
-
- if mqtt_host and not mqtt_topic then
- mqtt_topic = 'weathermon/{dev}/{type}/{id}/{param}'
- end
-
- if mqtt_host and not mqtt_alarm_topic then
- mqtt_alarm_topic = 'alarm/{dev}/{type}/{id}'
- end
-
-end
-
-function touch()
- if touch_file then
- local file = io.open(touch_file, 'w')
- file:close()
- end
-end
-
-function sleep(sec)
- socket.select(nil, nil, sec)
-end
-
-function splitStr(str,char)
-
- local res = {}
- local idx = 1
-
- while str:len()>0 do
- pos = str:find(char);
- if pos == nil then
- res[idx]=str
- str=""
- else
- res[idx]=str:sub(1,pos-1)
- idx=idx+1
- str=str:sub(pos+1)
- end
- end
-
- return res
-
-end
-
-function printLog(str)
- if logging=="on" then
- capture("logger -t weathermon "..str)
- print(str)
- elseif logging=="syslog" then
- capture("logger -t weathermon "..str)
- elseif logging=="stdout" then
- print(str)
- end
-end
-
-function submitValue(type,id,param,val)
-
- url = web_url.."?stype="..url_encode(type).."&sid="..url_encode(id).."¶m="..url_encode(param).."&value="..url_encode(val)
-
- command = "curl"
-
- if web_iface then
- command = command.." --interface "..ip_addr
- end
-
- if web_user then
- command = command.." -u "..web_user..":"..web_pass
- end
-
- command = command.." \""..url.."\" 2>&1"
-
- result = capture(command)
-
- touch()
-
-end
-
-function processJson(str)
-
- msg=json.decode(str)
-
- sensor={}
-
- for key,value in pairs(msg) do
- if value then
- if key=="model" or key=="device" then
- sensor_type=value
- elseif key=="id" then
- sensor_id=value
- elseif key=='time' then
- sensor_time=value
- else
- sensor[key]=value
- end
- end
- end
-
- if not sensor_id then
- sensor_id = web_devid
- end
-
- if not (sensor_type==nil or sensor_id==nil or sensor_type=='' or sensor_id=='') then
- if next(sensor)==nil then
- sensor["command"]="alarm"
- end
- for k,v in pairs(sensor) do
- printLog("Type = "..sensor_type..", ID = "..sensor_id..", Param = "..k..", Value = \""..v.."\"")
- submitValue(sensor_type,sensor_id,k,v)
- if mqtt_client then
- mqtt_path=string.gsub(mqtt_topic,"{(.-)}",
- function (name)
- if name=="dev" then
- return mqtt_encode(web_devid)
- elseif name=="type" then
- return mqtt_encode(sensor_type)
- elseif name=="id" then
- return mqtt_encode(sensor_id)
- elseif name=="param" then
- return k
- else
- return '{'..name..'}'
- end
- end)
- mqtt_client:publish(mqtt_path,v)
- end
- end
- else
- printLog("Cannot parse sensor input: "..str)
- end
-
-end
-
-function processLine(str)
-
- msg=splitStr(line,':')
- msg_type=msg[1] or ''
- msg_body=msg[2] or ''
- if msg_type=="STATUS" then
- printLog("Status: "..msg_body)
- elseif msg_type=="ERROR" then
- printLog("Error: "..msg_body)
- elseif msg_type=="SENSOR" then
- printLog("SENSOR: "..msg_body)
- sens = splitStr(msg_body,",")
- sensor = {}
- idx = 1
- sensor_type = nil
- sensor_id = web_devid
- for i,rec in ipairs(sens) do
- recrd=splitStr(rec,'=')
- key=recrd[1] or ''
- value=recrd[2] or ''
- if value then
- if key=="TYPE" then
- sensor_type=value
- elseif key=="ID" then
- sensor_id=value
- else
- sensor[key]=value
- end
- end
- end
- if not (sensor_type==nil or sensor_id==nil or sensor_type=='' or sensor_id=='') then
- for k,v in pairs(sensor) do
- printLog("Type = "..sensor_type..", ID = "..sensor_id..", Param = "..k..", Value = "..v)
- submitValue(sensor_type,sensor_id,k,v)
- if mqtt_client then
- mqtt_path=string.gsub(mqtt_topic,"{(.-)}",
- function (name)
- if name=="dev" then
- return web_devid
- elseif name=="type" then
- return sensor_type
- elseif name=="id" then
- return sensor_id
- elseif name=="param" then
- return k
- else
- return '{'..name..'}'
- end
- end)
- mqtt_client:publish(mqtt_path,v)
- end
- end
- else
- printLog("Cannot parse sensor input: "..msg_body)
- end
- elseif msg_type=="ALARM" then
- printLog("ALARM: "..msg_body)
- sens = splitStr(msg_body,",")
- sensor = {}
- idx = 1
- sensor_type = nil
- sensor_id = web_devid
- mqtt_param = {}
- for i,rec in ipairs(sens) do
- recrd=splitStr(rec,'=')
- key=recrd[1] or ''
- value=recrd[2] or ''
- if value then
- if key=="TYPE" then
- alarm_type=value
- elseif key=="ID" then
- alarm_id=value
- end
- end
- end
- if not (alarm_type==nil or alarm_id==nil or alarm_type=='' or alarm_id=='') then
- if mqtt_client then
- mqtt_path=string.gsub(mqtt_alarm_topic,"{(.-)}",
- function (name)
- if name=="dev" then
- return web_devid
- elseif name=="type" then
- return sensor_type
- elseif name=="id" then
- return sensor_id
- else
- return '{'..name..'}'
- end
- end)
- mqtt_client:publish(mqtt_path,msg_body)
- end
- if alarm_exec then
- command=alarm_exec..
- " \""..string.gsub(alarm_type,"\"","\\\"")..
- "\" \""..string.gsub(alarm_id,"\"","\\\"")..
- "\" \""..string.gsub(msg_body,"\"","\\\"").."\""
- capture(command)
- end
- else
- printLog("Cannot parse alarm input: "..msg_body)
- end
- end
-
-end
-
-getConfig(arg[1])
-
-if mqtt_host then
- MQTT = require "mosquitto"
- mqtt_client = MQTT.new(mqtt_id)
- if mqtt_user then
- mqtt_client:login_set(mqtt_user, mqtt_passwd)
- end
- mqtt_client:connect(mqtt_host,mqtt_port)
-end
-
-if serial_port then
- serialin=io.open(serial_port,"r")
-elseif input_file == "-" then
- serialin=io.stdin;
-elseif input_file then
- serialin=io.open(input_file,"r")
-elseif input_exec then
- serialin=io.popen(input_exec,"r")
-else
- printLog("No input selected")
- return
-end
-while 1 do
- line=serialin:read("*l")
- if line == nil then
- break
- end
- printLog("Received: "..line);
- if startswith(line,'{') then
- processJson(line)
- else
- processLine(line)
- end
-end