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

3.8 KiB
Raw Blame History

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

  1. Öffne ChirpStack → Device ProfileCodec
  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:

{
  "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