# ChirpStack Decoder Einrichtung ## Problem Die Payload wird als Hex-String angezeigt (`frm_payload:"008b"`), aber nicht dekodiert. ## Lösung: Decoder im Device Profile einrichten ### Schritt 1: Device Profile öffnen 1. Gehe zu **Device Profiles** in ChirpStack 2. Wähle das Device Profile aus, das dein Gerät verwendet 3. Falls du nicht weißt welches: Gehe zu deinem Device und schaue unter "Device Profile" ### Schritt 2: Codec konfigurieren #### Für ChirpStack v4: 1. Öffne dein **Device Profile** 2. Klicke auf den Tab **"Codec"** 3. Wähle bei **Codec**: `JavaScript` 4. Füge folgenden Code in das **Uplink decoder** Feld ein: ```javascript function decodeUplink(input) { // Robuster Decoder für HC-SR04 Ultraschallsensor var bytes = input.bytes; var fPort = input.fPort; // Debug-Informationen var debug = { bytes_received: bytes.length, fPort: fPort, raw_hex: "" }; // Bytes als Hex-String für Debug for (var i = 0; i < bytes.length; i++) { debug.raw_hex += bytes[i].toString(16).padStart(2, '0'); } // Validierung if (bytes.length !== 2) { return { errors: ["Invalid payload length - expected 2 bytes, got " + bytes.length + " bytes. Hex: " + debug.raw_hex] }; } // Port 1 = Distanz if (fPort !== 1) { return { errors: ["Invalid fPort - expected 1, got " + fPort] }; } // Distanz aus 2 Bytes (Big Endian) auslesen var distanceMm = (bytes[0] << 8) | bytes[1]; // Umrechnung in verschiedene Einheiten var distanceCm = distanceMm / 10.0; var distanceM = distanceMm / 1000.0; return { data: { distance_mm: distanceMm, distance_cm: distanceCm, distance_m: distanceM, debug: debug } }; } ``` 5. Klicke auf **"Submit"** oder **"Save"** #### Für ChirpStack v3: 1. Öffne dein **Device Profile** 2. Klicke auf den Tab **"Codec"** 3. Wähle bei **Payload codec**: `Custom JavaScript codec functions` 4. Füge folgenden Code in das **Decode function** Feld ein: ```javascript function Decode(fPort, bytes) { if (bytes.length !== 2) { return { error: "Invalid payload length - expected 2 bytes, got " + bytes.length }; } // Distanz aus 2 Bytes (Big Endian) auslesen var distanceMm = (bytes[0] << 8) | bytes[1]; // Umrechnung in verschiedene Einheiten var distanceCm = distanceMm / 10.0; var distanceM = distanceMm / 1000.0; return { distance_mm: distanceMm, distance_cm: distanceCm, distance_m: distanceM }; } ``` 5. Klicke auf **"Update device-profile"** ### Schritt 3: Decoder testen 1. Im Device Profile, unter **Codec** 2. Klicke auf **"Test decoder"** (falls vorhanden) 3. Gib ein: `008b` (deine aktuelle Payload) 4. Erwartetes Ergebnis: ```json { "data": { "distance_mm": 139, "distance_cm": 13.9, "distance_m": 0.139 } } ``` ### Schritt 4: Neue Daten empfangen 1. Warte auf die nächste Uplink-Nachricht (alle 30 Sekunden) 2. Gehe zu deinem **Device** → **LoRaWAN frames** oder **Events** 3. Bei der neuen Uplink-Message solltest du nun sehen: ```json { "object": { "distance_mm": 139, "distance_cm": 13.9, "distance_m": 0.139 } } ``` ## Deine aktuelle Payload dekodiert **Raw Payload:** `008b` - Byte 0: `00` (hex) = 0 (dezimal) - Byte 1: `8b` (hex) = 139 (dezimal) - **Distanz:** 0×256 + 139 = **139 mm = 13.9 cm** Das bedeutet, dein Sensor misst aktuell eine Distanz von **13.9 cm** zu einem Objekt! ## Weitere Beispiele | Hex Payload | Berechnung | Distanz | |-------------|------------|---------| | `008b` | (0×256) + 139 = 139 | 13.9 cm | | `04d2` | (4×256) + 210 = 1234 | 123.4 cm | | `0064` | (0×256) + 100 = 100 | 10.0 cm | | `03e8` | (3×256) + 232 = 1000 | 100.0 cm = 1 m | | `ffff` | (255×256) + 255 = 65535 | 6553.5 cm = 65.5 m | ## Alternative: Minimaler Decoder (ohne Validierung) Falls der obige Decoder Probleme macht, versuche diesen **minimalen Decoder**: ```javascript function decodeUplink(input) { var bytes = input.bytes; var distanceMm = (bytes[0] << 8) | bytes[1]; return { data: { distance_mm: distanceMm, distance_cm: distanceMm / 10.0, distance_m: distanceMm / 1000.0 } }; } ``` Dieser Decoder hat **keine Fehlerprüfung** und sollte immer funktionieren. ## Troubleshooting ### Decoder wird nicht angewendet **Problem:** Payload wird immer noch als Hex angezeigt **Lösungen:** 1. ✅ Stelle sicher, dass der Decoder im **Device Profile** gespeichert wurde 2. ✅ Warte auf eine **neue** Uplink-Message (alte Messages werden nicht neu dekodiert) 3. ✅ Prüfe, ob JavaScript-Fehler im Decoder vorhanden sind 4. ✅ Stelle sicher, dass das richtige Device Profile verwendet wird ### JavaScript Fehler im Decoder **Fehler:** `SyntaxError` oder `Unexpected token` **Lösung:** - Kopiere den Code genau wie oben angegeben - Achte auf korrekte Klammern `{ }` und Semikolons `;` - Verwende keinen Kommentar-Stil, der nicht unterstützt wird ### Payload hat falsche Länge **Fehler:** `Invalid payload length` **Problem:** Die Payload hat nicht genau 2 Bytes **Lösung:** - Überprüfe den Arduino-Code in `do_send()` Funktion - Stelle sicher, dass `sizeof(payload)` = 2 ist - Prüfe Serial Monitor Ausgabe ### Negative Distanzwerte **Problem:** Distanz wird als sehr große Zahl angezeigt **Ursache:** HC-SR04 liefert Fehler (-1), wird aber als uint16_t interpretiert **Lösung:** Der Code fängt dies bereits ab und sendet 0 bei Fehlern: ```cpp if (distance < 0) { distance = 0; // Fehlerfall } ``` ## Integration mit anderen Systemen ### InfluxDB / Grafana Nach Dekodierung kannst du die Daten in InfluxDB speichern: ```javascript // ChirpStack v4 Integration { "measurement": "distance_sensor", "tags": { "device": "hc-sr04-01" }, "fields": { "distance_cm": {{.object.distance_cm}}, "distance_m": {{.object.distance_m}} } } ``` ### MQTT Die dekodierten Daten werden automatisch über MQTT publiziert: **Topic:** `application/{application_id}/device/{dev_eui}/event/up` **Payload:** ```json { "deviceName": "hc-sr04-sensor-01", "devEUI": "70b3d57ed005a1b2", "object": { "distance_mm": 139, "distance_cm": 13.9, "distance_m": 0.139 } } ``` ### Node-RED Du kannst die Daten in Node-RED empfangen und verarbeiten: ```javascript // Node-RED Function Node var distance_cm = msg.payload.object.distance_cm; if (distance_cm < 20) { msg.payload = "Warnung: Objekt zu nah!"; return [msg, null]; } else { msg.payload = "Distanz OK: " + distance_cm + " cm"; return [null, msg]; } ``` ## Decoder mit erweiterten Features (Optional) Wenn du später mehr Daten senden möchtest, kannst du den Decoder erweitern: ```javascript function decodeUplink(input) { var bytes = input.bytes; var data = {}; // Port 1: Distanz (2 Bytes) if (input.fPort === 1 && bytes.length === 2) { var distanceMm = (bytes[0] << 8) | bytes[1]; data.distance_mm = distanceMm; data.distance_cm = distanceMm / 10.0; data.distance_m = distanceMm / 1000.0; } // Port 2: Temperatur (optional für später) else if (input.fPort === 2 && bytes.length === 2) { var temp = ((bytes[0] << 8) | bytes[1]) / 100.0; data.temperature = temp; } else { return { errors: ["Invalid fPort or payload length"] }; } return { data: data }; } ``` ## Zusammenfassung 1. ✅ Gehe zu **Device Profiles** → Dein Profil → **Codec** 2. ✅ Wähle **JavaScript** als Codec 3. ✅ Kopiere den Decoder-Code ein 4. ✅ Speichere das Device Profile 5. ✅ Warte auf nächste Uplink-Message 6. ✅ Überprüfe dekodierte Daten unter **Device** → **Events** Deine Sensordaten sollten nun lesbar sein! 🎉