Транзакционная работа с БД для избежания блокировок.
[weathermon.git] / bin / weather-lcd
index 69cd421134a33e6e9e529eeae101a0d61a9fc7ea..9abd84fac3d9cad802fe0c0e454ba0d62ff55723 100755 (executable)
@@ -12,6 +12,17 @@ if not config_name then
 end  
 
 weather_file = uci.get(config_name,"process","dump_file")
+weather_db = uci.get(config_name,"process","logdb")
+
+graph_duration = uci.get(config_name,"display","graph_duration")
+
+if graph_duration and not(weather_db == "") then
+  pcall(function ()
+      local dbdriver = require "luasql.sqlite3"
+      local env = assert(dbdriver.sqlite3())
+      log_con = assert(env:connect(weather_db))
+    end)  
+end
 
 function round(num, numDecimalPlaces)
   local mult = 10^(numDecimalPlaces or 0)
@@ -36,23 +47,34 @@ function process_file()
 end
 
 function get_display_config()
+
   width  = tonumber(uci.get(config_name,"display","width"))
   height = tonumber(uci.get(config_name,"display","height"))
-  cols   = tonumber(uci.get(config_name,"display","columns"))
+  charwidth  = tonumber(uci.get(config_name,"display","charwidth"))
+  charheight = tonumber(uci.get(config_name,"display","charheight"))
   title  = uci.get(config_name,"display","title")
-  col_width = math.floor(width/cols)
   
   pages = {}
   pagetitles = {}
+  pagedurations = {}
+  pagecolumns = {}
+  pagecolwidth = {}
   
   local page, def, line, col, pos
   
   cur.foreach(config_name,"display", function(s) 
       page = {}
+      local columns = s["columns"]
+      if not columns or columns == "" then
+        columns = 1
+      else 
+        columns = tonumber(columns)
+      end
       local pagetitle = s["title"]
       if not pagetitle then
         pagetitle = title
       end
+      local pageduration = s["duration"]
       if not (pagetitle=="") then
         line = 2
       else
@@ -76,13 +98,16 @@ function get_display_config()
           page[#page+1] = def
         end
         col = col + 1
-        if col > cols then
+        if col > columns then
           col = 1
           line = line + 1
         end
       end
       pages[#pages+1] = page
       pagetitles[#pages] = pagetitle
+      pagedurations[#pages] = pageduration
+      pagecolumns[#pages] = columns
+      pagecolwidth[#pages] = math.floor(width/columns)
     end)
 
 end
@@ -96,7 +121,8 @@ end
 
 function write_command(conn,command)
   conn:send(command.."\n")
-  return(conn:receive())
+  local str=conn:receive()
+  return str
 end
 
 function setup_pages(conn)
@@ -106,20 +132,45 @@ function setup_pages(conn)
     local pageid = "page"..trim(tostring(i))
     write_command(conn,"screen_add "..pageid)
     local pagetitle = pagetitles[i]
+    write_command(conn,"screen_set "..pageid.." -cursor off")
     if not(pagetitle == "") then
-      write_command(conn,"screen_set -name "..pagetitle)
+      write_command(conn,"screen_set "..pageid.." -name "..pagetitle)
       write_command(conn,"widget_add "..pageid.." "..pageid..".title title")
       write_command(conn,"widget_set "..pageid.." "..pageid..".title \"".. pagetitle.."\"")
     end
+    local pageduration = pagedurations[i]
+    if pageduration and not(pageduration == "") then
+      write_command(conn,"screen_set "..pageid.." -duration "..pageduration)
+    end
     for j,def in pairs(page) do
       defid = def["sensor"].."."..def["param"]
       write_command(conn,"widget_add "..pageid.." "..defid.." string")
     end
   end
+  if log_con then
+    for i,page in pairs(pages) do
+      for j,def in pairs(page) do
+        pageid = def["sensor"].."."..def["param"]
+        pagetitle = trim(def["label"])..", "..def["unit"]
+        write_command(conn,"screen_add "..pageid)
+        write_command(conn,"screen_set "..pageid.." -cursor off -name "..pagetitle.." -duration "..graph_duration)
+        write_command(conn,"widget_add "..pageid.." "..pageid..".title title")
+        if height>2 then
+          write_command(conn,"widget_add "..pageid.." "..pageid..".max string")
+          write_command(conn,"widget_add "..pageid.." "..pageid..".min string")
+          for k = 3,height-1 do
+            write_command(conn,"widget_add "..pageid.." "..pageid..".place"..trim(tostring(k)).." string")
+          end
+        end  
+        write_command(conn,"widget_set "..pageid.." "..pageid..".title \"".. pagetitle.."\"")
+      end
+    end
+  end
 end
 
 function process_vals(vals)
   for i,page in pairs(pages) do
+    col_width = pagecolwidth[i]
     local pageid = "page"..trim(tostring(i))
     for j,def in pairs(page) do
       val = vals[def["sensor"]][def["param"]]
@@ -136,6 +187,62 @@ function process_vals(vals)
   end
 end  
 
+function process_graphs()
+  for i,page in pairs(pages) do
+    for j,def in pairs(page) do
+      local sensor = def["sensor"]
+      local param  = def["param"]
+      local pageid = sensor.."."..param
+      local cur = assert (log_con:execute(string.format("select hour,avg(value) val from (select strftime('%%Y-%%m-%%d %%H',time_stamp)||':00' hour,value from log where sensor='%s' and param='%s') group by hour order by hour desc limit 24",sensor,param)))
+      local row = cur:fetch ({}, "a")
+      local vals = {}
+      local maxval = -99999999
+      local minval =  99999999
+      local len
+      for k=width,1,-1 do
+        if row then
+          val = row["val"] * def["scale"]
+          row = cur:fetch ({}, "a")
+        else
+          val = nil  
+        end  
+        vals[k] = val
+        if val and (val > maxval) then maxval = val; end
+        if val and (val < minval) then minval = val; end
+      end          
+      minval = math.floor(minval)
+      maxval = math.ceil(maxval)
+      if height>2 then
+        local minvalstr = trim(tostring(minval))
+        local maxvalstr = trim(tostring(maxval))
+        len = math.max(string.len(minvalstr),string.len(maxvalstr))
+        write_command(conn,"widget_set "..pageid.." "..pageid..".max "..trim(tostring(width-string.len(maxvalstr)+1)).." 2 "..maxvalstr)
+        write_command(conn,"widget_set "..pageid.." "..pageid..".min "..trim(tostring(width-string.len(minvalstr)+1)).." "..height.." "..minvalstr)
+        for k = 3,height-1 do
+          write_command(conn,"widget_set "..pageid.." "..pageid..".place"..trim(tostring(k)).." "..trim(tostring(width-len+1)).." "..k.." \" "..string.rep("-",len-1).."\"")
+        end
+      else
+        len = 0
+      end    
+      local m = width
+      for k=1,width do
+        write_command(conn,"widget_del "..pageid.." "..pageid..".bar"..trim(tostring(k)))
+      end
+      for k = width-len,1,-1 do
+        val = vals[m]
+        if val then
+          h = math.floor(0.5+(val-minval)/(maxval-minval)*(height-1)*charheight)
+        else
+          h = 0
+        end  
+        write_command(conn,"widget_add "..pageid.." "..pageid..".bar"..trim(tostring(k)).." vbar")
+        write_command(conn,"widget_set "..pageid.." "..pageid..".bar"..trim(tostring(k)).." "..k.." "..height.." "..h)
+        m = m - 1
+      end
+    end
+  end
+end
+
 get_display_config()
 
 conn = connect_server()
@@ -144,15 +251,19 @@ setup_pages(conn)
 
 while true do
 
-  pcall(function ()
+  pcall( function ()
 
       vals = process_file()
       process_vals(vals)
 
+      if log_con then
+        process_graphs()
+      end  
+      
       os.execute("inotifywait -e MODIFY \""..weather_file.."\"")
-      socket.sleep(3)
   
     end)
+
+    socket.sleep(3)
   
 end
-