FHEM Forum

FHEM => Automatisierung => DOIF => Thema gestartet von: IPWF am 05 Mai 2023, 14:57:39

Titel: set-Befehl mit RegEx in DOIF ?
Beitrag von: IPWF am 05 Mai 2023, 14:57:39
Hallo,

für meine Räume habe ich jeweils ein Dummy-Device namens Temp_<R> angelegt, wobei <R> = A|B|K|S|W = Anfangsbuchstabe des Raumnamens ist; also Temp_A, Temp_B usw.
Jedes dieser Devices besitzt die drei Readings setpointTemp, tempKom und tempRed, wobei letztere für die Komfort- bzw. reduzierte Temperatur stehen. Diese wurden mittels des Attributs readingList definiert und jeweils einmalig mit "set" auf einem festen Temperaturwert gesetzt, welcher für jedes Device individuell festgelegt wurde.
Mit einem Befehl wie "set Temp_B setpointTemp [Temp_B:tempKom]" kann ich die gewünschte Temperatur für diesen Raum auf die vordefinierte Komforttemperastur setzen; das so gesetzte Reading "setpointTemp" wird dann vom Heizregler des Raumes übernommen.

In einem DOIF steht dann z.B. in der DEFinition:
(Bedingung1)
  (set Temp_A setpointTemp [Temp_A:tempKom];
   set Temp_W setpointTemp [Temp_W:tempKom])
DOELSEIF (Bedingung2)
  (set Temp_A setpointTemp [Temp_A:tempRed];
   set Temp_W setpointTemp [Temp_W:tempRed])

Meine Frage lautet nun:
Kann ich die cmd-Zweige dieser Definitionen vereinfachen durch einen Ausdruck wie
set Temp_[AW] setpointTemp [$DEV:tempKom]        bzw.
set Temp_[AW] setpointTemp {([$DEV:tempKom])}
?
Um es vorweg zu sagen: so klappt es nicht. Aber irgendwie müßte es doch möglich sein, so etwas zu formulieren. Laut CommandRef soll "$DEV" in einem set-Befehl mit dem Namen des vom set betroffenen Gerätes ersetzt werden, aber das funktioniert in meinen bisherigen Versuchen nicht. Auch nicht mit $DEVICE.

Vielleicht könnt Ihr mir da weiterhelfen ?
Titel: Aw: set-Befehl mit RegEx in DOIF ?
Beitrag von: xenos1984 am 05 Mai 2023, 15:37:50
Vermutlich helfen dir Templates:

http://wiki.fhem.de/wiki/DOIF/Templates
Titel: Aw: set-Befehl mit RegEx in DOIF ?
Beitrag von: Damian am 05 Mai 2023, 16:48:48
$DEVICE würde funktionieren, allerdings wird [AW] im DOIF als Status vom Device AW interpretiert.
Titel: Aw: set-Befehl mit RegEx in DOIF ?
Beitrag von: IPWF am 05 Mai 2023, 19:50:08
Danke für Eure schnellen Beiträge.

@Damian: Temp_[AW] sollte ja ein RegEx für Temp_A bzw. Temp_W sein.
Wenn sich das so im DOIF nicht verwenden läßt, gibt es dann eine Alternative für eine solche devspec ?
Titel: Aw: set-Befehl mit RegEx in DOIF ?
Beitrag von: Damian am 05 Mai 2023, 20:05:10
Zitat von: IPWF am 05 Mai 2023, 19:50:08Danke für Eure schnellen Beiträge.

@Damian: Temp_[AW] sollte ja ein RegEx für Temp_A bzw. Temp_W sein.
Wenn sich das so im DOIF nicht verwenden läßt, gibt es dann eine Alternative für eine solche devspec ?

ja, es gibt nichts, was es nicht gibt :)

set Temp_[(A)(W)] ...
Das entspricht deiner Anforderung und wird von DOIF durchgelassen, weil es keiner DOIF-Syntax entspricht.

Titel: Aw: set-Befehl mit RegEx in DOIF ?
Beitrag von: IPWF am 09 Mai 2023, 14:32:46
Das war schon mal sehr hilfreich. Vielen Dank !
"set Temp_[(A)(W)]" funktioniert.

Aber "$DEVICE" funktioniert nicht so, wie ich dachte. Wenn die DOIF-DEFinition z.B.
([Schalter] eq "on")
  (set Temp_[(A)(W)] setpointTemp [$DEVICE:tempKom])
DOELSE
  (set Temp_[(A)(W)] setpointTemp [$DEVICE:tempRed])
ist, dann bezieht sich $DEVICE auf das Gerät "Schalter" und nicht auf das vom set-Befehl betroffene Gerät (Temp_A bzw. Temp_W).

$DEV, wie in der CommandRef zu set beschrieben, funktioniert auch nicht.
Gibt es eine andere vordefinierte Variable, die anders als $DEVICE den Namen des vom set betroffenen Gerätes liefert ?
Titel: Aw: set-Befehl mit RegEx in DOIF ?
Beitrag von: xenos1984 am 09 Mai 2023, 18:01:28
Zitat von: IPWF am 09 Mai 2023, 14:32:46$DEV, wie in der CommandRef zu set beschrieben, funktioniert auch nicht.

In der CommandRef steht nur, dass $DEV in Perl ersetzt wird.

([Schalter] eq "on")
  (set Temp_[(A)(W)] setpointTemp {ReadingsVal("$DEV", "tempKom", 0)})
DOELSE
  (set Temp_[(A)(W)] setpointTemp {ReadingsVal("$DEV", "tempRed", 0)})
Titel: Aw: set-Befehl mit RegEx in DOIF ?
Beitrag von: Damian am 09 Mai 2023, 18:13:32
ja, ist alles nicht so einfach.

Was geht in der Kommandozeile, ist:

set Temp_[ab] setpointTemp {(ReadingsVal("$DEV","tempKom",""))}
Allerdings wertet DOIF zuerst die Befehlskette {(...)} aus und meckert über $DEV, weil es diese Variable nicht kennt.

Was du machen kannst ist, eine Perlfunktion in FHEM zu definieren, die den set-Befehl so liefert wie es in der Kommandozeile funktioniert und im DOIF diese Funktion über die fhem-Funktion aufrufen.

in my_Utils:

sub my_set_Temp_Kom
{
  return ('set Temp_[ab] setpointTemp {(ReadingsVal("$DEV","tempKom",""))}')
}


im DOIF dann nur noch aufrufen

([Schalter] eq "on")
  {fhem my_set_Temp_Kom};
...


Titel: Aw: set-Befehl mit RegEx in DOIF ?
Beitrag von: IPWF am 28 Mai 2023, 01:14:24
Nach Euren sehr hilfreichen Hinweisen habe ich nun laaange experimentiert und bin tatsächlich zu einer funktionierenden Lösung gekommen.

Zunächst habe ich es, dem Vorschlag von xenos1984 folgend, mit DOIF-Templates versucht. Das funktioniert zwar, aber eine wirkliche Vereinfachung bringt es nicht, finde ich. Außerdem sind sie nur innerhalb des DOIFs gültig, in dem sie definiert sind. Könnte man die Templates global definieren, wären sie auch in anderen DOIFs nutzbar; aber das ist offenbar nicht möglich (oder habe ich da was überlesen ?).

Vielversprechender fand ich den Ansatz mit einer Funktion in my_Utils. Ich wollte allerdings eine universell einsetzbare Funktion haben (mit Parameterübergabe). Es hat viele Versuche erfordert, diese so zu formulieren, daß der Rückgabewert der Funktion auch tatsächlich in einem DOIF als set-Befehl akzeptiert und richtig ausgewertet wird. Am Ende ist folgendes entstanden:
In my_Utils lautet die Definition:
sub SetDEVreading($$$)
{
  my ($devspec, $setreading, $valreading) = @_;
  return( 'set '.$devspec.' '.$setreading.' {(ReadingsVal($DEV,"'.$valreading.'",""))}' );
}

sub SetTemp($$)
{
  my ($roomspec, $valreading) = @_;
  return( SetDEVreading("Temp_[($roomspec)]", "setpointTemp", $valreading) );
}
"SetDEVreading" ist hier die "universelle" und "SetTemp" die für meinen konkreten Anwendungsfall spezifische Funktion.

Zum Aufruf im DOIF kann man entweder z.B.
{ fhem( SetDEVreading("Temp_[(AC)]", "setpointTemp", "tempKom") ) }  oder
{ fhem( SetTemp("AC", "tempKom") ) }  eingeben.

Beide Funktionen liefern hier als Rückgabewert den String
'set Temp_[(AC)] setpointTemp {(ReadingsVal($DEV,"tempKom",""))}',
welcher dann im DOIF mit "fhem(..." ausführbar ist.
Was mich jedoch wundert: schreibe ich exakt diesen String direkt in einen "fhem("-Befehl (also ohne Nutzung der Funktionen aus my_Utils), funktioniert es nicht. FHEM meckert dann wieder, dass "$DEV" nicht definiert sei.
Warum ist das so? Was ist der Unterschied, wenn der String von einer Funktion zurückgegeben oder direkt in den "fhem("-Befehl geschrieben wird ?
Titel: Aw: set-Befehl mit RegEx in DOIF ?
Beitrag von: Damian am 28 Mai 2023, 11:49:10
Zitat von: IPWF am 28 Mai 2023, 01:14:24...
welcher dann im DOIF mit "fhem(..." ausführbar ist.
Was mich jedoch wundert: schreibe ich exakt diesen String direkt in einen "fhem("-Befehl (also ohne Nutzung der Funktionen aus my_Utils), funktioniert es nicht. FHEM meckert dann wieder, dass "$DEV" nicht definiert sei.
Warum ist das so? Was ist der Unterschied, wenn der String von einer Funktion zurückgegeben oder direkt in den "fhem("-Befehl geschrieben wird ?


Das habe ich bereits geschrieben.

Es ist nicht das FHEM-System, welches meckert, sondern DOIF:

ZitatAllerdings wertet DOIF zuerst die Befehlskette {(...)} aus und meckert über $DEV, weil es diese Variable nicht kennt.

Deswegen darf der DOIF-Interpreter die Variable $DEV nicht zu sehen bekommen. Das erreicht man, wenn man sie in einer Funktion versteckt.

Titel: Aw: set-Befehl mit RegEx in DOIF ?
Beitrag von: IPWF am 28 Mai 2023, 14:16:35
Danke für Deine erneute Erklärung. Das es so ist, hatte ich schon verstanden und auch entsprechend umgesetzt. Aber ein Punkt ist mir immer noch nicht ganz klar:
Zitat von: Damian am 28 Mai 2023, 11:49:10Deswegen darf der DOIF-Interpreter die Variable $DEV nicht zu sehen bekommen. Das erreicht man, wenn man sie in einer Funktion versteckt.
Die Funktion gibt doch den String zurück, der ja die Variable $DEV enthält. Und dieser String wird dann im DOIF ausgewertet, oder? Somit sieht der DOIF-Interpreter die Variable $DEV doch trotzdem.
Oder ist es so, daß die Interpretation des Strings bereits in der Funktion geschieht und diese dann nicht den String an sich, sondern dessen Interpretation (also direkt ausführbaren Code) zurückgibt? Dann würde ich es verstehen.
Sorry, wenn ich da etwas begriffsstutzig bin. Ich bin noch Perl-Neuling.
Titel: Aw: set-Befehl mit RegEx in DOIF ?
Beitrag von: Damian am 28 Mai 2023, 18:10:12
Zitat von: IPWF am 28 Mai 2023, 14:16:35Danke für Deine erneute Erklärung. Das es so ist, hatte ich schon verstanden und auch entsprechend umgesetzt. Aber ein Punkt ist mir immer noch nicht ganz klar:
Zitat von: Damian am 28 Mai 2023, 11:49:10Deswegen darf der DOIF-Interpreter die Variable $DEV nicht zu sehen bekommen. Das erreicht man, wenn man sie in einer Funktion versteckt.
Die Funktion gibt doch den String zurück, der ja die Variable $DEV enthält. Und dieser String wird dann im DOIF ausgewertet, oder? Somit sieht der DOIF-Interpreter die Variable $DEV doch trotzdem.
Oder ist es so, daß die Interpretation des Strings bereits in der Funktion geschieht und diese dann nicht den String an sich, sondern dessen Interpretation (also direkt ausführbaren Code) zurückgibt? Dann würde ich es verstehen.
Sorry, wenn ich da etwas begriffsstutzig bin. Ich bin noch Perl-Neuling.

Nein, DOIF wertet nicht mehr den Return-String aus, sondern gibt ihn an FHEM weiter.
Titel: Aw: set-Befehl mit RegEx in DOIF ?
Beitrag von: IPWF am 29 Mai 2023, 14:28:10
Ach so, wenn also der String aus einer Funktion kommt, wertet DOIF ihn nicht aus; wenn er aber direkt in der DOIF-Definition steht, wertet DOIF ihn aus, bevor das Ergebnis an FHEM weitergegeben wird.
Dann ist der Unterschied klar. Vielen Dank !