Bluetooth Quickstart
Background
Lager provides a simplified API for the most common Bluetooth tasks. If you need more control over the Bluetooth stack or are familiar with async Python, see Bluetooth (Advanced)
Creating a BLE Central
A BLE central object can be used to scan and connect to devices
from lager.ble import Central
central = Central()
Scanning
from lager.ble import Central
def main():
central = Central()
# `central.scan` takes two optional keyword args, `name` and `address`, which
# will filter the list of results down to those devices which match. If neither
# is provided, all scanned devices will be returned
for device in central.scan(name='MyDevice'):
print(device)
print(device.metadata)
if __name__ == '__main__':
main()
➜ lager python ble-scan.py
F2:E6:41:55:6F:09: MyDevice
{'uuids': ['0000fe78-0000-1000-8000-00805f9b34fb'], 'manufacturer_data': {101: b'\x01\xc9\x05'}}
Connecting and listing services and characteristics
from lager.ble import Central
def main():
central = Central()
with central.connect('F2:E6:41:55:6F:09') as client:
services = client.get_services()
print(services['0000180a-0000-1000-8000-00805f9b34fb'] is None)
print(services['a000180a-0000-1000-8000-00805f9b34fb'] is None)
for service in client.get_services():
print(service)
for characteristic in service.characteristics:
print(f'\t{characteristic}')
if __name__ == '__main__':
main()
➜ lager python ble-connect.py
False
True
00001801-0000-1000-8000-00805f9b34fb (Handle: 10): Generic Attribute Profile
00002a05-0000-1000-8000-00805f9b34fb (Handle: 11): Service Changed
0000180a-0000-1000-8000-00805f9b34fb (Handle: 14): Device Information
00002a29-0000-1000-8000-00805f9b34fb (Handle: 15): Manufacturer Name String
00002a26-0000-1000-8000-00805f9b34fb (Handle: 17): Firmware Revision String
00002a23-0000-1000-8000-00805f9b34fb (Handle: 19): System ID
0000180f-0000-1000-8000-00805f9b34fb (Handle: 21): Battery Service
00002a19-0000-1000-8000-00805f9b34fb (Handle: 22): Battery Level
8e7c6065-7656-17ad-1b41-b53d1a548e0d (Handle: 25): Unknown
10c2be2d-d2d5-b7a8-5f42-e2468c9ebbf5 (Handle: 26): Unknown
49e830a0-57dd-11e4-8ac4-0002a5d5c51b (Handle: 30): Unknown
453ad6d2-c7f2-16ae-6948-1859e5f040d0 (Handle: 34): Unknown
Read GATT characteristic
from lager.ble import Central
def main():
central = Central()
with central.connect('F2:E6:41:55:6F:09') as client:
val = client.read_gatt_char('00002a19-0000-1000-8000-00805f9b34fb')
print(val[0])
if __name__ == '__main__':
main()
➜ lager python ble-read.py
88
Write GATT characteristic
from lager.ble import Central
def main():
central = Central()
with central.connect('F2:E6:41:55:6F:09') as client:
client.write_gatt_char('00002a19-0000-1000-8000-00805f9b34fb', b'Data')
if __name__ == '__main__':
main()
Notify GATT characteristic
from lager.ble import Central
STREAMING_DATA_CHAR_UUID = "10c2be2d-d2d5-b7a8-5f42-e2468c9ebbf5"
def main():
central = Central()
with central.connect('F2:E6:41:55:6F:09') as client:
try:
# start_notify also takes an optional "callback" parameter that will be called as messages
# arrive; e.g. `callback=notify_cb`. The callback takes two arguments, an integer handle
# for the characteristic and a bytearray of the data received
timed_out, messages = client.start_notify(STREAMING_DATA_CHAR_UUID, max_messages=5, timeout=5)
print(f"Timed out: {timed_out}")
print(messages)
finally:
client.stop_notify(STREAMING_DATA_CHAR_UUID)
def notify_cb(handle: int, data: bytearray):
print(f"Received data: {data}")
if __name__ == '__main__':
main()
➜ lager python ble-notify.py
Received data: bytearray(b'1')
Received data: bytearray(b'2')
Received data: bytearray(b'3')
Received data: bytearray(b'4')
Received data: bytearray(b'5')
Timed out: False
[bytearray(b'1'), bytearray(b'2'), bytearray(b'3'), bytearray(b'4'), bytearray(b'5')]