MeshCore KISS-Modem-Protokoll
MeshCore KISS-Modem-Protokoll
Standard-KISS (Keep It Simple, Stupid)-TNC (Terminal Node Controller)-Firmware für MeshCore LoRa-Funkgeräte. Kompatibel mit jedem KISS-Client (wie Direwolf, APRSdroid, YAAC usw.) zum Senden und Empfangen von Rohdatenpaketen. MeshCore-spezifische Erweiterungen (Kryptographie, Funkkonfiguration, Telemetrie) sind über den Standard-SetHardware-Befehl (0x06) verfügbar.
Serielle Konfiguration
115200 Baud, 8N1 (8 Datenbits, keine Parität, 1 Stoppbit), keine Flusskontrolle.
Rahmenformat
Standard-KISS-Rahmenformat gemäß der KA9Q/K3MC-Spezifikation.
| Byte | Name | Beschreibung |
|---|---|---|
0xC0 | FEND | Rahmenbegrenzer (Frame Delimiter) |
0xDB | FESC | Escape-Zeichen |
0xDC | TFEND | Escapiertes FEND (FESC + TFEND = 0xC0) |
0xDD | TFESC | Escapiertes FESC (FESC + TFESC = 0xDB) |
Typ-Byte
Das Typ-Byte ist in zwei Nibbles (Halbbytes) aufgeteilt:
| Bits | Feld | Beschreibung |
|---|---|---|
| 7-4 | Port | Portnummer (0 für Einkanal-TNC) |
| 3-0 | Command | Befehlsnummer |
Maximale nicht-escapierte Rahmengröße: 512 Bytes.
Standard-KISS-Befehle
Host zum TNC
| Befehl | Wert | Daten | Beschreibung |
|---|---|---|---|
| Data | 0x00 | Rohpaket | Paket zur Übertragung in die Warteschlange stellen (jeweils eines ausstehend) |
| TXDELAY | 0x01 | Verzögerung (1 Byte) | Sende-Einschaltverzögerung in 10ms-Einheiten (Standard: 50 = 500ms) |
| Persistence | 0x02 | P (1 Byte) | CSMA (Carrier Sense Multiple Access)-Persistenzparameter 0-255 (Standard: 63) |
| SlotTime | 0x03 | Intervall (1 Byte) | CSMA-Slot-Intervall in 10ms-Einheiten (Standard: 10 = 100ms) |
| TXtail | 0x04 | Verzögerung (1 Byte) | Nach-Sende-Haltezeit in 10ms-Einheiten (Standard: 0) |
| FullDuplex | 0x05 | Modus (1 Byte) | 0 = Halbduplex, ungleich Null = Vollduplex (Standard: 0) |
| SetHardware | 0x06 | Unterbefehl + Daten | MeshCore-Erweiterungen (siehe unten) |
| Return | 0xFF | - | KISS-Modus verlassen (Keine Operation) |
TNC zum Host
| Typ | Wert | Daten | Beschreibung |
|---|---|---|---|
| Data | 0x00 | Rohpaket | Empfangenes Paket vom Funkgerät |
Datenrahmen enthalten ausschließlich Rohpaketdaten, ohne vorangestellte Metadaten. Die Nutzlast des Data-Befehls ist auf 255 Bytes begrenzt, um der maximalen Übertragungseinheit (MAX_TRANS_UNIT) von MeshCore zu entsprechen; Rahmen, die größer als 255 Bytes sind, werden stillschweigend verworfen. Die KISS-Spezifikation empfiehlt mindestens 1024 Bytes für universelle TNCs; dieses Modem ist jedoch ausschließlich für MeshCore-Pakete vorgesehen, deren Protokoll-MTU (Maximum Transmission Unit) 255 Bytes beträgt.
Es darf jeweils nur ein Paket zur Funkübertragung ausstehend sein. Wenn der Host einen zweiten Data-Rahmen sendet, bevor der erste abgeschlossen ist, antwortet das Modem mit Error (0xF1) und TxBusy (0x07).
Host-Ausgabe-Gegendruck (Backpressure)
Ausgehende Rahmen werden in eine Warteschlange mit zwei Plätzen kodiert und geleert, sobald serieller Ausgaberaum verfügbar ist; loop() blockiert niemals bei Schreibvorgängen. Der Funk-TX-Zustand schreitet unabhängig von der Host-Lesegeschwindigkeit voran. TxDone wird beibehalten, bis es in die Warteschlange gestellt werden kann. Wenn die ausgehende Warteschlange voll ist, antwortet das Modem mit Error (0xF1) und TxBusy (0x07). Hosts sollten die serielle Schnittstelle zeitnah lesen, um verzögerte Antworten zu vermeiden.
CSMA-Verhalten
Der TNC implementiert p-persistentes CSMA (Carrier Sense Multiple Access) für den Halbduplex-Betrieb:
- Wenn ein Paket in die Warteschlange gestellt wird, wird die Trägererkennung überwacht.
- Wenn der Kanal frei ist, wird ein Zufallswert zwischen 0 und 255 generiert.
- Wenn der Wert kleiner oder gleich P (Persistence) ist, wird TXDELAY gewartet und dann gesendet.
- Andernfalls wird SlotTime gewartet und ab Schritt 1 wiederholt.
SetHardware-Erweiterungen (0x06)
MeshCore-spezifische Funktionalität nutzt den Standard-KISS-SetHardware-Befehl. Das erste Byte der SetHardware-Daten ist ein Unterbefehl. Standard-KISS-Clients ignorieren diese Rahmen.
Rahmenformat
Anforderungs-Unterbefehle (Host zum TNC)
| Unterbefehl | Wert | Daten |
|---|---|---|
| GetIdentity | 0x01 | - |
| GetRandom | 0x02 | Länge (1 Byte, 1-64) |
| VerifySignature | 0x03 | PubKey (32) + Signatur (64) + Daten |
| SignData | 0x04 | Zu signierende Daten |
| EncryptData | 0x05 | Schlüssel (32) + Klartext |
| DecryptData | 0x06 | Schlüssel (32) + MAC (2) + Chiffretext |
| KeyExchange | 0x07 | Remote-PubKey (32) |
| Hash | 0x08 | Zu hashierende Daten |
| SetRadio | 0x09 | Frequenz (4) + Bandbreite (4) + SF (1) + CR (1) |
| SetTxPower | 0x0A | Sendeleistung dBm (1) |
| GetRadio | 0x0B | - |
| GetTxPower | 0x0C | - |
| GetCurrentRssi | 0x0D | - |
| IsChannelBusy | 0x0E | - |
| GetAirtime | 0x0F | Paketlänge (1) |
| GetNoiseFloor | 0x10 | - |
| GetVersion | 0x11 | - |
| GetStats | 0x12 | - |
| GetBattery | 0x13 | - |
| GetMCUTemp | 0x14 | - |
| GetSensors | 0x15 | Berechtigungen (1) |
| GetDeviceName | 0x16 | - |
| Ping | 0x17 | - |
| Reboot | 0x18 | - |
| SetSignalReport | 0x19 | Aktivieren (1): 0x00=deaktivieren, ungleich Null=aktivieren |
| GetSignalReport | 0x1A | - |
Antwort-Unterbefehle (TNC zum Host)
Antwortcodes verwenden die High-Bit-Konvention: Antwort = Befehl | 0x80. Generische und unaufgeforderte Antworten verwenden den Bereich 0xF0+.
| Unterbefehl | Wert | Daten |
|---|---|---|
| Identity | 0x81 | PubKey (32) |
| Random | 0x82 | Zufällige Bytes (1-64) |
| Verify | 0x83 | Ergebnis (1): 0x00=ungültig, 0x01=gültig |
| Signature | 0x84 | Signatur (64) |
| Encrypted | 0x85 | MAC (2) + Chiffretext |
| Decrypted | 0x86 | Klartext |
| SharedSecret | 0x87 | Gemeinsamer Schlüssel (32) |
| Hash | 0x88 | SHA-256 Hash (32) |
| Radio | 0x8B | Frequenz (4) + Bandbreite (4) + SF (1) + CR (1) |
| TxPower | 0x8C | Sendeleistung dBm (1) |
| CurrentRssi | 0x8D | RSSI dBm (1, vorzeichenbehaftet) |
| ChannelBusy | 0x8E | Ergebnis (1): 0x00=frei, 0x01=belegt |
| Airtime | 0x8F | Millisekunden (4) |
| NoiseFloor | 0x90 | dBm (2, vorzeichenbehaftet) |
| Version | 0x91 | Version (1) + Reserviert (1) |
| Stats | 0x92 | RX (4) + TX (4) + Fehler (4) |
| Battery | 0x93 | Millivolt (2) |
| MCUTemp | 0x94 | Temperatur (2, vorzeichenbehaftet) |
| Sensors | 0x95 | CayenneLPP-Nutzlast |
| DeviceName | 0x96 | Name (variabel, UTF-8) |
| Pong | 0x97 | - |
| SignalReport | 0x9A | Status (1): 0x00=deaktiviert, 0x01=aktiviert |
| OK | 0xF0 | - |
| Error | 0xF1 | Fehlercode (1) |
| TxDone | 0xF8 | Ergebnis (1): 0x00=fehlgeschlagen, 0x01=erfolgreich |
| RxMeta | 0xF9 | SNR (1) + RSSI (1) |
Fehlercodes
| Code | Wert | Beschreibung |
|---|---|---|
| InvalidLength | 0x01 | Anforderungsdaten zu kurz |
| InvalidParam | 0x02 | Ungültiger Parameterwert |
| NoCallback | 0x03 | Funktion nicht verfügbar |
| MacFailed | 0x04 | MAC-Verifizierung fehlgeschlagen |
| UnknownCmd | 0x05 | Unbekannter Unterbefehl |
| EncryptFailed | 0x06 | Verschlüsselung fehlgeschlagen |
| TxBusy | 0x07 | Funk-TX belegt, oder Host-Ausgangswarteschlange voll |
Unaufgeforderte Ereignisse
Der TNC sendet diese SetHardware-Rahmen ohne vorherige Anforderung:
TxDone (0xF8): Wird nach Abschluss der Funkübertragung gesendet. Enthält ein einzelnes Byte: 0x01 für Erfolg, 0x00 für Misserfolg. Die Zustellung an den Host kann unter seriellem Gegendruck verzögert werden, wird aber nicht verworfen. RxMeta (0xF9): Wird nach jedem Standarddatenrahmen (Typ 0x00) mit SNR (1 Byte, vorzeichenbehaftet, Wert x4) und RSSI (1 Byte, vorzeichenbehaftet, dBm) gesendet. Wird mit dem Datenrahmen in die Warteschlange gestellt; wird weggelassen, wenn der Datenrahmen nicht in die Warteschlange gestellt werden kann. Standardmäßig aktiviert; mit SetSignalReport umschaltbar. Standard-KISS-Clients ignorieren diesen Rahmen.Datenformate
Funkparameter (SetRadio / Radio-Antwort)
Alle Werte sind Little-Endian (niedrigstwertiges Byte zuerst).
| Feld | Größe | Beschreibung |
|---|---|---|
| Frequenz | 4 Bytes | Hz (z. B. 869618000) |
| Bandbreite | 4 Bytes | Hz (z. B. 62500) |
| SF | 1 Byte | Spreading Factor (Spreizfaktor) (5-12) |
| CR | 1 Byte | Coding Rate (Kodierrate) (5-8) |
Version (Version-Antwort)
| Feld | Größe | Beschreibung |
|---|---|---|
| Version | 1 Byte | Firmware-Version |
| Reserviert | 1 Byte | Immer 0 |
Verschlüsselt (Encrypted-Antwort)
| Feld | Größe | Beschreibung |
|---|---|---|
| MAC | 2 Bytes | HMAC-SHA256 auf 2 Bytes gekürzt |
| Chiffretext | variabel | AES-128 Blockverschlüsselte Daten mit Null-Padding |
Sendezeit (Airtime-Antwort)
Alle Werte Little-Endian.
| Feld | Größe | Beschreibung |
|---|---|---|
| Sendezeit | 4 Bytes | uint32_t, geschätzte Sendezeit in Millisekunden |
Rauschpegel (NoiseFloor-Antwort)
Alle Werte Little-Endian.
| Feld | Größe | Beschreibung |
|---|---|---|
| Rauschpegel | 2 Bytes | int16_t, dBm (vorzeichenbehaftet) |
Das Modem rekalibriert den Rauschpegel alle 2 Sekunden mit einem AGC (Automatic Gain Control)-Reset alle 30 Sekunden.
Statistiken (Stats-Antwort)
Alle Werte Little-Endian.
| Feld | Größe | Beschreibung |
|---|---|---|
| RX | 4 Bytes | Empfangene Pakete |
| TX | 4 Bytes | Gesendete Pakete |
| Fehler | 4 Bytes | Empfangsfehler |
Batterie (Battery-Antwort)
Alle Werte Little-Endian.
| Feld | Größe | Beschreibung |
|---|---|---|
| Millivolt | 2 Bytes | uint16_t, Batteriespannung in mV |
MCU-Temperatur (MCUTemp-Antwort)
Alle Werte Little-Endian.
| Feld | Größe | Beschreibung |
|---|---|---|
| Temperatur | 2 Bytes | int16_t, Zehntel von °C (z. B. 253 = 25,3°C) |
Gibt den NoCallback-Fehler zurück, wenn das Board keine Temperaturmessungen unterstützt.
Gerätename (DeviceName-Antwort)
| Feld | Größe | Beschreibung |
|---|---|---|
| Name | variabel | UTF-8-String, kein Null-Terminator |
Neustart (Reboot)
Sendet eine OK-Antwort, leert die serielle Schnittstelle und startet dann das Gerät neu. Der Host sollte damit rechnen, dass die Verbindung unterbrochen wird.
Sensorberechtigungen (GetSensors)
| Bit | Wert | Beschreibung |
|---|---|---|
| 0 | 0x01 | Basis (Batterie) |
| 1 | 0x02 | Position (GPS) |
| 2 | 0x04 | Umgebung (Temperatur, Luftfeuchtigkeit, Druck) |
Verwenden Sie 0x07 für alle Berechtigungen.
Sensordaten (Sensors-Antwort)
Die Daten werden im CayenneLPP-Format zurückgegeben. Siehe CayenneLPP-Dokumentation zum Parsen.
Kryptographische Algorithmen
| Operation | Algorithmus |
|---|---|
| Identität / Signieren / Verifizieren | Ed25519 |
| Schlüsselaustausch | X25519 (ECDH) |
| Verschlüsselung | AES-128 Blockverschlüsselung mit Null-Padding + HMAC-SHA256 (MAC auf 2 Bytes gekürzt) |
| Hashing | SHA-256 |
Hinweise
- Die Nutzlastbegrenzung für Daten (255 Bytes) entspricht der MeshCore MAX_TRANS_UNIT (maximalen Übertragungseinheit); keine Änderung für KISS "1024+ empfohlen" erforderlich (dies gilt für allgemeine TNCs, nicht für MeshCore).
- Das Modem generiert beim ersten Booten eine Identität (wird im Flash-Speicher abgelegt).
- Alle Mehrbyte-Werte sind Little-Endian, sofern nicht anders angegeben.
- SNR-Werte in RxMeta werden mit 4 multipliziert für eine 0,25 dB-Genauigkeit.
- TxDone wird nach jeder Übertragung als SetHardware-Ereignis gesendet.
- Standard-KISS-Clients empfangen nur Datenrahmen vom Typ 0x00 und können alle SetHardware-Rahmen (0x06) sicher ignorieren.
- Siehe packet_format.md für das Paketformat.