5 function getConfig(configname)
7 local uci=require("uci")
16 logging = cur.get(config,"logging","enabled")
18 mqtt_host = cur.get(config,"mqtt","host")
19 mqtt_port = cur.get(config,"mqtt","port")
20 mqtt_id = cur.get(config,"mqtt","id")
21 mqtt_topic = cur.get(config,"mqtt","topic")
23 mqtt_user = cur.get(config,"mqtt","user")
24 mqtt_passwd = cur.get(config,"mqtt","password")
26 if mqtt_host and not mqtt_id then
27 socket = require("socket")
28 posix = require("posix")
29 hostname = socket.dns.gethostname()
31 mqtt_id="beaconmon-"..hostname.."-"..pid
34 if mqtt_host and not mqtt_port then
38 if mqtt_host and not mqtt_topic then
39 mqtt_topic = 'beaconmon/{type}/{details}'
44 function capture(cmd, raw)
45 local f = assert(io.popen(cmd, 'r'))
46 local s = assert(f:read('*a'))
48 if raw then return s end
49 s = string.gsub(s, '^%s+', '')
50 s = string.gsub(s, '%s+$', '')
51 s = string.gsub(s, '[\n\r]+', ' ')
55 function mqtt_encode(str)
57 str = string.gsub (str, "\n", "")
58 str = string.gsub (str, ":", "-")
59 str = string.gsub (str, "/", "-")
60 str = string.gsub (str, " ", "_")
65 function printLog(str)
66 if logging=="yes" then
67 capture("logger -t beaconmon \""..str.."\"")
69 elseif logging=="syslog" then
70 capture("logger -t beaconmon \""..str.."\"")
71 elseif logging=="stdout" then
76 function run_command(cmd)
78 local file = assert(io.popen(cmd, 'r'))
79 local output = file:read('*all')
86 run_command("/bin/kill `/usr/bin/pgrep btmon`")
87 run_command("/bin/kill `/usr/bin/pgrep hcitool`")
88 f = assert(io.popen ("/usr/bin/stdbuf -o0 /usr/bin/btmon"))
89 run_command("/usr/bin/hciconfig hci0 down")
90 run_command("/usr/bin/hciconfig hci0 up")
91 f_null = assert(io.popen ("/usr/bin/hcitool lescan --duplicates --passive"))
102 return (s:gsub("^%s*(.-)%s*$", "%1"))
105 local function starts_with(str, start)
106 return str:sub(1, #start) == start
109 function mqtt_pub(path,value)
110 res=mqtt_client:publish(path,value)
111 printLog("Pub "..path.." returned "..res);
115 function process_packet(packet)
123 mac = packet['Address']
124 uuid = packet['UUID']
125 type = packet['Type']
126 name = packet['Name (complete)']
130 if type and starts_with(type,'iBeacon') then
144 if not (type=="unknown") then
145 mqtt_path=string.gsub(mqtt_topic,"{(.-)}",
148 return mqtt_encode(type)
149 elseif name=="details" then
150 return mqtt_encode(details)
152 return '{'..name..'}'
156 if not pcall(mqtt_pub,mqtt_path,dump(packet)) then
157 printLog('Reconnecting MQTT...')
158 mqtt_client:connect(mqtt_id)
165 function starts(String,Start)
166 return string.sub(String,1,string.len(Start))==Start
169 function split(inputstr, sep)
174 for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
198 value=trim(table.concat(t,':',2))
199 if name=="Address" then
200 value=split(value)[1]
203 elseif #t==1 and name then
204 if not(packet[name..'.list']) then
205 packet[name..'.list']={}
207 table.insert(packet[name..'.list'],(trim(t[1])))
211 if starts(str,'> HCI Event: LE Meta Event (0x3e)') then
214 elseif starts(str,'RSSI:') then
216 process_packet(packet)
226 io.stdout:setvbuf('no')
227 io.stdin:setvbuf('no')
232 MQTT = require "mosquitto"
233 mqtt_client = MQTT.new(mqtt_id)
235 mqtt_client:login_set(mqtt_user, mqtt_passwd)
237 mqtt_client:connect(mqtt_host,mqtt_port)