Companion-Protokoll
- Zuletzt aktualisiert: 2026-03-08
- Protokollversion: Companion Firmware v1.12.0+
HINWEIS: Dieses Dokument befindet sich noch in Entwicklung. Einige Informationen können ungenau sein.
Dieses Dokument bietet eine umfassende Anleitung zur Kommunikation mit MeshCore-Geräten über Bluetooth Low Energy (BLE).
Es ist plattformunabhängig und kann für Android, iOS, Python, JavaScript oder jede andere Plattform verwendet werden, die BLE unterstützt.
Offizielle Bibliotheken
Bitte beachten Sie die folgenden Repositories für bestehende Companion-Protokoll-Bibliotheken von MeshCore:
- JavaScript: https://github.com/meshcore-dev/meshcore.js
- Python: https://github.com/meshcore-dev/meshcore_py
Wichtiger Sicherheitshinweis
Alle in dieser Anleitung gezeigten Geheimnisse (Secrets), Hashes und kryptografischen Werte sind nur Beispielwerte.
- Alle Hexadezimalwerte, öffentlichen Schlüssel (Public Keys) und Hashes dienen nur zu Demonstrationszwecken.
- Verwenden Sie niemals Beispielgeheimnisse in der Produktion.
- Generieren Sie immer neue kryptografisch sichere Zufallsgeheimnisse.
- Bitte implementieren Sie geeignete Sicherheitsverfahren in Ihrer Implementierung.
- Diese Anleitung dient ausschließlich der Protokolldokumentation.
Inhaltsverzeichnis
- BLE-Verbindung
- Paketstruktur
- Befehle
- Kanalverwaltung
- Nachrichtenverarbeitung
- Antwort-Parsing
- Beispielhafter Implementierungsablauf
- Bewährte Verfahren
- Fehlerbehebung
BLE-Verbindung
Dienst (Service) und Eigenschaften (Characteristics)
MeshCore Companion-Geräte stellen einen BLE-Dienst mit den folgenden UUIDs (Universally Unique Identifiers) zur Verfügung:
- Dienst-UUID:
6E400001-B5A3-F393-E0A9-E50E24DCCA9E - RX-Eigenschaft (App → Firmware):
6E400002-B5A3-F393-E0A9-E50E24DCCA9E - TX-Eigenschaft (Firmware → App):
6E400003-B5A3-F393-E0A9-E50E24DCCA9E
Verbindungsschritte
- Nach Geräten suchen
- Mit GATT verbinden
- Dienste und Eigenschaften entdecken
6E400001-B5A3-F393-E0A9-E50E24DCCA9E.
- Entdecken Sie die RX-Eigenschaft 6E400002-B5A3-F393-E0A9-E50E24DCCA9E.
- Ihre App schreibt hierhin, die Firmware liest von hier.
- Entdecken Sie die TX-Eigenschaft 6E400003-B5A3-F393-E0A9-E50E24DCCA9E.
- Die Firmware schreibt hierhin, Ihre App liest von hier.
- Benachrichtigungen aktivieren
- Erste Befehle senden
CMD_APP_START, um Ihre App bei der Firmware zu identifizieren und Funk-Einstellungen zu erhalten.
- Senden Sie CMD_DEVICE_QUERY, um Geräteinformationen abzurufen und unterstützte Protokollversionen auszuhandeln.
- Senden Sie CMD_SET_DEVICE_TIME, um die Firmware-Uhr einzustellen.
- Senden Sie CMD_GET_CONTACTS, um alle Kontakte abzurufen.
- Senden Sie CMD_GET_CHANNEL mehrmals, um alle Kanal-Slots abzurufen.
- Senden Sie CMD_SYNC_NEXT_MESSAGE, um die nächste in der Firmware gespeicherte Nachricht abzurufen.
- Richten Sie Listener für Push-Codes ein, wie PUSH_CODE_MSG_WAITING oder PUSH_CODE_ADVERT.
- Im Abschnitt Befehle finden Sie Informationen zu anderen Befehlen.
Hinweis: MeshCore-Geräte können sich nach Inaktivitätsperioden trennen. Implementieren Sie eine automatische Wiederverbindungslogik mit exponentiellem Backoff (wiederholte Versuche mit zunehmenden Wartezeiten).
BLE-Schreibtyp
Beim Schreiben von Befehlen an die RX-Eigenschaft geben Sie den Schreibtyp an:
- Schreiben mit Antwort (Standard): Wartet auf eine Bestätigung vom Gerät.
- Schreiben ohne Antwort: Schneller, aber ohne Bestätigung.
- Android: Verwenden Sie
BluetoothGattCharacteristic.WRITE_TYPE_DEFAULToderWRITE_TYPE_NO_RESPONSE. - iOS: Verwenden Sie
CBCharacteristicWriteType.withResponseoder.withoutResponse. - Python (bleak): Verwenden Sie
write_gatt_char()mitresponse=TrueoderFalse.
MTU (Maximum Transmission Unit)
Die Standard-BLE-MTU beträgt 23 Bytes (20 Bytes Nutzdaten). Für größere Befehle wie SET_CHANNEL (50 Bytes) müssen Sie möglicherweise:
- Größere MTU anfordern: Fordern Sie eine MTU von 512 Bytes an, falls unterstützt.
gatt.requestMtu(512)
- iOS: peripheral.maximumWriteValueLength(for:)
- Python (bleak): MTU wird automatisch ausgehandelt.
Befehlssequenzierung
Kritisch: Befehle müssen in der richtigen Reihenfolge gesendet werden:- Nach der Verbindung:
- Befehl-Antwort-Abgleich:
CMD_GET_CHANNEL → RESP_CODE_CHANNEL_INFO).
Befehlswarteschlangenverwaltung
Für einen zuverlässigen Betrieb implementieren Sie eine Befehlswarteschlange.
Warteschlangenstruktur:- Verwalten Sie eine Warteschlange von ausstehenden Befehlen.
- Verfolgen Sie, welcher Befehl derzeit auf eine Antwort wartet.
- Senden Sie den nächsten Befehl erst nach Erhalt der Antwort oder nach einem Timeout.
- Bei Timeout: Aktuellen Befehl löschen, nächsten in der Warteschlange verarbeiten.
- Bei Fehler: Fehler protokollieren, aktuellen Befehl löschen, nächsten verarbeiten.
Paketstruktur
Das MeshCore-Protokoll verwendet ein Binärformat mit der folgenden Struktur:
- Befehle: Von der App an die Firmware über die RX-Eigenschaft gesendet.
- Antworten: Von der Firmware über TX-Eigenschaftsbenachrichtigungen empfangen.
- Alle Mehrbyte-Integer: Little-Endian-Byte-Reihenfolge (außer CayenneLPP, das Big-Endian ist).
- Alle Zeichenketten: UTF-8-Kodierung.
Das erste Byte gibt den Pakettyp an (siehe Antwort-Parsing).
---
Befehle
1. App-Start
Zweck: Initialisiert die Kommunikation mit dem Gerät. Muss als erstes nach der Verbindung gesendet werden. Befehlsformat: Beispiel (hexadezimal): Antwort:PACKET_SELF_INFO (0x05)
---
2. Geräteabfrage
Zweck: Abfrage von Geräteinformationen. Befehlsformat: Beispiel (hexadezimal): Antwort:PACKET_DEVICE_INFO (0x0D) mit Geräteinformationen
---
3. Kanalinformationen abrufen
Zweck: Informationen über einen bestimmten Kanal abrufen. Befehlsformat: Beispiel (Kanal 1 abrufen): Antwort:PACKET_CHANNEL_INFO (0x12) mit Kanaldetails
---
4. Kanal einstellen
Zweck: Erstellen oder Aktualisieren eines Kanals auf dem Gerät. Befehlsformat: Gesamtlänge: 50 Bytes Kanalindex:- Gültiger Bereich ist
0bismax_channels - 1. Lesen Siemax_channelsaus Byte 3 der
PACKET_DEVICE_INFO-Antwort; gehen Sie nicht von 8 aus. Builds werden mit
MAX_GROUP_CHANNELS von 1, 8 oder 40 geliefert, je nach Platine.
- Index 0: Von der Firmware mit dem integrierten "Public"-Kanal vorab belegt.
- Ein Index außerhalb des Bereichs wird mit
PACKET_ERROR/ERR_CODE_NOT_FOUNDabgelehnt.
- UTF-8-kodiert
- Maximal 32 Bytes
- Mit Null-Bytes (0x00) aufgefüllt, falls kürzer
- Immer ein echter 16-Byte-Schlüssel; die Firmware leitet den Kanal-Hash von
SHA256(secret) ab (BaseChatMesh.cpp:936-942). Es gibt keine "kein Geheimnis"-Form.
- Schreiben Sie kein Geheimnis, das nur aus Null-Bytes besteht.
SHA256über 16 Null-Bytes ist ein fester,
BaseChatMesh.cpp:392-401), aber ein Slot, der einen Namen
und ein Null-Geheimnis erhalten hat, wird nicht übersprungen und wird
Gruppenverkehr mit Null-Schlüssel von jedem Knoten im Mesh absorbieren.
- Der integrierte öffentliche Kanal verwendet den bekannten Schlüssel
izOH6cXN6mrJ5e26oRXNcg== (base64), d.h.
8b3387e9c5cdea6ac9e5edbaa115cd72 in Hex.
Beispiel (Kanal "YourChannelName" mit Geheimnis an Index 1 erstellen):
Hinweis: Die 32-Byte-Geheimnis-Variante wird nicht unterstützt und gibt PACKET_ERROR zurück.
Antwort: PACKET_OK (0x00) bei Erfolg, PACKET_ERROR (0x01) bei Fehler.
---
5. Kanalnachricht senden
Zweck: Eine Textnachricht an einen Kanal senden. Befehlsformat: Zeitstempel: Unix-Zeitstempel in Sekunden (32-Bit vorzeichenlose Ganzzahl, Little-Endian). Beispiel ("Hello" an Kanal 1 zum Zeitstempel 1234567890 senden): Antwort:PACKET_MSG_SENT (0x06) bei Erfolg.
---
6. Kanal-Datagramm senden
Zweck: Ein binäres Datagramm an einen Kanal senden. Im Gegensatz zu Kanal-Textnachrichten tragen Datagramme keine eingebaute Absenderidentität und keinen Zeitstempel – Anwendungen, die diese benötigen, müssen sie im binären Payload kodieren. Befehlsformat: Beispiel (Flood,DATA_TYPE_DEV, Payload A1 B2 C3, Kanal 1):
Datentyp / Transport-Mapping:
0x0000(DATA_TYPE_RESERVED) ist ungültig und wird mitPACKET_ERRORabgelehnt.0xFFFF(DATA_TYPE_DEV) ist der Entwickler-Namensraum zum Experimentieren und Entwickeln von Apps.- Werte
0x0001–0xFFFEsind für registrierte Anwendungs-/Community-Namensräume verfügbar. Siehe die Tabelle Registriertedata_type-Werte unten.
- Die maximale Payload-Länge beträgt 165 Bytes — `MAX_GROUP_DATA_LENGTH =
(src/MeshCore.h:21`). Dies ist die
Funk-seitige Begrenzung und die, die Clients durchsetzen sollten.
- Zwei verschiedene Grenzen werden überprüft, und sie stimmen nicht überein. Die Host-Frame-Prüfung
MAX_CHANNEL_DATA_LENGTH = MAX_FRAME_SIZE - 9 = 167
(companion_radio/MyMesh.cpp:1265); die Funk-seitige Prüfung verwendet 165
(BaseChatMesh.cpp:544).
- Payloads über 167 werden mit
ERR_CODE_ILLEGAL_ARG(6) abgelehnt. - Payloads von 166 oder 167 bestehen die Frame-Prüfung, schlagen dann aber bei der Funk-seitigen
ERR_CODE_TABLE_FULL (3) zurück. Trotz der üblichen
Bedeutung dieses Codes kann ein solcher Sendevorgang niemals erfolgreich sein — versuchen Sie es nicht erneut. Halten Sie Payloads bei
165 Bytes oder weniger, und dieser Fall kann nicht auftreten.
Antwort: PACKET_OK (0x00) bei Erfolg, oder PACKET_ERROR (0x01) mit einem der folgenden Fehler:
ERR_CODE_NOT_FOUND(2) — unbekannterchannel_idxERR_CODE_ILLEGAL_ARG(6) — ungültigepath_len, reservierterdata_type(0x0000), oder Payload größer alsMAX_CHANNEL_DATA_LENGTH(167)ERR_CODE_TABLE_FULL(3) — die Warteschlange für ausgehende Nachrichten ist voll (später erneut versuchen), oder ein Payload von 166-167 Bytes, der die Funk-seitige Begrenzung überschreitet (permanent; siehe Grenzwerte oben)
RESP_CODE_CHANNEL_DATA_RECV (0x1B) zugestellt; siehe Kanal-Datagramm empfangen.
Registrierte data_type-Werte
data_type ist ein Anwendungsbezeichner, kein Payload-Formatbezeichner. Jeder registrierte Wert identifiziert eine Anwendung, die ihre eigenen internen Payload-Schemas besitzt. Die Firmware inspiziert den Payload-Inhalt nicht — data_type wird undurchsichtig transportiert.
| Wert | Konstante | Zweck |
|---|---|---|
| 0x0000 | DATA_TYPE_RESERVED | Reserviert; ungültig beim Senden |
| 0x0001 – 0x00FF | — | Reserviert für interne Nutzung |
| 0x0100 – 0xFEFF | — | Registrierte Anwendungs-Namensräume (siehe nummern-zuteilungen) |
| 0xFF00 – 0xFFFE | — | Testen/Entwicklung; keine Registrierung erforderlich |
| 0xFFFF | DATA_TYPE_DEV | Entwickler-/Experimentier-Namensraum |
Um eine neue Anwendung zu registrieren, reichen Sie einen PR (Pull Request) ein, der eine Zeile zur Tabelle in docs/number_allocations.md hinzufügt. Interne Unterformate innerhalb einer zugewiesenen Anwendungs-ID gehören dieser Anwendung und werden weder in der MeshCore-Firmware noch in diesem Dokument verfolgt.
---
Kanal-Datagramm empfangen
Eingehende Gruppendatagramme (Funk-Ebene PAYLOAD_TYPE_GRP_DATA, 0x06) werden als RESP_CODE_CHANNEL_DATA_RECV-Benachrichtigungen an den Host weitergeleitet.
RESP_CODE_CHANNEL_DATA_RECV, 0x1B):
Pfad-Bytes werden nicht weitergeleitet: Nur path_len wird im Empfangs-Frame gemeldet – der Pfad selbst wird nicht auf den Host kopiert. Es gibt keine Pfad-Bytes zwischen Byte 5 und dem data_type-Feld bei Bytes 6–7, unabhängig von path_len.
Semantik der Pfadlänge unterscheidet sich zwischen Senden und Empfangen:
| Richtung | path_len = 0xFF | path_len ≠ 0xFF |
|---|---|---|
| Senden | Netzwerk fluten | Direkter Weg; der kodierte Pfad folgt (niedrige 6 Bits = Hash-Anzahl, obere 2 Bits + 1 = Hash-Größe; On-Wire-Byte-Anzahl = hash_count × hash_size) |
| Empfangen | Paket kam über direkten Weg an | Paket wurde geflutet; dies ist das kodierte pkt->path_len Feld wie beobachtet (keine Pfad-Bytes folgen) |
Mit anderen Worten, die Bedeutung von 0xFF ist zwischen den beiden Richtungen invertiert, und beim Empfang trägt das Feld nur Metadaten – niemals einen routbaren Pfad. path_len ist ein kodiertes Byte (siehe Packet::isValidPathLen / Packet::writePath in src/Packet.cpp), keine rohe Byte-Anzahl.
PACKET_MESSAGES_WAITING (0x83) ausgeben, um den Host darüber zu informieren, dass Datagramme in der Warteschlange liegen; fragen Sie mit CMD_SYNC_NEXT_MESSAGE (0x0A) ab, um sie abzurufen.
Parsing-Pseudocode:
---
7. Nachricht abrufen
Zweck: Die nächste in der Warteschlange befindliche Nachricht vom Gerät anfordern. Befehlsformat: Beispiel (hexadezimal): Antwort:PACKET_CHANNEL_MSG_RECV(0x08) oderPACKET_CHANNEL_MSG_RECV_V3(0x11) für Kanalnachrichten.PACKET_CONTACT_MSG_RECV(0x07) oderPACKET_CONTACT_MSG_RECV_V3(0x10) für Kontaktnachrichten.PACKET_CHANNEL_DATA_RECV(0x1B) für Kanal-Datagramme.PACKET_NO_MORE_MSGS(0x0A), wenn keine Nachrichten verfügbar sind.
PACKET_MESSAGES_WAITING (0x83) als Benachrichtigung senden, wenn Nachrichten verfügbar sind.
---
8. Batterie und Speicher abrufen
Zweck: Batteriespannung und Speichernutzung des Geräts abfragen. Befehlsformat: Beispiel (hexadezimal): Antwort:PACKET_BATTERY (0x0C) mit Batteriespannung in Millivolt und Speicherinformationen.
---
Kanalverwaltung
Kanaltypen
- Öffentlicher Kanal
8b3387e9c5cdea6ac9e5edbaa115cd72.
- Jeder kann diesem Kanal beitreten, Nachrichten sollten als öffentlich betrachtet werden.
- Wird als Standard-Gruppenchat verwendet.
- Hashtag-Kanäle
sha256("#test").
- Zum Beispiel hat der Hashtag-Kanal #test den Schlüssel: 9cd8fcf22a47333b591d96a2b848b73f.
- Der Verkehr ist in der Luft verschlüsselt, aber jeder, der den Kanalnamen kennt oder errät, kann den Schlüssel ableiten. Hashtag-Kanäle sollten nicht als privat behandelt werden.
- Wird als themenbasierter öffentlicher Gruppenchat verwendet, getrennt vom Standard-Öffentlichen Kanal.
- Private Kanäle
Kanal-Lebenszyklus
- Kanal einstellen:
CMD_SET_CHANNEL mit Namen und einem 16-Byte-Geheimnis senden.
- Kanal abrufen:
CMD_GET_CHANNEL mit Kanalindex senden.
- RESP_CODE_CHANNEL_INFO-Antwort parsen.
- Kanal löschen:
CMD_SET_CHANNEL mit leerem Namen und einem Geheimnis, das nur aus Null-Bytes besteht, senden.
- Oder mit einem neuen Kanal überschreiben.
---
Nachrichtenverarbeitung
Nachrichten empfangen
Nachrichten werden über die TX-Eigenschaft (Benachrichtigungen) empfangen. Das Gerät sendet:
- Kanalnachrichten:
PACKET_CHANNEL_MSG_RECV (0x08) – Standardformat
- PACKET_CHANNEL_MSG_RECV_V3 (0x11) – Version 3 mit SNR (Signal-Rausch-Verhältnis)
- Kontaktnachrichten:
PACKET_CONTACT_MSG_RECV (0x07) – Standardformat
- PACKET_CONTACT_MSG_RECV_V3 (0x10) – Version 3 mit SNR
- Benachrichtigungen:
PACKET_MESSAGES_WAITING (0x83) – Zeigt an, dass Nachrichten in der Warteschlange liegen
Kontaktnachrichtenformat
Standardformat (PACKET_CONTACT_MSG_RECV, 0x07):
V3-Format (PACKET_CONTACT_MSG_RECV_V3, 0x10):
Parsing-Pseudocode:
Kanalnachrichtenformat
Standardformat (PACKET_CHANNEL_MSG_RECV, 0x08):
V3-Format (PACKET_CHANNEL_MSG_RECV_V3, 0x11):
Parsing-Pseudocode:
Nachrichten senden
Verwenden Sie den SEND_CHANNEL_MESSAGE-Befehl (siehe Befehle).
- Nachrichten sind auf 133 Zeichen gemäß MeshCore-Spezifikation begrenzt.
- Lange Nachrichten sollten in Teile (Chunks) aufgeteilt werden.
- Fügen Sie einen Chunk-Indikator hinzu (z.B. "[1/3] Nachrichtentext").
Antwort-Parsing
Terminologie
Dieses Dokument verwendet eine spezifikationsgetreue Namenskonvention (PACKET_*) für Bytes, die die Firmware an den Host zurücksendet. Im Firmware-Quellcode sind diese Werte nach Zweck in zwei #define-Familien aufgeteilt:
RESP_CODE_*– direkte Antworten auf einen Befehl (z.B.RESP_CODE_CHANNEL_DATA_RECV=PACKET_CHANNEL_DATA_RECV= 0x1B).PUSH_CODE_*– asynchrone Benachrichtigungen, die nicht an einen bestimmten Befehl gebunden sind (z.B.PUSH_CODE_MSG_WAITING=PACKET_MESSAGES_WAITING= 0x83).
RESP_CODE_X / PUSH_CODE_X den PACKET_X dieses Dokuments mit demselben numerischen Wert.
Pakettypen
| Wert | Name | Beschreibung |
|---|---|---|
| 0x00 | PACKET_OK | Befehl erfolgreich ausgeführt |
| 0x01 | PACKET_ERROR | Befehl fehlgeschlagen |
| 0x02 | PACKET_CONTACT_START | Anfang der Kontaktliste |
| 0x03 | PACKET_CONTACT | Kontaktinformationen |
| 0x04 | PACKET_CONTACT_END | Ende der Kontaktliste |
| 0x05 | PACKET_SELF_INFO | Gerät-Selbstinformationen |
| 0x06 | PACKET_MSG_SENT | Bestätigung, dass Nachricht gesendet wurde |
| 0x07 | PACKET_CONTACT_MSG_RECV | Kontaktnachricht (Standard) |
| 0x08 | PACKET_CHANNEL_MSG_RECV | Kanalnachricht (Standard) |
| 0x09 | PACKET_CURRENT_TIME | Antwort auf aktuelle Zeit |
| 0x0A | PACKET_NO_MORE_MSGS | Keine weiteren Nachrichten verfügbar |
| 0x0C | PACKET_BATTERY | Batteriestand |
| 0x0D | PACKET_DEVICE_INFO | Geräteinformationen |
| 0x10 | PACKET_CONTACT_MSG_RECV_V3 | Kontaktnachricht (V3 mit SNR) |
| 0x11 | PACKET_CHANNEL_MSG_RECV_V3 | Kanalnachricht (V3 mit SNR) |
| 0x12 | PACKET_CHANNEL_INFO | Kanalinformationen |
| 0x1B | PACKET_CHANNEL_DATA_RECV | Kanal-Datagramm |
| 0x80 | PACKET_ADVERTISEMENT | Werbepaket |
| 0x82 | PACKET_ACK | Bestätigung |
| 0x83 | PACKET_MESSAGES_WAITING | Benachrichtigung über wartende Nachrichten |
| 0x88 | PACKET_LOG_DATA | RF-Logdaten (können ignoriert werden) |
Antworten parsen
PACKET_OK (0x00): PACKET_ERROR (0x01): PACKET_CHANNEL_INFO (0x12): Hinweis: Das Gerät gibt den 16-Byte-Kanal-Geheimschlüssel in dieser Antwort zurück. PACKET_DEVICE_INFO (0x0D): Parsing-Pseudocode: PACKET_BATTERY (0x0C): Parsing-Pseudocode: PACKET_SELF_INFO (0x05): Parsing-Pseudocode: PACKET_MSG_SENT (0x06): PACKET_ACK (0x82):Fehlercodes
PACKET_ERROR (0x01) enthält einen ein Byte großen Fehlercode in Byte 1. Die Werte entsprechen den ERR_CODE_*-Konstanten, die in examples/companion_radio/MyMesh.cpp definiert sind:
| Code | Konstante (Firmware) | Beschreibung |
|---|---|---|
| 1 | ERR_CODE_UNSUPPORTED_CMD | Unbekanntes oder nicht unterstütztes Befehlsbyte / Unterbefehl |
| 2 | ERR_CODE_NOT_FOUND | Ziel nicht gefunden (Kanal, Kontakt, Nachricht usw.) |
| 3 | ERR_CODE_TABLE_FULL | Interne Warteschlange oder Tabelle ist voll — später erneut versuchen |
| 4 | ERR_CODE_BAD_STATE | Operation im aktuellen Gerätezustand nicht gültig (z.B. Iterator läuft bereits) |
| 5 | ERR_CODE_FILE_IO_ERROR | Dateisystem- oder Speicher-I/O-Fehler |
| 6 | ERR_CODE_ILLEGAL_ARG | Ungültiges Argument (falsche Länge, Wert außerhalb des Bereichs, reserviertes Feld usw.) |
PACKET_ERROR-Antwort und behandeln Sie unbekannte Codes als generische Fehler.
Frame-Behandlung
BLE-Implementierungen reihen auf der Firmware-Ebene einen Protokoll-Frame pro BLE-Schreib-/Benachrichtigung ein und liefern ihn aus.
- Apps sollten jeden Charakteristik-Schreib-/Benachrichtigungsvorgang als genau einen Companion-Protokoll-Frame behandeln.
- Apps sollten weiterhin die Frame-Längen vor dem Parsen validieren.
- Zukünftige Transportmittel oder Firmware-Revisionen können abweichen, daher sollte man nicht von festen Payload-Größen für variablengroße Antworten ausgehen.
Antwort-Behandlung
- Befehl-Antwort-Muster:
- Asynchrone Nachrichten:
PACKET_MESSAGES_WAITING (0x83) behandeln, indem der GET_MESSAGE-Befehl abgefragt wird.
- Eingehende Nachrichten parsen und an die entsprechenden Handler weiterleiten.
- Frame-Länge vor dem Dekodieren validieren.
- Antwortabgleich:
APP_START → PACKET_SELF_INFO
- DEVICE_QUERY → PACKET_DEVICE_INFO
- GET_CHANNEL → PACKET_CHANNEL_INFO
- SET_CHANNEL → PACKET_OK oder PACKET_ERROR
- SEND_CHANNEL_MESSAGE → PACKET_MSG_SENT
- GET_MESSAGE → PACKET_CHANNEL_MSG_RECV, PACKET_CONTACT_MSG_RECV, PACKET_CHANNEL_DATA_RECV oder PACKET_NO_MORE_MSGS
- SEND_CHANNEL_DATA → PACKET_OK oder PACKET_ERROR
- GET_BATTERY → PACKET_BATTERY
- Timeout-Behandlung:
SET_CHANNEL kann 1-2 Sekunden benötigen).
- Längere Timeout-Werte für Kanaloperationen in Betracht ziehen.
- Fehlerbehebung:
PACKET_ERROR: Fehlercode protokollieren, aktuellen Befehl löschen.
- Bei Verbindungsverlust: Befehlswarteschlange löschen, Wiederverbindung versuchen.
- Bei ungültiger Antwort: Warnung protokollieren, aktuellen Befehl löschen, fortfahren.
---
Beispielhafter Implementierungsablauf
Initialisierung
Privaten Kanal erstellen
Nachricht senden
Nachrichten empfangen
---
Bewährte Verfahren
- Verbindungsmanagement:
- Geheimnisverwaltung:
- Nachrichtenverarbeitung:
CMD_SYNC_NEXT_MESSAGE, wenn PUSH_CODE_MSG_WAITING empfangen wird.
- Implementieren Sie die Nachrichten-Deduplizierung, um zu vermeiden, dass dieselbe Nachricht zweimal angezeigt wird.
- Kanalverwaltung:
- Fehlerbehandlung:
RESP_CODE_ERR-Antworten entsprechend.
---
Fehlerbehebung
Verbindungsprobleme
- Gerät nicht gefunden: Stellen Sie sicher, dass das Gerät eingeschaltet ist und sendet (advertising).
- Verbindungs-Timeout: Überprüfen Sie Bluetooth-Berechtigungen und die Gerätenähe.
- GATT-Fehler: Stellen Sie eine korrekte Dienst-/Eigenschaften-Erkennung sicher.
Befehlsprobleme
- Keine Antwort: Überprüfen Sie, ob Benachrichtigungen aktiviert sind und der Verbindungsstatus korrekt ist.
- Fehlerantworten: Überprüfen Sie das Befehlsformat und den Fehlercode.
- Timeout: Erhöhen Sie den Timeout-Wert oder versuchen Sie es erneut.
Nachrichtenprobleme
- Nachrichten werden nicht empfangen: Fragen Sie den
GET_MESSAGE-Befehl regelmäßig ab. - Doppelte Nachrichten: Implementieren Sie eine Nachrichten-Deduplizierung, indem Sie Zeitstempel/Inhalt als eindeutige ID verwenden.
- Nachrichten-Trunkierung: Senden Sie lange Nachrichten als separate, kürzere Nachrichten.