_bleio
– Bluetooth Low Energy (BLE) communication
The _bleio
module provides necessary low-level functionality for communicating
using Bluetooth Low Energy (BLE). The ‘_’ prefix indicates this module is meant
for internal use by libraries but not by the end user. Its API may change incompatibly
between minor versions of CircuitPython.
Please use the
adafruit_ble
CircuitPython library instead, which builds on _bleio
, and
provides higher-level convenience functionality, including predefined beacons, clients,
servers.
Available on these boards
- _bleio.adapter: Adapter
BLE Adapter used to manage device discovery and connections. This object is the sole instance of
_bleio.Adapter
.
- exception _bleio.BluetoothError
Bases:
Exception
Catchall exception for Bluetooth related errors.
Initialize self. See help(type(self)) for accurate signature.
- exception _bleio.RoleError
Bases:
BluetoothError
Raised when a resource is used as the mismatched role. For example, if a local CCCD is attempted to be set but they can only be set when remote.
Initialize self. See help(type(self)) for accurate signature.
- exception _bleio.SecurityError
Bases:
BluetoothError
Raised when a security related error occurs.
Initialize self. See help(type(self)) for accurate signature.
- _bleio.set_adapter(adapter: Adapter | None) None
Set the adapter to use for BLE, such as when using an HCI adapter. Raises
NotImplementedError
when the adapter is a singleton and cannot be set.
- class _bleio.Adapter(*, uart: busio.UART, rts: digitalio.DigitalInOut, cts: digitalio.DigitalInOut)
The BLE Adapter object manages the discovery and connection to other nearby Bluetooth Low Energy devices. This part of the Bluetooth Low Energy Specification is known as Generic Access Profile (GAP).
Discovery of other devices happens during a scanning process that listens for small packets of information, known as advertisements, that are broadcast unencrypted. The advertising packets have two different uses. The first is to broadcast a small piece of data to anyone who cares and and nothing more. These are known as beacons. The second class of advertisement is to promote additional functionality available after the devices establish a connection. For example, a BLE heart rate monitor would advertise that it provides the standard BLE Heart Rate Service.
The Adapter can do both parts of this process: it can scan for other device advertisements and it can advertise its own data. Furthermore, Adapters can accept incoming connections and also initiate connections.
On boards that do not have native BLE, you can use an HCI co-processor. Pass the uart and pins used to communicate with the co-processor, such as an Adafruit AirLift. The co-processor must have been reset and put into BLE mode beforehand by the appropriate pin manipulation. The
uart
,rts
, andcts
objects are used to communicate with the HCI co-processor in HCI mode. TheAdapter
object is enabled during this call.After instantiating an Adapter, call
_bleio.set_adapter()
to set_bleio.adapter
On boards with native BLE, you cannot create an instance of
_bleio.Adapter
; this constructor will raiseNotImplementedError
. Use_bleio.adapter
to access the sole instance already available.- name: str
name of the BLE adapter used once connected. The name is “CIRCUITPY” + the last four hex digits of
adapter.address
, to make it easy to distinguish multiple CircuitPython boards.
- start_advertising(data: circuitpython_typing.ReadableBuffer, *, scan_response: circuitpython_typing.ReadableBuffer | None = None, connectable: bool = True, anonymous: bool = False, timeout: int = 0, interval: float = 0.1, tx_power: int = 0, directed_to: Address | None = None) None
Starts advertising until
stop_advertising
is called or if connectable, another device connects to us.Warning
If data is longer than 31 bytes, then this will automatically advertise as an extended advertisement that older BLE 4.x clients won’t be able to scan for.
Note
If you set
anonymous=True
, then a timeout must be specified. If no timeout is specified, then the maximum allowed timeout will be selected automatically.- Parameters:
data (ReadableBuffer) – advertising data packet bytes
scan_response (ReadableBuffer) – scan response data packet bytes.
None
if no scan response is needed.connectable (bool) – If
True
then other devices are allowed to connect to this peripheral.anonymous (bool) – If
True
then this device’s MAC address is randomized before advertising.timeout (int) – If set, we will only advertise for this many seconds. Zero means no timeout.
interval (float) – advertising interval, in seconds
tx_power (int) – transmitter power while advertising in dBm
directed_to (Address) – peer to advertise directly to
- start_scan(prefixes: circuitpython_typing.ReadableBuffer = b'', *, buffer_size: int = 512, extended: bool = False, timeout: float | None = None, interval: float = 0.1, window: float = 0.1, minimum_rssi: int = -80, active: bool = True) Iterable[ScanEntry]
Starts a BLE scan and returns an iterator of results. Advertisements and scan responses are filtered and returned separately.
- Parameters:
prefixes (ReadableBuffer) – Sequence of byte string prefixes to filter advertising packets with. A packet without an advertising structure that matches one of the prefixes is ignored. Format is one byte for length (n) and n bytes of prefix and can be repeated.
buffer_size (int) – the maximum number of advertising bytes to buffer.
extended (bool) – When True, support extended advertising packets. Increasing buffer_size is recommended when this is set.
timeout (float) – the scan timeout in seconds. If None or zero, will scan until
stop_scan
is called.interval (float) – the interval (in seconds) between the start of two consecutive scan windows Must be in the range 0.0025 - 40.959375 seconds.
window (float) – the duration (in seconds) to scan a single BLE channel. window must be <= interval.
minimum_rssi (int) – the minimum rssi of entries to return.
active (bool) – retrieve scan responses for scannable advertisements.
- Returns:
an iterable of
_bleio.ScanEntry
objects- Return type:
iterable
- connected: bool
True when the adapter is connected to another device regardless of who initiated the connection. (read-only)
- connections: Tuple[Connection]
Tuple of active connections including those initiated through
_bleio.Adapter.connect()
. (read-only)
- connect(address: Address, *, timeout: float) Connection
Attempts a connection to the device with the given address.
- Parameters:
address (Address) – The address of the peripheral to connect to
timeout (float/int) – Try to connect for timeout seconds.
- class _bleio.Address(address: circuitpython_typing.ReadableBuffer, address_type: int)
Encapsulates the address of a BLE device.
Create a new Address object encapsulating the address value. The value itself can be one of:
- Parameters:
address (ReadableBuffer) – The address value to encapsulate. A buffer object (bytearray, bytes) of 6 bytes.
address_type (int) – one of the integer values:
PUBLIC
,RANDOM_STATIC
,RANDOM_PRIVATE_RESOLVABLE
, orRANDOM_PRIVATE_NON_RESOLVABLE
.
- address_bytes: bytes
The bytes that make up the device address (read-only).
Note that the
bytes
object returned is in little-endian order: The least significant byte isaddress_bytes[0]
. So the address will appear to be reversed if you print the rawbytes
object. If you print or usestr()
on theAttribute
object itself, the address will be printed in the expected order. For example:>>> import _bleio >>> _bleio.adapter.address <Address c8:1d:f5:ed:a8:35> >>> _bleio.adapter.address.address_bytes b'5\xa8\xed\xf5\x1d\xc8'
- type: int
The address type (read-only).
One of the integer values:
PUBLIC
,RANDOM_STATIC
,RANDOM_PRIVATE_RESOLVABLE
, orRANDOM_PRIVATE_NON_RESOLVABLE
.
- __eq__(other: object) bool
Two Address objects are equal if their addresses and address types are equal.
- PUBLIC: int
A publicly known address, with a company ID (high 24 bits)and company-assigned part (low 24 bits).
- RANDOM_STATIC: int
A randomly generated address that does not change often. It may never change or may change after a power cycle.
- class _bleio.Attribute
Definitions associated with all BLE attributes: characteristics, descriptors, etc.
Attribute
is, notionally, a superclass ofCharacteristic
andDescriptor
, but is not defined as a Python superclass of those classes.You cannot create an instance of
Attribute
.- ENCRYPT_NO_MITM: int
security_mode: unauthenticated encryption, without man-in-the-middle protection
- class _bleio.Characteristic
Stores information about a BLE service characteristic and allows reading and writing of the characteristic’s value.
There is no regular constructor for a Characteristic. A new local Characteristic can be created and attached to a Service by calling
add_to_service()
. Remote Characteristic objects are created byConnection.discover_remote_services()
as part of remote Services.- classmethod add_to_service(service: Service, uuid: UUID, *, properties: int = 0, read_perm: int = Attribute.OPEN, write_perm: int = Attribute.OPEN, max_length: int = 20, fixed_length: bool = False, initial_value: circuitpython_typing.ReadableBuffer | None = None, user_description: str | None = None) Characteristic
Create a new Characteristic object, and add it to this Service.
- Parameters:
service (Service) – The service that will provide this characteristic
uuid (UUID) – The uuid of the characteristic
properties (int) – The properties of the characteristic, specified as a bitmask of these values bitwise-or’d together:
BROADCAST
,INDICATE
,NOTIFY
,READ
,WRITE
,WRITE_NO_RESPONSE
.read_perm (int) – Specifies whether the characteristic can be read by a client, and if so, which security mode is required. Must be one of the integer values
Attribute.NO_ACCESS
,Attribute.OPEN
,Attribute.ENCRYPT_NO_MITM
,Attribute.ENCRYPT_WITH_MITM
,Attribute.LESC_ENCRYPT_WITH_MITM
,Attribute.SIGNED_NO_MITM
, orAttribute.SIGNED_WITH_MITM
.write_perm (int) – Specifies whether the characteristic can be written by a client, and if so, which security mode is required. Values allowed are the same as
read_perm
.max_length (int) – Maximum length in bytes of the characteristic value. The maximum allowed is is 512, or possibly 510 if
fixed_length
is False. The default, 20, is the maximum number of data bytes that fit in a single BLE 4.x ATT packet.fixed_length (bool) – True if the characteristic value is of fixed length.
initial_value (ReadableBuffer) – The initial value for this characteristic. If not given, will be filled with zeros.
user_description (str) – User friendly description of the characteristic
- Returns:
the new Characteristic.
- properties: int
An int bitmask representing which properties are set, specified as bitwise or’ing of of these possible values.
BROADCAST
,INDICATE
,NOTIFY
,READ
,WRITE
,WRITE_NO_RESPONSE
.
- uuid: UUID | None
The UUID of this characteristic. (read-only)
Will be
None
if the 128-bit UUID for this characteristic is not known.
- descriptors: Descriptor
A tuple of
Descriptor
objects related to this characteristic. (read-only)
- set_cccd(*, notify: bool = False, indicate: bool = False) None
Set the remote characteristic’s CCCD to enable or disable notification and indication.
- class _bleio.CharacteristicBuffer(characteristic: Characteristic, *, timeout: float = 1.0, buffer_size: int = 64)
Accumulates a Characteristic’s incoming values in a FIFO buffer.
Monitor the given Characteristic. Each time a new value is written to the Characteristic add the newly-written bytes to a FIFO buffer.
- Parameters:
characteristic (Characteristic) – The Characteristic to monitor. It may be a local Characteristic provided by a Peripheral Service, or a remote Characteristic in a remote Service that a Central has connected to.
timeout (float) – the timeout in seconds to wait for the first character and between subsequent characters.
buffer_size (int) – Size of ring buffer that stores incoming data coming from client. Must be >= 1.
- read(nbytes: int | None = None) bytes | None
Read characters. If
nbytes
is specified then read at most that many bytes. Otherwise, read everything that arrives until the connection times out. Providing the number of bytes expected is highly recommended because it will be faster.- Returns:
Data read
- Return type:
bytes or None
- readinto(buf: circuitpython_typing.WriteableBuffer, nbytes: int | None = None) int | None
Read bytes into the
buf
. Read at mostlen(buf)
bytes.You may reduce this maximum read using the
nbytes
argument.- Returns:
number of bytes read and stored into
buf
- Return type:
int or None (on a non-blocking error)
- class _bleio.Connection
A BLE connection to another device. Used to discover and interact with services on the other device.
Usage:
import _bleio my_entry = None for entry in _bleio.adapter.scan(2.5): if entry.name is not None and entry.name == 'InterestingPeripheral': my_entry = entry break if not my_entry: raise Exception("'InterestingPeripheral' not found") connection = _bleio.adapter.connect(my_entry.address, timeout=10)
Connections cannot be made directly. Instead, to initiate a connection use
Adapter.connect
. Connections may also be made when another device initiates a connection. To use a Connection created by a peer, read theAdapter.connections
property.- discover_remote_services(service_uuids_whitelist: Iterable[UUID] | None = None) Tuple[Service, Ellipsis]
Do BLE discovery for all services or for the given service UUIDS, to find their handles and characteristics, and return the discovered services.
Connection.connected
must be True.- Parameters:
service_uuids_whitelist (iterable) –
an iterable of
UUID
objects for the services provided by the peripheral that you want to use.The peripheral may provide more services, but services not listed are ignored and will not be returned.
If service_uuids_whitelist is None, then all services will undergo discovery, which can be slow.
If the service UUID is 128-bit, or its characteristic UUID’s are 128-bit, you you must have already created a
UUID
object for that UUID in order for the service or characteristic to be discovered. Creating the UUID causes the UUID to be registered for use. (This restriction may be lifted in the future.)- Returns:
A tuple of
_bleio.Service
objects provided by the remote peripheral.
- connection_interval: float
Time between transmissions in milliseconds. Will be multiple of 1.25ms. Lower numbers increase speed and decrease latency but increase power consumption.
When setting connection_interval, the peer may reject the new interval and
connection_interval
will then remain the same.Apple has additional guidelines that dictate should be a multiple of 15ms except if HID is available. When HID is available Apple devices may accept 11.25ms intervals.
- max_packet_length: int
The maximum number of data bytes that can be sent in a single transmission, not including overhead bytes.
This is the maximum number of bytes that can be sent in a notification, which must be sent in a single packet. But for a regular characteristic read or write, may be sent in multiple packets, so this limit does not apply.
- class _bleio.Descriptor
Stores information about a BLE descriptor.
Descriptors are attached to BLE characteristics and provide contextual information about the characteristic.
There is no regular constructor for a Descriptor. A new local Descriptor can be created and attached to a Characteristic by calling
add_to_characteristic()
. Remote Descriptor objects are created byConnection.discover_remote_services()
as part of remote Characteristics in the remote Services that are discovered.- classmethod add_to_characteristic(characteristic: Characteristic, uuid: UUID, *, read_perm: int = Attribute.OPEN, write_perm: int = Attribute.OPEN, max_length: int = 20, fixed_length: bool = False, initial_value: circuitpython_typing.ReadableBuffer = b'') Descriptor
Create a new Descriptor object, and add it to this Service.
- Parameters:
characteristic (Characteristic) – The characteristic that will hold this descriptor
uuid (UUID) – The uuid of the descriptor
read_perm (int) – Specifies whether the descriptor can be read by a client, and if so, which security mode is required. Must be one of the integer values
Attribute.NO_ACCESS
,Attribute.OPEN
,Attribute.ENCRYPT_NO_MITM
,Attribute.ENCRYPT_WITH_MITM
,Attribute.LESC_ENCRYPT_WITH_MITM
,Attribute.SIGNED_NO_MITM
, orAttribute.SIGNED_WITH_MITM
.write_perm (int) – Specifies whether the descriptor can be written by a client, and if so, which security mode is required. Values allowed are the same as
read_perm
.max_length (int) – Maximum length in bytes of the descriptor value. The maximum allowed is is 512, or possibly 510 if
fixed_length
is False. The default, 20, is the maximum number of data bytes that fit in a single BLE 4.x ATT packet.fixed_length (bool) – True if the descriptor value is of fixed length.
initial_value (ReadableBuffer) – The initial value for this descriptor.
- Returns:
the new Descriptor.
- characteristic: Characteristic
The Characteristic this Descriptor is a part of.
- class _bleio.PacketBuffer(characteristic: Characteristic, *, buffer_size: int, max_packet_size: int | None = None)
Accumulates a Characteristic’s incoming packets in a FIFO buffer and facilitates packet aware outgoing writes. A packet’s size is either the characteristic length or the maximum transmission unit (MTU) minus overhead, whichever is smaller. The MTU can change so check
incoming_packet_length
andoutgoing_packet_length
before creating a buffer to store data.When we’re the server, we ignore all connections besides the first to subscribe to notifications.
- Parameters:
characteristic (Characteristic) – The Characteristic to monitor. It may be a local Characteristic provided by a Peripheral Service, or a remote Characteristic in a remote Service that a Central has connected to.
buffer_size (int) – Size of ring buffer (in packets of the Characteristic’s maximum length) that stores incoming packets coming from the peer.
max_packet_size (int) – Maximum size of packets. Overrides value from the characteristic. (Remote characteristics may not have the correct length.)
- readinto(buf: circuitpython_typing.WriteableBuffer) int
Reads a single BLE packet into the
buf
. Raises an exception if the next packet is longer than the given buffer. Useincoming_packet_length
to read the maximum length of a single packet.- Returns:
number of bytes read and stored into
buf
- Return type:
- write(data: circuitpython_typing.ReadableBuffer, *, header: bytes | None = None) int
Writes all bytes from data into the same outgoing packet. The bytes from header are included before data when the pending packet is currently empty.
This does not block until the data is sent. It only blocks until the data is pending.
- Returns:
number of bytes written. May include header bytes when packet is empty.
- Return type:
- class _bleio.ScanEntry
Encapsulates information about a device that was received during scanning. It can be advertisement or scan response data. This object may only be created by a
_bleio.ScanResults
: it has no user-visible constructor.Cannot be instantiated directly. Use
_bleio.Adapter.start_scan
.- matches(prefixes: circuitpython_typing.ReadableBuffer, *, match_all: bool = True) bool
Returns True if the ScanEntry matches all prefixes when
match_all
is True. This is stricter than the scan filtering which accepts any advertisements that match any of the prefixes wherematch_all
is False.
- address: Address
The address of the device (read-only), of type
_bleio.Address
.
- class _bleio.ScanResults
Iterates over advertising data received while scanning. This object is always created by a
_bleio.Adapter
: it has no user-visible constructor.Cannot be instantiated directly. Use
_bleio.Adapter.start_scan
.- __next__() ScanEntry
Returns the next
_bleio.ScanEntry
. Blocks if none have been received and scanning is still active. RaisesStopIteration
if scanning is finished and no other results are available.
- class _bleio.Service(uuid: UUID, *, secondary: bool = False)
Stores information about a BLE service and its characteristics.
Create a new Service identified by the specified UUID. It can be accessed by all connections. This is known as a Service server. Client Service objects are created via
Connection.discover_remote_services
.To mark the Service as secondary, pass
True
assecondary
.- Parameters:
- Returns:
the new Service
- characteristics: Tuple[Characteristic, Ellipsis]
A tuple of
Characteristic
designating the characteristics that are offered by this service. (read-only)
- class _bleio.UUID(value: int | circuitpython_typing.ReadableBuffer | str)
A 16-bit or 128-bit UUID. Can be used for services, characteristics, descriptors and more.
Create a new UUID or UUID object encapsulating the uuid value. The value can be one of:
an
int
value in range 0 to 0xFFFF (Bluetooth SIG 16-bit UUID)a buffer object (bytearray, bytes) of 16 bytes in little-endian order (128-bit UUID)
a string of hex digits of the form ‘xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx’
Creating a 128-bit UUID registers the UUID with the onboard BLE software, and provides a temporary 16-bit UUID that can be used in place of the full 128-bit UUID.
- Parameters:
value (int, ReadableBuffer or str) – The uuid value to encapsulate
- uuid128: bytes
The 128-bit value of the UUID Raises AttributeError if this is a 16-bit UUID. (read-only)
- Type:
- size: int
128 if this UUID represents a 128-bit vendor-specific UUID. 16 if this UUID represents a 16-bit Bluetooth SIG assigned UUID. (read-only) 32-bit UUIDs are not currently supported.
- Type:
- pack_into(buffer: circuitpython_typing.WriteableBuffer, offset: int = 0) None
Packs the UUID into the given buffer at the given offset.