Поддержка подключения устройств по последовательному интерфейсу.
[weathermon.git] / bin / 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 require "wm_util"
11
12 io.stdout:setvbuf('no')
13
14 function get_device_list(config_name)
15
16   local devices
17   devices = {}
18
19   cur.foreach(config_name, "device", function(s)
20     devices[#devices+1] = s[".name"]
21   end)
22
23   return devices
24
25 end
26
27 function get_device(config_name,device_name)
28
29   local device
30   device = {}
31   
32   cur.foreach(config_name, "device", function(s)
33     if s[".name"] == device_name then
34       device = s
35     end
36   end)  
37   
38   return device
39   
40 end
41
42 function find_device(name,subsystem)
43
44   local search_base
45
46   if subsystem == "iio" then
47     search_base = "/sys/bus/iio/devices"
48     for file in lfs.dir(search_base) do
49       if get_file_content(search_base.."/"..file.."/name") == name then
50         return search_base.."/"..file
51       end
52     end
53   elseif subsystem == "hwmon" then
54     search_base = "/sys/class/hwmon"
55     for file in lfs.dir(search_base) do
56       if get_file_content(search_base.."/"..file.."/device/name") == name then
57         return search_base.."/"..file.."/device"
58       end
59     end  
60   end
61   
62   return nil
63
64 end
65
66 function get_parameter(record)
67   return tonumber(get_file_content(record["path"])) * record["scale"] + record["correction"]
68 end
69
70 function string.fromhex(str)
71   return (str:gsub('..', function (cc)
72     return string.char(tonumber(cc, 16))
73   end))
74 end
75
76 function string.tohex(str)
77   return (str:gsub('.', function (c)
78     return string.format('%02X', string.byte(c))
79   end))
80 end
81
82 function get_mhz(record)
83   local p = record["rs232"]  
84   p:write(string.fromhex("ff0186000000000079"))
85   local e, s = p:read(9,1000)
86   return s:byte(3)*256+s:byte(4)
87 end
88
89 function init_serial_device(device,subsystem,parameters)
90
91   rs232 = require("luars232")
92
93   pcall(function ()
94
95     local e, port = rs232.open(device["port"])
96   
97     if subsystem == "mhz" then
98     
99       assert(port:set_baud_rate(rs232.RS232_BAUD_9600) == rs232.RS232_ERR_NOERROR)
100       assert(port:set_data_bits(rs232.RS232_DATA_8) == rs232.RS232_ERR_NOERROR)
101       assert(port:set_parity(rs232.RS232_PARITY_NONE) == rs232.RS232_ERR_NOERROR)
102       assert(port:set_stop_bits(rs232.RS232_STOP_1) == rs232.RS232_ERR_NOERROR)
103       assert(port:set_flow_control(rs232.RS232_FLOW_OFF)  == rs232.RS232_ERR_NOERROR)
104     
105       getparameter = {}
106
107       getparameter["rs232"] = port
108       getparameter["function"] = get_mhz 
109       getparameter["name"] = "CO2_PPM"
110       getparameter["sensor"] = "MHZ19"
111       parameters[#parameters+1] = getparameter
112
113     end
114     
115   end)
116
117 end
118
119 function init_i2c_device(device,subsystem,parameters)
120
121   if not i2c_bus then
122     i2c_bus = 0
123   end
124
125   pcall(function ()
126     local f = io.open("/sys/class/i2c-dev/i2c-"..i2c_bus.."/device/new_device","w")
127     io.output(f)
128     io.write(device["name"].." "..device["address"])
129     io.close(f)
130   end)  
131
132   device_path=find_device(device["name"],subsystem)
133
134   if device_path and device["set_param"] then
135     for key,record in pairs(device["set_param"]) do
136       setparam = split(record,":")
137       setpath = device_path.."/"..setparam[1]
138       pcall(function ()
139         local f = io.open(setpath,"w")
140         io.output(f)
141         io.write(setparam[2])
142         io.close(f)
143       end)  
144     end
145   end
146
147   if device_path and device["parameter"] then
148
149     for key,record in pairs(device["parameter"]) do
150
151       getparam = split(record,":")
152       getparameter = {}
153       getparameter["path"] = device_path.."/"..getparam[1]
154       getparameter["name"] = getparam[2]
155       getscale = getparam[3]
156       getcorrection = getparam[4]
157       if not getscale then
158         getscale = 1
159       end  
160       if not getcorrection then
161         getcorrection = 0
162       end
163       getparameter["scale"] = tonumber(getscale)
164       getparameter["sensor"] = device["name"]:upper()
165       getparameter["correction"] = tonumber(getcorrection)
166       getparameter["function"] = get_parameter
167       parameters[#parameters+1] = getparameter
168
169     end
170
171   end
172   
173 end
174
175 function init_device(device,parameters)
176
177   if device["module"] then
178     os.execute("modprobe "..device["module"])
179   end    
180
181   if device["type"] then
182
183     devtype = split(device["type"],":")
184     bus = devtype[1]
185     subsystem = devtype[2]
186     
187     if (bus == "i2c") then
188
189       init_i2c_device(device,subsystem,parameters)
190     
191     elseif (bus == "serial") then
192       
193       init_serial_device(device,subsystem,parameters) 
194     
195     end
196     
197   end
198
199 end
200
201 function init(config_name)
202
203   local parameters= {}
204
205   i2c_bus = uci.get(config_name,"hardware","i2c_bus")
206
207   local devices = get_device_list(config_name)
208   
209   for key,devname in pairs(devices) do
210   
211     device = get_device(config_name,devname)
212     
213     if device then
214       init_device(device,parameters)
215     end  
216   
217   end
218
219   return parameters
220
221 end
222
223 function get_parameters(parameters)
224   local results = {}
225   for key,record in pairs(parameters) do
226
227     if not results[record["sensor"]] then 
228       results[record["sensor"]] = {}
229     end
230     pcall(function ()
231         results[record["sensor"]][record["name"]] = record["function"](record)
232       end)
233   end
234   
235   return results
236 end
237
238 config_name = arg[1]
239 if not config_name then
240   config_name = "weathermon"
241 end  
242
243 web_id = get_devid(config_name)
244
245 parameters = init(config_name)
246
247 local delay = uci.get(config_name,"process","delay")
248
249 local working_dir = uci.get(config_name,"process","working_dir")
250 if working_dir then
251   lfs.mkdir(working_dir)
252 end
253
254 if not delay then
255   delay = 60
256 end
257
258 while true do
259     values = get_parameters(parameters)
260     records = {}
261     records[web_id] = {}
262     for key,record in pairs(values) do
263       records[web_id][key] = record
264       records[web_id]["timestamp"] = os.date("%Y-%m-%dT%H:%M:%S")
265     end
266     for key,value in pairs(values) do
267       value["device"] = key
268       print(json.encode(value))
269     end
270   socket.sleep(delay)
271 end