Warum ein Pairing-Code 17 Sekunden zu spät kam

WLAN ist toll, um ein paar hundert Kartenkacheln auf die SD-Karte zu schieben. Für alles andere ist es zu umständlich. Niemand will unterwegs einen QR-Code scannen, nur um die Trackfarbe zu ändern. Seit dem 6. Oktober ist India Navi deshalb ein Bluetooth-LE-Peripheral, solange es eingeschaltet ist. Die Firmware nutzt NimBLE auf dem ESP32-S3, die App react-native-ble-plx.

Diagramm: Wander Navi und India Navi sprechen über Bluetooth LE für Einstellungen, Zeit, Position und Updates, über den WLAN-Access-Point für Kacheln, Tracks und Firmware
Zwei Kanäle, zwei Aufgaben: Bluetooth für die kleinen Dinge, die oft passieren, WLAN für die großen Datenmengen.

Über Bluetooth schickt die App die Uhrzeit und die Position des Handys. Beides geht weiter an das GPS-Modul (PMTK740/PMTK741), damit es die Satelliten schneller findet. Bis zum ersten eigenen Fix zeigt die Karte die Handyposition, ins Log kommt sie nie. Außerdem lässt sich der Access Point ein- und ausschalten, der Track und das Höhenprofil ein- und ausblenden und das Update-Intervall des Displays zwischen 30 Sekunden und 10 Minuten wählen. Das WLAN-Passwort geht nie über Bluetooth, das liest das Handy weiterhin vom Display.

Wenn die Theorie auf das E-Paper trifft

Die erste Version war in Teilen von einem Agenten geschrieben, ohne ESP-IDF-Toolchain. Im Commit steht das auch offen drin: Host-Tests grün, der ESP-Code nur gegen Stub-Header geprüft. Auf der Hardware ging dann erst einmal gar nichts. Drei Fehler, alle lehrreich:

  1. Bluetooth startete nicht, weil der Controller nur noch 2 KB internes RAM fand. Der Framebuffer mit 134 KB liegt jetzt im PSRAM und wird Byte für Byte ohne DMA verschickt.
  2. Der Pairing-Code erschien zu spät. Das Handy hat 30 Sekunden zum Pairen, ein Refresh des 7-Farben-Displays dauert rund 17 Sekunden. Jetzt wird der Code gewählt, sobald ein Handy verbindet, und für den nächsten Versuch behalten.
  3. Ein gepaartes Handy kam nicht wieder rein. Ein Kommando im Connect-Event hat den Host blockiert, während der Controller auf die Antwort zur Schlüsselanfrage wartete.

Ein vierter Fehler kam etwas später. Android schickt nach dem Wiederverbinden eine Indication, und NimBLE ohne GATT-Client antwortet mit „Request Not Supported“. Android hielt das für die Antwort auf die MTU-Anfrage der App, und die App gab 0,2 Sekunden nach dem Verbinden auf. Die Central-Rolle bringt den GATT-Client mit. Das Image wird dadurch 16 KB größer, der freie Heap bleibt gleich.

Firmware-Update aus der Hosentasche

Das Firmware-Update funktioniert jetzt über WLAN und über Bluetooth. Ein getaggter Release auf GitHub hängt die Firmware automatisch an. Die App bietet die neueste Version aus den GitHub Releases direkt zum Update an. Damit ein kaputtes Image das Gerät nicht unbrauchbar macht, ist Rollback aktiv: Eine neue Firmware gilt erst als bestätigt, wenn sie 60 Sekunden gelaufen ist. Stürzt sie vorher ab, startet der Bootloader die alte Version.

Tracks aufzeichnen

Das alte log.gpx, das einfach alles mitgeschrieben hat, ist Geschichte. Aufzeichnungen startet und stoppt man jetzt in der App. Jede Aufzeichnung landet als eigene Datei in TRACKS/ auf der SD-Karte, benannt nach der Startzeit, mit einem neuen Segment nach jedem Neustart. Die App listet und löscht die Aufzeichnungen über Bluetooth und lädt sie über WLAN herunter.

Statusleiste von India Navi mit Akku, Nordpfeil, Access-Point- und Bluetooth-Symbol
Die Statusleiste zeigt Akku, Nordpfeil, Access Point und die Bluetooth-Rune. Mit zwei Punkten daneben ist ein Handy verbunden.

Zwei Erkenntnisse nehme ich mit. Erstens: Ein Agent kann ein Protokoll sauber entwerfen und testen, die Fehler am echten Gerät findet er ohne Gerät nicht. Die Arbeitsteilung war deshalb klar: Er schreibt den Code, ich probiere ihn am Gerät aus. Zweitens: Bei einem Display, das 17 Sekunden für ein Bild braucht, muss man bei jedem Timeout im Protokoll diese 17 Sekunden einplanen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert