MQTT best current practice

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

Vorheriges Thema - Nächstes Thema

Prof. Dr. Peter Henning

ZitatDa die Welt der "typischen MQTT-Clients" sehr bunt ist (und teils dadurch geprägt zu sein scheint, dass mal eben der Azubi eine MQTT-Funktionalität eingebaut hat - ohne Rücksicht auf Sinnhaftigkeit dessen, was da passiert - ) ist leider weiter Stand der Dinge.

Gut formuliert. MQTT erfordert einfach, sich von den eigenen Vorurteilen in Bezug auf Standardisierung zu trennen.

LG

pah

martinp876

mir ist (ernsthaft) nicht klar, was an meiner Aussage unklar ist.
Der Server ist das IO welches die MQTT cienten mit den realen devices verbindet.
In der Welt ausserhalb kann man MQTT clienten direkt verbinden - das ist vollkommen klar.
Meine Annahme ist, dass ein Client in FHEM erst einmal "nur" alle Informationen des realen Device einsammelt und darstellt. Ok, die Senderichtung habe ich gerade unterschlagen.

So funktionieren zumindest einige andere Famielen in FHEM auch. Das ist eine Kernauffassung aus der sich dann exterm viel ableitet.
Also erste Frage: haben wir hier einen Konsenz oder sind die MQTT_DEVICES bei euch anders definiert?
a) mir ist klar, das man es anders machen KANN. Aber nicht muss.
b) ich muss und will nicht alles implementieren, was MQTT hergibt. Der obige Ansatz sollte reichen, MQTT in FHEM zu harmonisieren
c) mittelfristig ist es mir zu komplex, komplexe abhängigkeiten einzubauen - das werde ich in 2 Monaten nicht mehr warten können

Ich weiss also nicht, was ich durcheinander werfe. Ich habe gesehen, dass ein MQTT_DEVISE zugriff auf alle MQTT messages haben kann. Und genau das brauche ich nicht (KISS-Ansatz).

Ich wieder hole mich wohl,wenn ich also sage:
- die Funktion IO für den Server reicht mir aus
- ein Client  oder auch MQTT_DEVICE bekommt alle Nachrichten seines realen Partners (Kanäle ist eine Abwandlung des gleichen)
- sämtliche interne Trigger werden über notify erledigt.

Das sehe ich als schlank und daher übersichtlich.
Es beraucht noch eine best-practice (nach der ich hier eigentlich gefragt habe) wie man die messages parsed, in Readings wandelt, filtert,...

Wenn der Grundgedanke nicht übereinstimmt  - was ist ein Client "in FHEM"  - dann kommen wir klar zu anderen Ergebnissen.

Noch eines (evtl wiederholt es sich): Ich will MQTT in FHEM einbinden und nicht umgekehrt.

Noch einmal explizit die Frage an das Auditorium das ein MQTT Client in FHEM  leisten soll.
Und noch eines - sorry - meine (experiment-)shelly sind auch clients - formal. die tun auch real etwas. der fhem-client ist also immer nur ein Soft-Abbild. Das ist aus meiner sicht der entscheidende Unterschied zu realen Device.

Sidey

@martinp876


Mein erster Post am Sonntag hat es nicht geschafft, seit dem hat sich die Diskussion weiter entwickelt.
Mit scheint, jetzt ein guter Zeitpunkt für einen neuen Versuch gekommen zu sein.


Ich setze MQTT inzwischen recht umfangreich ein: Tasmota, Shelly Gen1/Gen2, Zigbee2MQTT, OwnTracks, AWTRIX und einige eigene Dienste. Als Broker verwende ich direkt MQTT2_SERVER:

    define MQTT2_FHEM_Server MQTT2_SERVER 1883 global
  attr MQTT2_FHEM_Server autocreate complex
 

  Meine Praxis ist dabei:

  1. attrTemplate als Ausgangspunkt verwenden.
  2. Danach readingList auf die wirklich benötigten Topics und Readings reduzieren.
  3. Mehrkanalgeräte in mehrere MQTT2_DEVICE-Entities aufteilen, wo sinnvoll. Beim Rolladen natürlich nicht.
  4. Mit devicetopic, jsonMap und manchmal auch etwas Perl in der readingList die MQTT-Daten auf FHEM-übliche Readings abbilden.
  5. Erreichbarkeit über LWT beziehungsweise online/availability behandeln.

  Ein Beispiel für einen Shelly Plus 1:

    define GartenSteckdose MQTT2_DEVICE shellyplus1_xxxxxx
  attr GartenSteckdose devicetopic zuhause/terrasse/steckdose

  attr GartenSteckdose jsonMap
  switch_state:state
  switch_temperature_tC:temperature
  switch_temperature_tF:0
  params_wifi_sta_ip:ip

  attr GartenSteckdose readingList
  $DEVICETOPIC/online:.* online
  $DEVICETOPIC/events/rpc:.* { json2nameValue($EVENT,"",$JSONMAP) }
  $DEVICETOPIC/status/switch_0:.* {
  $EVENT =~ s/"output":true/"state":"on"/g;;
  $EVENT =~ s/"output":false/"state":"off"/g;;
  json2nameValue($EVENT,"switch_",$JSONMAP)
  }

  attr GartenSteckdose setList
  toggle:noArg $DEVICETOPIC/rpc {"id":0,"src":"fhem","method":"Switch.Toggle","params":{"id":0}}
  off:noArg $DEVICETOPIC/rpc {"id":0,"src":"fhem","method":"Switch.Set","params":{"id":0,"on":false}}
  on:noArg $DEVICETOPIC/rpc {"id":0,"src":"fhem","method":"Switch.Set","params":{"id":0,"on":true}}
  on-for-timer $DEVICETOPIC/rpc {"id":0,"src":"fhem","method":"Switch.Set","params":{"id":0,"on":true,"toggle_after":$EVTPART1}}

  attr GartenSteckdose setStateList on off
 

  Damit wird aus dem Shelly-Feld output:true bewusst ein FHEM-typisches state:on. Die Zuordnung mache ich nicht erst nach dem vollständigen Flattening eines großen JSON-Baums, sondern bereits anhand des konkreten Topics status/switch_0.

  Für Mehrkanalgeräte verwende ich getrennte FHEM-Devices. Ein Tasmota-Gerät (Shelly analog) mit zwei Relais sieht bei mir vereinfacht so aus:

    define LichtTisch MQTT2_DEVICE DVES_xxxxxx
  attr LichtTisch devicetopic zuhause/wohnzimmer/licht
  attr LichtTisch readingList
  tele/$DEVICETOPIC/LWT:.* LWT
  tele/$DEVICETOPIC/STATE:.* {
  my $r=json2nameValue($EVENT);;
  return { map { $_ => $r->{$_} }
  grep { /^(?:Uptime|POWER1|RSSI)$/ } keys %{$r} };;
  }
  stat/$DEVICETOPIC/RESULT:.* { json2nameValue($EVENT) }
  attr LichtTisch setList
  off:noArg cmnd/$DEVICETOPIC/POWER1 0
  on:noArg cmnd/$DEVICETOPIC/POWER1 1
  toggle:noArg cmnd/$DEVICETOPIC/POWER1 2
  attr LichtTisch stateFormat POWER1

  define LichtCouch MQTT2_DEVICE DVES_xxxxxx
  attr LichtCouch devicetopic zuhause/wohnzimmer/licht
  attr LichtCouch readingList
  tele/$DEVICETOPIC/LWT:.* LWT
  tele/$DEVICETOPIC/STATE:.* {
  my $r=json2nameValue($EVENT);;
  return { map { $_ => $r->{$_} }
  grep { /^(?:Uptime|POWER2|RSSI)$/ } keys %{$r} };;
  }
  stat/$DEVICETOPIC/RESULT:.* { json2nameValue($EVENT) }
  attr LichtCouch setList
  off:noArg cmnd/$DEVICETOPIC/POWER2 0
  on:noArg cmnd/$DEVICETOPIC/POWER2 1
  toggle:noArg cmnd/$DEVICETOPIC/POWER2 2
  attr LichtCouch stateFormat POWER2
 

Beide Entities haben dieselbe CID und dasselbe devicetopic. Die Trennung erfolgt durch die konkreten Topics beziehungsweise durch das Filtern auf POWER1 oder POWER2. So können Automatisierungen mit normalen FHEM-Devices wie LichtTisch und LichtCouch arbeiten, ohne die MQTT-Kanalstruktur kennen zu müssen.

Bei Zigbee2MQTT ist es meist noch kürzer:

    define Kuechenlicht MQTT2_DEVICE zigbee_kuechenlicht
  attr Kuechenlicht devicetopic zigbee2mqtt/zuhause/kueche/licht
  attr Kuechenlicht readingList
  $DEVICETOPIC:.* {
  my $r=json2nameValue($EVENT);;
  $r->{state}=lc($r->{state}) if defined $r->{state};;
  return $r;;
  }
  $DEVICETOPIC/availability:.* availability

  attr Kuechenlicht setList
  on:noArg $DEVICETOPIC/set {"state":"ON"}
  off:noArg $DEVICETOPIC/set {"state":"OFF"}
  brightness:colorpicker,BRI,0,5,255 $DEVICETOPIC/set {"state":"ON","brightness":$EVTPART1}

  attr Kuechenlicht setStateList on off
 

Hier normalisiere ich ON/OFF direkt auf on/off. Die Erreichbarkeit kommt separat über availability.

Mein Fazit: Ich versuche nicht, aus jedem eingehenden JSON automatisch ein universelles FHEM-Device zu erzeugen. MQTT ist für mich zunächst der Transport. Die Übersetzung in die FHEM-Nomenklatur erfolgt pro Gerätefamilie über attrTemplate, readingList, jsonMap und gegebenenfalls eine kleine Perl-Funktion.

Die langen Attribute sind in der Weboberfläche tatsächlich wenig angenehm. In der Konfigurationsdatei sind sie mit Einrückung und Zeilenumbrüchen aber noch gut wartbar. Wichtig für die Performance ist aus meiner Sicht vor allem, Topics möglichst konkret zu abonnieren und aus großen JSON-
Nachrichten nur die tatsächlich benötigten Readings zurückzugeben.

Damit habe ich auch bei vielen Geräten und getrennten Kanal-Entities bislang keine praktischen Performanceprobleme festgestellt.

Grüße Sidey
Signalduino, Homematic, Raspberry Pi, Mysensors, MQTT, Alexa, Docker, AlexaFhem,zigbee2mqtt

Maintainer von: SIGNALduino, fhem-docker, alexa-fhem-docker, fhempy-docker, WebAuth, fhem-mcp