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>
3.8 KiB
3.8 KiB
ChirpStack Decoder für Füllstandsmessung
Payload-Format (8 Bytes)
Das Gerät sendet 8 Bytes via LoRaWAN:
| Bytes | Beschreibung | Einheit | Berechnung |
|---|---|---|---|
| 0-1 | Distanz | mm | Big Endian uint16 |
| 2-3 | Füllhöhe | mm | Big Endian uint16 |
| 4-5 | Füllstand | % × 10 | Big Endian uint16 (855 = 85.5%) |
| 6-7 | Batterie | mV | Big Endian uint16 (3700 = 3.7V) |
Decoder-Code für ChirpStack v4
function decodeUplink(input) {
var bytes = input.bytes;
var fPort = input.fPort;
// Validierung
if (bytes.length !== 8) {
return {
errors: ["Invalid payload length - expected 8 bytes, got " + bytes.length]
};
}
if (fPort !== 1) {
return {
errors: ["Invalid fPort - expected 1, got " + fPort]
};
}
// Distanz (Byte 0-1, Big Endian)
var distanceMm = (bytes[0] << 8) | bytes[1];
var distanceCm = distanceMm / 10.0;
var distanceM = distanceMm / 1000.0;
// Füllhöhe (Byte 2-3, Big Endian)
var fillHeightMm = (bytes[2] << 8) | bytes[3];
var fillHeightCm = fillHeightMm / 10.0;
var fillHeightM = fillHeightMm / 1000.0;
// Füllstand in % (Byte 4-5, Big Endian, × 10)
var fillPercentRaw = (bytes[4] << 8) | bytes[5];
var fillPercent = fillPercentRaw / 10.0;
// Batteriespannung (Byte 6-7, Big Endian, in mV)
var batteryMv = (bytes[6] << 8) | bytes[7];
var batteryV = batteryMv / 1000.0;
// Batterie-Prozent berechnen (LiPo: 3.0V = 0%, 4.2V = 100%)
var batteryPercent = ((batteryV - 3.0) / (4.2 - 3.0)) * 100.0;
if (batteryPercent < 0) batteryPercent = 0;
if (batteryPercent > 100) batteryPercent = 100;
return {
data: {
// Distanz (Sensor bis Flüssigkeit)
distance_mm: distanceMm,
distance_cm: distanceCm,
distance_m: distanceM,
// Füllhöhe (Flüssigkeitshöhe im Tank)
fill_height_mm: fillHeightMm,
fill_height_cm: fillHeightCm,
fill_height_m: fillHeightM,
// Füllstand in Prozent
fill_percent: fillPercent,
// Batterie
battery_mv: batteryMv,
battery_v: batteryV,
battery_percent: Math.round(batteryPercent)
}
};
}
Beispiel-Payloads
Angenommen: Tank-Höhe = 180 cm
| Payload (Hex) | Distanz | Füllhöhe | Füllstand |
|---|---|---|---|
0348 0AA0 0226 |
84.0 cm | 170.0 cm | 94.4% |
05DC 0708 0197 |
150.0 cm | 180.0 cm | 40.9% |
0708 0000 0000 |
180.0 cm | 0.0 cm | 0% |
0014 06F8 03E8 |
2.0 cm | 178.0 cm | 100.0% |
Berechnung Beispiel 1: 0348 0AA0 0226
- Distanz:
0x0348= 840 mm = 84.0 cm - Füllhöhe:
0x0AA0= 2720 mm = 272.0 cm (Fehler! sollte max 180cm sein) - Füllstand:
0x0226= 550 = 55.0%
Installation
- Öffne ChirpStack → Device Profile → Codec
- Wähle JavaScript als Codec
- Kopiere den Decoder-Code ins Uplink decoder Feld
- Klicke Submit
Anzeige in ChirpStack
Nach erfolgreicher Dekodierung siehst du in ChirpStack:
{
"distance_mm": 840,
"distance_cm": 84.0,
"distance_m": 0.084,
"fill_height_mm": 960,
"fill_height_cm": 96.0,
"fill_height_m": 0.096,
"fill_percent": 53.3,
"battery_mv": 3850,
"battery_v": 3.85,
"battery_percent": 71
}
Grafana Dashboard
Empfohlene Visualisierungen:
- Gauge:
fill_percent(0-100%) - Graph:
fill_height_cmüber Zeit - Gauge:
battery_percent(0-100%) - Graph:
battery_vüber Zeit (Batterie-Entladung) - Graph:
distance_cmüber Zeit (Fehlerdiagnose)
Troubleshooting
Negative Füllhöhe
Problem: Füllhöhe zeigt negative Werte
Lösung: Tank-Höhe (TANK_HEIGHT) im Code anpassen
Füllstand über 100%
Problem: Füllstand zeigt über 100%
Lösung: Sensor ist zu nah am Boden installiert oder Tank-Höhe falsch konfiguriert