Поддержка подключения устройств по последовательному интерфейсу.
authorRoman Bazalevsky <rvb@rvb.name>
Tue, 31 Dec 2019 07:43:03 +0000 (10:43 +0300)
committerRoman Bazalevsky <rvb@rvb.name>
Tue, 31 Dec 2019 07:43:03 +0000 (10:43 +0300)
Поддержка датчика углекислого газа MHZ-19.

bin/weathermon-iio

index f6e979f1c50939497b0c3234ff0452a1fe7c2d2f..9298f6f5a4aab760a6b6968f3ebbbebbd222a8ef 100755 (executable)
@@ -9,6 +9,8 @@ socket = require "socket"
 
 require "wm_util"
 
+io.stdout:setvbuf('no')
+
 function get_device_list(config_name)
 
   local devices
@@ -61,69 +63,134 @@ 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:write(string.fromhex("ff0186000000000079"))
+  local e, s = p:read(9,1000)
+  return s:byte(3)*256+s:byte(4)
+end
+
+function init_serial_device(device,subsystem,parameters)
+
+  rs232 = require("luars232")
+
+  pcall(function ()
+
+    local e, port = rs232.open(device["port"])
+  
+    if subsystem == "mhz" then
+    
+      assert(port:set_baud_rate(rs232.RS232_BAUD_9600) == rs232.RS232_ERR_NOERROR)
+      assert(port:set_data_bits(rs232.RS232_DATA_8) == rs232.RS232_ERR_NOERROR)
+      assert(port:set_parity(rs232.RS232_PARITY_NONE) == rs232.RS232_ERR_NOERROR)
+      assert(port:set_stop_bits(rs232.RS232_STOP_1) == rs232.RS232_ERR_NOERROR)
+      assert(port:set_flow_control(rs232.RS232_FLOW_OFF)  == rs232.RS232_ERR_NOERROR)
+    
+      getparameter = {}
+
+      getparameter["rs232"] = port
+      getparameter["function"] = get_mhz 
+      getparameter["name"] = "CO2_PPM"
+      getparameter["sensor"] = "MHZ19"
+      parameters[#parameters+1] = getparameter
+
+    end
+    
+  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
-      
-        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)
+    elseif (bus == "serial") then
       
-        parameters[#parameters+1] = getparameter
-       
-      end
+      init_serial_device(device,subsystem,parameters) 
     
     end
     
@@ -144,7 +211,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 +220,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
 
@@ -188,10 +255,8 @@ if not delay then
   delay = 60
 end
 
-io.stdout:setvbuf('no')
-
 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
@@ -202,7 +267,5 @@ while true do
       value["device"] = key
       print(json.encode(value))
     end
-  end  
   socket.sleep(delay)
 end
-  
\ No newline at end of file