Bluetooth LE Scanner with Asyncio
aioblescan is a Python library that allows for scanning Bluetooth Low Energy (BLE) advertised information using `asyncio`. It enables developers to build asynchronous applications that interact with BLE devices, decoding various advertising packet types. The current version is 0.2.14, with releases occurring periodically to add new plugin support and fix issues.
Common errors
-
aioblescan.hcitool.HCI_Exception: Cannot open Bluetooth device socket
cause The script does not have sufficient permissions to access the Bluetooth HCI device.fixRun the script with `sudo python3 your_script.py` or grant the Python interpreter `cap_net_raw` and `cap_net_admin` capabilities using `sudo setcap 'cap_net_raw,cap_net_admin+eip' $(which python3)`. -
ModuleNotFoundError: No module named 'aioblescan.scanner'
cause Incorrect import path. You might be trying to import `BLEScanner` directly from `aioblescan`.fixChange your import statement to `from aioblescan.scanner import BLEScanner`. -
TypeError: BLEScanner.process_data expected a callable or None, got <something_else>
cause The `process_data` attribute of `BLEScanner` is expected to be a function or method that processes detected data. This error occurs if you assign a non-callable object.fixEnsure you assign a valid function or lambda to `scanner.process_data = your_callback_function`.
Warnings
- gotcha aioblescan often requires elevated privileges (root or NET_RAW capabilities) to access the Bluetooth HCI device, especially on Linux systems. Running without these permissions will result in 'Permission denied' errors.
- breaking The console script support in version 0.2.14 and later explicitly targets Python 3.7 and up. While the library itself might still function on older Python 3 versions, the command-line utility for the Tilt plugin and other console scripts may not work correctly or be supported.
- gotcha When processing advertisement data, ensure your callback handles `None` or empty results from plugin `decode` methods gracefully, as not all received packets will match a registered plugin's format.
Install
-
pip install aioblescan -
pip install git+https://github.com/frawau/aioblescan.git
Imports
- BLEScanner
from aioblescan import BLEScanner
from aioblescan.scanner import BLEScanner
- Eddystone
from aioblescan.plugins import Eddystone
- HCITransport
from aioblescan.hcitool import HCITransport
Quickstart
import asyncio
from aioblescan.scanner import BLEScanner
from aioblescan.plugins import Eddystone
async def main():
scanner = BLEScanner()
eddystone = Eddystone()
def my_detection_callback(data):
try:
ev = eddystone.decode(data)
if ev:
print(f"Detected Eddystone: {ev}")
except Exception as e:
print(f"Error decoding packet: {e}")
scanner.register_plugin(eddystone)
scanner.process_data = my_detection_callback # Direct callback for all processed data
await scanner.start()
print("BLE scanning started... Press Ctrl+C to stop.")
try:
await asyncio.Event().wait() # Keep the main task running indefinitely
except asyncio.CancelledError:
pass
finally:
await scanner.stop()
print("BLE scanning stopped.")
if __name__ == "__main__":
try:
asyncio.run(main())
except KeyboardInterrupt:
print("Exiting.")