[gelöst] Modul DoIF Wert aus verknüpften Device "auslesen"

Begonnen von AnBad, 19 August 2021, 17:09:21

Vorheriges Thema - Nächstes Thema

AnBad

Hallo,
wie üblich wird ein DoIf form Typ DOIF bei mir bei Veränderungen eines verknüpften Device ausgelöst.

Die DoIf soll einen bestimmten Wert im verknüpften Device aktualisieren und dann den neuen Wert abgreifen.

Das Aktualisieren klappt mittels der DoIf einwandfrei mit entsprechenden get-Befehl des verknüpften Device.

Was nicht funktioniert ist, dass die DoIf dann, bzw. auch nach einer gewissen Sleepverzögerung den aktuellen Wert aus dem verknüften Device übernimmt. Die DoIf bekommt immer den "alten" Wert geliefert.

Woran liegt das?

Wie kann man das abstellen?

([dev_Zwischenschalter3:state] eq "on")
(
(get dev_Zwischenschalter3 measurement 0 energy),
(sleep 15; setreading doif_Strommesser_Betrieb 1_2_LetzterEnergy0 {(ReadingsNum("dev_Zwischenschalter3","energy0",0))})
)

Damian

#1
Die Ausführung der mit Komma getrennten Befehle läuft sequentiell ab, also nacheinander.

Vermutlich ist der Wert noch nicht gesetzt, wenn der Sleep-Befehl aufgesetzt wird, denn dann hat bereit DOIF  {(ReadingsNum("dev_Zwischenschalter3","energy0",0))} ausgewertet - dazwischen liegen nur wenige Millisekunden.

Ich würde dir empfehlen statt sleep das DOIF-Attribut wait zu verwenden, denn dann hast du 15 Sekunden Zeit bis zur Auswertung des Befehls.

(IF ([dev_Zwischenschalter3:state] eq "on") (get dev_Zwischenschalter3 measurement 0 energy))
(IF ([dev_Zwischenschalter3:state] eq "on") (setreading doif_Strommesser_Betrieb 1_2_LetzterEnergy0 {(ReadingsNum("dev_Zwischenschalter3","energy0",0))}))

attr wait 0,15
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

AnBad

Ja, das dachte ich mit der schneller Auswertung ja auch. Deswegen der "Sleep"-Befehl.

Ich habe hier mit Semikolon getrennt, und nicht mit Komma. "sequentiell" wäre doch auch richtig, oder? Erst sleep und dann Befehl.

"Wait", Wäre ok, Problem ist aber, dass ich hier nur die zwei Zeilen gezeigt habe und das DEF eigentlich ein ganzes Stück länger ist mit einigen FHEM-Ifs usw. Da weiß ich nicht, wie ich "wait" aufsetzen soll. für jeden FHEM-Befehl eine Zahl, obwohl mit if verschachtelt? usw. sleep wäre viel besser, da eigentlich nur die eine Anweisung verzögert werden muss. 

Damian

Zitat von: AnBad am 19 August 2021, 17:43:18
Ja, das dachte ich mit der schneller Auswertung ja auch. Deswegen der "Sleep"-Befehl.

Ich habe hier mit Semikolon getrennt, und nicht mit Komma. "sequentiell" wäre doch auch richtig, oder? Erst sleep und dann Befehl.

"Wait", Wäre ok, Problem ist aber, dass ich hier nur die zwei Zeilen gezeigt habe und das DEF eigentlich ein ganzes Stück länger ist mit einigen FHEM-Ifs usw. Da weiß ich nicht, wie ich "wait" aufsetzen soll. für jeden FHEM-Befehl eine Zahl, obwohl mit if verschachtelt? usw. sleep wäre viel besser, da eigentlich nur die eine Anweisung verzögert werden muss.

ja, man kann es eigentlich nur richtig verstehen, wenn man es selbst programmiert hat.  Das Ganze ist historisch gewachsen.

Die Möglichkeit Perlcode mit {(...)} im FHEM-Befehl auszuwerten gab es zuerst im DOIF, es wurde erst später im set-Befehl bzw. setreading eingebaut, daher wird es bei dir bereits vom DOIF ausgewertet und nicht erst 15 Sekunden später von setreading.

Alternativ kannst du den Sleep-Befehl komplett in Perl formulieren, dann fühlt sich DOIF bzw. setreading für die Auswertung von ReadingsNum nicht zuständig ;)


(sleep 15; {fhem("setreading doif_Strommesser_Betrieb 1_2_LetzterEnergy0 ". ReadingsNum("dev_Zwischenschalter3","energy0",0))})

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

AnBad

Hallo,
vielen Dank.
So mit Deiner Codezeile konnte ich das Problem lösen.

Schade, dass FHEM so schwierig ist. Schwierig, wenn man nicht ständig damit arbeitet, sondern nur hin und wieder.

Damian

Zitat von: AnBad am 19 August 2021, 21:26:32
Hallo,
vielen Dank.
So mit Deiner Codezeile konnte ich das Problem lösen.

Schade, dass FHEM so schwierig ist. Schwierig, wenn man nicht ständig damit arbeitet, sondern nur hin und wieder.

Schwierig, weil es viele Möglichkeiten gibt zum Ziel zu kommen - Fluch und Segen in Einem :)
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

AnBad

Hallo Damian,

sorry, dass ich auf diese Sache nochmals zurückkommen muss.

Ich habe jetzt angefangen meinen Code in meine erste 99_myUtils.pm zu schreiben, da ich mit den Verschachtelungen in den Modulen nicht mehr klar gekommen bin. Das, denke ich, hat auch soweit prima geklappt. Doch jetzt habe ich das gleiche Problem, welches ich mit dem DoIf-Modul hatte: Es werden Daten von einem Strommesser abgefragt. Bis die Ergebnisse "geliefert" werden, vergehen ein paar Millisekunden. Doch dann ist die Perl-Sub bereits fertig. Ich habe es probiert mit "sleep" zu lösen. Es klappt aber nicht. Was mache ich falsch?

Nach den beiden Abfragen "get .." müsste Perl erst auf die Ergebnisse warten...

Auszug aus Code:
#------"Neue" Daten abfragen/ermitteln/setzen
{fhem("get dev_Zwischenschalter3 measurement 0 energy")};
{fhem("get dev_Zwischenschalter3 measurement 0 power")};


Gesamtcode:
sub Sub_A_doifdevZwischenschalter3_WerteAbfragen_V21_08_24($$) {
###################Aufgabe der Sub/Function:  Werte aus Strommesser auslesen und verarbeiten############################

#------Variablen Deklarieren & Festlegen
# Übergabewert durch Sub
my ($Name_DoIf, $Name_devZwischenschalter3) = @_;
#------"Alte" Daten abfragen/ermitteln/setzen
my ($power0_SummeAlt) = ReadingsNum($Name_devZwischenschalter3,"power0",0);
my ($energy0_SummeAlt) = ReadingsNum($Name_devZwischenschalter3,"energy0",0);
my ($time_start_global) = time_str2num(ReadingsTimestamp($Name_devZwischenschalter3,"channel0",0));
{fhem("setreading $Name_DoIf 1.A_Zeit_Start_sec $time_start_global")};

#------"Neue" Daten abfragen/ermitteln/setzen
{fhem("get dev_Zwischenschalter3 measurement 0 energy")};
{fhem("get dev_Zwischenschalter3 measurement 0 power")};
{sleep(2)};
my ($power0_SummeNeu) = ReadingsNum($Name_devZwischenschalter3,"power0",0);
my ($energy0_SummeNeu) = ReadingsNum($Name_devZwischenschalter3,"energy0",0);
my ($time_start_round) = time_str2num(ReadingsTimestamp($Name_devZwischenschalter3,"energ0",0));

#------Variablen sonstige
my ($time_elaps_global) = $time_start_round - $time_start_global;
my ($time_elaps_round) = $time_start_round - ReadingsNum($Name_DoIf,"1.B_Zeit_Aktuell_sec",0);

#------Readings löschen
{fhem("deletereading $Name_DoIf .*")}; #zum Aufräumen währen Programmierung
#------Bearbeitung
    #A) XYZ
    #--------------------------------------------------
    #B) XYZ
    #--------------------------------------------------
    #C) XYZ
    #--------------------------------------------------
    #D) XYZ
    #--------------------------------------------------

#------Ausgabe

{fhem("setreading $Name_DoIf 1.A_Zeit_Start_sec $time_start_global")};
{fhem("setreading $Name_DoIf 1.B_Zeit_Aktuell_sec $time_start_round")};
{fhem("setreading $Name_DoIf 1.C_Zeit_VergangenGlobal_sec $time_elaps_global")};
{fhem("setreading $Name_DoIf 1.D_Zeit_VergangenRunde_sec $time_elaps_round")};
{fhem("setreading $Name_DoIf 1.E_power0Alt_Ws $power0_SummeAlt")};
{fhem("setreading $Name_DoIf 1.F_power0Neu_Ws $power0_SummeNeu")};
{fhem("setreading $Name_DoIf 1.G_energy0Alt_Ws $energy0_SummeAlt")};
{fhem("setreading $Name_DoIf 1.H_energy0Neu_Ws $energy0_SummeNeu")};

###########################ERGEBNIS################################
#### Ausgabevariable:
#### Veränderung der Arbeitsmappe: keine
#### sonstiges: ./.
###########################ERGEBNIS################################

}

Damian

Sleep in dem Sinne, wie du es brauchst, gibt es in Perl nicht. Nicht blockierend verzögern kannst du nur mit FHEM-Sleep oder z.B. im DOIF-Perlmodus mit set_Exec.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

AnBad

Hi,
OK,
dann muss ich die Sub aufteilen und nacheinander mit FHEM aufrufen.
Alles klar!!
Vielen Dank.