Hauptmenü

set-Befehl mit RegEx in DOIF ?

Begonnen von IPWF, 05 Mai 2023, 14:57:39

Vorheriges Thema - Nächstes Thema

IPWF

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 ?
FHEM auf Hardkernel ODROID-N2+ mit Ubuntu 22.04 LTS
Funkschnittstelle EnOcean

xenos1984


Damian

$DEVICE würde funktionieren, allerdings wird [AW] im DOIF als Status vom Device AW interpretiert.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

IPWF

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 ?
FHEM auf Hardkernel ODROID-N2+ mit Ubuntu 22.04 LTS
Funkschnittstelle EnOcean

Damian

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.

Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

IPWF

#5
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 ?
FHEM auf Hardkernel ODROID-N2+ mit Ubuntu 22.04 LTS
Funkschnittstelle EnOcean

xenos1984

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)})

Damian

#7
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};
...


Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

IPWF

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 ?
FHEM auf Hardkernel ODROID-N2+ mit Ubuntu 22.04 LTS
Funkschnittstelle EnOcean

Damian

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.

Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

IPWF

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.
FHEM auf Hardkernel ODROID-N2+ mit Ubuntu 22.04 LTS
Funkschnittstelle EnOcean

Damian

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.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

IPWF

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 !
FHEM auf Hardkernel ODROID-N2+ mit Ubuntu 22.04 LTS
Funkschnittstelle EnOcean