epaper-display/3_SENSOR_lorawan-ds18b20-local-lmic/CHIRPSTACK_DECODER_FUELLSTAND.md
Christian Mueller e706b22f31 Add design specification for LoRaWAN Web Portal
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>
2026-03-19 22:27:49 +01:00

147 lines
3.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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
```javascript
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
1. Öffne ChirpStack → **Device Profile****Codec**
2. Wähle **JavaScript** als Codec
3. Kopiere den Decoder-Code ins **Uplink decoder** Feld
4. Klicke **Submit**
## Anzeige in ChirpStack
Nach erfolgreicher Dekodierung siehst du in ChirpStack:
```json
{
"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:
1. **Gauge**: `fill_percent` (0-100%)
2. **Graph**: `fill_height_cm` über Zeit
3. **Gauge**: `battery_percent` (0-100%)
4. **Graph**: `battery_v` über Zeit (Batterie-Entladung)
5. **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