61 lines
1.8 KiB
Python
61 lines
1.8 KiB
Python
import asyncio
|
|
import logging
|
|
import re
|
|
from typing import Final
|
|
|
|
from bleak import BleakClient, BleakScanner, BLEDevice
|
|
from bleak.exc import (
|
|
BleakCharacteristicNotFoundError,
|
|
BleakDBusError,
|
|
BleakDeviceNotFoundError,
|
|
)
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
NUS_SERVICE_UUID = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
|
|
NUS_TX_CHAR_UUID = "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
|
|
|
|
MAC_ADDRESS_PATTERN: Final = re.compile(
|
|
r"([0-9A-F]{2}[:]){5}[0-9A-F]{2}$", flags=re.IGNORECASE
|
|
)
|
|
|
|
|
|
def is_mac_address(value: str) -> bool:
|
|
return MAC_ADDRESS_PATTERN.match(value)
|
|
|
|
|
|
async def logger_scan(name: str) -> BLEDevice | None:
|
|
_LOGGER.info("Scanning bluetooth for %s...", name)
|
|
device = await BleakScanner.find_device_by_name(name)
|
|
if not device:
|
|
_LOGGER.error("%s Bluetooth LE device was not found!", name)
|
|
return device
|
|
|
|
|
|
async def logger_connect(host: str) -> int | None:
|
|
disconnected_event = asyncio.Event()
|
|
|
|
def handle_disconnect(client):
|
|
disconnected_event.set()
|
|
|
|
def handle_rx(_, data: bytearray):
|
|
print(data.decode("utf-8"), end="")
|
|
|
|
_LOGGER.info("Connecting %s...", host)
|
|
try:
|
|
async with BleakClient(host, disconnected_callback=handle_disconnect) as client:
|
|
_LOGGER.info("Connected %s...", host)
|
|
try:
|
|
await client.start_notify(NUS_TX_CHAR_UUID, handle_rx)
|
|
except BleakDBusError as e:
|
|
_LOGGER.error("Bluetooth LE logger: %s", e)
|
|
disconnected_event.set()
|
|
await disconnected_event.wait()
|
|
except BleakDeviceNotFoundError:
|
|
_LOGGER.error("Device %s not found", host)
|
|
return 1
|
|
except BleakCharacteristicNotFoundError:
|
|
_LOGGER.error("Device %s has no NUS characteristic", host)
|
|
return 1
|