11.14. Riepilogo¶
Hai ripercorso il Bluetooth Low Energy dalla radio fino all’API Python usata per pilotarlo:
La motivazione – BLE e la risposta quando la camera vuole parlare con qualcosa nelle vicinanze senza alcuna infrastruttura tra loro. Un telefono nella stessa stanza, un dispositivo indossabile su un polso, un beacon su una parete. Corto raggio, nessuna rete a cui unirsi, quasi nessun consumo.
La radio – 2,4 GHz, 40 canali: tre per l’advertising, 37 per i dati di connessione, percorsi con hopping su una sequenza pseudo-casuale con evitamento adattivo dei canali rumorosi. Pacchetti brevi, radio per lo piu in sonno.
Il link layer – framing dei pacchetti, indirizzamento, schedulazione delle connessioni, ritrasmissione e cifratura a livello di link. Niente di tutto cio viene configurato da Python; tutto traspare nei parametri di connessione e nell’MTU.
Generic Access Profile (GAP) – scoperta e gestione delle connessioni. Quattro ruoli: peripheral e broadcaster (advertise), central e observer (scan). I payload di advertising trasportano il nome locale, gli UUID dei servizi, l’appearance e i dati specifici del produttore – 31 byte piu una scan response opzionale di 31 byte. L’intervallo di connessione, la peripheral latency e il supervision timeout governano come ci si sente in una connessione aperta.
Generic Attribute Profile (GATT) – un albero di servizi, ognuno contenente caratteristiche, ciascuna che opzionalmente contiene descrittori, identificati da UUID (a 16 bit per gli standard Bluetooth-SIG, a 128 bit per quelli personalizzati). Cinque operazioni: read e write (pull, avviate dal client), notify e indicate (push, avviate dal server, sottoscritte tramite il Client Characteristic Configuration Descriptor). La dimensione del payload e limitata dall’MTU negoziato.
L’API Python –
aiobletrasforma ogni pattern BLE in una coroutine asyncio. Un peripheral eaioble.advertise()in ciclo sulle connessioni, con oggettiService/Characteristiccostruiti una volta e registrati daaioble.register_services(). Un central eaioble.scan()per trovare un peer,connect()per aprire il collegamento,service()echaracteristic()per percorrere l’albero GATT remoto, poiread()/write()/subscribe()/notified()per i dati veri e propri. Le disconnessioni emergono comeaioble.DeviceDisconnectedErrorall’interno della coroutine che era in attesa.Canali L2CAP – la via di fuga per flussi di byte di grandi dimensioni che non si adattano al modello chiave/valore di GATT.
aioble.DeviceConnection.l2cap_accept()/l2cap_connect()aprono un canale per-applicazione sopra la connessione GAP, con invio / ricezione controllati a flusso di crediti e un MTU piu grande di quello che GATT puo trasportare.Pairing e cifratura – i collegamenti BLE sono pubblici per impostazione predefinita.
aioble.DeviceConnection.pair()avvia uno scambio di chiavi che produce un collegamento cifrato;bond=True(l’impostazione predefinita) persiste le chiavi cosi che le connessioni successive saltino l’handshake. Senzamitm=Truee una capacita di IO utilizzabile, la cifratura protegge dagli intercettatori passivi ma non da un reindirizzamento attivo durante il pairing originale.
Questo e sufficiente per scrivere applicazioni della camera che pubblicano lo stato come peripheral, leggono dati dei sensori come central, inviano valori live a un telefono via BLE, mettono in sicurezza il collegamento con un passo di pair-and-bond e – per il raro caso di trasferimento di grandi quantita di dati – escono da GATT verso un canale L2CAP.
11.14.1. Risoluzione dei problemi¶
I guasti BLE sono per lo piu disallineamenti tra cio che i due lati si aspettano, e un ispettore lato telefono e il modo piu rapido per vedere le aspettative di chi sono fuori posto. Lo strumento standard e nRF Connect for Mobile (Nordic Semiconductor, gratuito su Android e iOS): esegue la scansione, si connette, percorre il database GATT, legge e scrive le caratteristiche e si sottoscrive alle notifiche – cosi il comportamento lato camera puo essere testato isolatamente, senza scrivere affatto un’app companion.
Le modalita di guasto comuni:
«Il mio dispositivo appare nello scanner ma non si connette.» Il piu delle volte il pacchetto di advertising ha
connectable=False(modalita broadcaster), oppure una connessione precedente e ancora aperta e la cam ha gia superatoaioble.advertise(). Aggiungi istruzioni print attorno alla chiamata advertise per confermare.«exchange_mtu(512) e stato eseguito ma le mie notifiche sono ancora limitate a 20 byte.» L’MTU negoziato e
min(local, peer)– il telefono o la libreria central potrebbe non aver richiesto un MTU piu grande dal proprio lato, nel qual caso la connessione resta a 23. Ispezionamtudopo cheexchange_mtu()ritorna. Nota inoltre cheexchange_mtu()funziona solo una volta per connessione; chiamalo prima della prima operazione di grandi dimensioni.«Il pairing fallisce con un errore generico.» Due colpevoli abituali: il disallineamento della capacita di IO (richiedere
mitm=Truesu una cam che dichiaraio=3/ nessun input nessun output – non c’e modo di confermare il codice numerico, quindi il motore di pairing si arrende), e un orario di sistema molto sbagliato sulla cam quando il peer lo richiede. Imposta l’orologio conntptime.settime()prima del primo tentativo di pairing.«Le notifiche non arrivano mai al client.» Due cose da controllare, in ordine: (a) la caratteristica e stata dichiarata con
notify=True? – il bit della proprieta deve essere impostato sul lato server; (b) il client ha chiamatosubscribe()? – senza scrivere il Client Characteristic Configuration Descriptor (CCCD), al server viene comunicato che nessun client vuole le notifiche e le scarta silenziosamente.«Il nome pubblicizzato e troncato o mancante.» Il payload di advertising e di 31 byte, e i campi flags + service-UUID + appearance occupano ciascuno byte dall’inizio. Un
name=lungo piu diversi UUID di servizio va in overflow. O accorci il nome o usa la scansione attiva cosi che la scan response (altri 31 byte) trasporti l’eccedenza. nRF Connect mostra entrambe le meta separatamente, il che rende ovvia la suddivisione.«La connessione L2CAP solleva subito un’eccezione.» Di solito un disallineamento di PSM – entrambi i lati devono concordare lo stesso numero di PSM fuori banda. Una
L2CAPConnectionErrortrasporta il codice di stato Bluetooth come primo argomento; lo stato2(«PSM not supported») e l’indizio rivelatore.«Le connessioni in bonding scatenano comunque un handshake di pairing completo a ogni riconnessione.»
aioble.security.load_secrets()non e stato chiamato all’avvio. Senza di esso, le chiavi salvate sono sulla flash ma non vengono mai caricate in memoria, quindi l’identita del peer e sconosciuta e il pairing parte da zero ogni volta.
Quando tutto il resto fallisce, il modulo di piu basso livello bluetooth espone una callback IRQ che scatta per ogni evento sottostante; sottoscriversi ad essa brevemente e stampare gli eventi e l’equivalente di una traccia Wireshark per il lato cam.
11.14.2. Usare questo riferimento in seguito¶
Tratta i capitoli sul Bluetooth come materiale di riferimento; tornarci per il layout esatto del payload di advertising di un peripheral o per il flusso di scan-and-subscribe del central e l’uso previsto. Le pagine di riferimento aioble — BLE asincrono e bluetooth — Bluetooth a basso livello elencano ogni metodo, flag e costante in un unico posto quando la domanda e semplicemente «qual e il nome esatto di questa chiamata».