### Install Bleak Source: https://github.com/hbldh/bleak/blob/develop/README.rst Install the Bleak library using pip. Ensure you have Python installed. ```bash pip install bleak ``` -------------------------------- ### Install Stable Release of Bleak Source: https://github.com/hbldh/bleak/blob/develop/docs/installation.md Use this command to install the latest stable version of bleak. This is the recommended method for most users. ```console $ pip install bleak ``` -------------------------------- ### Install Bleak with Pythonista Support Source: https://github.com/hbldh/bleak/blob/develop/docs/backends/pythonista.md Use StaSh or Pythonista3_pip_Configration_Tool to install Bleak with Pythonista support. ```console $ pip install bleak[pythonista] ``` -------------------------------- ### Set up Python environment Source: https://github.com/hbldh/bleak/blob/develop/CONTRIBUTING.rst Install project dependencies using uv after navigating to the bleak directory. ```shell cd bleak/ uv sync ``` -------------------------------- ### Install Bleak from Develop Branch Source: https://github.com/hbldh/bleak/blob/develop/docs/installation.md Install bleak directly from the develop branch on GitHub to use the latest unreleased changes. This is useful for testing new features. ```console $ pip install https://github.com/hbldh/bleak/archive/refs/heads/develop.zip ``` -------------------------------- ### BleakScanner.start() Source: https://github.com/hbldh/bleak/blob/develop/docs/api/scanner.md Starts the BLE device scanning process. Raises BleakBluetoothNotAvailableError if Bluetooth is not available. ```APIDOC ## BleakScanner.start() ### Description Start scanning for devices. ### Method `async` ### Raises [BleakBluetoothNotAvailableError](index.md#bleak.exc.BleakBluetoothNotAvailableError) – if Bluetooth is not currently available ``` -------------------------------- ### Install Wireshark for Bluetooth Traffic Capture (Debian/Ubuntu) Source: https://github.com/hbldh/bleak/blob/develop/docs/troubleshooting.md Installs Wireshark on Debian/Ubuntu systems, which can be used to capture and analyze Bluetooth traffic. ```bash sudo apt update && sudo apt install wireshark ``` -------------------------------- ### Clone the bleak repository Source: https://github.com/hbldh/bleak/blob/develop/CONTRIBUTING.rst Clone your fork of the bleak repository locally to start development. ```shell git clone https://github.com:your_name_here/bleak.git ``` -------------------------------- ### Get Default Backend Source: https://github.com/hbldh/bleak/blob/develop/docs/backends/index.md Returns the preferred backend for the current platform/environment. ```APIDOC ## bleak.backends.get_default_backend() -> BleakBackend Returns the preferred backend for the current platform/environment. #### Versionadded Added in version 2.0. ``` -------------------------------- ### macOS Info.plist Bluetooth Permission Source: https://github.com/hbldh/bleak/blob/develop/docs/backends/macos.md Example of how to configure Bluetooth permissions in an application's Info.plist file on macOS. ```xml NSBluetoothAlwaysUsageDescription Some description why your app needs Bluetooth access ``` -------------------------------- ### BleakScanner Context Manager Source: https://github.com/hbldh/bleak/blob/develop/docs/api/scanner.md Demonstrates using BleakScanner as an async context manager for starting and stopping scans. ```APIDOC ## Starting and stopping with `async with` [`BleakScanner`](#bleak.BleakScanner) is an context manager so the recommended way to start and stop scanning is to use it in an `async with` statement: ```python import asyncio from bleak import BleakScanner async def main(): stop_event = asyncio.Event() # TODO: add something that calls stop_event.set() def callback(device, advertising_data): # TODO: do something with incoming data pass async with BleakScanner(callback) as scanner: ... # Important! Wait for an event to trigger stop, otherwise scanner # will stop immediately. await stop_event.wait() # scanner stops when block exits ... asyncio.run(main()) ``` ``` -------------------------------- ### Using BleakScanner as a Context Manager Source: https://github.com/hbldh/bleak/blob/develop/docs/api/scanner.md The recommended way to start and stop scanning is by using BleakScanner within an async with statement. Ensure an event is set to trigger the stop, otherwise the scanner will stop immediately upon exiting the block. ```python import asyncio from bleak import BleakScanner async def main(): stop_event = asyncio.Event() # TODO: add something that calls stop_event.set() def callback(device, advertising_data): # TODO: do something with incoming data pass async with BleakScanner(callback) as scanner: ... # Important! Wait for an event to trigger stop, otherwise scanner # will stop immediately. await stop_event.wait() # scanner stops when block exits ... asyncio.run(main()) ``` -------------------------------- ### Manual Connection Management - BleakClient.connect() / disconnect() Source: https://context7.com/hbldh/bleak/llms.txt Manages the BLE client connection explicitly using `connect()` and `disconnect()` methods, outside of the context manager pattern. This allows for more granular control over the connection lifecycle. The example demonstrates connecting, performing operations, and then disconnecting. ```python import asyncio from bleak import BleakClient async def main(): client = BleakClient("AA:BB:CC:DD:EE:FF", timeout=20.0) await client.connect() try: print(f"Connected: {client.is_connected}") # ... do work ... finally: await client.disconnect() print(f"Connected after disconnect: {client.is_connected}") asyncio.run(main()) ``` -------------------------------- ### Run tests Source: https://github.com/hbldh/bleak/blob/develop/CONTRIBUTING.rst Execute the test suite to verify your changes. ```shell uv run pytest ``` -------------------------------- ### Get Backend Identifier Source: https://github.com/hbldh/bleak/blob/develop/docs/api/client.md Retrieves the identifier of the backend in use. ```APIDOC ## backend_id ### Description Gets the identifier of the backend in use. ### Property Returns: BleakBackend | str - The identifier of the backend. ``` -------------------------------- ### Run Linting and Tests Source: https://github.com/hbldh/bleak/blob/develop/docs/contributing.md Ensure your changes pass linting and all tests before committing. Use uv for running these commands. ```shell uv run isort . uv run black . uv run flake8 uv run pytest ``` -------------------------------- ### Configure BlueZ Adapter and Filters Source: https://context7.com/hbldh/bleak/llms.txt Select a specific BlueZ adapter and set RSSI and duplicate data filters for active scanning. Requires the 'bluez' argument. ```python import asyncio from bleak import BleakScanner, BleakClient from bleak.assigned_numbers import AdvertisementDataType async def main(): # Linux: select specific adapter, set RSSI filter for active scan linux_scanner = BleakScanner( bluez={ "adapter": "hci1", "filters": {"RSSI": -80, "DuplicateData": False}, } ) # Linux: passive scanning with or-patterns (BlueZ advertisement monitor) passive_scanner = BleakScanner( scanning_mode="passive", bluez={ "or_patterns": [ (0, AdvertisementDataType.FLAGS, b"\x06"), ] }, ) # Windows: use public address type, skip OS service cache win_client = BleakClient( "AA:BB:CC:DD:EE:FF", winrt={"address_type": "public", "use_cached_services": False}, ) # macOS: use Bluetooth address instead of UUID mac_devices = await BleakScanner.discover( cb={"use_bdaddr": True} ) # macOS: custom notification discriminator to separate read vs notify async with BleakClient("AA:BB:CC:DD:EE:FF") as client: await client.start_notify( "00002a37-0000-1000-8000-00805f9b34fb", lambda char, data: print(data), cb={"notification_discriminator": lambda data: len(data) == 2}, ) await asyncio.sleep(5.0) # Linux: force StartNotify instead of AcquireNotify async with BleakClient("AA:BB:CC:DD:EE:FF") as client: await client.start_notify( "00002a37-0000-1000-8000-00805f9b34fb", lambda char, data: print(data), bluez={"use_start_notify": True}, ) await asyncio.sleep(5.0) asyncio.run(main()) ``` -------------------------------- ### Get Device Address Source: https://github.com/hbldh/bleak/blob/develop/docs/api/client.md Retrieves the Bluetooth address of the device. ```APIDOC ## address ### Description Gets the Bluetooth address of this device (UUID on macOS). ### Property Returns: str - The Bluetooth address. ``` -------------------------------- ### Get Device Name Source: https://github.com/hbldh/bleak/blob/develop/docs/api/client.md Retrieves a human-readable name for the peripheral device. ```APIDOC ## name ### Description Gets a human-readable name for the peripheral device. ### Property Returns: str - The device name. ``` -------------------------------- ### Run Integration Tests with Virtual Bluetooth Controllers (VHCI) Source: https://github.com/hbldh/bleak/blob/develop/tests/integration/README.rst Execute integration tests using virtual Bluetooth controllers managed by Bleak and Bumble via the VHCI interface on Linux. This method avoids the need for physical hardware. ```bash uv run pytest --bleak-bluez-vhci ``` -------------------------------- ### BleakScanner.backend_id Source: https://github.com/hbldh/bleak/blob/develop/docs/api/scanner.md Property to get the identifier of the backend currently in use by the scanner. ```APIDOC ## BleakScanner.backend_id ### Description Gets the identifier of the backend in use. ### NOTE The value is one of the `BleakBackend` enum values in case of built-in backends, or a string identifying a custom backend. ### Returns A `BleakBackend` enum value or a string identifying a custom backend. ### Versionadded Added in version 2.0. ``` -------------------------------- ### Discover and Connect to Multiple Devices Source: https://github.com/hbldh/bleak/blob/develop/docs/troubleshooting.md Scan for devices and then connect to each discovered device to access its services. This approach can help when direct connection attempts to multiple devices fail. ```python import asyncio from typing import Sequence from bleak import BleakClient, BleakScanner from bleak.backends.device import BLEDevice async def find_all_devices_services(): devices: Sequence[BLEDevice] = await BleakScanner.discover(timeout=5.0) for d in devices: async with BleakClient(d) as client: print(client.services) asyncio.run(find_all_devices_services()) ``` -------------------------------- ### name Source: https://github.com/hbldh/bleak/blob/develop/docs/backends/linux.md Property to get the name of the connected device, referencing `bleak.BleakClient.name()`. ```APIDOC ## property name *: str* See [`bleak.BleakClient.name()`](../api/client.md#bleak.BleakClient.name). ``` -------------------------------- ### BleakClient.connect() / disconnect() Source: https://context7.com/hbldh/bleak/llms.txt Allows explicit management of the client connection lifecycle outside of the asynchronous context manager pattern. Use `await client.connect()` to establish a connection and `await client.disconnect()` to terminate it. ```APIDOC ## BleakClient.connect() / disconnect() — Manual Connection Management `await client.connect()` and `await client.disconnect()` allow explicit connection lifecycle management when not using the context manager pattern. `connect()` also accepts kwargs for backwards compatibility. ### Parameters - **connect()**: Accepts kwargs for backwards compatibility. - **disconnect()**: No parameters. ### Request Example ```python import asyncio from bleak import BleakClient async def main(): client = BleakClient("AA:BB:CC:DD:EE:FF", timeout=20.0) await client.connect() try: print(f"Connected: {client.is_connected}") # ... do work ... finally: await client.disconnect() print(f"Connected after disconnect: {client.is_connected}") asyncio.run(main()) ``` ``` -------------------------------- ### BleakScanner.discovered_devices Source: https://github.com/hbldh/bleak/blob/develop/docs/api/scanner.md Property to get a list of discovered BLE devices after scanning has stopped. ```APIDOC ## BleakScanner.discovered_devices ### Description Gets list of the devices that the scanner has discovered during the scanning. ### NOTE If you also need advertisement data, use [`discovered_devices_and_advertisement_data`](#bleak.BleakScanner.discovered_devices_and_advertisement_data) instead. ### Returns A list of `BLEDevice` objects. ``` -------------------------------- ### Get MTU Size Source: https://github.com/hbldh/bleak/blob/develop/docs/api/client.md Retrieves the negotiated MTU size in bytes for the active connection. ```APIDOC ## mtu_size ### Description Gets the negotiated MTU size in bytes for the active connection. ### Property Returns: int - The negotiated MTU size. ``` -------------------------------- ### Accessing GATT Services and Characteristics Source: https://context7.com/hbldh/bleak/llms.txt Demonstrates how to find a device, connect, and then look up a specific GATT service by its UUID. It iterates through the service's characteristics and prints their details. ```python import asyncio from bleak import BleakClient, BleakScanner async def main(): device = await BleakScanner.find_device_by_address("AA:BB:CC:DD:EE:FF") async with BleakClient(device) as client: # Lookup service by UUID svc = client.services.get_service("0000180f-0000-1000-8000-00805f9b34fb") if svc: print(f"Service: {svc.uuid}") # full 128-bit UUID print(f" Handle: {svc.handle}") # integer handle print(f" Description: {svc.description}") # "Battery Service" for char in svc.characteristics: print(f" Char: {char}") # "00002a19-...: Battery Level" asyncio.run(main()) ``` -------------------------------- ### BleakScanner Class Initialization Source: https://github.com/hbldh/bleak/blob/develop/docs/api/scanner.md Initialize the BleakScanner with optional parameters for callbacks, service UUID filtering, scanning mode, and backend-specific arguments. ```APIDOC ## BleakScanner ### Description Interface for Bleak Bluetooth LE Scanners. The scanner will listen for BLE advertisements, optionally filtering on advertised services or other conditions, and collect a list of `BLEDevice` objects. These can subsequently be used to connect to the corresponding BLE server. A [`BleakScanner`](#bleak.BleakScanner) can be used as an asynchronous context manager in which case it automatically starts and stops scanning. ### Parameters: * **detection_callback** – Optional function that will be called each time a device is discovered or advertising data has changed. * **service_uuids** – Optional list of service UUIDs to filter on. Only advertisements containing this advertising data will be received. Required on macOS >= 12.0, < 12.3 (unless you create an app with `py2app`). * **scanning_mode** – Set to `"passive"` to avoid the `"active"` scanning mode. Passive scanning is not supported on macOS! Will raise `BleakError` if set to `"passive"` on macOS. * **bluez** – Dictionary of arguments specific to the BlueZ backend. * **cb** – Dictionary of arguments specific to the CoreBluetooth backend. * **backend** – Used to override the automatically selected backend (i.e. for a custom backend). * **kwargs** – Additional args for backwards compatibility. ``` -------------------------------- ### Using BleakGATTServiceCollection for Lookups Source: https://context7.com/hbldh/bleak/llms.txt Illustrates the capabilities of BleakGATTServiceCollection, including accessing all services and characteristics, looking up items by UUID or handle, and using subscript access for general item retrieval. ```python import asyncio from bleak import BleakClient, BleakScanner async def main(): device = await BleakScanner.find_device_by_address("AA:BB:CC:DD:EE:FF") async with BleakClient(device) as client: sc = client.services # All services (dict: handle -> BleakGATTService) print(f"Services: {list(sc.services.keys())}") # All characteristics (dict: handle -> BleakGATTCharacteristic) print(f"Total characteristics: {len(sc.characteristics)}") # Lookup characteristic by UUID char = sc.get_characteristic("00002a19-0000-1000-8000-00805f9b34fb") if char: print(f"Battery Level char at handle {char.handle}") # Lookup descriptor by handle desc = sc.get_descriptor(20) if desc: print(f"Descriptor at 20: {desc.description}") # Subscript access (returns first match among services, chars, descriptors) item = sc["0000180f-0000-1000-8000-00805f9b34fb"] print(f"Item: {item}") asyncio.run(main()) ``` -------------------------------- ### BleakClientWinRT Source: https://github.com/hbldh/bleak/blob/develop/docs/backends/windows.md Native Windows Bleak Client for connecting to BLE peripherals using WinRT. ```APIDOC ## *class* bleak.backends.winrt.client.BleakClientWinRT(address_or_ble_device: [BLEDevice](../api/index.md#bleak.backends.device.BLEDevice) | str, services: set[str] | None = None, , winrt: [WinRTClientArgs](../api/args.md#bleak.args.winrt.WinRTClientArgs), **kwargs: Any) ### Description Native Windows Bleak Client. Implemented with WinRT. ### Parameters * **address_or_ble_device** (*str* *or* [*BLEDevice*](../api/index.md#bleak.backends.device.BLEDevice)) – The Bluetooth address of the BLE peripheral to connect to or the `BLEDevice` object representing it. * **services** – Optional set of service UUIDs that will be used. * **winrt** (*dict*) – A dictionary of Windows-specific configuration values. ### *async* connect(pair: bool, **kwargs: Any) -> None Connect to the specified GATT server. ### Keyword Arguments **timeout** (*float*) – Timeout for required `BleakScanner.find_device_by_address` call. ``` -------------------------------- ### BleakScanner.discovered_devices_and_advertisement_data Source: https://github.com/hbldh/bleak/blob/develop/docs/api/scanner.md Property to get a dictionary mapping device addresses to discovered devices and their advertisement data. ```APIDOC ## BleakScanner.discovered_devices_and_advertisement_data ### Description Gets a map of device address to tuples of devices and the most recently received advertisement data for that device. ### NOTE The address keys are useful to compare the discovered devices to a set of known devices. If you don’t need to do that, consider using `discovered_devices_and_advertisement_data.values()` to just get the values instead. ### Returns A dictionary where keys are device addresses (string) and values are tuples of (`BLEDevice`, `AdvertisementData`). ### Versionadded Added in version 0.19. ``` -------------------------------- ### start_notify Source: https://github.com/hbldh/bleak/blob/develop/docs/backends/linux.md Activate notifications or indications on a characteristic. Supports additional BlueZ parameters for Linux. ```APIDOC ## async start_notify(characteristic: [BleakGATTCharacteristic](../api/index.md#bleak.backends.characteristic.BleakGATTCharacteristic), callback: Callable[[bytearray], None], **kwargs: Any) -> None Activate notifications/indications on a characteristic. * **Parameters:** * **characteristic** ([*BleakGATTCharacteristic*](../api/index.md#bleak.backends.characteristic.BleakGATTCharacteristic)) – The characteristic to activate notification/indication on. * **callback** (*NotifyCallback*) – The callback to call when a notification/indication is received. * **Keyword Arguments:** **bluez** (*dict*) – dictionary of additional parameters, see [Enabling notification/indication with start_notify](#linux-start-notify) for more details. ``` -------------------------------- ### BleakScanner.advertisement_data Source: https://github.com/hbldh/bleak/blob/develop/docs/api/scanner.md Asynchronously yields discovered devices and their advertisement data. Ensure scanning is started before calling this method. ```APIDOC ## BleakScanner.advertisement_data ### Description Yields devices and associated advertising data packets as they are discovered. ### NOTE Ensure that scanning is started before calling this method. ### Returns An async iterator that yields tuples (`BLEDevice`, `AdvertisementData`). ### Versionadded Added in version 0.21. ``` -------------------------------- ### Get GATT Services Source: https://github.com/hbldh/bleak/blob/develop/docs/api/client.md Retrieves the collection of GATT services available on the device. This property is only valid while the device is connected. ```APIDOC ## services ### Description Gets the collection of GATT services available on the device. ### Property Returns: BleakGATTServiceCollection - The collection of GATT services. ### Raises BleakError – if service discovery has not been performed yet during this connection. ``` -------------------------------- ### Initialize and Use BleakClient as Async Context Manager Source: https://github.com/hbldh/bleak/blob/develop/docs/api/client.md Use BleakClient as an asynchronous context manager for automatic connection and disconnection. This is the recommended approach for managing BLE client connections. ```python import asyncio from bleak import BleakClient async def main(): async with BleakClient("XX:XX:XX:XX:XX:XX") as client: # Read a characteristic, etc. ... # Device will disconnect when block exits. ... # Using asyncio.run() is important to ensure that device disconnects on # KeyboardInterrupt or other unhandled exception. asyncio.run(main()) ``` -------------------------------- ### List Serial Ports on Linux Source: https://github.com/hbldh/bleak/blob/develop/tests/integration/README.rst Command to find available serial ports on Linux, typically starting with /dev/ttyACM. ```bash ls /dev/ttyACM* ``` -------------------------------- ### get_platform_scanner_backend_type Source: https://github.com/hbldh/bleak/blob/develop/docs/backends/index.md Gets the platform-specific `BaseBleakScanner` type. This function is used internally by Bleak to instantiate the correct scanner backend for the operating system. ```APIDOC ## bleak.backends.scanner.get_platform_scanner_backend_type() -> tuple[type[BaseBleakScanner], BleakBackend] Gets the platform-specific [`BaseBleakScanner`](#bleak.backends.scanner.BaseBleakScanner) type. ``` -------------------------------- ### macOS Device Identifier Example Source: https://github.com/hbldh/bleak/blob/develop/docs/backends/macos.md This code snippet shows how to handle device identification on macOS, using UUIDs for Bluetooth devices instead of MAC addresses. ```python mac_addr = ( "24:71:89:cc:09:05" if platform.system() != "Darwin" else "243E23AE-4A99-406C-B317-18F1BD7B4CBE" ) ``` -------------------------------- ### Iterating Through GATT Characteristics and Descriptors Source: https://context7.com/hbldh/bleak/llms.txt Shows how to iterate through all services and their characteristics on a connected device. It prints characteristic details and checks for specific properties like 'write-without-response', also demonstrating how to find a descriptor by UUID. ```python import asyncio from bleak import BleakClient, BleakScanner async def main(): device = await BleakScanner.find_device_by_address("AA:BB:CC:DD:EE:FF") async with BleakClient(device) as client: for service in client.services: for char in service.characteristics: print(f"UUID: {char.uuid}") print(f"Handle: {char.handle}") print(f"Description: {char.description}") print(f"Properties: {char.properties}") # e.g. ['read', 'notify'] or ['write-without-response'] if "write-without-response" in char.properties: print(f"Max WoR size: {char.max_write_without_response_size} bytes") # Get descriptor by UUID cccd = char.get_descriptor("00002902-0000-1000-8000-00805f9b34fb") if cccd: print(f" CCCD handle: {cccd.handle}") asyncio.run(main()) ``` -------------------------------- ### Run code formatters and linters Source: https://github.com/hbldh/bleak/blob/develop/CONTRIBUTING.rst Ensure your code adheres to project standards by running isort, black, and flake8. ```shell uv run isort . uv run black . uv run flake8 ``` -------------------------------- ### Handling Notifications with Discriminator Source: https://github.com/hbldh/bleak/blob/develop/docs/backends/pythonista.md This example demonstrates how to use a `notification_discriminator` callback to differentiate between notification data and read data when using `start_notify` on Pythonista, as the _cb module does not distinguish between them. ```python event = asyncio.Event() async def notification_handler(char, data): event.set() def notification_check_handler(data): # We can identify notifications on this characteristic because they # only contain 1 byte of data. Read responses will have more than # 1 byte. return len(data) == 1 await client.start_notify( char, notification_handler, cb={"notification_discriminator": notification_check_handler}, ) while True: await event.wait() # We received a notification - prepare to receive another event.clear() # Then read the characteristic to get the full value data = await client.read_gatt_char(char) # Do stuff with data ``` -------------------------------- ### Connect and Disconnect using Async Context Manager Source: https://github.com/hbldh/bleak/blob/develop/docs/api/client.md The recommended way to connect and disconnect a BleakClient is by using it as an asynchronous context manager. This ensures the client is properly connected before entering the block and automatically disconnected upon exiting. ```APIDOC ## Connecting and disconnecting [`bleak.BleakClient`](#bleak.BleakClient) is a an async context manager, so the recommended way of connecting is to use it as such: ```default import asyncio from bleak import BleakClient async def main(): async with BleakClient("XX:XX:XX:XX:XX:XX") as client: # Read a characteristic, etc. ... # Device will disconnect when block exits. ... # Using asyncio.run() is important to ensure that device disconnects on # KeyboardInterrupt or other unhandled exception. asyncio.run(main()) ``` ``` -------------------------------- ### Start GATT Characteristic Notifications Source: https://github.com/hbldh/bleak/blob/develop/docs/api/client.md Activate notifications or indications on a GATT characteristic. A callback function is required to handle incoming data. The callback receives the characteristic and a bytearray of data. ```python def callback(sender: BleakGATTCharacteristic, data: bytearray): print(f"{sender}: {data}") client.start_notify(char_uuid, callback) ``` -------------------------------- ### Avoid Multiple asyncio.run() Calls (Python) Source: https://github.com/hbldh/bleak/blob/develop/docs/troubleshooting.md Ensure asyncio.run() is called only once at the program's start. Wrapping individual async functions in separate asyncio.run() calls leads to errors. ```python async def scan(): return await BleakScanner.find_device_by_name("My Device") async def connect(device): async with BleakClient(device) as client: data = await client.read_gatt_char(MY_CHAR_UUID) print("received:" data) # Do not wrap each function call in asyncio.run() like this! device = asyncio.run(scan()) if not device: print("Device not found") else: asyncio.run(connect(device)) ``` ```python async def scan(): return await BleakScanner.find_device_by_name("My Device") async def connect(device): async with BleakClient(device) as client: data = await client.read_gatt_char(MY_CHAR_UUID) print("received:" data) # Do have one async main function that does everything. async def main(): device = await scan() if not device: print("Device not found") return await connect(device) asyncio.run(main()) ``` ```python async def scan_and_connect(): device = await BleakScanner.find_device_by_name("My Device") if not device: print("Device not found") return async with BleakClient(device) as client: data = await client.read_gatt_char(MY_CHAR_UUID) print("received:" data) while True: # Don't call asyncio.run() multiple times like this! asyncio.run(scan_and_connect()) # Never use blocking sleep in an asyncio programs! time.sleep(5) ``` ```python async def scan_and_connect(): device = await BleakScanner.find_device_by_name("My Device") if not device: print("Device not found") return async with BleakClient(device) as client: data = await client.read_gatt_char(MY_CHAR_UUID) print("received:" data) # Do have one async main function that does everything. async def main(): while True: await scan_and_connect() # Do use asyncio.sleep() in an asyncio program. await asyncio.sleep(5) asyncio.run(main()) ``` -------------------------------- ### unpair Source: https://github.com/hbldh/bleak/blob/develop/docs/backends/linux.md Unpair with the peripheral. ```APIDOC ## async unpair() -> None Unpair with the peripheral. ``` -------------------------------- ### Enable Bleak Logging (Windows CMD) Source: https://github.com/hbldh/bleak/blob/develop/docs/troubleshooting.md Set the BLEAK_LOGGING environment variable to 1 in the Windows Command Prompt to enable detailed logging for troubleshooting. ```batch set BLEAK_LOGGING=1 ``` -------------------------------- ### Stream Advertisements - BleakScanner.advertisement_data Source: https://context7.com/hbldh/bleak/llms.txt Provides an asynchronous iterator to receive BLE advertisement data in real-time. This is useful for processing advertisement packets as they arrive without using callbacks. The example shows how to collect the first 5 advertisement packets. ```python import asyncio from bleak import BleakScanner async def main(): async with BleakScanner() as scanner: # Collect the first 5 advertisement packets count = 0 async for device, adv in scanner.advertisement_data(): print(f"{device.address}: RSSI={adv.rssi}, name={adv.local_name}") count += 1 if count >= 5: break asyncio.run(main()) ``` -------------------------------- ### Clean Recipe Build Command Source: https://github.com/hbldh/bleak/blob/develop/examples/kivy/README.md Command to clean the recipe build for Bleak when using local source changes. This is necessary because changes to `bleak/**` are not automatically detected during rebuilds. ```bash buildozer android p4a -- clean_recipe_build --local-recipes $(pwd)/../../bleak/backends/p4android/recipes bleak ``` -------------------------------- ### BleakClient.start_notify Source: https://github.com/hbldh/bleak/blob/develop/docs/api/client.md Activate notifications/indications on a characteristic. Callbacks are invoked when data is received. ```APIDOC ## BleakClient.start_notify ### Description Activate notifications/indications on a characteristic. Callbacks are invoked when data is received. ### Method `async` ### Parameters #### Path Parameters * **char_specifier** (BleakGATTCharacteristic | int | str | UUID) - Required - The characteristic to activate notifications/indications on, specified by either integer handle, UUID or directly by the BleakGATTCharacteristic object representing it. * **callback** (Callable[[BleakGATTCharacteristic, bytearray], None | Awaitable[None]]) - Required - The function to be called on notification. Can be a regular function or an async function. * **bluez** (BlueZNotifyArgs) - Optional - BlueZ backend-specific arguments. * **cb** (CBStartNotifyArgs) - Optional - CoreBluetooth backend-specific arguments. ### Request Example ```python def callback(sender: BleakGATTCharacteristic, data: bytearray): print(f"{sender}: {data}") client.start_notify(char_uuid, callback) ``` ### Response #### Success Response (None) This method does not return a value upon success. #### Errors * **BleakCharacteristicNotFoundError**: If a characteristic with the handle or UUID specified by `char_specifier` could not be found. * **backend-specific exceptions**: If the start notification operation failed. ``` -------------------------------- ### BleakScanner.discover() Source: https://github.com/hbldh/bleak/blob/develop/docs/api/scanner.md Scan for a specified duration and return discovered devices, optionally including their advertising data. ```APIDOC ## BleakScanner.discover ### Description Scan continuously for `timeout` seconds and return discovered devices. ### Parameters: * **timeout** – Time, in seconds, to scan for. * **return_adv** – If `True`, the return value will include advertising data. * **kwargs** – Additional arguments will be passed to the [`BleakScanner`](#bleak.BleakScanner) constructor. ### Returns: The value of [`discovered_devices_and_advertisement_data`](#bleak.BleakScanner.discovered_devices_and_advertisement_data) if `return_adv` is `True`, otherwise the value of [`discovered_devices`](#bleak.BleakScanner.discovered_devices). ### Example: ```python # Example for return_adv=False await BleakScanner.discover(timeout=5.0) # Example for return_adv=True await BleakScanner.discover(timeout=5.0, return_adv=True) ``` ``` -------------------------------- ### BLE Error Handling Source: https://context7.com/hbldh/bleak/llms.txt Demonstrates how to catch and handle various Bleak-specific exceptions, providing insights into Bluetooth availability, device discovery, GATT protocol errors, and general BLE issues. ```APIDOC ## Exception Hierarchy — Handling BLE Errors Bleak defines a hierarchy of exceptions in `bleak.exc`. `BleakError` is the base. `BleakBluetoothNotAvailableError` is raised when Bluetooth hardware is off or permission is denied (with `.reason` property). `BleakCharacteristicNotFoundError` when a UUID/handle lookup fails. `BleakDeviceNotFoundError` when the OS has never seen the requested device. `BleakGATTProtocolError` (v3.0+) wraps GATT ATT protocol errors with a `.code` property of type `BleakGATTProtocolErrorCode`. ```python import asyncio from bleak import BleakClient, BleakScanner from bleak.exc import ( BleakError, BleakBluetoothNotAvailableError, BleakBluetoothNotAvailableReason, BleakCharacteristicNotFoundError, BleakDeviceNotFoundError, BleakGATTProtocolError, BleakGATTProtocolErrorCode, ) async def main(): try: device = await BleakScanner.find_device_by_address("AA:BB:CC:DD:EE:FF") async with BleakClient(device) as client: await client.read_gatt_char("00002a19-0000-1000-8000-00805f9b34fb") except BleakBluetoothNotAvailableError as e: if e.reason == BleakBluetoothNotAvailableReason.POWERED_OFF: print("Please turn on Bluetooth") elif e.reason == BleakBluetoothNotAvailableReason.DENIED_BY_USER: print("Bluetooth permission denied") else: print(f"Bluetooth unavailable: {e.reason}") except BleakDeviceNotFoundError as e: print(f"Device {e.identifier} not found by OS") except BleakCharacteristicNotFoundError as e: print(f"Characteristic not found: {e.char_specifier}") except BleakGATTProtocolError as e: if e.code == BleakGATTProtocolErrorCode.READ_NOT_PERMITTED: print("Read not permitted on this characteristic") else: print(f"GATT protocol error: {e.code} ({e.code.name})") except BleakError as e: print(f"Generic BLE error: {e}") asyncio.run(main()) ``` ```