5 function getConfig(configname)
7 local status,uci = pcall(require,"uci")
19 local cur=uci.cursor()
21 logging = cur.get(config,"logging","enabled")
23 mqtt_host = cur.get(config,"mqtt","host")
24 mqtt_port = cur.get(config,"mqtt","port")
25 mqtt_id = cur.get(config,"mqtt","id")
26 mqtt_topic = cur.get(config,"mqtt","topic")
28 mqtt_user = cur.get(config,"mqtt","user")
29 mqtt_passwd = cur.get(config,"mqtt","password")
33 local status,ini = pcall(require,"ini")
41 config="/etc/beacon.ini"
44 local cur=ini.parse_file(config)
46 logging = cur["logging"]["enabled"]
48 mqtt_host = cur["mqtt"]["host"]
49 mqtt_port = cur["mqtt"]["port"]
50 mqtt_id = cur["mqtt"]["id"]
51 mqtt_topic = cur["mqtt"]["topic"]
53 mqtt_user = cur["mqtt"]["user"]
54 mqtt_passwd = cur["mqtt"]["password"]
58 if mqtt_host and not mqtt_id then
59 socket = require("socket")
60 posix = require("posix")
61 hostname = socket.dns.gethostname()
63 mqtt_id="beaconmon-"..hostname.."-"..pid
66 if mqtt_host and not mqtt_port then
70 if mqtt_host and not mqtt_topic then
71 mqtt_topic = 'beaconmon/{type}/{details}'
76 function capture(cmd, raw)
77 local f = assert(io.popen(cmd, 'r'))
78 local s = assert(f:read('*a'))
80 if raw then return s end
81 s = string.gsub(s, '^%s+', '')
82 s = string.gsub(s, '%s+$', '')
83 s = string.gsub(s, '[\n\r]+', ' ')
87 function mqtt_encode(str)
89 str = string.gsub (str, "\n", "")
90 str = string.gsub (str, ":", "-")
91 str = string.gsub (str, "/", "-")
92 str = string.gsub (str, " ", "_")
97 function printLog(str)
98 if logging=="yes" then
99 capture("logger -t beaconmon \""..str.."\"")
105 function run_command(cmd)
107 local file = assert(io.popen(cmd, 'r'))
108 local output = file:read('*all')
115 run_command("/usr/bin/pgrep btmon && /bin/kill `/usr/bin/pgrep btmon`")
116 run_command("/usr/bin/pgrep btmon && /bin/kill `/usr/bin/pgrep hcitool`")
117 f = assert(io.popen ("/usr/bin/stdbuf -o0 /usr/bin/btmon"))
118 run_command("hciconfig hci0 down")
119 run_command("hciconfig hci0 up")
120 f_null = assert(io.popen ("hcitool lescan --duplicates --passive"))
127 return json.encode(o)
131 return (s:gsub("^%s*(.-)%s*$", "%1"))
134 local function starts_with(str, start)
135 return str:sub(1, #start) == start
138 function mqtt_pub(path,value)
139 res=mqtt_client:publish(path,value)
140 printLog("Pub "..path.." returned "..res);
144 function process_packet(packet)
152 mac = packet['Address']
153 uuid = packet['UUID']
154 type = packet['Type']
155 name = packet['Name (complete)']
157 if type and starts_with(type,'iBeacon') then
171 if not (type=="unknown") then
172 mqtt_path=string.gsub(mqtt_topic,"{(.-)}",
175 return mqtt_encode(type)
176 elseif name=="details" then
177 return mqtt_encode(details)
179 return '{'..name..'}'
183 if not pcall(mqtt_pub,mqtt_path,dump(packet)) then
184 printLog('Reconnecting MQTT...')
185 mqtt_client:connect(mqtt_id)
192 function starts(String,Start)
193 return string.sub(String,1,string.len(Start))==Start
196 function split(inputstr, sep)
201 for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
225 value=trim(table.concat(t,':',2))
226 if name=="Address" then
227 value=split(value)[1]
230 elseif #t==1 and name then
231 if not(packet[name..'.list']) then
232 packet[name..'.list']={}
234 table.insert(packet[name..'.list'],(trim(t[1])))
238 if starts(str,'> HCI Event: LE Meta Event (0x3e)') then
241 elseif starts(str,'RSSI:') then
243 process_packet(packet)
253 io.stdout:setvbuf('no')
254 io.stdin:setvbuf('no')
259 MQTT = require "mosquitto"
260 mqtt_client = MQTT.new(mqtt_id)
262 mqtt_client:login_set(mqtt_user, mqtt_passwd)
264 mqtt_client:connect(mqtt_host,mqtt_port)