93b9cb5f716407af90b43a7198de1cc0f8709104
[weathermon.git] / weathermon-iio
1 #!/usr/bin/lua
2
3 require "uci"
4 cur = uci.cursor()
5
6 lfs = require "lfs"
7 json = require "json"
8 socket = require "socket"
9
10 function split(str, pat)
11    local t = {}  -- NOTE: use {n = 0} in Lua-5.0
12    local fpat = "(.-)" .. pat
13    local last_end = 1
14    local s, e, cap = str:find(fpat, 1)
15    while s do
16       if s ~= 1 or cap ~= "" then
17          table.insert(t,cap)
18       end
19       last_end = e+1
20       s, e, cap = str:find(fpat, last_end)
21    end
22    if last_end <= #str then
23       cap = str:sub(last_end)
24       table.insert(t, cap)
25    end
26    return t
27 end
28
29 function trim(s)
30    return (s:gsub("^%s*(.-)%s*$", "%1"))
31 end
32
33 function get_device_list(config_name)
34
35   local devices
36   devices = {}
37
38   cur.foreach(config_name, "device", function(s)
39     devices[#devices+1] = s[".name"]
40   end)
41
42   return devices
43
44 end
45
46 function get_device(config_name,device_name)
47
48   local device
49   device = {}
50   
51   cur.foreach(config_name, "device", function(s)
52     if s[".name"] == device_name then
53       device = s
54     end
55   end)  
56   
57   return device
58   
59 end
60
61 function get_file_content(name)
62   local f = io.open(name,"r")
63   if f ~= nil then 
64     local content = trim(f:read("*all"))
65     io.close(f) 
66     return content
67   else 
68     return false 
69   end
70 end
71
72 function find_device(name,subsystem)
73
74   local search_base
75
76   if subsystem == "iio" then
77     search_base = "/sys/bus/iio/devices"
78     for file in lfs.dir(search_base) do
79       if get_file_content(search_base.."/"..file.."/name") == name then
80         return search_base.."/"..file
81       end
82     end
83   elseif subsystem == "hwmon" then
84     search_base = "/sys/class/hwmon"
85     for file in lfs.dir(search_base) do
86       if get_file_content(search_base.."/"..file.."/device/name") == name then
87         return search_base.."/"..file.."/device"
88       end
89     end  
90   end
91   
92   return nil
93
94 end
95
96 function init_device(device,parameters,i2c_bus)
97
98   if not i2c_bus then
99     i2c_bus = 0
100   end
101
102   if device["module"] then
103     os.execute("modprobe "..device["module"])
104   end    
105
106   if device["type"] then
107
108     devtype = split(device["type"],":")
109     bus = devtype[1]
110     subsystem = devtype[2]
111     
112     if (bus == "i2c") and device["address"] and device["name"] then
113       pcall(function ()
114         local f = io.open("/sys/class/i2c-dev/i2c-"..i2c_bus.."/device/new_device","w")
115         io.output(f)
116         io.write(device["name"].." "..device["address"])
117         io.close(f)
118       end)  
119     end
120
121     device_path=find_device(device["name"],subsystem)
122
123     if device_path and device["set_param"] then
124       for key,record in pairs(device["set_param"]) do
125         setparam = split(record,":")
126         setpath = device_path.."/"..setparam[1]
127         pcall(function ()
128           local f = io.open(setpath,"w")
129           io.output(f)
130           io.write(setparam[2])
131           io.close(f)
132         end)  
133       end
134     end
135     
136     if device_path and device["parameter"] then
137     
138       for key,record in pairs(device["parameter"]) do
139       
140         getparam = split(record,":")
141         getparameter = {}
142         getparameter["path"] = device_path.."/"..getparam[1]
143         getparameter["name"] = getparam[2]
144         getscale = getparam[3]
145         getcorrection = getparam[4]
146         if not getscale then
147           getscale = 1
148         end  
149         if not getcorrection then
150           getcorrection = 0
151         end
152         getparameter["scale"] = tonumber(getscale)
153         getparameter["sensor"] = device["name"]:upper()
154         getparameter["correction"] = tonumber(getcorrection)
155       
156         parameters[#parameters+1] = getparameter
157        
158       end
159     
160     end
161     
162   end
163
164 end
165
166 function init(config_name)
167
168   local parameters= {}
169
170   i2c_bus = uci.get(config_name,"hardware","i2c_bus")
171
172   local devices = get_device_list(config_name)
173   
174   for key,devname in pairs(devices) do
175   
176     device = get_device(config_name,devname)
177     
178     if device then
179       init_device(device,parameters,i2c_bus)
180     end  
181   
182   end
183
184   return parameters
185
186 end
187
188 function get_parameter(parameter)
189   return tonumber(get_file_content(parameter["path"])) * parameter["scale"] + parameter["correction"]
190 end
191
192 function get_parameters(parameters)
193   local results = {}
194   for key,record in pairs(parameters) do
195     if not results[record["sensor"]] then 
196       results[record["sensor"]] = {}
197     end
198     results[record["sensor"]][record["name"]] = get_parameter(record)
199   end
200   return results
201 end
202
203 config_name = arg[1]
204 if not config_name then
205   config_name = "weathermon"
206 end  
207
208 parameters = init(config_name)
209
210 local delay = uci.get(config_name,"process","delay")
211
212 local working_dir = uci.get(config_name,"process","working_dir")
213 local dump_file = uci.get(config_name,"process","dump_file")
214 if working_dir then
215   lfs.mkdir(working_dir)
216 end
217
218 if not delay then
219   delay = 60
220 end
221
222 while true do
223   values = get_parameters(parameters)
224   for key,record in pairs(values) do
225     dump = record
226     dump["device"] = key 
227     print(json.encode(dump))
228   end
229   if dump_file then
230     local f = io.open(dump_file,"w")
231     io.output(f)
232     io.write(json.encode(values))
233     io.close(f)
234   end
235   socket.sleep(delay)
236 end
237