Обработка неопределенных значений в веб-интерфейсе.
[weathermon.git] / bin / weathermon
index 03fad42630200d77a989ee62d40f395aee07f183..fdf092a3406aa0c62a02fdc4954af2a618288e04 100755 (executable)
@@ -1,9 +1,7 @@
 #!/usr/bin/lua
 
 local json = require("json")
-local socket = require("socket")
-
-local http = require("socket.http")
+local signal = require("posix.signal")
 
 require "wm_util"
 
@@ -24,37 +22,12 @@ function getConfig(configname)
   web_user = cur.get(config,"web","user")
   web_timeout = cur.get(config,"web","timeout")
   web_pass = cur.get(config,"web","password")
-  web_devid = cur.get(config,"web","devid")
-
-  web_iface = cur.get(config,"web","iface")
  
   if not web_timeout then
     web_timeout = 10
   end
 
-  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
-
-    local mac = io.read("*line")
-    mac = mac:gsub(":","")
-    mac = mac:upper()
-
-    web_devid = mac
-
-  end
+  web_devid = get_devid(config)
 
   logging = cur.get(config,"logging","enabled") 
   touch_file = cur.get(config,"logging","touch_file") 
@@ -118,7 +91,9 @@ end
 
 function submitValue(type,id,param,val)
 
-  if web_url then
+  val = tonumber(val)
+
+  if web_url and val then
 
     local url = web_url.."?stype="..url_encode(type).."&sid="..url_encode(id).."&param="..url_encode(param).."&value="..url_encode(val)
 
@@ -126,15 +101,10 @@ function submitValue(type,id,param,val)
       url = url:gsub("//","//"..web_user..":"..web_pass.."@",1)
     end
 
-    local result,code = http.request ({
-      url=url, create=function()
-        local req_sock = socket.tcp()
-        req_sock:settimeout(web_timeout)
-        return req_sock
-      end})
+    local result,code = http.request (url)
 
-    if code ~= 200 then
-      print("writing record to backlog...")
+    if code ~= 200 and backlog_con then
+      printLog("writing record to backlog...")
       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))
     end
 
@@ -144,10 +114,6 @@ function submitValue(type,id,param,val)
     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))
   end
 
-  if touch_file then
-    touch(touch_file)
-  end  
-  
 end
 
 function storeRecord(id,sensor,param,value) 
@@ -198,7 +164,9 @@ function processJson(str)
     for k,v in pairs(sensor) do
       storeRecord(sensor_id,sensor_type,k,v)
       printLog("Type = "..sensor_type..", ID = "..sensor_id..", Param = "..k..", Value = \""..v.."\"")
-      submitValue(sensor_type,sensor_id,k,v)
+      if web_url then
+        submitValue(sensor_type,sensor_id,k,v)
+      end  
       if mqtt_client then
         mqtt_path=string.gsub(mqtt_topic,"{(.-)}", 
           function (name) 
@@ -214,9 +182,11 @@ function processJson(str)
               return '{'..name..'}'
             end      
           end)
-        mqtt_client:connect(mqtt_host,mqtt_port)
-        mqtt_client:publish(mqtt_path,v)
-        mqtt_client:disconnect()
+        if not mqtt_client:socket() then
+          mqtt_client:reconnect()
+        end  
+        mqtt_client:publish(mqtt_path,v,0,false)
+        mqtt_client:loop()
       end  
     end
   else
@@ -260,7 +230,9 @@ function processLine(str)
       for k,v in pairs(sensor) do
         storeRecord(sensor_id,sensor_type,k,v)
         printLog("Type = "..sensor_type..", ID = "..sensor_id..", Param = "..k..", Value = "..v)
-        submitValue(sensor_type,sensor_id,k,v)
+        if web_url then 
+          submitValue(sensor_type,sensor_id,k,v)
+        end  
         if mqtt_client then
           mqtt_path=string.gsub(mqtt_topic,"{(.-)}", 
             function (name) 
@@ -276,9 +248,11 @@ function processLine(str)
                 return '{'..name..'}'
               end      
             end)
-          mqtt_client:connect(mqtt_host,mqtt_port)
-          mqtt_client:publish(mqtt_path,v)
-          mqtt_client:disconnect()
+          if not mqtt_client:socket() then
+            mqtt_client:reconnect()
+          end  
+          mqtt_client:publish(mqtt_path,v,0,false)
+          mqtt_client:loop()
         end  
       end
     else
@@ -318,9 +292,11 @@ function processLine(str)
               return '{'..name..'}'
             end      
           end)
-        mqtt_client:connect(mqtt_host,mqtt_port)
-        mqtt_client:publish(mqtt_path,msg_body)
-        mqtt_client:disconnect()
+        if not mqtt_client:socket() then
+          mqtt_client:reconnect()
+        end  
+        mqtt_client:publish(mqtt_path,msg_body,0,false)
+        mqtt_client:loop()
       end
       if alarm_exec then
         command=alarm_exec..
@@ -338,6 +314,19 @@ end
 
 getConfig(arg[1])
 
+signal.signal(signal.SIGTERM, function(signum)
+
+  printLog("Terminating...")
+  local pids = get_children()
+  for k,v in pairs(pids) do
+    printLog("Terminating subprocess "..tostring(v).."...")
+    signal.kill(v,signal.SIGTERM)
+  end
+  printLog("Exiting...")
+  os.exit(0)
+
+end)
+
 if backlogdb or logdb then
   local dbdriver = require "luasql.sqlite3"
   env = assert(dbdriver.sqlite3())
@@ -346,22 +335,23 @@ end
 if backlogdb then
   if not file_exists(backlogdb) then
     touch(backlogdb)
-    backlog_con = assert(env:connect(backlogdb))
-    backlog_con:execute("CREATE TABLE queue(time_stamp datetime,sensor_id varchar(16),sensor varchar(16),param varchar(16),value float)")
-  else
-    backlog_con = assert(env:connect(backlogdb))
-  end
+  end  
+  backlog_con = assert(env:connect(backlogdb))
+  backlog_con:execute("CREATE TABLE queue(time_stamp datetime,sensor_id varchar(16),sensor varchar(16),param varchar(16),value float)")
 end
 
 if logdb then
   if not file_exists(logdb) then
     touch(logdb)
-    log_con = assert(env:connect(logdb))
-    log_con:execute("CREATE TABLE log(time_stamp datetime,sensor_id varchar(16),sensor varchar(16),param varchar(16),value float)")
-    log_con:execute("CREATE INDEX log_idx ON log(sensor_id,sensor,param,time_stamp)")
-  else
-    log_con = assert(env:connect(logdb))
-  end
+  end  
+  log_con = assert(env:connect(logdb))
+  log_con:execute("CREATE TABLE log(time_stamp datetime,sensor_id varchar(16),sensor varchar(16),param varchar(16),value float)")
+  log_con:execute("CREATE INDEX log_idx ON log(sensor_id,sensor,param,time_stamp)")
+end
+
+if web_url then
+  http = require("socket.http")
+  http.TIMEOUT = web_timeout
 end
 
 if mqtt_host then
@@ -370,6 +360,7 @@ if mqtt_host then
   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
@@ -385,24 +376,41 @@ else
   return
 end  
 
+serialin:setvbuf('no')
+
 records = {}
 
 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
 
-  if dump_file then
-    local f = io.open(dump_file,"w")
-    io.output(f)
-    io.write(json.encode(records))
-    io.close(f)
-  end
+  pcall(function ()
+  
+    printLog("Received: "..line)
+    if startswith(line,'{') then
+      processJson(line)
+    else
+      processLine(line)
+    end
+
+    if touch_file then
+      pcall(function () 
+        touch(touch_file) 
+      end)
+    end  
+
+    if dump_file then
+      pcall(function ()
+        local f = io.open(dump_file,"w")
+        io.output(f)
+        io.write(json.encode(records))
+        io.close(f)
+      end)  
+    end
+  end)
+    
 end