blatted/blatted/tools/ble/scanner.py

81 lines
2.7 KiB
Python
Raw Normal View History

2023-05-13 14:32:15 +02:00
import asyncio
from typing import Dict, Any
2023-05-13 14:32:15 +02:00
2023-05-19 15:49:25 +02:00
from rich.live import Live
from rich.table import Table
2023-05-13 14:32:15 +02:00
import bleak.exc
2023-05-13 13:31:49 +02:00
from bleak import BleakScanner
2023-05-13 14:32:15 +02:00
from bleak.backends.device import BLEDevice
from bleak.backends.scanner import AdvertisementData
from pydispatch import Dispatcher
2023-05-13 13:31:49 +02:00
from ...events.event import DeviceDiscovered
from ...tools import context
2023-05-19 15:49:25 +02:00
from ...tools.context import BlattedEnvironment
environment = context.get_environment()
console = context.get_console()
table = Table(width=100)
live = Live(table, console=console)
table.add_column("Address", max_width=18)
table.add_column("Name", max_width=32)
table.add_column("RSSI", max_width=5)
table.add_column("Services", width=100-55)
2023-05-13 14:32:15 +02:00
class Scanner(Dispatcher):
_events_ = ["device_discovered"]
2023-05-13 14:32:15 +02:00
def __init__(self) -> None:
self.environment = context.get_environment()
self.devices: Dict[str, Any] = {}
self.bind(device_discovered=self.on_device_discovered)
2023-05-13 14:32:15 +02:00
def discover_callback(
self, device: BLEDevice, advertising_data: AdvertisementData
) -> None:
if len(advertising_data.service_uuids) > 0:
#discovered = DiscoveredDevice(device, advertising_data)
discovered = DeviceDiscovered(device, advertising_data)
2023-05-19 15:49:25 +02:00
if environment == BlattedEnvironment.CLI:
self.emit("device_discovered", data=discovered)
2023-05-19 15:49:25 +02:00
live.update(table)
elif environment == BlattedEnvironment.TUI:
pass # TODO Implement
2023-05-13 14:32:15 +02:00
def on_device_discovered(self, data: DeviceDiscovered) -> None:
if data.device.address not in self.devices:
2023-05-19 15:49:25 +02:00
row = table.add_row(f"{data.device.address}", f"{data.device.name}",
f"{data.adverisement_data.rssi}",
"\n".join(data.adverisement_data.service_uuids))
self.devices[data.device.address] = {"data": data, "seen": 1}
else:
2023-05-19 15:49:25 +02:00
known_data = self.devices[data.device.address]
known_data["seen"] += 1
address_cells = table.columns[0]._cells
row_index = address_cells.index(data.device.address)
table.columns[1]._cells[row_index] = data.device.name
table.columns[2]._cells[row_index] = f"{data.adverisement_data.rssi}"
async def run(self) -> None:
stop_event = asyncio.Event()
async with BleakScanner(self.discover_callback):
await stop_event.wait()
2023-05-13 14:32:15 +02:00
def run():
2023-05-19 15:49:25 +02:00
if environment == BlattedEnvironment.CLI:
live.start()
2023-05-13 14:32:15 +02:00
try:
asyncio.run(Scanner().run())
2023-05-13 14:32:15 +02:00
except bleak.exc.BleakDBusError as exc:
2023-05-19 15:49:25 +02:00
console.log(f"ERROR: {exc}")
if environment == BlattedEnvironment.CLI:
live.stop()