Initial support for iBeacon BLE scanning for FakeMobileClient
This commit is contained in:
parent
2bc45ad762
commit
cb45142250
2 changed files with 71 additions and 1 deletions
4
tools/FAKEMOBILECLIENT.TXT
Normal file
4
tools/FAKEMOBILECLIENT.TXT
Normal file
|
@ -0,0 +1,4 @@
|
|||
For Wifi Scanning you need wireless_tools
|
||||
|
||||
For Bluetooth Scanning you need BlueZ bluetooth + Dev Lib libbluetooth and pip install bleak
|
||||
Edit /lib/systemd/system/bluetooth.service and add --experimental to ExecStart Line for bluetoothd
|
|
@ -4,9 +4,31 @@ import socketserver
|
|||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import struct
|
||||
import math
|
||||
|
||||
import asyncio
|
||||
from uuid import UUID
|
||||
|
||||
from construct import Array, Byte, Const, Int8sl, Int16ub, Struct
|
||||
from construct.core import ConstError
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
from bleak import BleakScanner
|
||||
from bleak.backends.device import BLEDevice
|
||||
from bleak.backends.scanner import AdvertisementData
|
||||
|
||||
|
||||
PORT = int(sys.argv[1]) if sys.argv[1:] else 8042
|
||||
|
||||
ibeacon_format = Struct(
|
||||
"type_length" / Const(b"\x02\x15"),
|
||||
"uuid" / Array(16, Byte),
|
||||
"major" / Int16ub,
|
||||
"minor" / Int16ub,
|
||||
"power" / Int8sl,
|
||||
)
|
||||
|
||||
def get_from_lines(lines, keyword):
|
||||
try:
|
||||
|
@ -14,6 +36,48 @@ def get_from_lines(lines, keyword):
|
|||
except StopIteration:
|
||||
return
|
||||
|
||||
def calc_distance(txPower, rssi):
|
||||
if (rssi == 0):
|
||||
return -1.0
|
||||
|
||||
ratio = rssi*1.0/txPower;
|
||||
if (ratio < 1.0):
|
||||
distance = math.pow(ratio,10);
|
||||
else:
|
||||
distance = (0.89976) * math.pow(ratio,7.7095) + 0.111;
|
||||
|
||||
return distance;
|
||||
|
||||
|
||||
async def ble_scan():
|
||||
beacons = []
|
||||
|
||||
devices = await BleakScanner.discover(return_adv=True)
|
||||
|
||||
devices = OrderedDict(
|
||||
sorted(devices.items(), key=lambda x: x[1][1].rssi, reverse=True)
|
||||
)
|
||||
|
||||
for i, (addr, (device, advertisement_data)) in enumerate(devices.items()):
|
||||
try:
|
||||
apple_data = advertisement_data.manufacturer_data[0x004C]
|
||||
ibeacon = ibeacon_format.parse(apple_data)
|
||||
uuid = UUID(bytes=bytes(ibeacon.uuid))
|
||||
beacons.append({'uuid': str(uuid), 'major': ibeacon.major, 'minor': ibeacon.minor, 'distance': calc_distance(ibeacon.power, advertisement_data.rssi), 'last_seen_ago': 0 })
|
||||
except KeyError:
|
||||
# Apple company ID (0x004c) not found
|
||||
pass
|
||||
except ConstError:
|
||||
# No iBeacon (type 0x02 and length 0x15)
|
||||
pass
|
||||
|
||||
return beacons
|
||||
|
||||
def async_to_sync(awaitable):
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
return loop.run_until_complete(awaitable)
|
||||
|
||||
class FakeMobileClientHandler(http.server.BaseHTTPRequestHandler):
|
||||
def do_GET(self):
|
||||
"""Serve a GET request."""
|
||||
|
@ -51,11 +115,13 @@ class FakeMobileClientHandler(http.server.BaseHTTPRequestHandler):
|
|||
|
||||
break
|
||||
|
||||
beacons = async_to_sync(ble_scan())
|
||||
|
||||
self.send_response(200)
|
||||
self.send_header('Content-Type', 'application/json')
|
||||
self.send_header('Access-Control-Allow-Origin', '*')
|
||||
self.end_headers()
|
||||
self.wfile.write(json.dumps({'wifi':stations}).encode())
|
||||
self.wfile.write(json.dumps({'wifi':stations, 'ibeacon':beacons}).encode())
|
||||
return True
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue