- Добавлен процесс для чтения iio-датчиков
[weathermon.git] / bin / weather-display
diff --git a/bin/weather-display b/bin/weather-display
new file mode 100755 (executable)
index 0000000..1e0993b
--- /dev/null
@@ -0,0 +1,262 @@
+#!/usr/bin/lua
+
+require "uci"
+local cur = uci.cursor()
+local socket = require "socket"
+local lfs = require "lfs"
+local json = require "json"
+
+require "wm_util"
+
+function get_levels_list(config_name)
+  local levels, engage, engage_mode, disengage_mode, levels_idx
+  levels = {}
+  levels_idx = {}
+  engage = {}
+  engage_mode = {}
+  disengage_mode = {}
+  cur.foreach(config_name, "alarm", function(s)
+    local idx = #levels+1
+    levels[idx] = s["name"]
+    engage[idx] = s["engage"]
+    engage_mode[idx] = s["engage_mode"]
+    disengage_mode[idx] = s["disengage_mode"]
+    levels_idx[s[".name"]] = idx
+  end)
+  return levels, engage, engage_mode, disengage_mode, levels_idx
+end
+
+function get_params(config_name,levels_idx)
+  local a_names, a_formats, a_limits
+  a_names = {}
+  a_formats = {}
+  a_limits = {}
+  cur.foreach(config_name,"params", function(s)
+    if s["name"] then
+      a_names[s["param"]] = s["name"]
+    end
+    if s["format"] or s["scale"] then
+      local format, scale
+      if s["scale"] then
+        scale = s["scale"]
+      else
+        scale = 1  
+      end
+      if s["format"] then
+        format = s["format"]
+      else
+        format = "4s"
+      end
+      a_formats[s["param"]] = {format,scale}
+    end  
+    if s["limits"] then
+      for i,record in pairs(s["limits"]) do
+        rec = split(record,":")
+        idx = levels_idx[rec[1]]
+        low = tonumber(rec[2])
+        high = tonumber(rec[3])
+        if not a_limits[s["param"]] then
+          a_limits[s["param"]] = {}
+        end
+        if not a_limits[s["param"]][idx] then
+          a_limits[s["param"]][idx] = {}
+        end
+        rec = a_limits[s["param"]][idx]
+        a_limits[s["param"]][idx][#rec+1] = {low,high}
+      end  
+    end
+  end)
+  return a_names,a_formats,a_limits;
+end
+
+function check_limit(param,value,limits)
+
+  limit = limits[param]
+  if limit then
+  
+    for level,ranges in pairs(limit) do
+      for key,range in pairs(ranges) do
+        if value>=range[1] and value<range[2] then
+          return level
+        end  
+      end
+    end
+
+    return 0
+  
+  else
+  
+    return 0
+  
+  end
+
+end
+
+local config_name = arg[1]
+
+if not config_name then
+  config_name = "weathermon"
+end
+
+print("loading config...")
+
+local a_levels, a_engage, a_engage_mode, a_disengage_mode, levels_idx = get_levels_list(config_name)
+
+a_leds = {}
+
+for level,leds in pairs(a_engage) do
+
+  for key,led in pairs(leds) do
+  
+    a_leds[led] = a_disengage_mode[level]
+  
+  end
+
+end
+
+local a_names,a_formats,limits = get_params(config_name,levels_idx)
+
+local w_led = cur.get(config_name, "process", "engage")
+local w_engage = cur.get(config_name, "process", "engage_mode")
+local w_disengage = cur.get(config_name, "process", "disengage_mode")
+
+local senstemplate = string.gsub(cur.get(config_name, "display", "formatstr"),"~",string.char(223))
+local out_file = cur.get(config_name, "display", "file")
+
+local watch_file = cur.get(config_name,"process","dump_file")
+
+if not watch_file then
+  return
+end  
+
+local last = 0
+
+local data = ""
+local old_data = ""
+local sensor_data
+local res
+
+local mute_file=cur.get(config_name, "process", "mute_file")
+local mute_time=tonumber(cur.get(config_name, "process", "mute_time"))
+local alarm_raise = 2
+local onoff=true
+
+local timestr_template = cur.get(config_name, "display", "timestr")
+if not timestr_template then
+  timestr_template = "  %d.%m.%y   %H:%M  "
+end
+
+local alarmstr_len = cur.get(config_name, "display", "strlen")
+if not alarmstr_len then
+  alarmstr_len = 20
+end
+alarmstr_len=tonumber(alarmstr_len)
+
+web_id = uci.get(config_name,"web","devid")
+
+while true do
+
+  onoff = not onoff
+
+  local timestr = os.date(timestr_template)
+
+  local mod = lfs.attributes(watch_file,"modification")
+  local muted_mod = lfs.attributes(mute_file,"modification")
+  local muted_beep = muted_mod and (muted_mod > (os.time() - mute_time))
+  
+  if mod then
+  
+    if last < mod then
+      last = mod
+      res,sensor_data = pcall(function ()
+        local f = io.open(watch_file,"r")
+        content = f:read("*all")
+        io.close(f)
+        return json.decode(content)
+      end)      
+    
+      write_file(w_led,w_engage)
+   
+    else
+
+      write_file(w_led,w_disengage)
+      
+    end 
+
+    local values = {}
+    local printable = {}
+
+    for sensor,sensor_params in pairs(sensor_data[web_id]) do
+      if sensor ~= "timestamp" then
+        for param,value in pairs(sensor_params) do
+          local name = sensor.."."..param
+          values[name]=value
+          if a_formats[name] then
+            printable[name]=string.format("%"..a_formats[name][1],value*a_formats[name][2])
+          end  
+        end
+      end  
+    end
+
+    level = 1
+    alarms = ""
+
+    if not muted_beep then
+      for key,value in pairs(values) do
+        value_level = check_limit(key,value,limits)
+        if value_level > level then
+          level = value_level
+          alarms = a_names[key]
+        elseif value_level == level then  
+          alarms = alarms.." "..a_names[key]
+        end   
+      end
+    end  
+
+    leds_engage = {} 
+    
+    for key,value in pairs(a_engage[level]) do
+      leds_engage[value] = a_engage_mode[level]
+    end
+
+    for led,mode in pairs(a_leds) do
+      if leds_engage[led] then
+        write_file(led,leds_engage[led])
+      else  
+        write_file(led,mode)
+      end
+    end
+  
+    alarms = trim(alarms)
+    alarmstr = a_levels[level]..": "..alarms
+    
+    if alarmstr:len()>alarmstr_len then
+      alarmstr=alarmstr:sub(1,alarmstr_len)
+    elseif alarmstr:len()<alarmstr_len then
+      local delta = alarmstr_len - alarmstr:len()
+      local before = math.floor(delta/2)
+      local after = delta - before
+      alarmstr = string.rep(" ",before)..alarmstr..string.rep(" ",after)
+    end
+
+    sensstr = string.gsub(senstemplate,"%{.-%}", function (s) return printable[s:sub(2,s:len()-1)]; end)
+
+    if onoff and (level>=alarm_raise) then
+       data = alarmstr..sensstr
+    else
+        data = timestr..sensstr
+    end
+
+    if old_data ~= data then
+   
+      old_data = data
+      print(data)
+      write_file(out_file,data)
+   
+    end   
+  
+  end
+  
+  socket.sleep(1)
+
+end