[Bugs] 00_MQTT2_SERVER / 10_MQTT2_DEVICE

Begonnen von betateilchen, 10 August 2018, 18:01:33

Vorheriges Thema - Nächstes Thema

rudolfkoenig

@ThoTo: kannst du mir erklaeren, warum man %TOPIC (was vmtl $NAME ist) im Topic ersetzt haben will?
Wenn ich es verstanden, und nicht fuer einen Sonderfall halte, baue ich es gerne ein.

ThoTo

#46
Zitat von: rudolfkoenig am 15 August 2018, 08:27:32
@ThoTo: kannst du mir erklaeren, warum man %TOPIC (was vmtl $NAME ist) im Topic ersetzt haben will?
Wenn ich es verstanden, und nicht fuer einen Sonderfall halte, baue ich es gerne ein.

Meine Geräte mit Tasmota haben um sie einfach zuordnen zu können als MQTT Topic "Sonoff-[MAC]" konfiguriert: Sonoff-AB12CF, Sonoff-450AF1 usw.
Schaltbefehle entsprechend mit cmnd/Sonoff-[MAC]/POWER, Status Messages kommen über tele/Sonoff-[MAC]/STATE herein.

In jedem MQTT2_DEVICE kommt das idente Topic in setList, getList, readingList mehrfach vor.
Ein konfigurierbares Topic (bzw. Topic Level) pro MQTT2_DEVICE kann einfach an einer Stelle geändert werden und muss eben nicht in x Attributen angepasst werden.

Mein Patch dazu sieht im Moment so aus:
Index: 10_MQTT2_DEVICE.pm
===================================================================
--- 10_MQTT2_DEVICE.pm  (revision 17140)
+++ 10_MQTT2_DEVICE.pm  (working copy)
@@ -40,11 +40,17 @@
{
   my ($hash, $def) = @_;
   my @a = split("[ \t][ \t]*", $def);
-  my $name = shift @a;
-  my $type = shift @a; # always MQTT2_DEVICE
+
+  my ($name, $type, $dTopic) = @a;
   shift(@a) if(@a && $a[0] eq "autocreated");

-  return "wrong syntax for $name: define <name> MQTT2_DEVICE" if(int(@a));
+  return "wrong syntax for $name: define <name> MQTT2_DEVICE [<devicetopic>]" if(int(@a)>3);
+
+  if (defined($dTopic) && $dTopic ne "") {
+     $hash->{DEVICETOPIC} = $dTopic;
+  } else {
+     $hash->{DEVICETOPIC} = $name;
+  }

   AssignIoPort($hash);
   return undef;
@@ -57,6 +63,8 @@
   my ($iodev, $msg) = @_;
   my $ioname = $iodev->{NAME};
   my @ret;
+  my $dTopic;
+  my $code;

   sub
   checkForGet($$$)
@@ -71,15 +79,28 @@

   my ($cid, $topic, $value) = split(":", $msg, 3);
   my $dp = $modules{MQTT2_DEVICE}{defptr};
-  foreach my $re (keys %{$dp}) {
+  PARENT: foreach my $re (keys %{$dp}) {
+    my $rea = $re;
+    my $reb = $re;
+    $re =~ s/%DEVICETOPIC%/\.\*/g;
+
     next if(!("$topic:$value" =~ m/^$re$/s ||
               "$cid:$topic:$value" =~ m/^$re$/s));
-    foreach my $dev (keys %{$dp->{$re}}) {
+    foreach my $dev (keys %{$dp->{$rea}}) {
+      my $hash = $defs{$dev};
+
+      $dTopic = $hash->{DEVICETOPIC};
+      $code = $dp->{$rea}{$dev};
+      $reb = $rea;
+      $reb =~ s/%DEVICETOPIC%/$dTopic/g;
+
+      next if(!("$topic:$value" =~ m/^$reb$/s ||
+                "$cid:$topic:$value" =~ m/^$reb$/s));
+
       next if(IsDisabled($dev));
       my @retData;
-      my $code = $dp->{$re}{$dev};
+
       Log3 $dev, 4, "MQTT2_DEVICE_Parse: $dev $topic => $code";
-      my $hash = $defs{$dev};

       if($code =~ m/^{.*}$/s) {
         $code = EvalSpecials($code,
@@ -169,6 +190,9 @@
     shift @a;
     $cmd .= " ".join(" ",@a) if(@a);
   }
+
+  my $dTopic = $hash->{DEVICETOPIC};
+  $cmd =~ s/%DEVICETOPIC%/$dTopic/g;

   IOWrite($hash, split(" ",$cmd,2));
   return undef;
@@ -198,6 +222,10 @@
     shift @a;
     $cmd .= " ".join(" ",@a) if(@a);
   }
+
+  my $dTopic = $hash->{DEVICETOPIC};
+  $cmd =~ s/%DEVICETOPIC%/$dTopic/g;
+
   IOWrite($hash, split(" ",$cmd,2));
   return undef;
}
@@ -306,7 +334,7 @@
   <a name="MQTT2_DEVICEdefine"></a>
   <b>Define</b>
   <ul>
-    <code>define &lt;name&gt; MQTT2_DEVICE</code>
+    <code>define &lt;name&gt; MQTT2_DEVICE [&lt;devicetopic&gt;]</code>
     <br><br>
     To enable a meaningful function you will need to set at least one of the
     readingList, setList or getList attributes below.<br>


Idee wäre das DeviceTopic als Parameter für define zu nehmen, das habe ich aber noch nicht eingebaut. Wird der Parameter im Define nicht gesetzt, wird %DEVICETOPIC% durch den Devicenamen, also Sonoff_Test ersetzt. Verwendung immer optional, da ja nur %DEVICETOPIC% ersetzt wird.

define Sonoff_Test MQTT2_DEVICE Test/Sub/Sonoff-123456
attr Sonoff_Test setList on cmnd/%DEVICETOPIC%/POWER on

Ergebnis: cmnd/Test/Sub/Sonoff-123456/POWER on

define Sonoff_Test MQTT2_DEVICE
attr Sonoff_Test setList on cmnd/%DEVICETOPIC%/POWER on

Ergebnis: cmnd/Sonoff_Test/POWER on


Ich hoffe etwas mehr Licht ins Dunkle gebracht zu haben  :D

Update: Patch angepasst, DEVICETOPIC kann im define mitangegeben werden.

LG Thomas
KNX | MQTT | Docker | Sonos | FHEMapp

"Zwei Dinge sind unendlich, das Universum und die menschliche Dummheit, aber bei dem Universum bin ich mir noch nicht ganz sicher." (Albert Einstein)

betateilchen

Zitat von: rudolfkoenig am 14 August 2018, 22:16:07
da ich nicht weiss, womit.

Auf meinem Android Telefon habe ich einen mqtt Client, mit dem ich beliebige topics subscriben und auch wieder unsubscriben (schreckliches Deutsch...) kann.

https://play.google.com/store/apps/details?id=in.dc297.mqttclpro

Zitat von: rudolfkoenig am 14 August 2018, 22:16:07
SAP ist bei mir in der Kategorie "Tage mit Installation von Programmen verbringen"

Das ist aber das Denken von SAP Leuten, die SAP seit 20 Jahren oder noch länger machen und den aktuellen Stand der Entwicklung in den vergangenen 10 Jahren nicht vollumfänglich kennen. Für die Nutzung der SAP Cloud Platform zu Testzwecken reicht ein S-User (bzw. sogar schon ein kostenfreier P-User). Alles andere passiert online und Du brauchst nur einen Browser auf Deinem Laptop.

-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

Zitat von: rudolfkoenig am 15 August 2018, 08:27:32
Wenn ich es verstanden, und nicht fuer einen Sonderfall halte, baue ich es gerne ein.

Ich halte das für einen Sonderfall. Normalerweise wird man in den topics der Geräte einen "sprechenderen" Namen konfigurieren, um sie auseinanderhalten zu können und nicht die letzten 6 Stellen der MAC Adresse.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

ThoTo

Zitat von: betateilchen am 15 August 2018, 10:28:56
Ich halte das für einen Sonderfall. Normalerweise wird man in den topics der Geräte einen "sprechenderen" Namen konfigurieren, um sie auseinanderhalten zu können und nicht die letzten 6 Stellen der MAC Adresse.

Gut, dann gehen wir vom "Normalfall", also einem sprechenden Devicenamen "Gartenleuchte1" aus.
Das Attribut readingList wäre dann trotzdem mehrfach damit befüllt oder habe ich gerade einen Denkfehler?
tele/Gartenleuchte1/STATE:.* { MQTT2_JSON($EVENT) }
stat/Gartenleuchte1/STATUS5:.* { MQTT2_JSON($EVENT) }
stat/Gartenleuchte1/POWER:.* state
tele/Gartenleuchte1/LWT:.* presence


KNX | MQTT | Docker | Sonos | FHEMapp

"Zwei Dinge sind unendlich, das Universum und die menschliche Dummheit, aber bei dem Universum bin ich mir noch nicht ganz sicher." (Albert Einstein)

betateilchen

Zitat von: ThoTo am 15 August 2018, 10:35:44
Das Attribut readingList wäre dann trotzdem mehrfach damit befüllt oder habe ich gerade einen Denkfehler?

Genau dafür und in dieser Form ist das Attribut vorgesehen.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

hexenmeister

Ich würde eine entsprechende Umsetzung auch befürworten. Macht alles kürzer, übersichtlicher und bei einem eventuellen Änderungsbedarf leichter und weniger fehleranfällig.
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

ThoTo

Zitat von: betateilchen am 15 August 2018, 11:20:46
Genau dafür und in dieser Form ist das Attribut vorgesehen.

Alles klar, hatte mich somit nicht ganz getäuscht.

Dann vereinfacht und generalisiert meine vorgeschlagene Änderung die Nutzung der Attribute indem Topic bzw. Topic Level nur mehr einmal pro MQTT2_DEVICE konfiguriert und in den einzelnen Attributen der Platzhalter %DEVICETOPIC% verwendet wird.


LG Thomas
KNX | MQTT | Docker | Sonos | FHEMapp

"Zwei Dinge sind unendlich, das Universum und die menschliche Dummheit, aber bei dem Universum bin ich mir noch nicht ganz sicher." (Albert Einstein)

betateilchen

Ok, die Idee mit dem DEVICETOPIC finde ich auch gut - der erste Ansatz mit dem Attribut-Gedöns war aber wirklich ein Holzweg :)
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

eldrik

Zitat von: rudolfkoenig am 14 August 2018, 22:16:07
Na was sonst soll ich machen? Die andere Seite erwartet eine klare Antwort, wenn ich nichts antworte, dann beendet sie die Verbindung. Ich habe jetzt UNSUBSCRIBE implementiert.

2018.08.16 09:19:51.311 4: mqtt_10.0.81.60_49738 MQTT_FX_Client SUBSCRIBE
2018.08.16 09:19:51.311 4:   topic:home/garden/fountain qos:0
2018.08.16 09:19:56.932 4: mqtt_10.0.81.60_49738 MQTT_FX_Client UNSUBSCRIBE
2018.08.16 09:19:56.933 4:   topic:home/garden/fountain


Danke funktioniert.

Greetz
Eldrik

ThoTo

Zitat von: betateilchen am 15 August 2018, 17:56:38
Ok, die Idee mit dem DEVICETOPIC finde ich auch gut - der erste Ansatz mit dem Attribut-Gedöns war aber wirklich ein Holzweg :)

Sag ich doch  8)


Kurzes allgemeins Update:
Ich habe nun seit 24 Stunden meine Geräte von den alten MQTT Modulen auf MQTT2 inkl. dem Patch umgebaut sowie getestet und dabei keine Auffälligkeiten festgestellt.
Verhalten ist wie beabsichtigt, insbes. die Readings werden sauber erstellt/aktualisiert.
KNX | MQTT | Docker | Sonos | FHEMapp

"Zwei Dinge sind unendlich, das Universum und die menschliche Dummheit, aber bei dem Universum bin ich mir noch nicht ganz sicher." (Albert Einstein)

rudolfkoenig

Ich habe $DEVICETOPIC (Achtung, nicht %DEVICETOPIC) hinzugefuegt, da ueberall sonst auch $ verwendet wird. Der Wert ist entweder $NAME, oder das Attribut devicetopic, falls gesetzt. $DEVICETOPIC kann auch im perl Ausdruck verwendet werden.

Falls das Attribut autocreate beim MQTT2_SERVER gesetzt ist, und ein published topic nirgendwo verwendet wird, dann wird ein MQTT2_DEVICE mit dem clientId angelegt (optionaler Parameter beim define). Das readingList von diesem Geraet wird nach und nach so erweitert, dass es alle topics von dieser Quelle akzeptiert. Die so angelegten Geraete koennen auch umbenannt werden, da die Identifizierung anhand der clientid durchgefuehrt wird. Fuer den Normallfall empfehle ich den MQTT2_SERVER mit diesem Attribut anzulegen. Die Voreinstellung ist z.Zt. noch aus.

Weiternhin habe ich beim PUBLISH ein Bug gefixt, die Laenge fuer Daten > 127 Bytes wird jetzt richtig berechnet. Bisher ist bei solchen Daten mosquitto_sub mit dem Text "Error: A network protocol error occurred when communicating with the broker" abgebrochen.

SamNitro

Kann mir mal einer bitte den Platzhalter mit $NAME erklären!

defmod sonoff_bu_led MQTT2_DEVICE DVES_CCD0A7
attr sonoff_bu_led IODev m2s
attr sonoff_bu_led devicetopic sonoff_bu_led
attr sonoff_bu_led event-on-change-reading .*
attr sonoff_bu_led eventMap on:ON off:OFF
attr sonoff_bu_led readingList DVES_CCD0A7:tele/sonoff_bu_led/STATE:.* { json2nameValue($EVENT) }\
DVES_CCD0A7:tele/sonoff_bu_led/LWT:.* sonoff_bu_led/LWT\
DVES_CCD0A7:cmnd/sonoff_bu_led/POWER:.* sonoff_bu_led/POWER\
DVES_CCD0A7:tele/sonoff_bu_led/INFO1:.* { json2nameValue($EVENT) }\
DVES_CCD0A7:tele/sonoff_bu_led/INFO2:.* { json2nameValue($EVENT) }\
DVES_CCD0A7:tele/sonoff_bu_led/INFO3:.* { json2nameValue($EVENT) }\
DVES_CCD0A7:stat/sonoff_bu_led/RESULT:.* { json2nameValue($EVENT) }\
DVES_CCD0A7:stat/sonoff_bu_led/POWER1:.* sonoff_bu_led/POWER1\
DVES_CCD0A7:tele/sonoff_bu_led/UPTIME:.* { json2nameValue($EVENT) }
attr sonoff_bu_led room MQTT2_DEVICE
attr sonoff_bu_led setList on cmnd/$NAME/POWER1 on\
off cmnd/$NAME/POWER1 off
attr sonoff_bu_led stateFormat POWER1


$NAME wird bei mir einfach so weiter geleitet.

$DEVICETOPIC funktioniert bei mir,

und LWT wird leider immer noch nicht im Device angezeigt trotz per Autocreate erstelle readingList.
(Intel-Nuc Proxmox) (Homematic) (EnOcean) (CUL868) (CUL433) (Zigbee2MQTT) (ESP8266) (Echo) (DUOFERN)

SamNitro

ach und noch etwas,
z.B. bei dem Topic
tele/sonoff_bu_led/INFO1
{"Module":"Sonoff S2X","Version":"6.1.1c","FallbackTopic":"DVES_CCD0A7","GroupTopic":"sonoffs"}


werden keine Readings erzeugt.
Versucht habe ich
DVES_CCD0A7:tele/sonoff_bu_led/INFO1:.* { MQTT2_JSON($EVENT) }
oder
DVES_CCD0A7:tele/sonoff_bu_led/INFO1:.* { json2nameValue($EVENT) }
(Intel-Nuc Proxmox) (Homematic) (EnOcean) (CUL868) (CUL433) (Zigbee2MQTT) (ESP8266) (Echo) (DUOFERN)

rudolfkoenig

ZitatKann mir mal einer bitte den Platzhalter mit $NAME erklären!
Ist der Name der MQTT2_DEVICE Instanz. Kann im readingsList verwendet werden, wenn es Perl ist.

Zitatund LWT wird leider immer noch nicht im Device angezeigt trotz per Autocreate erstelle readingList.
Beim autocreate ging der erste Wert eines Topics verloren, das habe ich jetzt gefixt.
Weiterhin gab es ein Problem beim bestimmen des Reading-Namens fuer einfache (nicht JavaScript) Readings, er sollte kein / enthalten. Das habe ich jetzt auch gefixt.

In deinem Fall muesstest du entweder readingList direkt anpassen, oder auf dem update morgen warten, und nach dem FHEM-Neustart readingList entfernen.

Wg. dem DVES_CCD0A7 Readings: versuch es ohne CID, oder bitte anhand "list TYPE=MQTT2_SERVER" & Detailansicht verifizieren, dass CID richtig ist.