BLE beacon scan added (initial commit, still too many TODOs)
authorRoman Bazalevskiy <rvb@rvb.name>
Sun, 19 Mar 2017 19:15:40 +0000 (22:15 +0300)
committerRoman Bazalevskiy <rvb@rvb.name>
Sun, 19 Mar 2017 19:15:40 +0000 (22:15 +0300)
mqtt-bt/scan-beacons [new file with mode: 0644]

diff --git a/mqtt-bt/scan-beacons b/mqtt-bt/scan-beacons
new file mode 100644 (file)
index 0000000..747c295
--- /dev/null
@@ -0,0 +1,123 @@
+#!/usr/bin/env lua
+
+function run_command(cmd)
+
+  local file = assert(io.popen(cmd, 'r'))
+  local output = file:read('*all')
+  file:close()
+
+end
+
+function open_dump()
+
+  f = assert(io.popen ("hcidump --raw"))
+  run_command("kill `pgrep hcitool`")
+  run_command("hciconfig hci0 down")
+  run_command("hciconfig hci0 up")
+  f_null = assert(io.popen ("hcitool lescan --duplicates"))
+
+  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
+end
+
+function trim(s)
+  return (s:gsub("^%s*(.-)%s*$", "%1"))
+end
+
+function process_packet(packet)
+
+  bytes={}
+  idx=1
+
+  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
+      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"
+         uuid1=bytes[j+6]..bytes[j+7]..bytes[j+8]..bytes[j+9]
+         uuid2=bytes[j+10]..bytes[j+11]
+         uuid3=bytes[j+12]..bytes[j+13]
+         uuid4=bytes[j+14]..bytes[j+15]
+         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
+        print(string.format("{type:'ibeacon',mac:'%s',uuid:'%s',major:'%s',minor:'%s',power:%d,tx:%d}",mac,uuid,major,minor,power,tx))
+      else
+        print(dump(bytes))
+      end
+    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
+
+    if not (lchr == " ") then
+      process_packet(packet)
+      packet = ""
+    end
+
+    llen=line:len()
+
+    if llen<59 then
+      packet = packet .. " " .. line
+      process_packet(packet)
+      packet=""
+    else
+      packet = packet .. " " .. line
+    end    
+    
+  end
+
+end
+
+inp = open_dump()
+
+read_loop()