Tasmota MQTT QoS

  • Ich arbeite nach wie vor an meinem Zisternen-Messsystem. Es arbeitet bestens und zuverlässig. Inzwischen fiel mir aber etwas auf.

    Hin und wieder wird mal eine MQTT Nachricht nicht gesendet oder vom MQTT Broker nicht verarbeitet. Solange das die zu sendenden Messwerte betrifft, ist das kein Problem. Dann wird halt mal ein Messwert-Datensatz nicht gespeichert. Es gibt trotzdem genügend Datensätze, die alle 2 Minuten erfasst und gespeichert werden.

    Die Ursache liegt offensichtlich in der von Tasmota verwendeten MQTT Bibliothek "pubsub client". Darin ist die Quality of Service (QoS) nicht implementiert. Somit steht ausschließlich QoS 0 = fire and forget zur Verfügung. Eine diesbezüglich "bessere" Bibliothek könnte zukünftig zumindest in Tasmota32 verwendet/vorgesehen werden, da der ESP32 über relativ viel Speicher verfügt.

    Ich suche nun aber nach einem Workaround zu einer Art Nachbildung der QoS 2, die eine sichere und einmalige Übertragung einer Nachricht gewährleisten soll. Dazu erscheint mir meine Rahmenbedingung durchaus geeignet:

    Mein Messsystem erfasst die Unterschreitung eines benutzerdefiniertem Mindest-Wasservorrats. Daraufhin sendet es eine benutzerdefinierte MQTT Nachricht, die einen Wasserzulauf starten soll. Der Wasserzulauf wird von einem Shelly 1 mit Tasmota per Rules gesteuert. Das hier vermutlich nützliche und imho entscheidende Prinzip liegt darin, dass es genau einen zuständigen Empfänger, hier der Shelly 1, gibt. Entsprechendes ist zur Überschreitung eines Maximums implementiert.

    Meine Idee zur Nachbildung einer QoS 2:

    Der Sender, hier mein Messsystem, sendet eine retained Steuerungsnachricht. Der Empfänger, hier der Shelly 1, empfängt irgendwann diese Nachricht, wobei es sich bei irgendwann typischerweise um maximal wenige Sekunden später handelt. Da letztlich die Übertragung der Nachricht vom einzigen Adressaten empfangen wird, solange er funktioniert, kann dieser diesen Empfang durch eine Nachricht quittieren, dir zur Löschung der empfangenen Nachricht sorgt. Zu kompliziert? Ok, etwas einfacher:

    Sender sendet Steuerungsnachricht retained -> MQTT Broker -> einziger Abonnent empfängt Nachricht -> Abonnent sendet Nachricht zum löschen der retained Nachricht

    Nachdenk ... wie kann der Empfänger das Löschen der retained Nachricht erzwingen? Hm, per retained? Das habe ich noch nie nicht getestet.

    Frage:

    Hat jemand hier einschlägige Erfahrung mit einem solchen oder ähnlich gelagerten Workaround für QoS 2?

    Anmerkung:

    Für Steuerungen, die je Nachricht einmalig erfolgen sollen, sind retained Nachrichten zu unterlassen, da sich ansonsten ungewollte Phantom-Schaltvorgänge ereignen können.

    Gegen dieses Prinzip verstößt meine obige Workround-Idee. Ich vermute aber, dass sie trotzdem wie gewünscht funktionieren kann, da die retained Nachricht nach deren Empfang gelöscht werden soll.

    Irgendwie bleibt in mir der Verdacht haften, dass dieses Problem eine höhere Relevanz verdient. ;)

  • Hi.

    da hab ich keine Idee wie man QoS 2 nachbilden könnte.

    Das einzige was mir einfällt wäre, serverseitig für mehr Sicherheit zu sorgen.

    Sollte es ein Linux Server sein (RaspBerry) auf dem die Sensordaten in ein File geschrieben werden, würden ja ohne Sensoränderungen spätestens die Teleperiod Sensordaten übertragen. Erstellt man ein Bash-Skript das besagte Datendatei auf die letzte Schreibzugriffzeit (geht mit while do und find) überprüft und dieser letzte Schreibzugriff länger her ist als die Teleperioddauer (MQTT Übertragung verloren), dann könnte man das senden der Teleperiod mit den aktuellen Sensorwerten erneut per MQTT antriggern (mosquitto_pub -t cmnd/<topic>/teleperiod -n)

    Das muss natürlich nicht zwangsweiße Teleperiod sein obwohl man da auch mit der Häufigkeit spielen kann. Zumindest wird so sichergestellt das man innerhalb einer gewissen Zeit Daten erhält und könnte sogar nach X Fehlversuchen oder Schreibzugriffüberschreitung + X einen Alarm absetzen (Telegramm Mesenger o.ä.)

    benzino77 Tasmocompiler

    Gitpod Master Release

    Gitpod Development Release

    Sonoff-Basic / Sonoff-RF / Sonoff-Touch / Sonoff S20 / PowStro Basic / MagicHome / Sonoff-RF-Bridge mit diversen 433MHz RF Sender/Empfänger / Shelly_1 / ESP-WiFi-Dimmer / Gosund SP111 / ESP12E / WEMOS D1 Mini / ESP32Cam

    Sensoren: BME280/BMP280/HC-SR501/HC-SR04/ACS712/INA219/MHZ19B/DS3231

    Alexa Sprachsteuerung

    mosquitto/bash/html/cgi auf Wyse5070

    Einmal editiert, zuletzt von HoerMirAuf (6. September 2021 um 14:33)

  • Vielen Dank HoerMirAuf .

    Ich las mit Freude deine Reaktion, da ich mit keiner Reaktion rechnen musste.

    Deine Idee eines auf MQTT aufgesetzten eigenen Protokolls hat bei mir eine weitere Idee gebären lassen, die aber leider gegen mein Konzept (s.u. 2.) verstößt.

    Zu deiner Anregung:

    1. Es sind nicht Messdaten, die ich vermisse. Wenn da mal ein Datensatz nicht gespeichert wird - btw inzwischen in einer InfluxDB Datenbank, dann stört mich das nicht.
      Es ist eine Hysterese bedingt einmalig gesendete Steuerungsnachricht, die nicht verloren gehen soll.
      Konkret: Wenn ein Benutzer definiertes Minimum des Wasserstandes unterschritten wird, wird eine Nachricht zum öffnen des Wasserzulaufs gesendet. Diese Nachricht ist tatsächlich Benutzer definiert. Trägt der Anwender dafür nichts ein, wird auch nichts gesendet. Das Öffnen des Wasserzulaufs ist ein beispielhafter Parameterwert in der von mir implementierten Konfiguration. Bei Überschreitung des Benutzer definierten Maximums wird auf entsprechende Weise eine andere Benutzer definierte Nachricht gesendet. Da diese Ereignisse, Unterschreitung Minimum und Überschreitung Maximum, eine relativ hohe Bedeutung haben, sollten sie, anders als Messwerte, nicht verloren gehen können. Der Vergleich mit der Temperaturüberwachung in einem Motor mag dies verdeutlichen.
      (Nebenbei angemerkt nutze ich TelePeriod in meinem Messsystem nicht.)
    2. Mein Messsystem Konzept beinhaltet eine hohe Flexibilität in der Anwendung und demzufolge in der Konfiguration. Bezüglich o.a. Benutzer definierter Nachrichten bedeutet dies, dass im System keine Kenntnis über die Wirkung der Nachrichten vorliegen kann. Ich mag solche hohen Flexibilitäten, das ist evtl. mein Manko. ;)

    Vielleicht sollte ich bei Unterschreitung des Minimums die Einmaligkeit des Nachrichtsendens verlassen. Dann bliebe aber das Problem immer noch bei der Überschreitung des Maximums. Also komme ich womöglich nicht an einem Protokoll vorbei, das ähnlich dem von dir aufgezeigtem sein könnte.

    Nachdenken erforderlich ... brainstorming ... mal sehen.

    Wie dem auch sei, nochmals vielen Dank für deine Reaktion.

    Nachtrag:

    Ich setze einen Raspberry Pi 4 mit 8 GB RAM und dem Raspberry OS lite ein. Auf diesem werkeln der MQTT Broker, Node-RED, InfluxDB und Grafana. Das System läuft seit dem 2021-08-29 stabil. Mein Messsytem besteht aus einem ESP32 Board mit Tasmota32 und in Berry geschriebener Anwendungsschicht incl. nativer Rules. Auch das Messsystem arbeitet zuverlässig - bis auf die vermisste QoS 2.

    Einmal editiert, zuletzt von eich (6. September 2021 um 15:22)

  • Hi eich

    Also wenn es sich nur um EIN spezielles Signal handelt würde ich das mir Rules lösen.

    Rule1 wertet den Sensor aus. Wird ein Grenzwert unterschritten wird Rule2 aktiv, wird der Grenzwert überschritten wird die Rule2 deaktiviert.

    Rule2 sendet in einer Schleife (Ruletimer der sich selbst neu setzte) eine MQTT Nachricht und/oder machst sonst noch was sie soll.

    Das ist zwar kein QoS 2 aber immerhin eine Redundanz des MQTT Signals.

    Ich würde die MQTT Nachricht die in Rule2 gesendet wird am Server auswerten und bei Empfang eine MQTT Nachricht zurückschicken die Rule2 deaktiviert. z.B. wenn der Grenzwert wieder überschritten ist, anstatt das von Rule1 machen zu lassen. Oder eben vor dem in der Rule1 festgelegtem Grenzwert.

    Dann wäre die Sicherheit falls die Nachricht vom Server zum Gerät verloren geht sich die Rule2 vom Gerät bei einem Maximum auf jeden Fall deaktiviert wird.

    Damit wäre die Hysterese vorhanden und auch eine Art QoS

    benzino77 Tasmocompiler

    Gitpod Master Release

    Gitpod Development Release

    Sonoff-Basic / Sonoff-RF / Sonoff-Touch / Sonoff S20 / PowStro Basic / MagicHome / Sonoff-RF-Bridge mit diversen 433MHz RF Sender/Empfänger / Shelly_1 / ESP-WiFi-Dimmer / Gosund SP111 / ESP12E / WEMOS D1 Mini / ESP32Cam

    Sensoren: BME280/BMP280/HC-SR501/HC-SR04/ACS712/INA219/MHZ19B/DS3231

    Alexa Sprachsteuerung

    mosquitto/bash/html/cgi auf Wyse5070

  • Zwei Node-RED Flows oder zwei Shellscripts, die ein solches proprietäres Protokoll serverseitig implementieren. Das ist eine sehr interessante, ergänzende Idee.

    Meine Rules sind zwar stark belegt, auch mit enable/disable, aber in Verbindung mit einer Berry Kommandofunktion könnte das gelingen.

    Der Timer könnte ständig laufen, die Berry Funktion kann per Boolwert oder Moduswert etwas tun oder auch nichts tun, abhängig von einer erhaltenen Quittierung.

    Auch das Umstellen auf eine andere Kommandofunktion, ähnlich einer Fallunterscheidung, nur halt ereignisgesteuert, ist eine implementierbare Option.

    Elegant und leicht anpassbar sollte dies mit Funktionszeigern gelingen. Das erinnert bereits an Schrittkettensteuerung.

    Das werde ich bei Muße mal genauer betrachten und prüfen.

    Danke für deine Anregungen, das wird mich vermutlich dem Ziel näherbringen.

  • Meine Rules sind zwar stark belegt, auch mit enable/disable, aber in Verbindung mit einer Berry Kommandofunktion könnte das gelingen.

    Ich hab keinerlei Ahnung von Berry. Aber eventuell würd es dir viel nutzen mit den Conditional Rules zu arbeiten:

    https://tasmota.github.io/docs/Rules/#conditional-rules

    Mit if then else solltest du da eigentlich recht weit kommen.

    benzino77 Tasmocompiler

    Gitpod Master Release

    Gitpod Development Release

    Sonoff-Basic / Sonoff-RF / Sonoff-Touch / Sonoff S20 / PowStro Basic / MagicHome / Sonoff-RF-Bridge mit diversen 433MHz RF Sender/Empfänger / Shelly_1 / ESP-WiFi-Dimmer / Gosund SP111 / ESP12E / WEMOS D1 Mini / ESP32Cam

    Sensoren: BME280/BMP280/HC-SR501/HC-SR04/ACS712/INA219/MHZ19B/DS3231

    Alexa Sprachsteuerung

    mosquitto/bash/html/cgi auf Wyse5070