11.2. Der BLE-Stack

Wie bei der Vernetzung ist Bluetooth Low Energy als ein Stapel von Schichten aufgebaut, von denen jede ein einzelnes Problem löst und der darüberliegenden Schicht eine saubere Abstraktion bereitstellt. Die untenstehenden Namen stammen direkt aus der Bluetooth-Core-Spezifikation und tauchen in den aioble- und bluetooth-APIs auf.

Ein vertikaler Stapel aus fünf beschrifteten Kästen. Von unten nach oben: Physical (Funk), Link Layer, GAP, GATT, Application. Ein Pfeil rechts zeigt den Stapel hinauf, beschriftet mit "was wir bauen". Ein Pfeil links zeigt den Stapel hinab, beschriftet mit "was bereitgestellt wird".

Der Bluetooth-Low-Energy-Stack. Jede Schicht reicht eine sauberere Abstraktion an die nächste hinauf, dasselbe Muster, das der Netzwerk-Stack verwendet.

Physikalische Schicht. Bewegt Bits zwischen zwei Geräten über das 2,4-GHz-Funkmodul. Kanalauswahl, Modulation, Sendeleistung. Die Aufgabe der Kamera ist es, eingeschaltet zu sein; das Silizium erledigt den Rest.

Link-Schicht. Bewegt Pakete zwischen zwei Geräten, die sich darauf einigen, miteinander zu kommunizieren. Fügt Geräteadressen hinzu, damit jedes Paket an einen einzelnen Nachbarn gerichtet werden kann, plant die periodischen Funkereignisse, die eine Verbindung ausmachen, und kümmert sich um die erneute Übertragung jedes Pakets, das der Empfänger nicht bestätigt hat.

Generic Access Profile (GAP). Die Erkennungs- und Verbindungsschicht. Definiert vier Rollen – Broadcaster, Observer, Peripheriegerät, zentrales Gerät – und das Advertising-/Scanning-Protokoll, mit dem zwei Geräte sich überhaupt erst finden, sowie das Verfahren zum Öffnen und Schließen einer Verbindung zwischen ihnen. Hier sind Adressen, Advertising-Nutzlasten, Verbindungsparameter und Pairing angesiedelt.

Generic Attribute Profile (GATT). Die Datenschicht. Sie sitzt auf einer offenen GAP-Verbindung und stellt eine kleine Schlüssel-/Wert-Datenbank bereit: Eine Seite hostet einen Baum benannter Werte, Charakteristiken genannt, die andere Seite liest sie, schreibt sie oder abonniert sie. Hier fließen die eigentlichen Anwendungsbytes.

Anwendung. Was auch immer die Kamera und die Gegenstelle als Bedeutung der Bytes vereinbaren. Die Bluetooth SIG veröffentlicht standardisierte Profile – Herzfrequenz, Akkustand, Umgebungssensorik – die häufig verwendete Charakteristiken definieren, damit nicht verwandte Geräte zusammenarbeiten können, doch jede Anwendung steht es frei, ihre eigenen zu definieren.

11.2.1. Wie die Schichten zur Laufzeit gestapelt sind

Das Muster entspricht dem Netzwerk-Stack:

  • Die Bytes der Anwendung gehen in einen Charakteristik-Wert.

  • GATT umhüllt diesen mit einem Header, der angibt, zu welcher Charakteristik die Bytes gehören.

  • GAP hält eine offene Verbindung am Laufen, damit GATT einen Ort zum Senden hat.

  • Die Link-Schicht verpackt das Ganze in ein Paket, adressiert an die Geräteadresse der Gegenstelle, und plant ein Funkereignis, um es zu übertragen.

  • Die physikalische Schicht verwandelt das Paket in einen kurzen Burst aus 2,4-GHz-Funk.

Die physikalische Schicht und die Link-Schicht sind aus Python heraus nahezu unsichtbar – das Silizium und die Funk-Firmware kümmern sich um sie. Ab GAP aufwärts hat der Python-Code der Kamera mehr mitzureden.

11.2.2. Zwei Schichten, die die nutzerseitige API stillschweigend überspringt

Die Bluetooth-Spezifikation benennt zwei weitere Schichten, die zwischen der Link-Schicht und GAP/GATT sitzen: das Host Controller Interface (HCI) – das Protokoll, mit dem die Host-CPU einen separaten Funk-Chip ansteuert – und L2CAP – den Multiplexer, der eine Link-Schicht-Verbindung in mehrere logische Kanäle aufteilt.

Keine der beiden ist in der aioble-API sichtbar, doch keine verschwindet. HCI sitzt innerhalb des BLE-Ports und ist unsichtbar, es sei denn, ein benutzerdefinierter Build von MicroPython ist im Spiel, und L2CAP ist der Träger, auf dem GATT aufsetzt. Eine Anwendung, die rohe Byte-Streams möchte, kann ihren eigenen L2CAP-Kanal beanspruchen (L2CAP-Kanäle).