Android Bluetooth Low Energy

Latest version on PyPi

Python interface to Android Bluetooth Low Energy API.

Code repository:
 https://github.com/b3b/able
Documentation:https://herethere.me/able
Changelog:https://github.com/b3b/able/blob/master/CHANGELOG.rst

Quick start development environment

able is included in PythonHere app, together with the Jupyter Notebook it could be used as a development environment.

Usage example: https://herethere.me/pythonhere/examples/ble.html

Build

The following instructions are for building app with buildozer tool.

able_recipe recipe should be added to buildozer.spec requirements:

requirements = python3,kivy,android,able_recipe

Bluetooth permissions should be requested in buildozer.spec:

android.permissions = BLUETOOTH, BLUETOOTH_ADMIN, BLUETOOTH_SCAN, BLUETOOTH_CONNECT, BLUETOOTH_ADVERTISE, ACCESS_FINE_LOCATION

App configuration example: buildozer.spec

Build with a local version

To build app with a local (modified) version of able,

path to able recipes directory should be set in buildozer.spec:

p4a.local_recipes = /path/to/cloned/repo/recipes

API

Client

BluetoothDispatcher

Decorators

Services

Constants

Permissions

Scan settings

>>> settings = ScanSettingsBuilder() \
...  .setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE) \
...  .setCallbackType(
...     ScanSettings.CALLBACK_TYPE_FIRST_MATCH |
...     ScanSettings.CALLBACK_TYPE_MATCH_LOST
...   )

Scan filters

Advertising

Advertiser

Payload

Constants

Usage Examples

Alert

Full example code: alert

Change MTU

Scan settings

from able import BluetoothDispatcher
from able.scan_settings import ScanSettingsBuilder, ScanSettings

# Use faster detection (more power usage) mode
settings = ScanSettingsBuilder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
BluetoothDispatcher().start_scan(settings=settings)

Scan filters

from able import BluetoothDispatcher
from able.filters import (
    DeviceAddressFilter,
    DeviceNameFilter,
    ManufacturerDataFilter,
    ServiceDataFilter,
    ServiceUUIDFilter
)

ble = BluetoothDispatcher()

# Start scanning with the condition that device has one of names: "Device1" or "Device2"
ble.start_scan(filters=[DeviceNameFilter("Device1"), DeviceNameFilter("Device2")])
ble.stop_scan()

# Start scanning with the condition that
# device advertises "180f" service and one of names: "Device1" or "Device2"
ble.start_scan(filters=[
    ServiceUUIDFilter('0000180f-0000-1000-8000-00805f9b34fb') & DeviceNameFilter("Device1"),
    ServiceUUIDFilter('0000180f-0000-1000-8000-00805f9b34fb') & DeviceNameFilter("Device2")
])

Adapter state

Advertising

Set and advertise device name

from able import BluetoothDispatcher
from able.advertising import Advertiser, AdvertiseData, DeviceName

ble = BluetoothDispatcher()
ble.name = "New test device name"

# There must be a wait and check, it takes time for new name to take effect
print(f"New device name is set: {ble.name}")

Advertiser(
    ble=ble,
    data=AdvertiseData(DeviceName())
)

Battery service data

Use iBeacon advertising format

import uuid
from able import BluetoothDispatcher
from able.advertising import Advertiser, AdvertiseData, ManufacturerData


data = AdvertiseData(
    ManufacturerData(
        0x4C,  # Apple Manufacturer ID
        bytes([
            0x2, # SubType: Custom Manufacturer Data
            0x15 # Subtype lenth
        ]) +
        uuid.uuid4().bytes +  # UUID of beacon
        bytes([
            0, 15,  # Major value
            0, 1,  # Minor value
            10  # RSSI, dBm at 1m
        ]))
)

Advertiser(BluetoothDispatcher(), data).start()

Android Services

BLE devices scanning service

main.py

service.py

Full example code: service_scan

Advertising service

main.py

service.py

Full example code: service_advertise

Connect to multiple devices

Full example code: multi_devices