4 local cur = uci.cursor()
5 local socket = require "socket"
6 local lfs = require "lfs"
7 local json = require "json"
11 function get_levels_list(config_name)
12 local levels, engage, engage_mode, disengage_mode, levels_idx
18 cur.foreach(config_name, "alarm", function(s)
20 levels[idx] = s["name"]
21 engage[idx] = s["engage"]
22 engage_mode[idx] = s["engage_mode"]
23 disengage_mode[idx] = s["disengage_mode"]
24 levels_idx[s[".name"]] = idx
26 return levels, engage, engage_mode, disengage_mode, levels_idx
29 function get_params(config_name,levels_idx)
30 local a_names, a_formats, a_limits
34 cur.foreach(config_name,"params", function(s)
36 a_names[s["param"]] = s["name"]
38 if s["format"] or s["scale"] then
50 a_formats[s["param"]] = {format,scale}
53 for i,record in pairs(s["limits"]) do
54 rec = split(record,":")
55 idx = levels_idx[rec[1]]
56 low = tonumber(rec[2])
57 high = tonumber(rec[3])
58 if not a_limits[s["param"]] then
59 a_limits[s["param"]] = {}
61 if not a_limits[s["param"]][idx] then
62 a_limits[s["param"]][idx] = {}
64 rec = a_limits[s["param"]][idx]
65 a_limits[s["param"]][idx][#rec+1] = {low,high}
69 return a_names,a_formats,a_limits;
72 function check_limit(param,value,limits)
77 for level,ranges in pairs(limit) do
78 for key,range in pairs(ranges) do
79 if value>=range[1] and value<range[2] then
95 local config_name = arg[1]
97 if not config_name then
98 config_name = "weathermon"
101 web_id = get_devid(config_name)
103 local a_levels, a_engage, a_engage_mode, a_disengage_mode, levels_idx = get_levels_list(config_name)
107 for level,leds in pairs(a_engage) do
109 for key,led in pairs(leds) do
111 a_leds[led] = a_disengage_mode[level]
117 local a_names,a_formats,limits = get_params(config_name,levels_idx)
119 local w_led = cur.get(config_name, "process", "engage")
120 local w_engage = cur.get(config_name, "process", "engage_mode")
121 local w_disengage = cur.get(config_name, "process", "disengage_mode")
123 local senstemplate = string.gsub(cur.get(config_name, "display", "formatstr"),"~",string.char(223))
124 local out_file = cur.get(config_name, "display", "file")
126 local watch_file = cur.get(config_name,"process","dump_file")
128 if not watch_file then
139 local mute_file=cur.get(config_name, "process", "mute_file")
140 local mute_time=tonumber(cur.get(config_name, "process", "mute_time"))
141 local alarm_raise = 2
144 local timestr_template = cur.get(config_name, "display", "timestr")
145 if not timestr_template then
146 timestr_template = " %d.%m.%y %H:%M "
149 local alarmstr_len = cur.get(config_name, "display", "strlen")
150 if not alarmstr_len then
153 alarmstr_len=tonumber(alarmstr_len)
159 local timestr = os.date(timestr_template)
163 local mod = lfs.attributes(watch_file,"modification")
164 local muted_mod = lfs.attributes(mute_file,"modification")
165 local muted_beep = muted_mod and (muted_mod > (os.time() - mute_time))
171 res,sensor_data = pcall(function ()
172 local f = io.open(watch_file,"r")
173 content = f:read("*all")
175 return json.decode(content)
178 write_file(w_led,w_engage)
182 write_file(w_led,w_disengage)
189 for sensor,sensor_params in pairs(sensor_data[web_id]) do
190 if sensor ~= "timestamp" then
191 for param,value in pairs(sensor_params) do
192 local name = sensor.."."..param
194 if a_formats[name] then
195 printable[name]=string.format("%"..a_formats[name][1],value*a_formats[name][2])
204 if not muted_beep then
205 for key,value in pairs(values) do
206 value_level = check_limit(key,value,limits)
207 if value_level > level then
209 alarms = a_names[key]
210 elseif value_level == level then
211 alarms = alarms.." "..a_names[key]
218 for key,value in pairs(a_engage[level]) do
219 leds_engage[value] = a_engage_mode[level]
222 for led,mode in pairs(a_leds) do
223 if leds_engage[led] then
224 write_file(led,leds_engage[led])
230 alarms = trim(alarms)
231 alarmstr = a_levels[level]..": "..alarms
233 if alarmstr:len()>alarmstr_len then
234 alarmstr=alarmstr:sub(1,alarmstr_len)
235 elseif alarmstr:len()<alarmstr_len then
236 local delta = alarmstr_len - alarmstr:len()
237 local before = math.floor(delta/2)
238 local after = delta - before
239 alarmstr = string.rep(" ",before)..alarmstr..string.rep(" ",after)
242 sensstr = string.gsub(senstemplate,"%{.-%}", function (s) return printable[s:sub(2,s:len()-1)]; end)
244 if onoff and (level>=alarm_raise) then
245 data = alarmstr..sensstr
247 data = timestr..sensstr
250 if old_data ~= data then
254 write_file(out_file,data)
262 local t = os.date("*t",os.time()+60)
264 local sec = os.time(t)-os.time()