Merge branch 'master' of rvb.name:openhab-process
authorRoman Bazalevskiy <rvb@rvb.name>
Sun, 16 Sep 2018 16:08:55 +0000 (19:08 +0300)
committerRoman Bazalevskiy <rvb@rvb.name>
Sun, 16 Sep 2018 16:08:55 +0000 (19:08 +0300)
1  2 
mqtt-bt/scan-beacons

diff --combined mqtt-bt/scan-beacons
index b73d6747abdad876a4937f85eecf9e5c7790ea5f,a574f664249410ca789b671eefe37233a21e2779..17e553308c15a067544f4b337a62603469215b39
@@@ -1,5 -1,7 +1,7 @@@
  #!/usr/bin/lua
  
+ json = require("json")
  function getConfig(configname)
  
    local uci=require("uci")
    mqtt_passwd = cur.get(config,"mqtt","password")
  
    if mqtt_host and not mqtt_id then
-     mqtt_id="beaconmon"
+     socket = require("socket")
+     posix = require("posix")
+     hostname = socket.dns.gethostname()
+     pid = posix.getpid()
+     mqtt_id="beaconmon-"..hostname.."-"..pid
    end
  
    if mqtt_host and not mqtt_port then
@@@ -49,15 -55,13 +55,15 @@@ en
  function mqtt_encode(str)
    if (str) then
      str = string.gsub (str, "\n", "")
 +    str = string.gsub (str, ":", "-")
      str = string.gsub (str, "/", "-")
 +    str = string.gsub (str, " ", "_")
    end
    return str  
  end
  
  function printLog(str)
-   if logging=="on" then
+   if logging=="yes" then
      capture("logger -t beaconmon "..str)
    else 
      print(str)  
@@@ -74,29 -78,19 +80,19 @@@ en
  
  function open_dump()
  
-   run_command("/bin/kill `/usr/bin/pgrep hcidump`")
+   run_command("/bin/kill `/usr/bin/pgrep btmon`")
    run_command("/bin/kill `/usr/bin/pgrep hcitool`")
-   f = assert(io.popen ("/usr/bin/hcidump --raw"))
+   f = assert(io.popen ("/usr/bin/stdbuf -o0 /usr/bin/btmon"))
    run_command("/usr/bin/hciconfig hci0 down")
    run_command("/usr/bin/hciconfig hci0 up")
-   f_null = assert(io.popen ("/usr/bin/hcitool lescan --duplicates"))
+   f_null = assert(io.popen ("/usr/bin/hcitool lescan --duplicates --passive"))
  
    return f
  
  end
  
  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) .. ','
- --         s = s .. dump(v) .. ','
-       end
-       return s .. '} '
-    else
-       return tostring(o)
-    end
+   return json.encode(o)
  end
  
  function trim(s)
  end
  
  function mqtt_pub(path,value)
-   printLog("Pub "..path.." "..value)
-   return mqtt_client:publish(path,value)
+   res=mqtt_client:publish(path,value)
+   printLog("Pub "..path.." "..value.." returned "..res);
+   return res
  end
  
  function process_packet(packet)
  
-   local bytes={}
-   local idx=1
-   local len
    local mac
-   local flags
-   local power
-   local tx
-   local type
-   local paysublen
    local uuid
-   local major
-   local minor
    local details
+   local type
+   local name
+   mac = packet['Address']
+   uuid = packet['uuid']
+   type = packet['Type']
+   name = packet['Name (complete)']
+   if type=='iBeacon' then
+     details=uuid
+   elseif name then
+     if not(type) then
+       type="name"
+     end  
+     details=name
+   else
+     if not type then 
+       type='unknown'
+     end  
+     details=mac
+   end
  
-   if packet:len()>1 then
-     while packet:len()>2 do
-       bytes[idx]=trim(packet:sub(1,3))
-       idx=idx+1
-       packet=packet:sub(4)
-     end
-     len = idx-1
-     if bytes[1]=='04' and bytes[2]=='3E' then
-       -- BLE Beacon?
-       type=""
-       mac=bytes[13]..':'..bytes[12]..':'..bytes[11]..':'..bytes[10]..':'..bytes[9]..':'..bytes[8]
-       flags=bytes[14]
-       power=tonumber("0x"..bytes[len-1])-256
-       tx=tonumber("0x"..bytes[len])-256
-       local j = 15
-       while j<len-2 do
-         paysublen=tonumber('0x'..bytes[j])
-       if bytes[j+1]=="FF" and bytes[j+2]=="4C" and bytes[j+3]=="00" and bytes[j+4]=="02" and bytes[j+5]=="15" then
-         -- Standard UUID iBeacon
-           type="ibeacon"
-         local uuid1=bytes[j+6]..bytes[j+7]..bytes[j+8]..bytes[j+9]
-         local uuid2=bytes[j+10]..bytes[j+11]
-         local uuid3=bytes[j+12]..bytes[j+13]
-         local uuid4=bytes[j+14]..bytes[j+15]
-         local uuid5=bytes[j+16]..bytes[j+17]..bytes[j+18]..bytes[j+19]..bytes[j+20]..bytes[j+21]
-         uuid=string.lower(uuid1..'-'..uuid2..'-'..uuid3..'-'..uuid4..'-'..uuid5)
-           major=bytes[j+23]..bytes[j+22]
-           minor=bytes[j+25]..bytes[j+24]
-       end
-         j=j+1+paysublen
-       end
-       if type=="ibeacon" then
-         printLog(string.format("{type:'ibeacon',mac:'%s',uuid:'%s',major:'%s',minor:'%s',power:%d,tx:%d}",mac,uuid,major,minor,power,tx))
-         details=uuid..'/'..major..'/'..minor
-       else
-         type='unknown'
-         details=dump(bytes)
- --        printLog(details)
-       end
-       if not (type=="unknown") then
-         mqtt_path=string.gsub(mqtt_topic,"{(.-)}", 
-           function (name) 
-             if name=="type" then
-               return mqtt_encode(type)
-             elseif name=="details" then
-               return mqtt_encode(details)
-             else
-               return '{'..name..'}'
-             end      
-           end)
+   if not (type=="unknown") then
+     mqtt_path=string.gsub(mqtt_topic,"{(.-)}",
+       function (name) 
+         if name=="type" then
+           return mqtt_encode(type)
+         elseif name=="details" then
+           return mqtt_encode(details)
+         else
+           return '{'..name..'}'
+         end      
+       end)
          
-         if not pcall(mqtt_pub,mqtt_path,tx) then
-           printLog('Reconnecting MQTT...')
-           mqtt_client:connect(mqtt_id)
-         end
-       end        
+     if not pcall(mqtt_pub,mqtt_path,dump(packet)) then
+       printLog('Reconnecting MQTT...')
+       mqtt_client:connect(mqtt_id)
      end
    end
  
  end
  
- function read_loop()
-   packet = ""
-   for line in inp:lines() do
-     lchr=line:sub(1,1)
-     line=trim(line)
-     if lchr=="<" or lchr==">" then
-       line = trim(line:sub(2))
-     end
+ function starts(String,Start)
+    return string.sub(String,1,string.len(Start))==Start
+ end
  
-     if not (lchr == " ") then
-       process_packet(packet)
-       packet = ""
-     end
+ function split(inputstr, sep)
+         if sep == nil then
+                 sep = "%s"
+         end
+         local t={} ; i=1
+         for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
+                 t[i] = str
+                 i = i + 1
+         end
+         return t
+ end
  
    llen=line:len()
function read_loop()
  
-     if llen<59 then
-       packet = packet .. " " .. line
-       process_packet(packet)
-       packet=""
-     else
-       packet = packet .. " " .. line
-     end    
+   packet={}
+   inbound=false
+   while true do
+     str=inp:read("*l")
+     if str then 
+       str=trim(str)
+       if inbound then
+         t = split(str,':')
+         if #t>=2 then
+           name=t[1]
+           value=trim(table.concat(t,':',2))
+           if name=="Address" then
+             value=split(value)[1]
+           end
+           packet[name]=value
+         elseif #t==1 and name then
+           if not(packet[name..'.list']) then
+             packet[name..'.list']={}
+           end  
+           table.insert(packet[name..'.list'],(trim(t[1])))
+         end  
+       end  
+       if starts(str,'> HCI Event: LE Meta Event (0x3e)') then
+         inbound=true
+         name=nil
+       elseif starts(str,'RSSI:') then
+         inbound=false
+         process_packet(packet)
+         packet={}
+       end
+       
+     end  
      
    end
  
  end
  
+ io.stdout:setvbuf('no')
+ io.stdin:setvbuf('no') 
  getConfig(arg[1])
  
  if mqtt_host then
-   MQTT = require "paho.mqtt"
-   mqtt_client = MQTT.client.create(mqtt_host, mqtt_port)
+   MQTT = require "mosquitto"
+   mqtt_client = MQTT.new(mqtt_id)
    if mqtt_user then
-     mqtt_client:auth(mqtt_user, mqtt_passwd)
+     mqtt_client:login_set(mqtt_user, mqtt_passwd)
    end
-   mqtt_client:connect(mqtt_id)
+   mqtt_client:connect(mqtt_host,mqtt_port)
  end
  
  inp = open_dump()