Обработка сообщений MQTT в формате rtl_433
[weathermon.git] / bin / weathermon-iio
index df32c3ad5849bc90d793f4379aa76b61667f1da0..c5a8102f6f038fc74bb76571b1613e25f6e5c37a 100755 (executable)
@@ -9,6 +9,21 @@ 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
@@ -61,69 +76,174 @@ function find_device(name,subsystem)
 
 end
 
-function init_device(device,parameters,i2c_bus)
+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
 
-  if device["module"] then
-    os.execute("modprobe "..device["module"])
-  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)  
 
-  if device["type"] then
+  device_path=find_device(device["name"],subsystem)
 
-    devtype = split(device["type"],":")
-    bus = devtype[1]
-    subsystem = devtype[2]
-    
-    if (bus == "i2c") and device["address"] and device["name"] then
+  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("/sys/class/i2c-dev/i2c-"..i2c_bus.."/device/new_device","w")
+        local f = io.open(setpath,"w")
         io.output(f)
-        io.write(device["name"].." "..device["address"])
+        io.write(setparam[2])
         io.close(f)
       end)  
     end
+  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)  
+  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 device_path and device["parameter"] then
+    if (bus == "i2c") then
+
+      init_i2c_device(device,subsystem,parameters)
     
-      for key,record in pairs(device["parameter"]) do
+    elseif (bus == "serial") then
       
-        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)
-      
-        parameters[#parameters+1] = getparameter
-       
-      end
+      init_serial_device(device,subsystem,parameters) 
     
     end
     
@@ -144,7 +264,7 @@ function init(config_name)
     device = get_device(config_name,devname)
     
     if device then
-      init_device(device,parameters,i2c_bus)
+      init_device(device,parameters)
     end  
   
   end
@@ -153,18 +273,18 @@ function init(config_name)
 
 end
 
-function get_parameter(parameter)
-  return tonumber(get_file_content(parameter["path"])) * parameter["scale"] + parameter["correction"]
-end
-
 function get_parameters(parameters)
   local results = {}
   for key,record in pairs(parameters) do
+
     if not results[record["sensor"]] then 
       results[record["sensor"]] = {}
     end
-    results[record["sensor"]][record["name"]] = get_parameter(record)
+    pcall(function ()
+        results[record["sensor"]][record["name"]] = record["function"](record)
+      end)
   end
+  
   return results
 end
 
@@ -173,7 +293,7 @@ if not config_name then
   config_name = "weathermon"
 end  
 
-web_id = uci.get(config_name,"web","devid")
+web_id = get_devid(config_name)
 
 parameters = init(config_name)
 
@@ -189,7 +309,7 @@ if not delay then
 end
 
 while true do
-  if pcall(function () values = get_parameters(parameters) end) then
+    values = get_parameters(parameters)
     records = {}
     records[web_id] = {}
     for key,record in pairs(values) do
@@ -200,7 +320,5 @@ while true do
       value["device"] = key
       print(json.encode(value))
     end
-  end  
   socket.sleep(delay)
 end
-  
\ No newline at end of file