X-Git-Url: https://git.rvb.name/openhab-process.git/blobdiff_plain/254111f3712b8ac6dceeffe2518340e8ada36888..37883fdd57e2246043ee9f1f4c4c488104216cb5:/mqtt-bt/scan-beacons diff --git a/mqtt-bt/scan-beacons b/mqtt-bt/scan-beacons index 747c295..210bcfb 100644 --- a/mqtt-bt/scan-beacons +++ b/mqtt-bt/scan-beacons @@ -1,4 +1,107 @@ -#!/usr/bin/env lua +#!/usr/bin/lua + +json = require("json") +socket = require("socket") + +function getConfig(configname) + + local status,uci = pcall(require,"uci") + + local config + + if status then + + if configname then + config=configname + else + config="beacon" + end + + local cur=uci.cursor() + + logging = cur.get(config,"logging","enabled") + + mqtt_host = cur.get(config,"mqtt","host") + mqtt_port = cur.get(config,"mqtt","port") + mqtt_id = cur.get(config,"mqtt","id") + mqtt_topic = cur.get(config,"mqtt","topic") + + mqtt_user = cur.get(config,"mqtt","user") + mqtt_passwd = cur.get(config,"mqtt","password") + + else + + local status,ini = pcall(require,"ini") + if not status then + os.exit(1) + end + + if configname then + config=configname + else + config="/etc/beacon.ini" + end + + local cur=ini.parse_file(config) + + logging = cur["logging"]["enabled"] + + mqtt_host = cur["mqtt"]["host"] + mqtt_port = cur["mqtt"]["port"] + mqtt_id = cur["mqtt"]["id"] + mqtt_topic = cur["mqtt"]["topic"] + + mqtt_user = cur["mqtt"]["user"] + mqtt_passwd = cur["mqtt"]["password"] + + end + + hostname = socket.dns.gethostname() + if mqtt_host and not mqtt_id then + socket = require("socket") + posix = require("posix") + pid = posix.getpid() + mqtt_id="beaconmon-"..hostname.."-"..pid + end + + if mqtt_host and not mqtt_port then + mqtt_port = 1883 + end + + if mqtt_host and not mqtt_topic then + mqtt_topic = 'beaconmon/{type}/{details}' + end + +end + +function capture(cmd, raw) + local f = assert(io.popen(cmd, 'r')) + local s = assert(f:read('*a')) + f:close() + if raw then return s end + s = string.gsub(s, '^%s+', '') + s = string.gsub(s, '%s+$', '') + s = string.gsub(s, '[\n\r]+', ' ') + return s +end + +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=="yes" then + capture("logger -t beaconmon \""..str.."\"") + else + print(str) + end +end function run_command(cmd) @@ -10,114 +113,160 @@ end function open_dump() - f = assert(io.popen ("hcidump --raw")) - run_command("kill `pgrep hcitool`") + run_command("/usr/bin/pkill btmon") + run_command("/usr/bin/pkill hcitool") + f = assert(io.popen ("/usr/bin/stdbuf -o0 /usr/bin/btmon")) run_command("hciconfig hci0 down") run_command("hciconfig hci0 up") - f_null = assert(io.popen ("hcitool lescan --duplicates")) + f_null = assert(io.popen ("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) return (s:gsub("^%s*(.-)%s*$", "%1")) end +local function starts_with(str, start) + return str:sub(1, #start) == start +end + +function mqtt_pub(path,value) + res=mqtt_client:publish(path,value) + printLog("Pub "..path.." returned "..res); + return res +end + function process_packet(packet) - bytes={} - idx=1 + local mac + local uuid + local details + local type + local name - if packet:len()>1 then + packet['origin'] = hostname - 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" then - line = trim(line:sub(2)) - end + if str then - if not (lchr == " ") then - process_packet(packet) - packet = "" - end + str=trim(str) - llen=line:len() + 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 llen<59 then - packet = packet .. " " .. line - process_packet(packet) - packet="" - else - packet = packet .. " " .. line - 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 "mosquitto" + mqtt_client = MQTT.new(mqtt_id) + if mqtt_user then + mqtt_client:login_set(mqtt_user, mqtt_passwd) + end + mqtt_client:connect(mqtt_host,mqtt_port) +end + inp = open_dump() read_loop()