+#!/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()