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