Switch to bleak for reliable BLE scanning with RSSI
- Replace hcitool-based BT scanning with bleak Python library - Bleak provides reliable RSSI values via D-Bus/BlueZ - BLE scan now finds devices that hcitool missed - Update project docs to reflect resolved BT RSSI blocker - Add bleak>=0.21.0 to dependencies Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -814,61 +814,32 @@ def create_app(config: Config | None = None) -> Flask:
|
||||
|
||||
@app.route("/api/scan/bt", methods=["POST"])
|
||||
def api_scan_bt():
|
||||
"""Quick Bluetooth-only scan for real-time tracking using hcitool"""
|
||||
import subprocess
|
||||
import re
|
||||
"""Quick Bluetooth-only scan for real-time tracking using bleak (BLE)"""
|
||||
import asyncio
|
||||
from bleak import BleakScanner
|
||||
|
||||
bt = []
|
||||
try:
|
||||
# Use hcitool inq for classic BT (more reliable)
|
||||
result = subprocess.run(
|
||||
['sudo', 'hcitool', 'inq', '--flush'],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=12
|
||||
)
|
||||
|
||||
for line in result.stdout.split('\n'):
|
||||
# Parse: " E0:03:6B:FE:24:A1 clock offset: 0x15c7 class: 0x08043c"
|
||||
m = re.match(r'\s*([0-9A-Fa-f:]+)\s+clock offset.*class:\s*0x([0-9A-Fa-f]+)', line)
|
||||
if m:
|
||||
addr = m.group(1)
|
||||
device_class = m.group(2)
|
||||
|
||||
# Get device name
|
||||
name = '<unknown>'
|
||||
try:
|
||||
name_result = subprocess.run(
|
||||
['sudo', 'hcitool', 'name', addr],
|
||||
capture_output=True, text=True, timeout=5
|
||||
)
|
||||
if name_result.stdout.strip():
|
||||
name = name_result.stdout.strip()
|
||||
except:
|
||||
pass
|
||||
|
||||
# Get RSSI (only works if device is connectable)
|
||||
rssi = -70 # Default
|
||||
try:
|
||||
rssi_result = subprocess.run(
|
||||
['sudo', 'hcitool', 'rssi', addr],
|
||||
capture_output=True, text=True, timeout=3
|
||||
)
|
||||
rssi_match = re.search(r'RSSI return value:\s*(-?\d+)', rssi_result.stdout)
|
||||
if rssi_match:
|
||||
rssi = int(rssi_match.group(1))
|
||||
except:
|
||||
pass
|
||||
|
||||
bt.append({
|
||||
async def do_scan():
|
||||
devices = await BleakScanner.discover(timeout=3.0, return_adv=True)
|
||||
results = []
|
||||
for addr, (device, adv) in devices.items():
|
||||
rssi = adv.rssi if adv else -70
|
||||
name = device.name or '<unknown>'
|
||||
results.append({
|
||||
'address': addr,
|
||||
'name': name,
|
||||
'rssi': rssi,
|
||||
'device_class': device_class
|
||||
'device_class': 'BLE'
|
||||
})
|
||||
return results
|
||||
|
||||
# Run async scan in sync context
|
||||
bt = asyncio.run(do_scan())
|
||||
print(f"[BT] Bleak scan found {len(bt)} devices")
|
||||
|
||||
except Exception as e:
|
||||
print(f"[BT] hcitool scan error: {e}")
|
||||
print(f"[BT] Bleak scan error: {e}")
|
||||
bt = []
|
||||
|
||||
# The scanner already does auto-identification if enabled
|
||||
|
||||
Reference in New Issue
Block a user