Berry-Skript für Tasmota:
So bindest du den Dragino LDS02 via LoRaWAN ein!

Tasmota Lora LoraWAN LDS02

Vorwort: Worum geht es in diesem Skript?

Hier ist das Skript, das ich in diesem YouTube-Video vorgestellt habe. Ich habe es etwas optimiert und alles Unnötige entfernt, sodass nur noch der Teil mit dem LDS02 übrig geblieben ist. Das Skript ist besonders hilfreich, wenn man nicht nur die Daten per MQTT oder ähnliches auslesen möchte, sondern sie auch direkt auf der Web-UI darstellen will.

Falls ihr den Empfang eures LoRaWAN-ESP32 testen möchtet, schaut gerne hier vorbei: Dort findet ihr ein Skript, das alle 5 Sekunden eine Testnachricht sendet. Damit könnt ihr ganz einfach die Empfangsqualität prüfen und optimieren!

Weiterführende Informationen zu LoRa, LoRaWAN usw. findet ihr auf der Tasmota GitHub Seite.


Verwendete Hardware:

Affiliate-Links:
»Heltec« ☛ https://amzn.to/3XlQ47q
»LilyGo« ☛ https://amzn.to/3XkM5rG
»Dragino« ☛ https://amzn.to/3D9BlWs


TasmotaSendeEmpfangenLora

Damit das Skript funktioniert, müssen einige Bedingungen erfüllt sein:

  1. Es muss ein Sensor vorhanden sein, den man mittels LoRaWANName1 xxx in LDS02 umbenannt hat.
  2. Es muss ein Feld mit „Name“ vorhanden sein und eines mit „Doorstatus“.
  3. Außerdem müssen folgende Einstellungen gesetzt werden:
    • SetOption100 1: Entfernt LwReceived aus der JSON-Nachricht.
    • SetOption119 1: Entfernt die Geräteadresse aus dem JSON-Payload. Dies ist nützlich, wenn der Name bereits über LoRaWANName bekannt ist und die Adresse nicht benötigt wird.

Wenn alles korrekt eingerichtet ist, wird euch auf der Web-UI folgendes angezeigt:

  • Der Türstatus (offen/geschlossen).
  • Die Signalstärke (RSSI) und Signalqualität (SNR).
  • Die Uhrzeit der letzten Änderung.
Berry-Skript für die Web-UI anzeige des Dragino LDS02 in Tasmota

Diese Informationen können vor allem bei der Inbetriebnahme sehr hilfreich sein.
Hinweis: Denkt daran, wie im Video erwähnt, den LDS02 fest auf eine Frequenz und einen SF (Spreading Factor) einzustellen. Detaillierte Informationen dazu findet ihr in meinem Video auf YouTube.


Erklärung der relevanten Zeilen

1. Initialisierung der Variablen

Berry
  def init()
    self.rssi_value = 0.0
    self.snr_value = 0.0
    self.door_status_value = "Tür Status unbekannt"
    self.door_status_change_time = "0:00"
  end
  • Was passiert hier?
    • Beim Start des Skripts werden die Variablen initialisiert, also mit „0-Werte“ beschrieben:
      • rssi_value und snr_value speichern die Signalstärke und -qualität.
      • door_status_value speichert den aktuellen Türstatus.
      • door_status_change_time speichert die Uhrzeit der letzten Statusänderung.

2. Aktualisierung der Signalstärke (RSSI)

Berry
  def update_rssi(value)
    self.rssi_value = value
  end
  • Was passiert hier?
    • Diese Methode aktualisiert den Wert der Signalstärke (RSSI), der in dBm gemessen wird.

3. Aktualisierung der Signalqualität (SNR)

Berry
  def update_snr(value)
    self.snr_value = value
  end
  • Was passiert hier?
    • Diese Methode aktualisiert den Wert der Signalqualität (SNR), der in dB gemessen wird.

4. Aktualisierung der Uhrzeit

Berry
  def update_time()
    var t = tasmota.time_dump(tasmota.rtc()["local"])
    self.door_status_change_time = format("%02d:%02d:%02d Uhr", t["hour"], t["min"], t["sec"])
  end
  • Was passiert hier?
    • Die Methode holt die aktuelle Uhrzeit vom System (tasmota.rtc()["local"]).
    • Die Zeit wird im Format HH:MM:SS Uhr formatiert und in door_status_change_time gespeichert.

5. Änderung des Türstatus

Berry
  def doorstatuschange(doorstatus)
    if (doorstatus == 1)
      self.door_status_value = "offen"
    else
      self.door_status_value = "geschlossen"
    end
    self.update_time()
  end
  • Was passiert hier?
    • Diese Methode wird aufgerufen, wenn sich der Türstatus ändert.
    • Wenn doorstatus den Wert 1 hat, ist die Tür offen, sonst geschlossen.
    • Die Uhrzeit der letzten Änderung wird aktualisiert.

6. Anzeige der Daten auf der Webseite

Berry
  def web_sensor()
    webserver.content_send("<h1 style='font-size:32px; text-align:center;'>LDS02 Status</h1>")
    webserver.content_send("<table style='width:100%; border-bottom:2px solid white; margin-bottom:10px;'>")
    webserver.content_send("<tr><td></td></tr>")
    webserver.content_send("</table>")
    webserver.content_send("<div style='text-align:center; margin-bottom:10px; font-size:16px; font-weight:bold;'>")
    webserver.content_send(format("{s}Türstatus:{m}%s{e}", self.door_status_value))
    webserver.content_send("</div>")
    webserver.content_send("<div style='text-align:center; margin-bottom:10px; font-size:smaller;'>")
    webserver.content_send(format("{s}RSSI:{m}%.1f dBm{e}", self.rssi_value))
    webserver.content_send("  ")
    webserver.content_send(format("{s}SNR:{m}%.1f dB{e}", self.snr_value))
    webserver.content_send("</div>")
    webserver.content_send("<div style='text-align:center; margin-bottom:10px; font-size:smaller;'>")
    webserver.content_send(format("{s}Letzte Änderung:{m}%s{e}", self.door_status_change_time))
    webserver.content_send("</div>")
  end
Vollständige Code anzeigen
  • Was passiert hier?
    • Die Methode erstellt die Texte auf der Web-UI, die die gesammelten Daten anzeigt.
    • Überschrift: „LDS02 Status“ in großer Schrift (32px) und zentriert.
    • Trennlinie: Eine weiße, horizontale Linie (2px dick).
    • Türstatus: Wird in fetter Schrift (16px) angezeigt.
    • RSSI und SNR: Werden in einer Zeile mit kleinerer Schriftgröße angezeigt.
    • Letzte Änderung: Die Uhrzeit der letzten Türstatusänderung wird in kleinerer Schriftgröße angezeigt.

7. Event-Handler für RSSI und SNR

Berry
tasmota.add_rule('RSSI', def (v,t,d) global.sensor_handler_instance.update_rssi(v) end)
tasmota.add_rule('SNR', def (v,t,d) global.sensor_handler_instance.update_snr(v) end)
  • Was passiert hier?
    • Diese Regeln aktualisieren die Werte für RSSI und SNR, sobald neue Daten empfangen werden.

8. Event-Handler für Türstatusänderung

Berry
tasmota.add_rule(['DoorOpen','Name=LDS02'],
  def (values, trigger, data)
    var doorstatus = values[0]
    global.sensor_handler_instance.doorstatuschange(doorstatus)
  end)
  • Was passiert hier?
    • Diese Regel wird ausgelöst, wenn sich der Türstatus ändert.
    • Der neue Türstatus wird an die Methode doorstatuschange übergeben, um den Status und die Uhrzeit zu aktualisieren.

9. Gesamte Fertige Code

Berry
import webserver

class SensorHandler : Driver
  var rssi_value
  var snr_value
  var door_status_value
  var door_status_change_time  # Speichert die Zeit der letzten Türstatusänderung

  def init()
    self.rssi_value = 0.0
    self.snr_value = 0.0
    self.door_status_value = "  Tür Status unbekannt"
    self.door_status_change_time = "  0:00 Uhr"  # Initialzeit für die Türstatusänderung
  end

  def update_rssi(value)
    self.rssi_value = value
  end

  def update_snr(value)
    self.snr_value = value
  end

  def update_time()
    var t = tasmota.time_dump(tasmota.rtc()["local"])
    self.door_status_change_time = format("%02d:%02d:%02d Uhr", t["hour"], t["min"], t["sec"])  # Uhrzeit mit "Uhr" formatieren
  end

  def doorstatuschange(doorstatus)
    print(f"Aktueller Türstatus: {self.door_status_value}")
    if (doorstatus == 1)
      self.door_status_value = "  offen"
    else
      self.door_status_value = "  geschlossen"
    end
    # Aktualisiere die Zeit nur, wenn sich der Türstatus ändert
    self.update_time()
    print(f"Türstatus geändert auf: {self.door_status_value} um {self.door_status_change_time}")
  end

  def web_sensor()
    # Überschrift "LDS02 Status" mit Schriftgröße 32, zentriert
    webserver.content_send("<h1 style='font-size:32px; text-align:center;'>LDS02 Status</h1>")

    # Horizontale Trennlinie (weiß, 2px) mit Tabelle
    webserver.content_send("<table style='width:100%; border-bottom:2px solid white; margin-bottom:10px;'>")
    webserver.content_send("<tr><td></td></tr>")  # Leere Zeile für die Trennlinie
    webserver.content_send("</table>")

    # Türstatus anzeigen (zentriert, Schriftgröße 16px, fett)
    webserver.content_send("<div style='text-align:center; margin-bottom:10px; font-size:16px; font-weight:bold;'>")
    webserver.content_send(format("{s}Türstatus:{m}%s{e}", self.door_status_value))
    webserver.content_send("</div>")

    # RSSI und SNR in einer Zeile, Schriftgröße 3 Stufen kleiner
    webserver.content_send("<div style='text-align:center; margin-bottom:10px; font-size:smaller;'>")
    webserver.content_send(format("{s}RSSI: {m}%.1f dBm{e}", self.rssi_value))
    webserver.content_send("  ")  # Abstand zwischen RSSI und SNR
    webserver.content_send(format("{s}SNR: {m}%.1f dB{e}", self.snr_value))
    webserver.content_send("</div>")

    # Letzte Änderung (zentriert, Schriftgröße 3 Stufen kleiner)
    webserver.content_send("<div style='text-align:center; margin-bottom:10px; font-size:smaller;'>")
    webserver.content_send(format("{s}Letzte Änderung: {m}%s{e}", self.door_status_change_time))
    webserver.content_send("</div>")
  end
end

# Alte Instanz bereinigen
try
  if global.sensor_handler_instance
    tasmota.remove_driver(global.sensor_handler_instance)
  end
except .. as e
  print("Fehler beim Bereinigen der alten Instanz:", e)
end

# Neue Instanz erstellen
global.sensor_handler_instance = SensorHandler()
tasmota.add_driver(global.sensor_handler_instance)

# Event-Handler
tasmota.add_rule('RSSI', def (v,t,d) global.sensor_handler_instance.update_rssi(v) end)
tasmota.add_rule('SNR', def (v,t,d) global.sensor_handler_instance.update_snr(v) end)

# Türstatus-Regel
tasmota.add_rule(['DoorOpen','Name=LDS02'],
  def (values, trigger, data)
    var doorstatus = values[0]  # Der ausgelöste Wert
    var alarm = data['Alarm']  # Ein weiteres Feld aus der Nutzlast
    global.sensor_handler_instance.doorstatuschange(doorstatus)  # Setzt den Türstatus
  end)
Vollständige Code anzeigen

Hinweis und Community-Beitrag

Ich bin kein professioneller Programmierer, sondern ein begeisterter Smart-Home-Enthusiast, der gerne mit LoRa und Tasmota experimentiert. Daher kann es sein, dass das Skript nicht perfekt ist oder sich bestimmte Dinge noch optimieren lassen.

Falls euch beim Testen Fehler auffallen oder ihr Ideen habt, wie man das Skript verbessern kann, freue ich mich über euer Feedback! Schreibt mir gerne eure Vorschläge, und ich werde sinnvolle Änderungen übernehmen. Natürlich werde ich jede Anpassung nur mit eurer Zustimmung veröffentlichen, sodass die Community von den Verbesserungen profitieren kann.

⚠️ Hinweis zu Affiliate-Links:
Alle Links zu Produkten auf dieser Website sind Affiliate-Links. Durch das Anklicken dieser Links unterstützt du meine Arbeit und hilfst mir, diese Website zu finanzieren.
Für dich entstehen dabei keine zusätzlichen Kosten – der Preis bleibt gleich.
Ich erhalte lediglich eine kleine Provision vom Händler oder Amazon. Vielen Dank für deine Unterstützung! 🙏