ubluepy — periferica e centrale Bluetooth LE#

Il modulo ubluepy è la vecchia API Bluetooth LE distribuita con il port nRF di MicroPython. È modellato approssimativamente sulla libreria Python Linux bluepy e si appoggia direttamente sul SoftDevice Nordic — non esiste alcun back-end portabile, quindi il modulo è disponibile solo sui target Nordic (l’Arduino Nano 33 BLE Sense nella gamma OpenMV). Le più recenti API bluetooth / aioble non sono abilitate in questa build, quindi ubluepy è l’unico modo per pilotare la radio integrata nel chip.

L’insieme di funzionalità disponibili dipende dal SoftDevice flashato dal firmware:

  • s140 (Nano 33 BLE Sense) — entrambi i ruoli, periferica e centrale (scanner). È quanto distribuisce il firmware OpenMV.

  • s132 — sia periferica che centrale.

  • s110 — solo periferica; i metodi scanner / connect sono esclusi dalla compilazione.

Esempio di periferica#

Pubblicizza il dispositivo come periferica Bluetooth LE con un singolo servizio di rilevamento ambientale e notifica una caratteristica di temperatura a ogni scrittura sul suo 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])

Esempio di centrale#

Esegue la scansione dei dispositivi in advertising nelle vicinanze per 100 ms e decodifica i dati di advertising di ciascun 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))

Contenuto del modulo#

Classi#

class ubluepy.UUID(value)#

Costruisce un UUID Bluetooth a 16 o 128 bit.

value

Uno tra:

  • int — un UUID numerico a 16 bit (UUID(0x180A)).

  • Stringa "0xXXXX" di 6 caratteri — un UUID a 16 bit, ad esempio UUID("0x181A").

  • Stringa "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" di 36 caratteri — un UUID completo a 128 bit. La porzione specifica del vendor viene registrata con il SoftDevice al momento della costruzione.

  • Un’altra istanza UUID — esegue una copia.

Qualsiasi altra lunghezza solleva ValueError("Invalid UUID string length").

binVal() int#

Restituisce i 16 bit meno significativi dell’UUID come int. Per gli UUID a 128 bit viene restituito solo il campo a 16 bit incorporato nell’UUID specifico del vendor (il valore completo a 128 bit è accessibile solo tramite l’indice specifico del vendor del SoftDevice).

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

Definisce un servizio GATT che verrà registrato con il SoftDevice quando viene aggiunto a un Peripheral.

uuid

Un’istanza UUID. Passare un oggetto non UUID solleva ValueError.

type

Uno tra Service.PRIMARY (predefinito) o Service.SECONDARY. Altri valori sollevano ValueError.

uuid() UUID#

Restituisce l’istanza UUID del servizio.

addCharacteristic(characteristic: Characteristic) None#

Registra una Characteristic con il servizio. L’handle GATT della caratteristica viene assegnato durante questa chiamata.

getCharacteristic(uuid: UUID) Characteristic | None#

Cerca per UUID una Characteristic precedentemente aggiunta. Restituisce l’istanza della caratteristica, oppure None se non viene trovata alcuna corrispondenza.

getCharacteristics() list#

Restituisce l’elenco di tutte le caratteristiche aggiunte al servizio.

PRIMARY: int#

Costante di tipo servizio per i servizi primari (1).

SECONDARY: int#

Costante di tipo servizio per i servizi secondari (2).

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

Definisce una caratteristica GATT. Aggiungila a un Service con Service.addCharacteristic() prima che il Peripheral genitore inizi l’advertising.

uuid

Un’istanza UUID.

props (solo keyword)

Maschera di bit di uno o più valori Characteristic.PROP_* che descrivono quali operazioni la caratteristica supporta.

attrs (solo keyword)

Maschera di bit di attributi GATT aggiuntivi. Usa Characteristic.ATTR_CCCD per associare un Client Characteristic Configuration Descriptor — necessario per far funzionare le caratteristiche PROP_NOTIFY / PROP_INDICATE.

uuid() UUID#

Restituisce l’istanza UUID della caratteristica.

properties() int#

Restituisce la maschera di bit props impostata al momento della costruzione.

read() bytearray#

Solo ruolo centrale. Legge il valore della caratteristica dal peer connesso. Restituisce un bytearray con il valore più recente. Su una periferica è un’operazione nulla e restituisce None.

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

Scrive sulla caratteristica.

  • Su una periferica, se PROP_NOTIFY è impostato nelle proprietà della caratteristica, il valore viene inviato come notifica GATT alla centrale connessa; altrimenti viene aggiornato il valore dell’attributo locale.

  • Su una centrale, il valore viene scritto sul peer remoto. Imposta with_response=True per emettere una richiesta di scrittura e attendere la conferma del peer invece di un comando di scrittura.

data è qualsiasi oggetto conforme al buffer protocol (bytes, bytearray, memoryview).

PROP_BROADCAST: int#

La caratteristica può trasmettere in broadcast il proprio valore (0x01).

PROP_READ: int#

La caratteristica supporta le letture (0x02).

PROP_WRITE_WO_RESP: int#

La caratteristica supporta le scritture senza risposta (0x04).

PROP_WRITE: int#

La caratteristica supporta le scritture con risposta (0x08).

PROP_NOTIFY: int#

La caratteristica può inviare notifiche a una centrale sottoscritta (0x10).

PROP_INDICATE: int#

La caratteristica può inviare indicazioni (notifiche con conferma) a una centrale sottoscritta (0x20).

PROP_AUTH_SIGNED_WR: int#

La caratteristica supporta scritture firmate autenticate (0x40).

ATTR_CCCD: int#

Aggiunge un Client Characteristic Configuration Descriptor alla caratteristica (0x01). Necessario affinché i client possano sottoscriversi a notifiche/indicazioni.

class ubluepy.Descriptor(uuid: UUID)#

Classe stub per rappresentare i descrittori GATT. L’implementazione attuale si limita a memorizzare l’UUID e non espone alcun metodo — è fornita per compatibilità futura con revisioni successive del modulo.

class ubluepy.Peripheral#

Il dispositivo Bluetooth LE locale. La stessa classe viene usata sia per il ruolo di periferica che per quello di centrale; il ruolo è selezionato in base ai metodi che si chiamano (advertise() seleziona la periferica, connect() seleziona la centrale).

addService(service: Service) None#

Registra un Service (e tutte le caratteristiche precedentemente aggiunte ad esso) con il server GATT locale.

getServices() list#

Restituisce l’elenco dei servizi attualmente registrati con questo Peripheral.

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

Avvia l’advertising nel ruolo di periferica.

device_name

Nome locale completo pubblicizzato nel payload GAP.

services

Elenco di istanze Service da pubblicizzare. L’UUID di ciascun servizio è incluso nell’advertising.

data

Payload di advertising raw opzionale (bytes / bytearray) accodato all’header generato automaticamente. Usalo per payload specifici del vendor o per beacon come Eddystone.

connectable

Quando è True (predefinito), pubblicizza il dispositivo come connettibile e registra i gestori di eventi GAP / GATTS in modo che il callback configurato con setConnectionHandler() venga invocato in caso di connessione, disconnessione e scritture CCCD. Quando è False, pubblicizza il dispositivo come beacon — non viene associato alcun gestore e il dispositivo non può essere connesso.

advertise_stop() None#

Interrompe qualsiasi advertising in corso.

setConnectionHandler(func) None#

Registra un callback invocato in caso di eventi GAP e GATTS. Il callback viene chiamato come func(event_id, conn_handle, data) dove event_id è uno tra i valori constants.EVT_GAP_CONNECTED, constants.EVT_GAP_DISCONNECTED o constants.EVT_GATTS_WRITE, conn_handle è l’handle di connessione del SoftDevice (o l’handle di attributo per le scritture GATTS) e data è il payload raw dell’evento come bytearray (oppure None per connessione / disconnessione).

setNotificationHandler(func) None#

Registra un callback per gli eventi di notifica ricevuti nel ruolo di centrale.

withDelegate(delegate: DefaultDelegate) None#

Associa un’istanza DefaultDelegate per ricevere gli eventi GATT decodificati.

disconnect() None#

Chiude la connessione attiva (attualmente uno stub a operazione nulla in questa build).

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

Solo ruolo centrale. Si connette al peer con l’indirizzo indicato e ne scopre in modo sincrono i servizi primari e le caratteristiche. Si blocca finché la connessione non è stabilita e la discovery non è completata; i servizi scoperti sono quindi disponibili tramite getServices().

addr

Indirizzo del peer come stringa "xx:xx:xx:xx:xx:xx" di 17 caratteri (ad esempio quella ottenuta da ScanEntry.addr()).

addr_type (solo keyword)

Uno tra constants.ADDR_TYPE_PUBLIC (predefinito) o constants.ADDR_TYPE_RANDOM_STATIC.

class ubluepy.Scanner#

Observer GAP per scoprire i dispositivi in advertising nelle vicinanze. Disponibile solo quando il firmware è compilato con un SoftDevice dotato di supporto centrale (s132 / s140).

scan(timeout: int) list#

Esegue una scansione passiva per timeout millisecondi e restituisce un elenco di istanze ScanEntry — una per ciascun report di advertising ricevuto durante la finestra.

class ubluepy.ScanEntry#

Un singolo report di advertising catturato da Scanner.scan(). Le istanze vengono restituite dallo scanner — non esiste un costruttore pubblico.

addr() str#

Restituisce l’indirizzo del peer come stringa "xx:xx:xx:xx:xx:xx" di 17 caratteri.

addr_type() int#

Restituisce il tipo di indirizzo del peer (constants.ADDR_TYPE_PUBLIC o constants.ADDR_TYPE_RANDOM_STATIC).

rssi() int#

Restituisce l’indicatore di intensità del segnale in dBm.

getScanData() list#

Decodifica il payload di advertising in un elenco di tuple (ad_type, description, value). ad_type è il byte numerico del tipo AD (vedi constants.ad_types), description è il nome della costante corrispondente come stringa (oppure None se il tipo è sconosciuto) e value è il corpo del record AD come bytearray.

class ubluepy.DefaultDelegate#

Classe base per gli oggetti passati a Peripheral.withDelegate(). Crea una sottoclasse ed esegui l’override di handleConnection() / handleNotification() per reagire agli eventi GATT.

handleConnection() None#

Chiamato in caso di eventi GAP di connessione / disconnessione. L’implementazione predefinita è vuota.

handleNotification() None#

Chiamato in caso di notifiche GATT in arrivo. L’implementazione predefinita è vuota.

Costanti#

L’attributo constants del modulo è uno spazio dei nomi contenente gli identificatori degli eventi GAP/GATT, i valori di tipo indirizzo e lo spazio dei nomi annidato ad_types.

ubluepy.constants: type#

Contenitore che espone le costanti elencate di seguito.

constants.EVT_GAP_CONNECTED: int#

Valore di event_id del gestore di connessione di Peripheral per la connessione GAP (16).

constants.EVT_GAP_DISCONNECTED: int#

Valore di event_id del gestore di connessione di Peripheral per la disconnessione GAP (17).

constants.EVT_GATTS_WRITE: int#

Valore di event_id del gestore di connessione di Peripheral per una scrittura su un attributo GATT locale, incluse le scritture su un CCCD che abilitano/disabilitano le notifiche (80).

constants.UUID_CCCD: int#

UUID Bluetooth standard per il Client Characteristic Configuration Descriptor (0x2902).

constants.ADDR_TYPE_PUBLIC: int#

Indirizzo di dispositivo Bluetooth pubblico (0).

constants.ADDR_TYPE_RANDOM_STATIC: int#

Indirizzo di dispositivo Bluetooth casuale statico (1).

constants.ad_types: type#

Spazio dei nomi delle costanti di tipo AD per i dati di advertising tratte dal Bluetooth Core Specification Supplement. Ogni nome corrisponde al relativo tipo AD a 1 byte:

Nome

Valore

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