ubluepy — periférico y central Bluetooth LE

El módulo ubluepy es la API heredada de Bluetooth LE que se distribuye con la adaptación nRF de MicroPython. Está vagamente modelado a partir de la biblioteca de Python bluepy de Linux y se asienta directamente sobre el Nordic SoftDevice — no hay un back-end portable, por lo que el módulo solo está disponible en plataformas Nordic (la Arduino Nano 33 BLE Sense en la gama de OpenMV). Las APIs más recientes bluetooth / aioble no están habilitadas en esta compilación, por lo que ubluepy es la única forma de controlar la radio integrada en el chip.

El conjunto de funciones disponible depende del SoftDevice grabado por el firmware:

  • s140 (Nano 33 BLE Sense) — ambos roles, periférico y central (escáner). Esto es lo que distribuye el firmware de OpenMV.

  • s132 — tanto periférico como central.

  • s110 — solo periférico; los métodos de escáner / conexión se excluyen de la compilación.

Ejemplo de periférico

Anuncia como periférico Bluetooth LE con un único servicio de detección ambiental y notifica una característica de temperatura en cada escritura a su descriptor de configuración de característica de cliente (CCCD):

from ubluepy import Service, Characteristic, UUID, Peripheral, constants
from machine import LED

notif_enabled = False

def event_handler(event_id, handle, data):
    global notif_enabled
    if event_id == constants.EVT_GAP_CONNECTED:
        LED("LED_GREEN").on()
    elif event_id == constants.EVT_GAP_DISCONNECTED:
        LED("LED_GREEN").off()
        periph.advertise(device_name="Nano 33", services=[svc])
    elif event_id == constants.EVT_GATTS_WRITE:
        notif_enabled = bool(data[0])

svc = Service(UUID("181A"))            # Environmental Sensing
char = Characteristic(UUID("2A6E"),
                      props=Characteristic.PROP_NOTIFY | Characteristic.PROP_READ,
                      attrs=Characteristic.ATTR_CCCD)
svc.addCharacteristic(char)

periph = Peripheral()
periph.addService(svc)
periph.setConnectionHandler(event_handler)
periph.advertise(device_name="Nano 33", services=[svc])

Ejemplo de central

Busca dispositivos cercanos que estén anunciando durante 100 ms y decodifica los datos de anuncio de cada ScanEntry:

from ubluepy import Scanner, constants

s = Scanner()
for entry in s.scan(100):
    print(entry.addr(), entry.rssi(), "dBm")
    for ad_type, name, value in entry.getScanData():
        print(" ", ad_type, name, bytes(value))

Contenido del módulo

Clases

class ubluepy.UUID(value)

Construye un UUID de Bluetooth de 16 o 128 bits.

value

Uno de:

  • int — un UUID numérico de 16 bits (UUID(0x180A)).

  • Cadena "0xXXXX" de 6 caracteres — un UUID de 16 bits, p. ej. UUID("0x181A").

  • Cadena "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" de 36 caracteres — un UUID completo de 128 bits. La parte específica del proveedor se registra en el SoftDevice durante la construcción.

  • Otra instancia de UUID — realiza una copia.

Cualquier otra longitud genera ValueError("Invalid UUID string length").

binVal() int

Devuelve los 16 bits inferiores del UUID como un int. Para los UUID de 128 bits solo se devuelve el campo de 16 bits incrustado dentro del UUID específico del proveedor (el valor completo de 128 bits solo es accesible mediante el índice específico del proveedor del SoftDevice).

class ubluepy.Service(uuid: UUID, type: int = Service.PRIMARY)

Define un servicio GATT que se registrará en el SoftDevice cuando se añada a un Peripheral.

uuid

Una instancia de UUID. Pasar un objeto que no sea un UUID genera ValueError.

type

Service.PRIMARY (predeterminado) o Service.SECONDARY. Otros valores generan ValueError.

uuid() UUID

Devuelve la instancia UUID del servicio.

addCharacteristic(characteristic: Characteristic) None

Registra una Characteristic en el servicio. El identificador GATT de la característica se asigna durante esta llamada.

getCharacteristic(uuid: UUID) Characteristic | None

Busca una Characteristic añadida previamente por UUID. Devuelve la instancia de la característica, o None si no se encuentra ninguna coincidencia.

getCharacteristics() list

Devuelve la lista de todas las características añadidas al servicio.

PRIMARY: int

Constante de tipo de servicio para los servicios primarios (1).

SECONDARY: int

Constante de tipo de servicio para los servicios secundarios (2).

class ubluepy.Characteristic(uuid: UUID, *, props: int = PROP_READ | PROP_WRITE, attrs: int = 0)

Define una característica GATT. Añádala a un Service con Service.addCharacteristic() antes de que el Peripheral padre empiece a anunciar.

uuid

Una instancia de UUID.

props (solo por palabra clave)

Máscara de bits de uno o más valores Characteristic.PROP_* que describen qué operaciones admite la característica.

attrs (solo por palabra clave)

Máscara de bits de atributos GATT adicionales. Use Characteristic.ATTR_CCCD para adjuntar un descriptor de configuración de característica de cliente (CCCD) — necesario para que funcionen las características PROP_NOTIFY / PROP_INDICATE.

uuid() UUID

Devuelve la instancia UUID de la característica.

properties() int

Devuelve la máscara de bits props establecida en el momento de la construcción.

read() bytearray

Solo rol central. Lee el valor de la característica desde el par conectado. Devuelve un bytearray con el valor más reciente. En un periférico esto no hace nada y devuelve None.

write(data, *, with_response: bool = False) None

Escribe en la característica.

  • En un periférico, si PROP_NOTIFY está establecido en las propiedades de la característica, el valor se envía como notificación GATT al central conectado; de lo contrario se actualiza el valor del atributo local.

  • En un central, el valor se escribe en el par remoto. Establezca with_response=True para emitir una solicitud de escritura y esperar el reconocimiento del par en lugar de un comando de escritura.

data es cualquier objeto que admita el protocolo de búfer (bytes, bytearray, memoryview).

PROP_BROADCAST: int

La característica puede difundir su valor (0x01).

PROP_READ: int

La característica admite lecturas (0x02).

PROP_WRITE_WO_RESP: int

La característica admite escrituras sin respuesta (0x04).

PROP_WRITE: int

La característica admite escrituras con respuesta (0x08).

PROP_NOTIFY: int

La característica puede enviar notificaciones a un central suscrito (0x10).

PROP_INDICATE: int

La característica puede enviar indicaciones (notificaciones reconocidas) a un central suscrito (0x20).

PROP_AUTH_SIGNED_WR: int

La característica admite escrituras firmadas autenticadas (0x40).

ATTR_CCCD: int

Añade un descriptor de configuración de característica de cliente (CCCD) a la característica (0x01). Necesario para que los clientes puedan suscribirse a notificaciones/indicaciones.

class ubluepy.Descriptor(uuid: UUID)

Clase de relleno para representar descriptores GATT. La implementación actual solo almacena el UUID y no expone ningún método — se proporciona para compatibilidad futura con próximas revisiones del módulo.

class ubluepy.Peripheral

El dispositivo Bluetooth LE local. Se usa la misma clase para los roles de periférico y de central; el rol se selecciona según los métodos que se llamen (advertise() selecciona periférico, connect() selecciona central).

addService(service: Service) None

Registra un Service (y todas sus características añadidas previamente) en el servidor GATT local.

getServices() list

Devuelve la lista de servicios registrados actualmente en este Peripheral.

advertise(*, device_name: str | None = None, services: list | None = None, data: bytes | None = None, connectable: bool = True) None

Comienza a anunciar en rol de periférico.

device_name

Nombre local completo anunciado en la carga útil GAP.

services

Lista de instancias Service que se van a anunciar. El UUID de cada servicio se incluye en el anuncio.

data

Carga útil de anuncio sin procesar opcional (bytes / bytearray) que se añade a la cabecera generada automáticamente. Úsela para cargas útiles específicas del proveedor o de baliza, como Eddystone.

connectable

Cuando es True (predeterminado), anuncia como dispositivo conectable y registra los manejadores de eventos GAP / GATTS para que la función de retorno (callback) setConnectionHandler() configurada se active al conectarse, desconectarse y en las escrituras de CCCD. Cuando es False, anuncia como baliza — no se adjunta ningún manejador y no es posible conectarse al dispositivo.

advertise_stop() None

Detiene cualquier anuncio en curso.

setConnectionHandler(func) None

Registra una función de retorno (callback) invocada en los eventos GAP y GATTS. La función de retorno se llama como func(event_id, conn_handle, data) donde event_id es uno de los valores constants.EVT_GAP_CONNECTED, constants.EVT_GAP_DISCONNECTED o constants.EVT_GATTS_WRITE, conn_handle es el identificador de conexión del SoftDevice (o el identificador de atributo para las escrituras GATTS), y data es la carga útil sin procesar del evento como bytearray (o None para conexión / desconexión).

setNotificationHandler(func) None

Registra una función de retorno (callback) para los eventos de notificación recibidos en rol central.

withDelegate(delegate: DefaultDelegate) None

Adjunta una instancia de DefaultDelegate para recibir los eventos GATT decodificados.

disconnect() None

Cierra la conexión activa (actualmente es un relleno que no hace nada en esta compilación).

connect(addr, *, addr_type: int = constants.ADDR_TYPE_PUBLIC) None

Solo rol central. Se conecta al par con la dirección indicada y descubre de forma síncrona sus servicios y características primarios. Se bloquea hasta que se establece la conexión y se completa el descubrimiento; los servicios descubiertos quedan entonces disponibles mediante getServices().

addr

Dirección del par como cadena "xx:xx:xx:xx:xx:xx" de 17 caracteres (p. ej. la obtenida de ScanEntry.addr()).

addr_type (solo por palabra clave)

constants.ADDR_TYPE_PUBLIC (predeterminado) o constants.ADDR_TYPE_RANDOM_STATIC.

class ubluepy.Scanner

Observador GAP para descubrir dispositivos cercanos que estén anunciando. Disponible únicamente cuando el firmware está compilado contra un SoftDevice con soporte de central (s132 / s140).

scan(timeout: int) list

Ejecuta un escaneo pasivo durante timeout milisegundos y devuelve una lista de instancias ScanEntry — una por cada informe de anuncio recibido durante la ventana.

class ubluepy.ScanEntry

Un único informe de anuncio capturado por Scanner.scan(). Las instancias las devuelve el escáner — no hay un constructor público.

addr() str

Devuelve la dirección del par como cadena "xx:xx:xx:xx:xx:xx" de 17 caracteres.

addr_type() int

Devuelve el tipo de dirección del par (constants.ADDR_TYPE_PUBLIC o constants.ADDR_TYPE_RANDOM_STATIC).

rssi() int

Devuelve el indicador de intensidad de señal en dBm.

getScanData() list

Decodifica la carga útil del anuncio en una lista de tuplas (ad_type, description, value). ad_type es el byte numérico del tipo de AD (consulte constants.ad_types), description es el nombre de la constante coincidente como cadena (o None si el tipo es desconocido), y value es el cuerpo del registro AD como bytearray.

class ubluepy.DefaultDelegate

Clase base para los objetos que se pasan a Peripheral.withDelegate(). Cree una subclase y sobrescriba handleConnection() / handleNotification() para reaccionar a los eventos GATT.

handleConnection() None

Se llama en los eventos GAP de conexión / desconexión. La implementación predeterminada está vacía.

handleNotification() None

Se llama en las notificaciones GATT entrantes. La implementación predeterminada está vacía.

Constantes

El atributo constants del módulo es un espacio de nombres que contiene identificadores de eventos GAP/GATT, valores de tipo de dirección y el espacio de nombres anidado ad_types.

ubluepy.constants: type

Contenedor que expone las constantes siguientes.

constants.EVT_GAP_CONNECTED: int

Valor event_id del manejador de conexión de Peripheral para la conexión GAP (16).

constants.EVT_GAP_DISCONNECTED: int

Valor event_id del manejador de conexión de Peripheral para la desconexión GAP (17).

constants.EVT_GATTS_WRITE: int

Valor event_id del manejador de conexión de Peripheral para una escritura a un atributo GATT local, incluidas las escrituras a un CCCD que habilitan/deshabilitan notificaciones (80).

constants.UUID_CCCD: int

UUID estándar de Bluetooth para el descriptor de configuración de característica de cliente (0x2902).

constants.ADDR_TYPE_PUBLIC: int

Dirección pública de dispositivo Bluetooth (0).

constants.ADDR_TYPE_RANDOM_STATIC: int

Dirección aleatoria estática de dispositivo Bluetooth (1).

constants.ad_types: type

Espacio de nombres de las constantes de tipo de AD de los datos de anuncio del Bluetooth Core Specification Supplement. Cada nombre se corresponde con el tipo de AD de 1 byte correspondiente:

Nombre

Valor

AD_TYPE_FLAGS

0x01

AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE

0x02

AD_TYPE_16BIT_SERVICE_UUID_COMPLETE

0x03

AD_TYPE_32BIT_SERVICE_UUID_MORE_AVAILABLE

0x04

AD_TYPE_32BIT_SERVICE_UUID_COMPLETE

0x05

AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE

0x06

AD_TYPE_128BIT_SERVICE_UUID_COMPLETE

0x07

AD_TYPE_SHORT_LOCAL_NAME

0x08

AD_TYPE_COMPLETE_LOCAL_NAME

0x09

AD_TYPE_TX_POWER_LEVEL

0x0A

AD_TYPE_CLASS_OF_DEVICE

0x0D

AD_TYPE_SIMPLE_PAIRING_HASH_C

0x0E

AD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R

0x0F

AD_TYPE_SECURITY_MANAGER_TK_VALUE

0x10

AD_TYPE_SECURITY_MANAGER_OOB_FLAGS

0x11

AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE

0x12

AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT

0x14

AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT

0x15

AD_TYPE_SERVICE_DATA

0x16

AD_TYPE_PUBLIC_TARGET_ADDRESS

0x17

AD_TYPE_RANDOM_TARGET_ADDRESS

0x18

AD_TYPE_APPEARANCE

0x19

AD_TYPE_ADVERTISING_INTERVAL

0x1A

AD_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS

0x1B

AD_TYPE_LE_ROLE

0x1C

AD_TYPE_SIMPLE_PAIRING_HASH_C256

0x1D

AD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R256

0x1E

AD_TYPE_SERVICE_DATA_32BIT_UUID

0x20

AD_TYPE_SERVICE_DATA_128BIT_UUID

0x21

AD_TYPE_URI

0x24

AD_TYPE_3D_INFORMATION_DATA

0x3D

AD_TYPE_MANUFACTURER_SPECIFIC_DATA

0xFF