MQTT2_DEVICE - setList mit regex?

Begonnen von betateilchen, 09 Juni 2023, 11:45:53

Vorheriges Thema - Nächstes Thema

betateilchen

Gegeben sein ein MQTT2_DEVICE, das folgende readings erzeugt:

setstate ub1 2023-06-09 11:00:00 w1_mode 5
setstate ub1 2023-06-09 11:00:00 w1_state pause
setstate ub1 2023-06-09 11:00:00 w2_mode 5
setstate ub1 2023-06-09 11:00:00 w2_state pause
setstate ub1 2023-06-09 11:00:00 w3_mode 5
setstate ub1 2023-06-09 11:00:00 w3_state pause

Diese sechs readings kann ich problemlos mittels einem (1) Eintrag im Attribut readingList erzeugen:

attr ub1 readingList $DEVICETOPIC/(w\d)/(state|mode):.* { $TOPIC =~ m/(w\d)\/(state|mode)/;; my $r=$1.'_'.$2;; {"$r" => $EVTPART0} }

Nun hat das device aber auch noch drei Einträge im Attribut setList, die eigentlich alle bis auf eine Ziffer identisch sind:

attr ub1 setList winder1:1,2,3,4,5,0 {"fhemhome/$DEVICETOPIC/w1/mode $EVTPART1"}\
winder2:1,2,3,4,5,0 {"fhemhome/$DEVICETOPIC/w2/mode $EVTPART1"}\
winder3:1,2,3,4,5,0 {"fhemhome/$DEVICETOPIC/w3/mode $EVTPART1"}

Bis jetzt habe ich noch keinen Weg gefunden, das zu vereinfachen/vereinheitlichen.
Mir schwebt so etwas vor wie:

attr ub1 setList winder([123]):1,2,3,4,5,0 {"fhemhome/$DEVICETOPIC/w$1/mode $EVTPART1"}

Grundsätzlich kann ich mit den drei Einträgen leben - mich interessiert nur, ob man das nicht doch irgendwie anders machen könnte. Bei drei Einträgen ist das noch überschaubar, aber bei neun wäre es optisch schon recht unübersichtlich.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

rudolfkoenig

setList wird auch als Vorschlag fuer das Frontend fuer die Auswahl genommen.

D.h. wenn Regexp zugelassen ist, dann brauchen wir einen Mechanismus, der aus diesem Regexp eine ausformulierte Liste aller Moeglichkeiten erstellt. Fuer [123] ist das noch machbar, bei [123]* wird es problematisch.

Etwas Off-Topic: solche zusammengesetzte Geraete sind in FHEM kompliziert zu handhaben (Darstellung des Zustandes, SetExtensions, etc), ich bin eher fuer das Aufteilein.

betateilchen

#2
Danke für Deine schnelle Antwort.

Zitat von: rudolfkoenig am 09 Juni 2023, 11:58:21setList wird auch als Vorschlag fuer das Frontend fuer die Auswahl genommen.

Das ist mir schon klar, ich ahnte auch, dass es nicht einfach wird  8)

Zitat von: rudolfkoenig am 09 Juni 2023, 11:58:21wenn Regexp zugelassen ist, dann brauchen wir einen Mechanismus, der aus diesem Regexp eine ausformulierte Liste aller Moeglichkeiten erstellt. Fuer [123] ist das noch machbar, bei [123]* wird es problematisch.

Diese Antwort hatte ich befürchtet.

Zitat von: rudolfkoenig am 09 Juni 2023, 11:58:21Etwas Off-Topic: solche zusammengesetzte Geraete

Naja, es kommt darauf an, was man als "zusammengesetztes Gerät" bezeichnet.
Im vorliegenden Fall ist es ein (1) physikalisches Gerät, mit einem Mikrocontroller, der die eingebauten drei Motoren im Gerät steuert https://forum.fhem.de/index.php?topic=133867.0


Edit: es gibt solche Geräte auch mit 48 Motoren...
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

#3
Könnte man als Kompromiss darüber nachdenken, im Attributwert (von setList)* künftig perl-Code zuzulassen? Die Verantwortung für den Inhalt des Attributes liegt logischerweise dann vollständig beim Anwender.

perl-Code hätte an dieser Stelle den zusätzlichen Charme der Wiederverwendbarkeit in mehreren gleichartigen devices.

attr <device1> setList {ubSetList(3)}

erzeugt die Einträge für ein Gerät mit 3 Motoren.

attr <device2> setList {ubSetList(48)}

erzeugt mit dem gleichen Code die Einträge für ein zweites Gerät mit 48 Motoren.


sub ubSetList {
  my $ubNum = shift;
  my @setList = ();
  for (my $i=1; $i <= $ubNum; $i++) {
    push(@setList,"winder$i:1,2,3,4,5,0 {\"fhemhome/\$DEVICETOPIC/w$i/mode \$EVTPART1\"}");
  }
  return join("\n",@setList);
}


*Edit: ich frage mich gerade, ob es überhaupt schon irgendwo eine Möglichkeit gibt, einen Attributwert komplett aus perl Code zu erzeugen. Also quasi die Frage, ob das type-spezifisch wäre oder ob es ins Framework gehört.
Diese Frage ist zurückgezogen. Es gibt natürlich solche Fälle schon.

-----------------------
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: betateilchen am 09 Juni 2023, 20:36:40
Könnte man als Kompromiss darüber nachdenken, im Attributwert (von setList)* künftig perl-Code zuzulassen? Die Verantwortung für den Inhalt des Attributes liegt logischerweise dann vollständig beim Anwender.

Dazu wäre nicht besonders viel zu tun:

Index: 10_MQTT2_DEVICE.pm
===================================================================
--- 10_MQTT2_DEVICE.pm  (revision 27668)
+++ 10_MQTT2_DEVICE.pm  (working copy)
@@ -310,6 +310,16 @@
 MQTT2_getCmdHash($)
 {
   my ($list) = @_;

+  if ($list =~ m/^{(.*)}/s) {
+    my $a = eval $1;
+    if($@) {
+      Log 1, "Error evaluating setList: $@";
+      return undef;
+    }
+    $list = $a;
+  }
+
   my (%h, @cmd);
   map {
     my ($k,$v) = split(" ",$_,2);

Das Einzige, was dabei jetzt noch "stört", ist die pingelige Syntaxprüfung in der AttrFn(), die darauf besteht, dass man bei setList zwei leerzeichengetrennte Parameter im Attribut angeben muss.

Das umgehe ich aktuell so:

attr ub3 setList {ubSetList(3)} ""
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

rudolfkoenig

Ich habe eine modifizierte Version eingecheckt, bitte pruefen.

Die Syntaxpruefung kann man auch mit
attr ub3 setList { ubSetList(3) }
umgehen.

betateilchen

Danke für die Änderung.

Das Ergebnis des perl-Codes in das Attribut selbst zu schreiben, hatte ich absichtlich nicht gemacht. So geht nämlich der Funktionsaufruf im Attribut beim "save" komplett verloren und es wird letztlich etwas anderes abgespeichert als das, was ich als User mir vorgestellt habe. Das bedeutet bei einer Änderung im Code zur Erzeugung der setList nämlich

  • dass ich wissen / mir merken muss, in welchen devices "eigentlich" Code ausgeführt werden soll
  • dass ich nach der Änderung sämtliche devices wieder anfassen muss, um das Ergebnis der Änderung in die devices zu bekommen
  • dass ich dadurch im Endeffekt noch mehr Arbeit habe als vorher :(

Aber wenn Du das so, wie es jetzt ist, gut findest, werde ich wohl damit leben müssen.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

rudolfkoenig

ZitatDas Ergebnis des perl-Codes in das Attribut selbst zu schreiben, hatte ich absichtlich nicht gemacht.
Das wollte ich auch nicht, und ein kurzes save-test hat das auch nicht bestaetigt.
Kannst Du mir zum Nachstellen ein HOWTO schreiben?

betateilchen

Ok, das scheint ein Einmaleffekt gewesen zu sein.

Beim ersten FHEM Neustart nach dem Update wurde in allen devices das Attribut durch das Ergebnis der perl-Auswertung überschrieben. Nachdem ich nun alle nochmal auf perl-Code geändert habe, tritt der Effekt nicht mehr auf.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!