KISS-Modem-Protokoll
MeshCore KISS-Modem-Protokoll
Standard-KISS-TNC-Firmware (Terminal Node Controller) für MeshCore-LoRa-Funkgeräte. Das Modem ist mit jedem KISS-Client (z. B. Direwolf, APRSdroid, YAAC usw.) kompatibel und ermöglicht das Senden und Empfangen von Roh-Paketen. MeshCore-spezifische Erweiterungen für Kryptografie, Funkparameter-Konfiguration und Telemetrie stehen über den standardmäßigen SetHardware-Befehl (0x06) zur Verfügung.
Serielle Konfiguration
115200 Baud, 8N1, keine Flusskontrolle.
Frame-Format
Standard-KISS-Framing gemäß der KA9Q/K3MC-Spezifikation.
| Byte | Name | Beschreibung |
|---|---|---|
0xC0 | FEND | Frame-Begrenzungszeichen (Frame Delimiter) |
0xDB | FESC | Escape-Zeichen |
0xDC | TFEND | Escaped FEND (FESC + TFEND = 0xC0) |
0xDD | TFESC | Escaped FESC (FESC + TFESC = 0xDB) |
Type-Byte
Das Type-Byte ist in zwei Nibbles (Halbbytes) aufgeteilt:
| Bits | Feld | Beschreibung |
|---|---|---|
| 7–4 | Port | Portnummer (0 bei Single-Port-TNC) |
| 3–0 | Command | Befehlsnummer |
Maximale Frame-Größe (unescaped): 512 Bytes.
Standard-KISS-Befehle
Host an TNC
| Befehl | Wert | Daten | Beschreibung |
|---|---|---|---|
| Data | 0x00 | Roh-Paket | Paket zur Übertragung in die Warteschlange stellen |
| TXDELAY | 0x01 | Verzögerung (1 Byte) | Sender-Hochlaufverzögerung in 10-ms-Einheiten (Standard: 50 = 500 ms) |
| Persistence | 0x02 | P (1 Byte) | CSMA-Persistenz-Parameter 0–255 (Standard: 63) |
| SlotTime | 0x03 | Intervall (1 Byte) | CSMA-Slot-Intervall in 10-ms-Einheiten (Standard: 10 = 100 ms) |
| TXtail | 0x04 | Verzögerung (1 Byte) | Haltezeit nach dem Senden in 10-ms-Einheiten (Standard: 0) |
| FullDuplex | 0x05 | Modus (1 Byte) | 0 = Halbduplex, ungleich 0 = Vollduplex (Standard: 0) |
| SetHardware | 0x06 | Sub-Command + Daten | MeshCore-Erweiterungen (siehe unten) |
| Return | 0xFF | – | KISS-Modus verlassen (keine Funktion) |
TNC an Host
| Typ | Wert | Daten | Beschreibung |
|---|---|---|---|
| Data | 0x00 | Roh-Paket | Vom Funk empfangenes Paket |
Data-Frames enthalten ausschließlich die rohen Paketdaten – es werden keine Metadaten vorangestellt. Die Nutzlast des Data-Befehls ist auf 255 Bytes begrenzt, was der maximalen Übertragungseinheit von MeshCore (MAX_TRANS_UNIT) entspricht. Frames, die größer als 255 Bytes sind, werden stillschweigend verworfen. Die KISS-Spezifikation empfiehlt mindestens 1024 Bytes für Allzweck-TNCs; dieses Modem ist jedoch ausschließlich für MeshCore-Pakete gedacht, deren Protokoll-MTU bei 255 Bytes liegt.
CSMA-Verhalten
Der TNC implementiert p-persistentes CSMA (Carrier Sense Multiple Access) für den Halbduplex-Betrieb:
- Sobald ein Paket in die Warteschlange kommt, wird die Trägererkennung (Carrier Detect) überwacht.
- Wenn der Kanal frei ist, wird ein Zufallswert zwischen 0 und 255 erzeugt.
- Ist der Wert kleiner oder gleich P (Persistence), wird nach Ablauf von TXDELAY gesendet.
- Andernfalls wird die SlotTime abgewartet und ab Schritt 1 wiederholt.
SetHardware-Erweiterungen (0x06)
MeshCore-spezifische Funktionalität nutzt den Standard-KISS-Befehl SetHardware. Das erste Byte der SetHardware-Daten ist ein Sub-Command (Unterbefehl). Standard-KISS-Clients ignorieren diese Frames.
Frame-Format
Anfrage-Sub-Commands (Host an TNC)
| Sub-Command | 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 | Key (32) + Klartext |
| DecryptData | 0x06 | Key (32) + MAC (2) + Chiffretext |
| KeyExchange | 0x07 | Remote PubKey (32) |
| Hash | 0x08 | Zu hashende Daten |
| SetRadio | 0x09 | Freq (4) + BW (4) + SF (1) + CR (1) |
| SetTxPower | 0x0A | Sendeleistung in 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 | Enable (1): 0x00=deaktiviert, ungleich 0=aktiviert |
| GetSignalReport | 0x1A | – |
Antwort-Sub-Commands (TNC an Host)
Antwort-Codes verwenden die High-Bit-Konvention: response = command | 0x80. Generische und unaufgeforderte Antworten nutzen den Bereich ab 0xF0.
| Sub-Command | Wert | Daten |
|---|---|---|
| Identity | 0x81 | PubKey (32) |
| Random | 0x82 | Zufallsbytes (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 | Gemeinsames Geheimnis (32) |
| Hash | 0x88 | SHA-256-Hash (32) |
| Radio | 0x8B | Freq (4) + BW (4) + SF (1) + CR (1) |
| TxPower | 0x8C | Sendeleistung in dBm (1) |
| CurrentRssi | 0x8D | RSSI in 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) + Errors (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 | Anfragedaten zu kurz |
| InvalidParam | 0x02 | Ungültiger Parameterwert |
| NoCallback | 0x03 | Funktion nicht verfügbar |
| MacFailed | 0x04 | MAC-Verifizierung fehlgeschlagen |
| UnknownCmd | 0x05 | Unbekannter Sub-Command |
| EncryptFailed | 0x06 | Verschlüsselung fehlgeschlagen |
| TxBusy | 0x07 | Sender beschäftigt |
Unaufgeforderte Ereignisse
Der TNC sendet diese SetHardware-Frames ohne vorangegangene Anfrage:
TxDone (0xF8): Wird nach dem Senden eines Pakets gesendet. Enthält ein einzelnes Byte:0x01 bei Erfolg, 0x00 bei Fehler.
RxMeta (0xF9): Wird unmittelbar nach jedem Standard-Data-Frame (Typ 0x00) gesendet und enthält Metadaten zum empfangenen Paket. Aufbau: SNR (1 Byte, vorzeichenbehaftet, Wert ×4 für 0,25-dB-Auflösung), gefolgt von RSSI (1 Byte, vorzeichenbehaftet, in dBm). Standardmäßig aktiviert; kann mit SetSignalReport ein- und ausgeschaltet werden. Standard-KISS-Clients ignorieren diesen Frame.
Datenformate
Funkparameter (SetRadio / Radio-Antwort)
Alle Werte sind Little-Endian (niedrigstwertiges Byte zuerst).
| Feld | Größe | Beschreibung |
|---|---|---|
| Frequency | 4 Bytes | Frequenz in Hz (z. B. 869618000) |
| Bandwidth | 4 Bytes | Bandbreite in Hz (z. B. 62500) |
| SF | 1 Byte | Spreizfaktor (Spreading Factor, 5–12) |
| CR | 1 Byte | Codierungsrate (Coding Rate, 5–8) |
Version (Version-Antwort)
| Feld | Größe | Beschreibung |
|---|---|---|
| Version | 1 Byte | Firmware-Version |
| Reserved | 1 Byte | Immer 0 |
Verschlüsselt (Encrypted-Antwort)
| Feld | Größe | Beschreibung |
|---|---|---|
| MAC | 2 Bytes | HMAC-SHA256, auf 2 Bytes gekürzt |
| Ciphertext | variabel | AES-128-Block-verschlüsselte Daten mit Zero-Padding |
Sendezeit (Airtime-Antwort)
Alle Werte sind Little-Endian.
| Feld | Größe | Beschreibung |
|---|---|---|
| Airtime | 4 Bytes | uint32_t, geschätzte Sendezeit in Millisekunden |
Grundrauschen (NoiseFloor-Antwort)
Alle Werte sind Little-Endian.
| Feld | Größe | Beschreibung |
|---|---|---|
| Noise Floor | 2 Bytes | int16_t, dBm (vorzeichenbehaftet) |
Das Modem kalibriert den Noise Floor (Grundrauschpegel) alle 2 Sekunden neu und führt alle 30 Sekunden einen AGC-Reset (Automatic Gain Control) durch.
Statistik (Stats-Antwort)
Alle Werte sind Little-Endian.
| Feld | Größe | Beschreibung |
|---|---|---|
| RX | 4 Bytes | Empfangene Pakete |
| TX | 4 Bytes | Gesendete Pakete |
| Errors | 4 Bytes | Empfangsfehler |
Batterie (Battery-Antwort)
Alle Werte sind Little-Endian.
| Feld | Größe | Beschreibung |
|---|---|---|
| Millivolts | 2 Bytes | uint16_t, Batteriespannung in mV |
MCU-Temperatur (MCUTemp-Antwort)
Alle Werte sind Little-Endian.
| Feld | Größe | Beschreibung |
|---|---|---|
| Temperature | 2 Bytes | int16_t, Zehntel °C (z. B. 253 = 25,3 °C) |
Gibt den Fehler NoCallback zurück, wenn das Board keine Temperaturmessung unterstützt.
Gerätename (DeviceName-Antwort)
| Feld | Größe | Beschreibung |
|---|---|---|
| Name | variabel | UTF-8-String, ohne Null-Terminierung |
Reboot (Neustart)
Sendet eine OK-Antwort, leert den seriellen Puffer und startet das Gerät anschließend neu. Der Host sollte damit rechnen, dass die Verbindung unterbrochen wird.
Sensor-Berechtigungen (GetSensors)
| Bit | Wert | Beschreibung |
|---|---|---|
| 0 | 0x01 | Basis (Batterie) |
| 1 | 0x02 | Standort (GPS) |
| 2 | 0x04 | Umgebung (Temperatur, Luftfeuchtigkeit, Luftdruck) |
0x07 verwenden, um alle Berechtigungen anzufordern.
Sensordaten (Sensors-Antwort)
Die Daten werden im CayenneLPP-Format zurückgegeben. Informationen zum Parsen finden sich in der CayenneLPP-Dokumentation.
Kryptografische Algorithmen
| Vorgang | Algorithmus |
|---|---|
| Identität / Signieren / Verifizierung | Ed25519 |
| Schlüsselaustausch (Key Exchange) | X25519 (ECDH) |
| Verschlüsselung | AES-128-Blockverschlüsselung mit Zero-Padding + HMAC-SHA256 (MAC auf 2 Bytes gekürzt) |
| Hashing | SHA-256 |
Hinweise
- Die Nutzlast-Beschränkung auf 255 Bytes entspricht der MeshCore-Konstante MAX_TRANS_UNIT. Die KISS-Empfehlung von „mindestens 1024 Bytes" gilt für Allzweck-TNCs und ist für MeshCore nicht relevant.
- Das Modem erzeugt beim ersten Start automatisch eine Identität, die im Flash-Speicher abgelegt wird.
- Alle Mehrbyte-Werte sind Little-Endian, sofern nicht anders angegeben.
- SNR-Werte in RxMeta sind mit 4 multipliziert, um eine Auflösung von 0,25 dB zu erreichen.
- TxDone wird nach jeder Übertragung als SetHardware-Ereignis gesendet.
- Standard-KISS-Clients empfangen ausschließlich Data-Frames vom Typ
0x00und können alle SetHardware-Frames (0x06) gefahrlos ignorieren. - Siehe Paket-Format für die Paketstruktur.