ubluepy — periférico e central Bluetooth LE

O módulo ubluepy é a API Bluetooth LE legada fornecida com a portação nRF do MicroPython. Baseia-se livremente na biblioteca Python bluepy para Linux e assenta diretamente sobre o Nordic SoftDevice — não existe um backend portável, pelo que o módulo está disponível apenas em alvos Nordic (o Arduino Nano 33 BLE Sense na gama da OpenMV). As APIs mais recentes bluetooth / aioble não estão ativadas nesta compilação, pelo que ubluepy é a única forma de controlar o rádio integrado.

O conjunto de funcionalidades disponíveis depende do SoftDevice instalado pelo firmware:

  • s140 (Nano 33 BLE Sense) — funções de periférico e central (scanner). É o que o firmware da OpenMV inclui.

  • s132 — funções de periférico e central.

  • s110 — apenas periférico; os métodos de scanner/ligação são excluídos da compilação.

Exemplo de periférico

Anunciar como periférico Bluetooth LE com um único serviço de monitorização ambiental e notificar uma característica de temperatura em cada escrita no seu Client Characteristic Configuration Descriptor (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])

Exemplo de central

Procurar dispositivos a anunciar nas proximidades durante 100 ms e descodificar os dados de anúncio 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))

Conteúdos do módulo

Classes

class ubluepy.UUID(value)

Constrói um UUID Bluetooth de 16 ou 128 bits.

value

Um dos seguintes:

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

  • Cadeia de caracteres "0xXXXX" de 6 caracteres — um UUID de 16 bits, por exemplo UUID("0x181A").

  • Cadeia de caracteres "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" de 36 caracteres — um UUID completo de 128 bits. A parte específica do fornecedor é registada no SoftDevice na construção.

  • Outra instância de UUID — efetua uma cópia.

Qualquer outro comprimento lança ValueError("Invalid UUID string length").

binVal() int

Devolve os 16 bits inferiores do UUID como um int. Para UUIDs de 128 bits, é devolvido apenas o campo de 16 bits incorporado no UUID específico do fornecedor (o valor completo de 128 bits é acessível apenas através do índice específico do fornecedor do SoftDevice).

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

Define um serviço GATT que será registado no SoftDevice quando adicionado a um Peripheral.

uuid

Uma instância de UUID. Passar um objeto que não seja UUID lança ValueError.

type

Ou Service.PRIMARY (predefinição) ou Service.SECONDARY. Outros valores lançam ValueError.

uuid() UUID

Devolve a instância UUID do serviço.

addCharacteristic(characteristic: Characteristic) None

Regista uma Characteristic no serviço. O handle GATT da característica é atribuído durante esta chamada.

getCharacteristic(uuid: UUID) Characteristic | None

Procura uma Characteristic anteriormente adicionada pelo UUID. Devolve a instância da característica, ou None se não for encontrada correspondência.

getCharacteristics() list

Devolve a lista de todas as características adicionadas ao serviço.

PRIMARY: int

Constante de tipo de serviço para serviços primários (1).

SECONDARY: int

Constante de tipo de serviço para serviços secundários (2).

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

Define uma característica GATT. Adicioná-la a um Service com Service.addCharacteristic() antes do Peripheral pai começar a anunciar.

uuid

Uma instância de UUID.

props (apenas por palavra-chave)

Máscara de bits de um ou mais valores Characteristic.PROP_* que descrevem quais as operações que a característica suporta.

attrs (apenas por palavra-chave)

Máscara de bits de atributos GATT adicionais. Use Characteristic.ATTR_CCCD para anexar um Client Characteristic Configuration Descriptor — necessário para que as características PROP_NOTIFY / PROP_INDICATE funcionem.

uuid() UUID

Devolve a instância UUID da característica.

properties() int

Devolve a máscara de bits props definida no momento da construção.

read() bytearray

Apenas função central. Lê o valor da característica a partir do par ligado. Devolve um bytearray com o valor mais recente. Num periférico, esta operação não tem efeito e devolve None.

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

Escreve na característica.

  • Num periférico, se PROP_NOTIFY estiver definido nas propriedades da característica, o valor é enviado como uma notificação GATT para o central ligado; caso contrário, o valor do atributo local é atualizado.

  • Num central, o valor é escrito no par remoto. Defina with_response=True para emitir um pedido de escrita e aguardar a confirmação do par, em vez de um comando de escrita.

data é qualquer objeto com protocolo buffer (bytes, bytearray, memoryview).

PROP_BROADCAST: int

A característica pode transmitir o seu valor (0x01).

PROP_READ: int

A característica suporta leituras (0x02).

PROP_WRITE_WO_RESP: int

A característica suporta escritas sem resposta (0x04).

PROP_WRITE: int

A característica suporta escritas com resposta (0x08).

PROP_NOTIFY: int

A característica pode enviar notificações para um central subscrito (0x10).

PROP_INDICATE: int

A característica pode enviar indicações (notificações com confirmação) para um central subscrito (0x20).

PROP_AUTH_SIGNED_WR: int

A característica suporta escritas assinadas autenticadas (0x40).

ATTR_CCCD: int

Adiciona um Client Characteristic Configuration Descriptor à característica (0x01). Necessário para que os clientes possam subscrever notificações/indicações.

class ubluepy.Descriptor(uuid: UUID)

Classe de atalho para representar descritores GATT. A implementação atual armazena apenas o UUID e não expõe métodos — é fornecida por compatibilidade futura com revisões futuras do módulo.

class ubluepy.Peripheral

O dispositivo Bluetooth LE local. A mesma classe é utilizada para funções de periférico e central; a função é selecionada pelos métodos que se chamam (advertise() seleciona periférico, connect() seleciona central).

addService(service: Service) None

Regista um Service (e todas as suas características anteriormente adicionadas) no servidor GATT local.

getServices() list

Devolve a lista de serviços atualmente registados neste Peripheral.

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

Inicia o anúncio em função de periférico.

device_name

Nome local completo anunciado no payload GAP.

services

Lista de instâncias Service a anunciar. O UUID de cada serviço é incluído no anúncio.

data

Payload de anúncio bruto opcional (bytes / bytearray) acrescentado ao cabeçalho gerado automaticamente. Use isto para payloads específicos do fornecedor ou de beacon, como Eddystone.

connectable

Quando True (predefinição), anuncia como dispositivo ligável e regista handlers de eventos GAP / GATTS para que o callback setConnectionHandler() configurado seja acionado na ligação, desconexão e escritas CCCD. Quando False, anuncia como beacon — não são anexados handlers e o dispositivo não pode ser ligado.

advertise_stop() None

Para qualquer anúncio em curso.

setConnectionHandler(func) None

Regista um callback invocado em eventos GAP e GATTS. O callback é chamado como func(event_id, conn_handle, data) onde event_id é um dos valores constants.EVT_GAP_CONNECTED, constants.EVT_GAP_DISCONNECTED ou constants.EVT_GATTS_WRITE, conn_handle é o handle de ligação do SoftDevice (ou handle de atributo para escritas GATTS), e data é o payload bruto do evento como bytearray (ou None para ligar / desligar).

setNotificationHandler(func) None

Regista um callback para eventos de notificação recebidos em função central.

withDelegate(delegate: DefaultDelegate) None

Anexa uma instância de DefaultDelegate para receber eventos GATT descodificados.

disconnect() None

Termina a ligação ativa (atualmente um stub sem efeito nesta compilação).

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

Apenas função central. Liga ao par com o endereço fornecido e descobre de forma síncrona os seus serviços primários e características. Bloqueia até que a ligação seja estabelecida e a descoberta esteja concluída; os serviços descobertos ficam então disponíveis via getServices().

addr

Endereço do par como cadeia de caracteres "xx:xx:xx:xx:xx:xx" de 17 caracteres (por exemplo, retirado de ScanEntry.addr()).

addr_type (apenas por palavra-chave)

Ou constants.ADDR_TYPE_PUBLIC (predefinição) ou constants.ADDR_TYPE_RANDOM_STATIC.

class ubluepy.Scanner

Observador GAP para descobrir dispositivos a anunciar nas proximidades. Disponível apenas quando o firmware é compilado com um SoftDevice com suporte central (s132 / s140).

scan(timeout: int) list

Executa uma análise passiva durante timeout milissegundos e devolve uma lista de instâncias ScanEntry — uma por relatório de anúncio recebido durante a janela.

class ubluepy.ScanEntry

Um único relatório de anúncio capturado por Scanner.scan(). As instâncias são devolvidas pelo scanner — não existe construtor público.

addr() str

Devolve o endereço do par como cadeia de caracteres "xx:xx:xx:xx:xx:xx" de 17 caracteres.

addr_type() int

Devolve o tipo de endereço do par (constants.ADDR_TYPE_PUBLIC ou constants.ADDR_TYPE_RANDOM_STATIC).

rssi() int

Devolve o indicador de intensidade de sinal em dBm.

getScanData() list

Descodifica o payload de anúncio numa lista de tuplos (ad_type, description, value). ad_type é o byte numérico do tipo AD (ver constants.ad_types), description é o nome da constante correspondente como cadeia de caracteres (ou None se o tipo for desconhecido), e value é o corpo do registo AD como bytearray.

class ubluepy.DefaultDelegate

Classe base para objetos passados a Peripheral.withDelegate(). Crie uma subclasse e substitua handleConnection() / handleNotification() para reagir a eventos GATT.

handleConnection() None

Chamado em eventos de ligação / desconexão GAP. A implementação predefinida está vazia.

handleNotification() None

Chamado em notificações GATT recebidas. A implementação predefinida está vazia.

Constantes

O atributo constants do módulo é um espaço de nomes que contém identificadores de eventos GAP/GATT, valores de tipo de endereço e o espaço de nomes aninhado ad_types.

ubluepy.constants: type

Contentor que expõe as constantes abaixo.

constants.EVT_GAP_CONNECTED: int

Valor de event_id do handler de ligação do Peripheral para ligação GAP (16).

constants.EVT_GAP_DISCONNECTED: int

Valor de event_id do handler de ligação do Peripheral para desconexão GAP (17).

constants.EVT_GATTS_WRITE: int

Valor de event_id do handler de ligação do Peripheral para uma escrita num atributo GATT local, incluindo escritas num CCCD que ativam/desativam notificações (80).

constants.UUID_CCCD: int

UUID Bluetooth padrão para o Client Characteristic Configuration Descriptor (0x2902).

constants.ADDR_TYPE_PUBLIC: int

Endereço de Dispositivo Bluetooth Público (0).

constants.ADDR_TYPE_RANDOM_STATIC: int

Endereço de Dispositivo Bluetooth Aleatório Estático (1).

constants.ad_types: type

Espaço de nomes das constantes de tipo AD de dados de anúncio da Bluetooth Core Specification Supplement. Cada nome mapeia para o tipo AD de 1 byte correspondente:

Nome

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