MQTT best current practice

Begonnen von martinp876, 26 Juli 2026, 09:56:44

Vorheriges Thema - Nächstes Thema

martinp876

nachdem Homematic nun EOL ist - und teuer - und die IP version auch teuer und mächtig indirekt bin ich bei shelly und Tasmota vermeintlich fündig geworden. Ich versuche nun diese beiden in deren generischen Versionen über MQTT2 in die bestehende Installation einzubinden. Die bestehende Beschreibubg ist sehr mächtig - ich hatte jedoch einige Probleme (auch weil ich nur sehr selten weiter arbeite...) das ganze mit Hand und Fuss einzubauen - und habe es immer noch nicht. Ertstes wirkliches Objekt ist ein  Shelly 2 kanal schalter (eigentlich einfach).
Anforderungen der Implementierung sind (für mich auf der Hand liegend):
- einfache Handhabung der Installation (keine endlos langen Attribute!)
- performantes System - ich rechne leicht mit 30+ devices und 100+ entities in fhem.
- automatische Systemprüfung - sind alle devices erreichbar
- nahtlose Einbindung in das bestehende System - beinhaltet, dass alle Readingnamen denen üblichen konventionen entsprechen
- Kanal Entities - zumindest möglich. Ein System funktioniert nur so generisch

Dass mir die Attribute zu lang sind, somit schlecht überprüfbar und ausserdem die Webdarstellung torpedeiren  - nun ja - werde ich ändern.
Performance-wise: die CID muss der Schlüssel zur Prüfung und erstellung der Readings sein. Das ist aktuell ein suchen über sämtliche regexp - passt mit meinen Performance-regeln nicht zusammen.
Die Erstellung der ReadingsList regeln ist für meine Lesart komplex - da die Namen der einzelnen Elements nicht klar erklärt ist - ich habe es am Ende durch endlose Experimente geprüft.
Schlüssel zur Erstellung der Readings ist "json2nameValue". zum Ersten fehlt hier eine "ordentliche" Dokumentation (und wie immer - im Forum nachlesen ist für Anwendung, ersetzt nie eine Dokumentation). wie wann und wo die postitiv und negativ filter eingesetzt werden, welche Optionen von anderen abhängig sind,... am Besten den Code nachlesen. Wie die jsonmap aussehen muss - keine Beispiele.
json2nameValue nutzt als Trenner der hierarchiestufen "_". Das ist m.E. maxinal ungeschickt, da dies typisch auch in den Namen vorkommt. In den endgültigen Readigns will ich natürlich nur "temperatur" stehen haben - und nicht die dem device eigene MQTT Hierarchie. Leider kann ich die Stufen nachträglich nicht mehr identifizieren, also nach "_" splitten - zumindest nicht sauber.
Logisch (für mich) - ich will die gemeldeten Datenpunkte verarbeiten (zustand des Ausgangs), egal über welche Methode er eingeholt wurde. Ich muss die Stufen also auflösen können.
Anhand der Stufen muss ich erkennen können, welcher Kanal sich gemeldet hat.
Am Ende muss ich die Kanalangabe, den Readingnamen und den Value in FHEM-Momenklatur übersetzen. Also ein
...switch_1_...output true
in
<channel1>level on
sowie dupliziert - da fhem dies bspw bei dimmern auch als state und pct benötigt - sowie der korrekten entity zugewiesen.
==> es ist (für mich) nicht hinnehmbar, dass MQTT im Frontend (readings) sich von anderen unterscheidet
==> die einfachen Methoden, dies zu übersetzen, entites zuzuweisen und auch die Values anzupassen habe ich nicht gefunden.
==> eine performante Lösung für das auflösen der Events in Readings - ohne exzesives regexp gesuche - suche ich ebenfalls

wie geht ihr damit um? Bin ich allein und bin ich auf den Holzweg?
ggf. werde ich wieder einmal den Code frisieren müssen

betateilchen

Warum nicht im richtige Forumbereich "MQTT" diskutieren?

Als ich mit mqtt angefangen habe, war mein erster Schritt, mich von dem ganzen Attribut-Gedöns, das man versucht, per template aufzuzwingen, verabschiedet habe. Die devices habe ich so angelegt, wie ich es mir vorgestellt habe.

Wenn ich einmal ein device eines bestimmten Typs erstellt habe, verwende ich dieses als Vorlage, falls weitere Geräte des gleiche Typs dazukommen. Im devicetopic muss ich dann nur die eindeutige ID ändern, und schon läuft das neue device.

Die ClientID spielt bei mir überhaupt keine Rolle. Sie ist nirgends definiert.

Als mqtt Server verwende ich mosquitto (auf einer Lightsail Instanz bei Amazon) und nanomq (hier im lokalen Netzwerk in einem proxmox container).
Diese Trennung mache ich deshalb, weil ich alle JsonMOD und HTTPMOD devices, die externe Quellen abfragen, auf Amazon ausgelagert habe und die ermittelten Werte dann per mqtt übertragen werden.
Die ganzen lokalen Shellies etc. brauchen aber keine Internetverbindung. Diese arbeiten komplett über den lokalen nanomq server.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Prof. Dr. Peter Henning

Ist ja alles nett, und wer MQTT liebt, soll es auch nutzen. Aber versuch doch einfach mal (und bei ca. 30 Devices geht das problemlos...) das generische Shelly-Modul.

LG

pah

martinp876

Zitat von: Prof. Dr. Peter Henning am 26 Juli 2026, 13:14:12Ist ja alles nett, und wer MQTT liebt, soll es auch nutzen. Aber versuch doch einfach mal (und bei ca. 30 Devices geht das problemlos...) das generische Shelly-Modul.
es gibt weitere MQTT - wie ich schon sagte bspw Tasmote (generisch,also nocht sonos). Die (meine) Idee ist, nicht x unterschiedliche Protokolle zu prüfen, lernen, anpassen. Shelly ist nur ein Beispiel - ESP32 und derivate ist für generische Ansätze in sonderfällen maximal flexiben. Eine spezial-Shelly Lösung ist daher endlich - und einarbeiten müssste ich mich auch noch. Ich sprach von 30+ devices - wenn man einmal anfängt geht es hier erst los!

martinp876

ZitatDie ClientID spielt bei mir überhaupt keine Rolle. Sie ist nirgends definiert.
die CID wird in MQTT quasi immer einbezogen - und steht in der ReadingList an erster Stelle, vor dem ":". Ausserdem erscheint sie im define - oder was soll da rein?
Diesen Teil sehe ich einmal so (korrigieren mich)
define devicename CID
attr devicename readinglist CID:<topic>:<value> <action>
eigentlich hätte ich mir genau so die Definition des Attributs vorgestellt. Allerdings ist die CID in der Definition nicht vorgeschrieben. Daher werden bei jeder FHEM entity auch alle CIDs zugelassen.
Die CID ist prädestiniert um als Adresse zu fungieren (sagt ja der Name schon).
Wenn ich keine sinnvolle Alternative finde werde ich es genau so - und stringent - implementieren:
  • im Define steht die CID
  • Für Kanäle einer CID überlege ich noch. Der 2-fach switch hat eigentlich 4 Kanäle, frei programmierbar: 2 mal out und 2 mal in
  • Readings werden auf die CID gefiltert - die wird in der message immer geliefert - bietet sich nicht nur an, das ist sicher die Idee von MQTT
  • Readings der Kanäle brauchen einen diskriminator - definier ich mir noch
  • Auswertung der Readings (readinglist-pendant) wird über die Adresse/ID (bei MQTT also CID) der/den entities zugewiesen
  • Templates muss es auch geben hier bietet es sich an, wie bei CUL_HM (und sicher auch anderen) ein "model" zu definieren (Attribut) worüber das template ausgewählt wird
  • da es wie immer keine weiteren interessenten gibt ist es nicht (wie bei CUL_HM) notwendig, user-templates zuzulassen. Wäre aber kein Problem, ist schon erprobt.
  • ich werde nicht umhin kommen, eine subroutine zu schreiben, welche die Auswertung durchführt
  • Giganto-Attribute mit unendlikch code sind keine Option - nicht übersichtlich, nicht wartbar, nicht managebar.

Noch einmal, es ins rechte Licht zu rücken -  vielen Dank für MQTT2 und auch json2nameval. Ist prima - aber ist für meine Ansprüche nicht ausreichend.
Eine Lösung mit auslagerungen - auch nach Amazon - lehne ich (bis jetzt) strikt ab.




betateilchen

Zitat von: martinp876 am 26 Juli 2026, 14:11:38die CID wird in MQTT quasi immer einbezogen - und steht in der ReadingList an erster Stelle, vor dem ":".

Dein Versteifen auf die CID halte ich persönlich für einen Holzweg.
Und in MQTT 5 ist die CID mehr oder weniger vollständig optional bzw. wird leer übergeben.

Zitat von: martinp876 am 26 Juli 2026, 14:11:38Ausserdem erscheint sie im define - oder was soll da rein?

Bei mir erscheint in keinem define eine CID.

defmod ku_Licht_Vintage MQTT2_DEVICE
attr ku_Licht_Vintage IODev nanomq
attr ku_Licht_Vintage devicetopic shellies/ShellyVintage-34945479E80B/light/0

Basierend auf dem devicetopic werden dann readingList und setList befüllt.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

passibe

Ich glaube, die CID erscheint im define, wenn autocreate das device erstellt. Autocreate setzt die ja auch in die readingList, wenn mich nicht alles täuscht.

Kann man sich aber, wie betateilchen richtig sagt, komplett sparen. Das ist nur eine zusätzliche Fehlerquelle. Einfach in den Geräten ordentliche Topics konfigurieren und gut ist.

Prof. Dr. Peter Henning

Zitat von: martinp876 am 26 Juli 2026, 13:43:25nicht x unterschiedliche Protokolle zu prüfen, lernen, anpassen
Na, da ich die ersten Jahre über das Shelly-Modul gepflegt habe, kenne ich das API sehr genau. Protokoll gibt es da, wenn man es genau nimmt, genau eines: REST. Aber, und das vor allem wegen der starken Veränderung des API über die Zeit, mit ganz unterschiedlichen Spezifikationen. Das Shelly-Modul verbirgt das vor dem Anwender, um eben nicht diesen ganzen Zoo verstehen zu müssen.

LG

pah


betateilchen

#8
@pah: Du hast ja recht, aber die Frage hier im Thread ist nicht "Shelly best practice" sondern "MQTT best practice".
Spätestens, wenn man irgendwann ein mqtt-sprechendes device einsetzt, das nicht vom Shelly-Modul abgedeckt wird (z.B. weil es gar nicht von Shelly stammt) muss man mit (mindestens) zwei verschiedenen Ansätzen arbeiten. MQTT ist dabei der Weg, das mehr oder weniger zu vereinheitlichen.

Zitat von: passibe am 26 Juli 2026, 16:37:06Ich glaube, die CID erscheint im define, wenn autocreate das device erstellt

Ok, ich arbeite weder mit autocreate noch mit attrTemplate.
Das macht mir die Arbeit schon erheblich leichter und meine mqtt devices funktionieren so, wie ich es mir vorgestellt habe.

Für mich ist das Attribut devicetopic jedenfalls sehr viel wichtiger und hilfreicher als eine CID, zumal man in dem Attribut innerhalb eines devices sogar unterschiedliche devicetopics definieren kann, um beispielsweise eingehende mqtt-Nachrichten unterschiedlicher Geräte in einem einzigen FHEM device zusammenzuführen.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Prof. Dr. Peter Henning

Zitat von: betateilchen am 26 Juli 2026, 16:55:47MQTT ist dabei der Weg, das mehr oder weniger zu vereinheitlichen.
Ich habe viele Devices, die FHEM via MQTT versorgen, dazu gehören zwei E-Autos und drei Staubsaugerroboter.

Meine Erfahrung: Nix einheitlich, Geräte verhalten sich komplett unterschiedlich.

LG

pah

rudolfkoenig

#10
Etwas Hintergrund zu ClientID (aka CID) in FHEM:
- die CID des Senders kennt nur der MQTT Server. "Normale" MQTT Clients, die ueber einen externen Broker arbeiten, haben keine Ahnung, wer eine Nachricht gesendet hat.
- MQTT2_SERVER & MQTT2_DEVICE sind entstanden, damit die MQTT Anbindung in FHEM einfacher wird, autocreate war einer der Ziele.
- MQTT2_DEVICE erweitert beim Empfang einer unbekannter Nachricht das readingsList der Instanz mit der gleichen ClientID.
- das funktioniert ohne Weiteres mit MQTT2_SERVER. Bei einem externen Broker (d.h. MQTT2_CLIENT) muss man ein bridgeRegexp Attribut setzen (was je nach Topic eine ClientID erfindet), damit autocreate funktioniert.
- beim Implementieren von MQTT2 hatte ich keine Erfahrung mit MQTT Geraeten, ich bin davon ausgegangen, dass Geraete der gleichen Art auch die gleichen Topics verwenden. Deswegen wurde das ClientID Teil der readingList. Aus heutiger Sicht ist ClientID im readingList ueberfluessig und sollte ausgebaut werden, da ein so angelegtes readingList nicht ohne Aenderung ueber einen externen Broker bedient werden kann.
- ClientID in der readingList ist ueberfluessig, weil die ueblichen MQTT-Geraete eine eindeutige ID als Teil des Topics seinden. Es sei denn der (unerfahrene) Benutzer meint das Topic selbst bestimmen zu wollen, wodurch die muehsam vorbereiteten attrTemplates nicht mehr anwendbar sind.
- es gibt einige Geraete (eher selten), die temporaere oder leere ClientIDs verwenden.