#!/usr/bin/lua require "uci" cur = uci.cursor() lfs = require "lfs" json = require "json" socket = require "socket" require "wm_util" io.stdout:setvbuf('no') function dump(o) if type(o) == 'table' then local s = '{ ' for k,v in pairs(o) do if type(k) ~= 'number' then k = '"'..k..'"' end s = s .. '['..k..'] = ' .. dump(v) .. ',' end return s .. '} ' else return tostring(o) end end function get_device_list(config_name) local devices devices = {} cur.foreach(config_name, "device", function(s) devices[#devices+1] = s[".name"] end) return devices end function get_device(config_name,device_name) local device device = {} cur.foreach(config_name, "device", function(s) if s[".name"] == device_name then device = s end end) return device end function find_device(name,subsystem) local search_base if subsystem == "iio" then search_base = "/sys/bus/iio/devices" for file in lfs.dir(search_base) do if get_file_content(search_base.."/"..file.."/name") == name then return search_base.."/"..file end end elseif subsystem == "hwmon" then search_base = "/sys/class/hwmon" for file in lfs.dir(search_base) do if get_file_content(search_base.."/"..file.."/device/name") == name then return search_base.."/"..file.."/device" end end end return nil end function get_parameter(record) return tonumber(get_file_content(record["path"])) * record["scale"] + record["correction"] end function string.fromhex(str) return (str:gsub('..', function (cc) return string.char(tonumber(cc, 16)) end)) end function string.tohex(str) return (str:gsub('.', function (c) return string.format('%02X', string.byte(c)) end)) end function get_mhz(record) local p = record["rs232"] p:read(9,100) p:write(string.fromhex("ff0186000000000079")) local e, s = p:read(9,1000) if (e == 0) and (s:len() == 9) and (s:byte(1) == 255) then local crc = 0 for i = 2, 8 do crc = crc + s:byte(i) if (crc>=256) then crc = crc - 256 end end crc = 255 - crc crc = crc + 1; if crc == s:byte(9) then return s:byte(3)*256+s:byte(4) end end return nil end function search_rs232_const(rs232,prefix,value) for k,v in pairs(rs232) do if k == prefix..value:upper() then return v end end return nil end function init_serial_device(device,subsystem,parameters) rs232 = require("luars232") pcall(function () local e, port = rs232.open(device["port"]) local baud = device["baud"]; if baud == nil then baud = 9600; end local bits = device["bits"]; if bits == nil then bits = 8; end local stop_bits = device["stop_bits"]; if stop_bits == nil then stop_bits = 1; end local parity = device["parity"]; if parity == nil then parity = "NONE"; end local flowctl = device["flowctl"]; if flowctl == nil then flowctl = "OFF"; end assert(port:set_baud_rate(search_rs232_const(rs232,"RS232_BAUD_",baud)) == rs232.RS232_ERR_NOERROR) assert(port:set_data_bits(search_rs232_const(rs232,"RS232_DATA_",bits)) == rs232.RS232_ERR_NOERROR) assert(port:set_parity(search_rs232_const(rs232,"RS232_PARITY_",parity)) == rs232.RS232_ERR_NOERROR) assert(port:set_stop_bits(search_rs232_const(rs232,"RS232_STOP_",stop_bits)) == rs232.RS232_ERR_NOERROR) assert(port:set_flow_control(search_rs232_const(rs232,"RS232_FLOW_",flowctl)) == rs232.RS232_ERR_NOERROR) getparameter = {} getparameter["rs232"] = port if subsystem == "mhz" then getparameter["function"] = get_mhz getparameter["name"] = "CO2PPM" getparameter["sensor"] = "MHZ19" parameters[#parameters+1] = getparameter end parameters[#parameters+1] = getparameter end) end function init_i2c_device(device,subsystem,parameters) if not i2c_bus then i2c_bus = 0 end pcall(function () local f = io.open("/sys/class/i2c-dev/i2c-"..i2c_bus.."/device/new_device","w") io.output(f) io.write(device["name"].." "..device["address"]) io.close(f) end) device_path=find_device(device["name"],subsystem) if device_path and device["set_param"] then for key,record in pairs(device["set_param"]) do setparam = split(record,":") setpath = device_path.."/"..setparam[1] pcall(function () local f = io.open(setpath,"w") io.output(f) io.write(setparam[2]) io.close(f) end) end end if device_path and device["parameter"] then for key,record in pairs(device["parameter"]) do getparam = split(record,":") getparameter = {} getparameter["path"] = device_path.."/"..getparam[1] getparameter["name"] = getparam[2] getscale = getparam[3] getcorrection = getparam[4] if not getscale then getscale = 1 end if not getcorrection then getcorrection = 0 end getparameter["scale"] = tonumber(getscale) getparameter["sensor"] = device["name"]:upper() getparameter["correction"] = tonumber(getcorrection) getparameter["function"] = get_parameter parameters[#parameters+1] = getparameter end end end function init_device(device,parameters) if device["module"] then os.execute("modprobe "..device["module"]) end if device["type"] then devtype = split(device["type"],":") bus = devtype[1] subsystem = devtype[2] if (bus == "i2c") then init_i2c_device(device,subsystem,parameters) elseif (bus == "serial") then init_serial_device(device,subsystem,parameters) end end end function init(config_name) local parameters= {} i2c_bus = uci.get(config_name,"hardware","i2c_bus") local devices = get_device_list(config_name) for key,devname in pairs(devices) do device = get_device(config_name,devname) if device then init_device(device,parameters) end end return parameters end function get_parameters(parameters) local results = {} for key,record in pairs(parameters) do if not results[record["sensor"]] then results[record["sensor"]] = {} end pcall(function () results[record["sensor"]][record["name"]] = record["function"](record) end) end return results end config_name = arg[1] if not config_name then config_name = "weathermon" end web_id = get_devid(config_name) parameters = init(config_name) local delay = uci.get(config_name,"process","delay") local working_dir = uci.get(config_name,"process","working_dir") if working_dir then lfs.mkdir(working_dir) end if not delay then delay = 60 end while true do values = get_parameters(parameters) records = {} records[web_id] = {} for key,record in pairs(values) do records[web_id][key] = record records[web_id]["timestamp"] = os.date("%Y-%m-%dT%H:%M:%S") end for key,value in pairs(values) do value["device"] = key print(json.encode(value)) end socket.sleep(delay) end