11.14. Sammanfattning¶
Du har gått igenom Bluetooth Low Energy från radion upp till det Python-API som används för att driva den:
Motivationen – BLE är svaret när kameran vill prata med något i närheten utan någon infrastruktur mellan dem. En telefon i samma rum, en bärbar enhet på en handled, en beacon på en vägg. Kort räckvidd, inget nätverk att ansluta sig till, nästan ingen effekt.
Radion – 2,4 GHz, 40 kanaler: tre för annonsering, 37 för anslutningsdata, hoppade i en pseudoslumpmässig sekvens med adaptivt undvikande av brusiga kanaler. Korta paket, mestadels sovande radioenheter.
Länklagret – paketinramning, adressering, anslutningsschemaläggning, omsändning och länklagerskryptering. Inget av det konfigureras från Python; allt syns igenom i anslutningsparametrarna och MTU:n.
Generic Access Profile (GAP) – upptäckt och anslutningshantering. Fyra roller: peripheral och broadcaster (annonserar), central och observer (skannar). Annonseringsnyttolaster bär det lokala namnet, tjänste-UUID:n, utseende och tillverkarspecifika data – 31 bytes plus ett valfritt 31-bytes skanningssvar. Anslutningsintervallet, peripheral-latensen och övervakningstimeouten styr hur en öppen anslutning känns.
Generic Attribute Profile (GATT) – ett träd av tjänster, var och en med karakteristiker, var och en eventuellt med deskriptorer, identifierade av UUID:n (16-bitars för Bluetooth-SIG-standarder, 128-bitars för anpassade). Fem operationer: read och write (hämta, klientinitierad), notify och indicate (skicka, serverinitierad, prenumererad via Client Characteristic Configuration Descriptor). Nyttolaststorleken begränsas av den förhandlade MTU:n.
Python-API:t –
aiobleförvandlar varje BLE-mönster till en asyncio-coroutine. En peripheral äraioble.advertise()som loopar över anslutningar, medService- /Characteristic-objekt byggda en gång och bekräftade avaioble.register_services(). En central äraioble.scan()för att hitta en motpart,connect()för att öppna länken,service()ochcharacteristic()för att vandra genom det fjärranslutna GATT-trädet, sedanread()/write()/subscribe()/notified()för själva datan. Frånkopplingar dyker upp somaioble.DeviceDisconnectedErrorinuti den coroutine som väntade.L2CAP-kanaler – nödutgången för stora byteströmmar som inte passar GATT:s nyckel/värde-modell.
aioble.DeviceConnection.l2cap_accept()/l2cap_connect()öppnar en kanal per applikation ovanpå GAP-anslutningen, med kreditflödesstyrd send / recv och en större MTU än GATT kan bära.Parkoppling och kryptering – BLE-länkar är offentliga som standard.
aioble.DeviceConnection.pair()initierar ett nyckelutbyte som producerar en krypterad länk;bond=True(standard) sparar nycklarna så att efterföljande anslutningar hoppar över handskakningen. Utanmitm=Trueoch en användbar IO-förmåga skyddar kryptering mot passiva avlyssnare men inte mot en aktiv omdirigering under den ursprungliga parkopplingen.
Det räcker för att skriva kameraapplikationer som publicerar status som en peripheral, läser sensordata som en central, skickar livevärden till en telefon över BLE, säkrar länken med ett parkopplings-och-bindningssteg och – för det sällsynta fallet med massöverföring – kliver av GATT in i en L2CAP-kanal.
11.14.1. Felsökning¶
BLE-fel är mestadels diskrepanser mellan vad de två sidorna förväntar sig, och en inspektör på telefonsidan är det snabbaste sättet att se vems förväntningar som är fel. Standardverktyget är nRF Connect for Mobile (Nordic Semiconductor, gratis på Android och iOS): det skannar, ansluter, vandrar genom GATT-databasen, läser och skriver karakteristiker och prenumererar på aviseringar – så beteendet på kamerasidan kan testas isolerat, utan att skriva någon medföljande app alls.
De vanliga felsätten:
”Min enhet dyker upp i skannern men ansluter inte.” Oftast har annonseringspaketet
connectable=False(broadcaster-läge), eller så är en tidigare anslutning fortfarande öppen och kameran är redan förbiaioble.advertise(). Lägg till print-satser runt advertise-anropet för att bekräfta.”exchange_mtu(512) kördes men mina aviseringar är fortfarande begränsade till 20 bytes.” Den förhandlade MTU:n är
min(local, peer)– telefonen eller centralbiblioteket kanske inte har begärt en större MTU på sin sida, i vilket fall anslutningen stannar på 23. Inspekteramtuefter attexchange_mtu()returnerat. Observera också attexchange_mtu()bara fungerar en gång per anslutning; anropa det före den första stora operationen.”Parkoppling misslyckas med ett generiskt fel.” Två vanliga orsaker: IO-förmåge-diskrepansen (att begära
mitm=Truepå en kamera som deklarerario=3/ ingen inmatning ingen utmatning – det finns inget sätt att bekräfta den numeriska koden, så parkopplingsmotorn ger upp), och en helt felaktig väggklockstid på kameran när motparten kräver det. Ställ in klockan medntptime.settime()före det första parkopplingsförsöket.”Aviseringar når aldrig fram till klienten.” Två saker att kontrollera, i tur och ordning: (a) deklarerades karakteristiken med
notify=True? – egenskapsbiten måste vara satt på serversidan; (b) anropade klientensubscribe()? – utan att skriva Client Characteristic Configuration Descriptor (CCCD) får servern höra att ingen klient vill ha aviseringar och kastar dem tyst.”Det annonserade namnet är avhugget eller saknas.” Annonseringsnyttolasten är 31 bytes, och flaggorna + tjänste-UUID:n + utseendefälten tar var och en bytes från toppen. Ett långt
name=plus flera tjänste-UUID:n svämmar över. Antingen förkorta namnet eller använd aktiv skanning så att skanningssvaret (ytterligare 31 bytes) bär överflödet. nRF Connect visar båda halvorna separat, vilket gör uppdelningen uppenbar.”L2CAP-anslutning utlöser ett undantag omedelbart.” Vanligtvis en PSM-diskrepans – båda sidor måste komma överens om samma PSM-nummer utanför bandet. Ett
L2CAPConnectionErrorbär Bluetooth-statuskoden som sitt första argument; status2(”PSM not supported”) är det avslöjande tecknet.”Bundna anslutningar utlöser fortfarande en fullständig parkopplingshandskakning vid varje återanslutning.”
aioble.security.load_secrets()anropades inte vid uppstart. Utan det ligger de sparade nycklarna på flashminnet men läses aldrig in i minnet, så motpartens identitet är okänd och parkoppling körs från grunden varje gång.
När allt annat misslyckas exponerar lågnivåmodulen bluetooth ett IRQ-återanrop som utlöses för varje underliggande händelse; att prenumerera på det en kort stund och skriva ut händelserna är motsvarigheten till en Wireshark-spårning för kamerasidan.
11.14.2. Använda denna referens senare¶
Behandla Bluetooth-kapitlen som referensmaterial; att komma tillbaka för den exakta layouten av en peripherals annonseringsnyttolast eller flödet för central skanning-och-prenumeration är den avsedda användningen. Referenssidorna aioble — Asynkron BLE och bluetooth — lågnivå-Bluetooth listar varje metod, flagga och konstant på ett ställe när frågan bara är ”vad är det exakta namnet på det här anropet”.