bluetooth — Bluetooth a basso livello¶
Questo modulo fornisce un’interfaccia al controller Bluetooth integrato. Supporta Bluetooth Low Energy (BLE) nei ruoli Central, Peripheral, Broadcaster e Observer, oltre a GATT Server e Client e ai canali L2CAP orientati alla connessione. Un dispositivo può operare contemporaneamente in più ruoli. Sono supportati anche il pairing e il bonding.
Questa API è pensata per corrispondere al protocollo Bluetooth a basso livello e per fornire i blocchi costitutivi di astrazioni di più alto livello, come tipi di dispositivo specifici.
Suggerimento
Per la maggior parte delle applicazioni, è preferibile la libreria di più alto livello aioble, che fornisce un wrapper basato su asyncio attorno a questo modulo. Vedi aioble — BLE asincrono.
class BLE¶
- class bluetooth.BLE¶
Restituisce l’oggetto singleton BLE.
Configurazione
- active(active: bool | None = None, /) bool¶
Modifica opzionalmente lo stato attivo della radio BLE e restituisce lo stato corrente.
La radio deve essere resa attiva prima di usare qualsiasi altro metodo di questa classe.
- config(param: str, /) Any¶
- config(*, **kwargs: Any) None
Ottiene o imposta i valori di configurazione dell’interfaccia BLE. Per ottenere un valore, il nome del parametro deve essere indicato come stringa tra virgolette e si può interrogare un solo parametro alla volta. Per impostare i valori usare la sintassi a parole chiave; è possibile impostare uno o più parametri alla volta.
I valori attualmente supportati sono:
'mac': L’indirizzo attualmente in uso, a seconda della modalità di indirizzo corrente. Restituisce una tupla(addr_type, addr).Vedi
gap_scanper dettagli sul tipo di indirizzo.Questo può essere interrogato solo mentre l’interfaccia è attiva.
'addr_mode': Imposta la modalità di indirizzo. I valori sono:Valore
Nome
Comportamento
0x00PUBLIC
Usa l’indirizzo pubblico del controller.
0x01RANDOM
Usa un indirizzo statico generato.
0x02RPA
Usa indirizzi privati risolvibili.
0x03NRPA
Usa indirizzi privati non risolvibili.
Per impostazione predefinita l’interfaccia userà un indirizzo PUBLIC se disponibile, altrimenti userà un indirizzo RANDOM.
'gap_name': Ottiene/imposta il nome del dispositivo GAP usato dal servizio Generic Access (UUID0x1800), caratteristica Device Name (UUID0x2a00). Può essere impostato in qualsiasi momento e modificato più volte.'rxbuf': Ottiene/imposta la dimensione in byte del buffer interno usato per memorizzare gli eventi in arrivo. Questo buffer è globale per l’intero driver BLE e quindi gestisce i dati in arrivo per tutti gli eventi, incluse tutte le caratteristiche. Aumentarlo consente una migliore gestione dei dati in arrivo a raffica (per esempio i risultati di scansione) e la possibilità di ricevere valori di caratteristiche più grandi.'mtu': Ottiene/imposta l’MTU che verrà usato durante uno scambio ATT MTU. L’MTU risultante sarà il minimo tra questo e l’MTU del dispositivo remoto. Lo scambio ATT MTU non avverrà automaticamente (a meno che non sia il dispositivo remoto a iniziarlo) e deve essere avviato manualmente congattc_exchange_mtu. Usa l’evento_IRQ_MTU_EXCHANGEDper scoprire l’MTU di una determinata connessione.'bond': Imposta se il bonding sarà abilitato durante il pairing. Quando è abilitato, le richieste di pairing imposteranno il flag «bond» e le chiavi saranno memorizzate da entrambi i dispositivi.'mitm': Imposta se la protezione MITM è richiesta per il pairing.'io': Imposta le capacità di I/O di questo dispositivo.Le opzioni disponibili sono:
Costante
Valore
Capacità
_IO_CAPABILITY_DISPLAY_ONLY0
Solo display
_IO_CAPABILITY_DISPLAY_YESNO1
Display con input sì/no
_IO_CAPABILITY_KEYBOARD_ONLY2
Solo tastiera
_IO_CAPABILITY_NO_INPUT_OUTPUT3
Nessun input o output
_IO_CAPABILITY_KEYBOARD_DISPLAY4
Tastiera e display
'le_secure': Imposta se è richiesto il pairing «LE Secure». Il valore predefinito è false (cioè consente il «Legacy Pairing»).
Gestione degli eventi
- irq(handler: Callable[[int, Tuple], Any | None], /) None¶
Registra una callback per gli eventi dello stack BLE. L”handler accetta due argomenti,
event(che sarà uno dei codici sotto) edata(che è una tupla di valori specifica per l’evento).Nota: Come ottimizzazione per evitare allocazioni inutili, le voci
addr,adv_data,char_data,notify_dataeuuidnelle tuple sono istanze memoryview di sola lettura che puntano al ringbuffer interno dibluetoothe sono valide solo durante l’invocazione della funzione handler dell’IRQ. Se il programma deve salvare uno di questi valori per accedervi dopo che l’handler dell’IRQ è ritornato (per esempio salvandolo in un’istanza di classe o in una variabile globale), deve farne una copia, usandobytes()oppurebluetooth.UUID(), in questo modo:connected_addr = bytes(addr) # equivalently: adv_data, char_data, or notify_data matched_uuid = bluetooth.UUID(uuid)
Per esempio, l’handler dell’IRQ per un risultato di scansione potrebbe ispezionare
adv_dataper decidere se è il dispositivo corretto e solo allora copiare i dati dell’indirizzo da usare altrove nel programma. E per stampare i dati dall’interno dell’handler dell’IRQ sarà necessarioprint(bytes(addr)).Un handler tipicamente effettua il dispatch in base al codice dell’evento e spacchetta la tupla del payload specifico dell’evento:
def bt_irq(event, data): if event == _IRQ_CENTRAL_CONNECT: conn_handle, addr_type, addr = data ... elif event == _IRQ_SCAN_RESULT: addr_type, addr, adv_type, rssi, adv_data = data ...
Ogni codice di evento, il payload che fornisce e una breve descrizione sono elencati di seguito. Per gli eventi il cui campo
statusè menzionato,statusè0in caso di successo e un valore diverso da zero specifico dell’implementazione in caso di errore.Costante
Valore
Evento
Tupla del payload
_IRQ_CENTRAL_CONNECT1
Un central si è connesso a questo peripheral.
(conn_handle, addr_type, addr)_IRQ_CENTRAL_DISCONNECT2
Un central si è disconnesso da questo peripheral.
(conn_handle, addr_type, addr)_IRQ_GATTS_WRITE3
Un client connesso ha scritto su una caratteristica o un descrittore locale. Usa
gatts_readper recuperare il nuovo valore.(conn_handle, attr_handle)_IRQ_GATTS_READ_REQUEST4
Un client connesso ha emesso una lettura. Restituisci un codice di errore diverso da zero dalla tabella sottostante per negare la lettura, oppure
0/Noneper accettarla.(conn_handle, attr_handle)_IRQ_SCAN_RESULT5
È stato ricevuto un singolo pacchetto di advertising durante una scansione attiva.
(addr_type, addr, adv_type, rssi, adv_data)_IRQ_SCAN_DONE6
La scansione corrente è terminata, perché è trascorsa la durata configurata oppure perché è stato chiamato
gap_scan(None).()_IRQ_PERIPHERAL_CONNECT7
Una
gap_connectemessa in precedenza è andata a buon fine.(conn_handle, addr_type, addr)_IRQ_PERIPHERAL_DISCONNECT8
Un peripheral connesso si è disconnesso.
(conn_handle, addr_type, addr)_IRQ_GATTC_SERVICE_RESULT9
È stato trovato un servizio da
gattc_discover_services.(conn_handle, start_handle, end_handle, uuid)_IRQ_GATTC_SERVICE_DONE10
La scoperta dei servizi è terminata.
(conn_handle, status)_IRQ_GATTC_CHARACTERISTIC_RESULT11
È stata trovata una caratteristica da
gattc_discover_characteristics.(conn_handle, end_handle, value_handle, properties, uuid)_IRQ_GATTC_CHARACTERISTIC_DONE12
La scoperta delle caratteristiche è terminata.
(conn_handle, status)_IRQ_GATTC_DESCRIPTOR_RESULT13
È stato trovato un descrittore da
gattc_discover_descriptors.(conn_handle, dsc_handle, uuid)_IRQ_GATTC_DESCRIPTOR_DONE14
La scoperta dei descrittori è terminata.
(conn_handle, status)_IRQ_GATTC_READ_RESULT15
Una
gattc_reademessa in precedenza ha restituito dati.(conn_handle, value_handle, char_data)_IRQ_GATTC_READ_DONE16
Una
gattc_reademessa in precedenza è terminata.(conn_handle, value_handle, status)_IRQ_GATTC_WRITE_DONE17
Una
gattc_writeemessa in precedenza è stata confermata.(conn_handle, value_handle, status)_IRQ_GATTC_NOTIFY18
Un server remoto ha inviato una notifica (non confermata).
(conn_handle, value_handle, notify_data)_IRQ_GATTC_INDICATE19
Un server remoto ha inviato un’indicazione (confermata).
(conn_handle, value_handle, notify_data)_IRQ_GATTS_INDICATE_DONE20
Un’indicazione inviata in precedenza è stata confermata dal client (o è andata in timeout).
(conn_handle, value_handle, status)_IRQ_MTU_EXCHANGED21
Uno scambio ATT MTU è stato completato (avviato da entrambi i lati).
(conn_handle, mtu)_IRQ_L2CAP_ACCEPT22
Un dispositivo remoto ha richiesto una connessione L2CAP su un PSM su cui questo dispositivo è in ascolto. Restituisci un intero diverso da zero per rifiutare, oppure
0/Noneper accettare.(conn_handle, cid, psm, our_mtu, peer_mtu)_IRQ_L2CAP_CONNECT23
Un canale L2CAP è ora stabilito, sia accettando una richiesta in arrivo sia completando una
l2cap_connectin uscita.(conn_handle, cid, psm, our_mtu, peer_mtu)_IRQ_L2CAP_DISCONNECT24
Un canale L2CAP è stato disconnesso.
statusè0per una disconnessione pulita, oppure diverso da zero se un tentativo di connessione in uscita è fallito.(conn_handle, cid, psm, status)_IRQ_L2CAP_RECV25
Sono arrivati dati su un canale L2CAP. Chiama
l2cap_recvintoper leggerli.(conn_handle, cid)_IRQ_L2CAP_SEND_READY26
Una precedente
l2cap_sendche aveva restituitoFalsesi è svuotata e il canale è di nuovo pronto. Unostatusdiverso da zero significa che il buffer di trasmissione è andato in overflow e l’applicazione deve reinviare i dati.(conn_handle, cid, status)_IRQ_CONNECTION_UPDATE27
Il dispositivo remoto ha aggiornato i parametri di connessione (interval, latency, supervision timeout).
(conn_handle, conn_interval, conn_latency, supervision_timeout, status)_IRQ_ENCRYPTION_UPDATE28
Lo stato di crittografia di una connessione è cambiato, tipicamente dopo il completamento del pairing o del bonding.
(conn_handle, encrypted, authenticated, bonded, key_size)_IRQ_GET_SECRET29
Lo stack sta richiedendo un segreto di bonding memorizzato. Se
keyèNone, restituisci il valore memorizzato di posizioneindexdi tiposec_type; altrimenti restituisci il valore associato alla coppia(sec_type, key)indicata. RestituisciNonese non c’è nulla di memorizzato.(sec_type, index, key)_IRQ_SET_SECRET30
Lo stack chiede all’applicazione di rendere persistente un segreto di bonding. Restituisci
Trueuna volta memorizzato.(sec_type, key, value)_IRQ_PASSKEY_ACTION31
È richiesta un’azione di passkey come parte del pairing. Rispondi usando
gap_passkey; vedi la tabella delle azioni di passkey sottostante per le azioni possibili.(conn_handle, action, passkey)Per l’evento
_IRQ_GATTS_READ_REQUEST, i codici di ritorno disponibili sono:Costante
Valore
Significato
_GATTS_NO_ERROR0x00Accetta la lettura.
_GATTS_ERROR_READ_NOT_PERMITTED0x02Lettura non consentita.
_GATTS_ERROR_WRITE_NOT_PERMITTED0x03Scrittura non consentita.
_GATTS_ERROR_INSUFFICIENT_AUTHENTICATION0x05Il client non è autenticato.
_GATTS_ERROR_INSUFFICIENT_AUTHORIZATION0x08Il client non è autorizzato.
_GATTS_ERROR_INSUFFICIENT_ENCRYPTION0x0fIl link non è crittografato.
Per l’evento
_IRQ_PASSKEY_ACTION, le azioni disponibili sono:Costante
Valore
Significato
_PASSKEY_ACTION_NONE0
Nessuna azione richiesta.
_PASSKEY_ACTION_INPUT2
Chiedi all’utente di inserire la passkey mostrata sul dispositivo remoto.
_PASSKEY_ACTION_DISPLAY3
Mostra una passkey di 6 cifre che il dispositivo remoto dovrà inserire.
_PASSKEY_ACTION_NUMERIC_COMPARISON4
Conferma che la passkey corrisponde a quella mostrata sul dispositivo remoto.
Per risparmiare spazio nel firmware, queste costanti non sono incluse nel modulo
bluetooth. Aggiungi al tuo programma quelle che ti servono dagli elenchi sopra.
Ruolo Broadcaster (Advertiser)
- gap_advertise(interval_us: int | None, adv_data: bytes | None = None, *, resp_data: bytes | None = None, connectable: bool = True) None¶
Avvia l’advertising all’intervallo specificato (in microsecondi). Questo intervallo verrà arrotondato per difetto al multiplo di 625us più vicino. Per interrompere l’advertising, imposta interval_us a
None.adv_data e resp_data possono essere di qualsiasi tipo che implementi il buffer protocol (per esempio
bytes,bytearray,str). adv_data è incluso in tutti i broadcast, mentre resp_data viene inviato in risposta a una scansione attiva.Nota: se adv_data (o resp_data) è
None, allora verranno riutilizzati i dati passati alla precedente chiamata agap_advertise. Questo consente a un broadcaster di riprendere l’advertising con il sologap_advertise(interval_us). Per cancellare il payload di advertising passa unbytesvuoto, cioèb''.
Ruolo Observer (Scanner)
- gap_scan(duration_ms: int | None, interval_us: int = 1280000, window_us: int = 11250, active: bool = False, /) None¶
Esegue un’operazione di scansione che dura per la durata specificata (in millisecondi).
Per eseguire la scansione a tempo indefinito, imposta duration_ms a
0.Per interrompere la scansione, imposta duration_ms a
None.Usa interval_us e window_us per configurare opzionalmente il duty cycle. Lo scanner verrà eseguito per window_us microsecondi ogni interval_us microsecondi per un totale di duration_ms millisecondi. L’intervallo e la finestra predefiniti sono rispettivamente 1,28 secondi e 11,25 millisecondi (scansione in background).
Per ogni risultato di scansione verrà generato l’evento
_IRQ_SCAN_RESULT, con dati dell’evento(addr_type, addr, adv_type, rssi, adv_data).I valori di
addr_typeindicano indirizzi pubblici o casuali:Valore
Nome
Significato
0x00PUBLIC
Indirizzo di dispositivo pubblico.
0x01RANDOM
Indirizzo casuale (statico, RPA o NRPA; il tipo è codificato nell’indirizzo stesso).
I valori di
adv_typecorrispondono alla Bluetooth Specification:Valore
Nome
Significato
0x00ADV_IND
Advertising non diretto, connettibile e scansionabile.
0x01ADV_DIRECT_IND
Advertising diretto e connettibile.
0x02ADV_SCAN_IND
Advertising non diretto e scansionabile.
0x03ADV_NONCONN_IND
Advertising non diretto e non connettibile.
0x04SCAN_RSP
Risposta alla scansione.
activepuò essere impostato aTruese vuoi ricevere le risposte di scansione nei risultati.Quando la scansione viene interrotta (per il termine della durata o quando viene esplicitamente fermata), verrà generato l’evento
_IRQ_SCAN_DONE.
Ruolo Central
Un dispositivo central può connettersi a peripheral che ha scoperto usando il ruolo observer (vedi
gap_scan) oppure con un indirizzo noto.- gap_connect(addr_type: int | None, addr: bytes | None = None, scan_duration_ms: int = 2000, min_conn_interval_us: int | None = None, max_conn_interval_us: int | None = None, /) None¶
Si connette a un peripheral.
Vedi
gap_scanper dettagli sui tipi di indirizzo.Per annullare anticipatamente un tentativo di connessione in sospeso, chiama
gap_connect(None).In caso di successo, verrà generato l’evento
_IRQ_PERIPHERAL_CONNECT. Se si annulla un tentativo di connessione, verrà generato l’evento_IRQ_PERIPHERAL_DISCONNECT.Il dispositivo attenderà fino a scan_duration_ms per ricevere un payload di advertising dal dispositivo.
L’intervallo di connessione può essere configurato in microsecondi usando min_conn_interval_us e/o max_conn_interval_us. Altrimenti verrà scelto un intervallo predefinito, tipicamente compreso tra 30000 e 50000 microsecondi. Un intervallo più breve aumenterà il throughput, a scapito del consumo energetico.
Ruolo Peripheral
Ci si aspetta che un dispositivo peripheral invii advertising connettibili (vedi
gap_advertise). Di solito agirà come GATT server, avendo prima registrato servizi e caratteristiche usandogatts_register_services.Quando un central si connette, verrà generato l’evento
_IRQ_CENTRAL_CONNECT.Ruoli Central e Peripheral
- gap_disconnect(conn_handle: int, /) bool¶
Disconnette l’handle di connessione specificato. Può trattarsi di un central che si è connesso a questo dispositivo (se agisce come peripheral) oppure di un peripheral a cui questo dispositivo si era connesso in precedenza (se agisce come central).
In caso di successo, verrà generato l’evento
_IRQ_PERIPHERAL_DISCONNECTo_IRQ_CENTRAL_DISCONNECT.Restituisce
Falsese l’handle di connessione non era connesso, altrimentiTrue.
GATT Server
Un GATT server ha un insieme di servizi registrati. Ogni servizio può contenere caratteristiche, ognuna delle quali ha un valore. Le caratteristiche possono anche contenere descrittori, che a loro volta hanno valori.
Questi valori sono memorizzati localmente e vi si accede tramite il loro «value handle» generato durante la registrazione del servizio. Possono anche essere letti o scritti da un dispositivo client remoto. Inoltre, un server può «notificare» una caratteristica a un client connesso tramite un handle di connessione.
Un dispositivo nel ruolo central o peripheral può funzionare come GATT server, tuttavia nella maggior parte dei casi sarà più comune che sia un dispositivo peripheral ad agire come server.
Le caratteristiche e i descrittori hanno una dimensione massima predefinita di 20 byte (l’ATT MTU predefinito di 23 byte meno un header ATT di 3 byte; un MTU negoziato più grande non aumenta di per sé questo limite). Tutto ciò che vi viene scritto da un client sarà troncato a questa lunghezza. Tuttavia, qualsiasi scrittura locale aumenterà la dimensione massima, quindi se vuoi consentire scritture più grandi da un client verso una determinata caratteristica, usa
gatts_writedopo la registrazione, per esempiogatts_write(char_handle, bytes(100)).- gatts_register_services(services_definition: Sequence[Sequence], /) Sequence[Sequence[int]]¶
Configura il server con i servizi specificati, sostituendo eventuali servizi esistenti.
services_definition è una lista di services, dove ogni service è una tupla di due elementi contenente un UUID e una lista di characteristics.
Ogni characteristic è una tupla di due o tre elementi contenente un UUID, un valore flags e, opzionalmente, una lista di descriptors.
Ogni descriptor è una tupla di due elementi contenente un UUID e un valore flags.
I flags sono una combinazione OR bit a bit dei flag definiti sotto. Impostano sia il comportamento della caratteristica (o del descrittore) sia i requisiti di sicurezza e privacy.
Il valore restituito è una lista (un elemento per servizio) di tuple (ogni elemento è un value handle). Gli handle delle caratteristiche e dei descrittori sono appiattiti nella stessa tupla, nell’ordine in cui sono definiti.
L’esempio seguente registra due servizi (Heart Rate e Nordic UART):
bt = bluetooth.BLE() bt.active(True) # Heart Rate service: one Heart Rate Measurement characteristic. HR_SERVICE = ( bluetooth.UUID(0x180D), ( (bluetooth.UUID(0x2A37), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY), ), ) # Nordic UART service: a TX characteristic the client subscribes # to for notifications, and an RX characteristic it writes to. UART_SERVICE = ( bluetooth.UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E'), ( (bluetooth.UUID('6E400003-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY), (bluetooth.UUID('6E400002-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_WRITE), ), ) ((hr,), (tx, rx)) = bt.gatts_register_services( (HR_SERVICE, UART_SERVICE), )
I tre value handle (
hr,tx,rx) possono essere usati congatts_read,gatts_write,gatts_notifyegatts_indicate.Nota: L’advertising deve essere interrotto prima di registrare i servizi.
I flag disponibili per caratteristiche e descrittori sono:
Costante
Valore
Significato
_FLAG_BROADCAST0x0001La caratteristica può essere trasmessa in broadcast.
_FLAG_READ0x0002Il client può leggere il valore.
_FLAG_WRITE_NO_RESPONSE0x0004Il client può scrivere senza attendere una risposta.
_FLAG_WRITE0x0008Il client può scrivere con una risposta confermata.
_FLAG_NOTIFY0x0010Il server può inviare notifiche (non confermate).
_FLAG_INDICATE0x0020Il server può inviare indicazioni (confermate).
_FLAG_AUTHENTICATED_SIGNED_WRITE0x0040Il client può emettere scritture firmate.
_FLAG_AUX_WRITE0x0100Proprietà estese: sono consentite scritture in coda/affidabili.
_FLAG_READ_ENCRYPTED0x0200La lettura richiede un link crittografato.
_FLAG_READ_AUTHENTICATED0x0400La lettura richiede un link autenticato (protetto da MITM).
_FLAG_READ_AUTHORIZED0x0800La lettura richiede un’autorizzazione a livello applicativo.
_FLAG_WRITE_ENCRYPTED0x1000La scrittura richiede un link crittografato.
_FLAG_WRITE_AUTHENTICATED0x2000La scrittura richiede un link autenticato (protetto da MITM).
_FLAG_WRITE_AUTHORIZED0x4000La scrittura richiede un’autorizzazione a livello applicativo.
Come per le costanti di evento sopra, questi flag non sono forniti dal modulo
bluetooth; copia nel tuo programma quelli che ti servono.
- gatts_read(value_handle: int, /) bytes¶
Legge il valore locale per questo handle (che è stato scritto da
gatts_writeoppure da un client remoto).
- gatts_write(value_handle: int, data: bytes, send_update: bool = False, /) None¶
Scrive il valore locale per questo handle, che può essere letto da un client.
Se send_update è
True, allora qualsiasi client iscritto verrà notificato (o indicato, a seconda di ciò a cui è iscritto e di quali operazioni la caratteristica supporta) riguardo a questa scrittura.
- gatts_notify(conn_handle: int, value_handle: int, data: bytes | None = None, /) None¶
Invia una richiesta di notifica a un client connesso.
Se data è
None(il valore predefinito), allora verrà inviato il valore locale corrente (come impostato congatts_write).Altrimenti, se data non è
None, quel valore viene inviato al client come parte della notifica. Il valore locale non verrà modificato.Nota: La notifica verrà inviata indipendentemente dallo stato di iscrizione del client a questa caratteristica.
- gatts_indicate(conn_handle: int, value_handle: int, data: bytes | None = None, /) None¶
Invia una richiesta di indicazione a un client connesso.
Se data è
None(il valore predefinito), allora verrà inviato il valore locale corrente (come impostato congatts_write).Altrimenti, se data non è
None, quel valore viene inviato al client come parte dell’indicazione. Il valore locale non verrà modificato.Alla conferma (o in caso di fallimento, per esempio timeout), verrà generato l’evento
_IRQ_GATTS_INDICATE_DONE.Nota: L’indicazione verrà inviata indipendentemente dallo stato di iscrizione del client a questa caratteristica.
- gatts_set_buffer(value_handle: int, len: int, append: bool = False, /) None¶
Imposta la dimensione del buffer interno per un valore, in byte. Questo limiterà la scrittura più grande che può essere ricevuta. Il valore predefinito è 20 byte (ATT MTU predefinito di 23 meno l’header ATT di 3 byte).
Impostare append a
Truefarà sì che tutte le scritture remote vengano accodate al valore corrente, anziché sostituirlo. In questo modo possono essere bufferizzati al massimo len byte. Quando usigatts_read, il valore verrà cancellato dopo la lettura. Questa funzionalità è utile quando si implementa qualcosa come il Nordic UART Service.
GATT Client
Un GATT client può scoprire e leggere/scrivere caratteristiche su un GATT server remoto.
È più comune che un dispositivo nel ruolo central agisca come GATT client, tuttavia è anche possibile che un peripheral agisca come client per scoprire informazioni sul central che si è connesso ad esso (per esempio per leggere il nome del dispositivo dal device information service).
- gattc_discover_services(conn_handle: int, uuid: UUID | None = None, /) None¶
Interroga un server connesso per i suoi servizi.
Specifica opzionalmente un uuid di servizio per interrogare solo quel servizio.
Per ogni servizio scoperto, verrà generato l’evento
_IRQ_GATTC_SERVICE_RESULT, seguito da_IRQ_GATTC_SERVICE_DONEal completamento.
- gattc_discover_characteristics(conn_handle: int, start_handle: int, end_handle: int, uuid: UUID | None = None, /) None¶
Interroga un server connesso per le caratteristiche nell’intervallo specificato.
Specifica opzionalmente un uuid di caratteristica per interrogare solo quella caratteristica.
Passando
start_handle=1edend_handle=0xffffsi copre l’intero intervallo di attribute handle del GATT, quindi questa combinazione di fatto cerca in ogni servizio del dispositivo remoto.Per ogni caratteristica scoperta, verrà generato l’evento
_IRQ_GATTC_CHARACTERISTIC_RESULT, seguito da_IRQ_GATTC_CHARACTERISTIC_DONEal completamento.
- gattc_discover_descriptors(conn_handle: int, start_handle: int, end_handle: int, /) None¶
Interroga un server connesso per i descrittori nell’intervallo specificato.
Per ogni descrittore scoperto, verrà generato l’evento
_IRQ_GATTC_DESCRIPTOR_RESULT, seguito da_IRQ_GATTC_DESCRIPTOR_DONEal completamento.
- gattc_read(conn_handle: int, value_handle: int, /) None¶
Emette una lettura remota verso un server connesso per l’handle di caratteristica o descrittore specificato.
Quando un valore è disponibile, verrà generato l’evento
_IRQ_GATTC_READ_RESULT, seguito da_IRQ_GATTC_READ_DONEal completamento.
- gattc_write(conn_handle: int, value_handle: int, data: bytes, mode: int = 0, /) None¶
Emette una scrittura remota verso un server connesso per l’handle di caratteristica o descrittore specificato.
L’argomento mode specifica il comportamento della scrittura; i valori attualmente supportati sono:
mode=0(predefinito) è una scrittura senza risposta: la scrittura verrà inviata al server remoto ma non verrà restituita alcuna conferma e non verrà generato alcun evento.mode=1è una scrittura con risposta: al server remoto viene richiesto di inviare una risposta/conferma di aver ricevuto i dati.
Se viene ricevuta una risposta dal server remoto, verrà generato l’evento
_IRQ_GATTC_WRITE_DONE.
- gattc_exchange_mtu(conn_handle: int, /) None¶
Avvia lo scambio MTU con un server connesso, usando l’MTU preferito impostato con
BLE.config(mtu=value).L’evento
_IRQ_MTU_EXCHANGEDverrà generato al completamento dello scambio MTU.Lo scambio MTU è tipicamente avviato dal central; NimBLE supporta entrambi i ruoli.
Canali L2CAP orientati alla connessione
Questa funzionalità consente uno scambio di dati simile ai socket tra due dispositivi BLE. Una volta che i dispositivi sono connessi tramite GAP, ciascun dispositivo può mettersi in ascolto affinché l’altro si connetta su un PSM numerico (Protocol/Service Multiplexer).
Può essere attivo un solo canale L2CAP alla volta (cioè non è possibile connettersi mentre si è in ascolto).
I canali L2CAP attivi sono identificati dall’handle di connessione su cui sono stati stabiliti e da un CID (channel ID).
I canali orientati alla connessione hanno un controllo di flusso integrato basato su crediti. A differenza di ATT, dove i dispositivi negoziano un MTU condiviso, sia il dispositivo in ascolto sia quello che si connette impostano ciascuno un MTU indipendente che limita la quantità massima di dati in sospeso che il dispositivo remoto può inviare prima che siano completamente consumati in
l2cap_recvinto.- l2cap_listen(psm: int, mtu: int, /) None¶
Inizia a mettersi in ascolto delle richieste di canale L2CAP in arrivo sul psm specificato, con l’MTU locale impostato a mtu.
Quando un dispositivo remoto avvia una connessione, verrà generato l’evento
_IRQ_L2CAP_ACCEPT, che dà al server in ascolto la possibilità di rifiutare la connessione in arrivo (restituendo un intero diverso da zero).Una volta accettata la connessione, verrà generato l’evento
_IRQ_L2CAP_CONNECT, consentendo al server di ottenere il channel ID (CID) e l’MTU locale e remoto.Nota: Attualmente non è possibile interrompere l’ascolto.
- l2cap_connect(conn_handle: int, psm: int, mtu: int, /) None¶
Si connette a un peer in ascolto sul psm specificato, con l’MTU locale impostato a mtu.
In caso di connessione riuscita, verrà generato l’evento
_IRQ_L2CAP_CONNECT, consentendo al client di ottenere il CID e l’MTU locale e remoto (peer).Una connessione non riuscita genererà l’evento
_IRQ_L2CAP_DISCONNECTcon uno status diverso da zero.
- l2cap_disconnect(conn_handle: int, cid: int, /) None¶
Disconnette un canale L2CAP attivo con i conn_handle e cid specificati.
- l2cap_send(conn_handle: int, cid: int, buf: bytes, /) bool¶
Invia il buf specificato (che deve supportare il buffer protocol) sul canale L2CAP identificato da conn_handle e cid.
Il buffer deve soddisfare entrambi i limiti: non deve superare l’MTU remoto (peer) e non deve superare il doppio dell’MTU locale.
Questo restituirà
Falsese il canale è ora «in stallo», il che significa chel2cap_sendnon deve essere chiamato di nuovo finché non viene ricevuto l’evento_IRQ_L2CAP_SEND_READY(che avverrà quando il dispositivo remoto concederà più crediti, tipicamente dopo aver ricevuto ed elaborato i dati).
- l2cap_recvinto(conn_handle: int, cid: int, buf: Any | None, /) int¶
Riceve dati dai conn_handle e cid specificati nel buf fornito (che deve supportare il buffer protocol, per esempio bytearray o memoryview).
Restituisce il numero di byte letti dal canale.
Se buf è
None, restituisce il numero di byte disponibili.Nota: Dopo aver ricevuto l’evento
_IRQ_L2CAP_RECV, l’applicazione dovrebbe continuare a chiamarel2cap_recvintofinché non ci sono più byte disponibili nel buffer di ricezione (tipicamente fino alla dimensione dell’MTU remoto (peer)).Finché il buffer di ricezione non è vuoto, al dispositivo remoto non verranno concessi più crediti di canale e non potrà inviare altri dati.
Pairing e Bonding
Il pairing consente di crittografare e autenticare una connessione tramite lo scambio di segreti (con protezione MITM opzionale tramite autenticazione passkey).
Il bonding è il processo di memorizzazione di quei segreti in una memoria non volatile. Quando è effettuato il bonding, un dispositivo è in grado di risolvere un indirizzo privato risolvibile (RPA) di un altro dispositivo in base alla identity resolving key (IRK) memorizzata. Per supportare il bonding, un’applicazione deve implementare gli eventi
_IRQ_GET_SECRETe_IRQ_SET_SECRET.- gap_pair(conn_handle: int, /) None¶
Avvia il pairing con il dispositivo remoto.
Prima di chiamare questo metodo, assicurati che le opzioni di configurazione
io,mitm,le_secureebondsiano impostate (tramiteconfig).In caso di pairing riuscito, verrà generato l’evento
_IRQ_ENCRYPTION_UPDATE.
- gap_passkey(conn_handle: int, action: int, passkey: int, /) None¶
Risponde a un evento
_IRQ_PASSKEY_ACTIONper i conn_handle e action specificati. Il significato di passkey dipende da action (che a sua volta dipende dalla capacità di I/O configurata):Azione
Risposta passkey richiesta
_PASSKEY_ACTION_INPUTLa passkey che l’utente legge dal dispositivo remoto.
_PASSKEY_ACTION_DISPLAYUna passkey casuale di 6 cifre generata localmente e mostrata all’utente.
_PASSKEY_ACTION_NUMERIC_COMPARISON1per accettare la passkey mostrata nell’evento_IRQ_PASSKEY_ACTION, oppure0per annullare il pairing.
class UUID¶
- class bluetooth.UUID(value: int | bytes | str, /)¶
Crea un’istanza UUID con il
valuespecificato. Bluetooth usa tre larghezze di UUID;UUIDaccetta tutte:Larghezza UUID
Tipi di
valueaccettatiEsempio
16 bit
into un buffer di 2 byte (little-endian)UUID(0x2908)oppureUUID(b'\x08\x29')32 bit
buffer di 4 byte (little-endian)
UUID(b'\x08\x29\x00\x00')128 bit
buffer di 16 byte o una stringa con trattini
UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E')Gli UUID a 16 e 32 bit sono tipicamente identificatori allocati dal SIG (vedi i numeri assegnati Bluetooth); gli UUID a 128 bit sono normalmente definiti dal vendor.