Based on Pflichtenheft v2.2, documents the full system design including daemon, API, frontend, and infrastructure with agreed deviations (Axum 0.8, SQLx 0.8, Vite 6, Tailwind 4). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
7.5 KiB
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
- Gehe zu Device Profiles in ChirpStack
- Wähle das Device Profile aus, das dein Gerät verwendet
- Falls du nicht weißt welches: Gehe zu deinem Device und schaue unter "Device Profile"
Schritt 2: Codec konfigurieren
Für ChirpStack v4:
- Öffne dein Device Profile
- Klicke auf den Tab "Codec"
- Wähle bei Codec:
JavaScript - Füge folgenden Code in das Uplink decoder Feld ein:
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
}
};
}
- Klicke auf "Submit" oder "Save"
Für ChirpStack v3:
- Öffne dein Device Profile
- Klicke auf den Tab "Codec"
- Wähle bei Payload codec:
Custom JavaScript codec functions - Füge folgenden Code in das Decode function Feld ein:
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
};
}
- Klicke auf "Update device-profile"
Schritt 3: Decoder testen
- Im Device Profile, unter Codec
- Klicke auf "Test decoder" (falls vorhanden)
- Gib ein:
008b(deine aktuelle Payload) - Erwartetes Ergebnis:
{
"data": {
"distance_mm": 139,
"distance_cm": 13.9,
"distance_m": 0.139
}
}
Schritt 4: Neue Daten empfangen
- Warte auf die nächste Uplink-Nachricht (alle 30 Sekunden)
- Gehe zu deinem Device → LoRaWAN frames oder Events
- Bei der neuen Uplink-Message solltest du nun sehen:
{
"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:
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:
- ✅ Stelle sicher, dass der Decoder im Device Profile gespeichert wurde
- ✅ Warte auf eine neue Uplink-Message (alte Messages werden nicht neu dekodiert)
- ✅ Prüfe, ob JavaScript-Fehler im Decoder vorhanden sind
- ✅ 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:
if (distance < 0) {
distance = 0; // Fehlerfall
}
Integration mit anderen Systemen
InfluxDB / Grafana
Nach Dekodierung kannst du die Daten in InfluxDB speichern:
// 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:
{
"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:
// 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:
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
- ✅ Gehe zu Device Profiles → Dein Profil → Codec
- ✅ Wähle JavaScript als Codec
- ✅ Kopiere den Decoder-Code ein
- ✅ Speichere das Device Profile
- ✅ Warte auf nächste Uplink-Message
- ✅ Überprüfe dekodierte Daten unter Device → Events
Deine Sensordaten sollten nun lesbar sein! 🎉