DOIF mit relativer Zeitangabe wird nicht ausgeführt

Begonnen von Eckat, 07 Juli 2023, 09:00:02

Vorheriges Thema - Nächstes Thema

Eckat

Moin  :)

Ich habe ein Problem das für mich wie eine Anfängerfrage aussieht, daher habe ich dieses Forum genutzt.
Allerdings habe ich schon viele DOIFs im Einsatz, jedoch nur dieses eine mit relativer Zeitangabe.

Hier mein aktueller Code:
defmod check_auto.DI DOIF ([+00:15])

(
set eNiro.Text.dummy Start-1,
{
fhem("set eNiro.Text.dummy Start-2");;
my $uhrzeit = time();;
my $last_run = ReadingsVal("eNiro.DI", "last_run", 0);;
my $alter = $uhrzeit - $last_run;;

my $text = '['.strftime('%d.%m.%y - %H:%M:%S', localtime).'] DOIF - Start / Pre-Call - Alter: '.$alter;;

fhem("set eNiro.Text.dummy ".$text);;

if (($alter > 900 && ReadingsVal('go_eCharger.no3_V3', 'car_state', 'NA') > 1) || $alter > 3600) {
fhem ('setreading eNiro.DI last_run '.$uhrzeit);;
system('node /home/fhem/bluelinky/kia.js &');;
$text = '['.strftime('%d.%m.%y - %H:%M:%S', localtime).'] DOIF - allowcharging: '.ReadingsVal('go_eCharger.no3_V3', 'allow_charging', 'NA').', carstate: '.ReadingsVal('go_eCharger.no3_V3', 'car_state', 'NA').', bat12V: '.ReadingsVal('eNiro', 'battery12V', 'NA').', SoC: '.ReadingsVal('eNiro', 'soc', 'NA').'% | fhem - eNiro.DI';;
if (AttrVal("eNiro.DI", "verbose", 2) > 2) {
fhem ('set CarstenPush message '.$text);;
}
fhem("set eNiro.Text.dummy ".$text);;
}
}
)

Das soll halt alle 15 Minuten ausgeführt werden und den Status des Autos in ein Dummy schreiben, wenn die Bedingung im Perl Teil erfüllt sind. Das erzeugt dann ein FileLog.
Führe ich das mit "checkall" per Hand aus, wird state auf cmd_2 gesetzt, da ja die Bedingung nicht erfüllt ist. Soweit OK.
Mit "set check_auto.DI cmd_1" führt er das sauber aus und die gesetzten Texte sind sowohl im Dummy als auch im FileLog alle zu sehen.

Nur automatisch passiert quasi nix. Quasi deshalb, weil irgendwie doch alle paar Tage mal ein Durchlauf zum Erfolg führt.

Was ich schon getestet habe ist
defmod check_auto.DI DOIF ([+00:15])

{
fhem ("set eNiro.Text.dummy Start-1");;
[...]
}
Also den Ausführungsblock ohne () anzugeben und alles in Perl zu machen bzw. war das der ursprüngliche Teil.
Das mit "Start-1" vor der Bedingung im Perl-Teil ist auch eher ein Debugging Versuch, aber selbst das wird nie (fast nie) ausgegeben. An der Logik-Bedingung im Perl Teil liegt es also nicht.

Hat jemand eine Idee?
Wahrscheinlich sehe ich nur den Wald vor lauter Bäumen nicht.

Danke und Gruß,
Carsten

Damian

Du hast hier ein DOIF im FHEM-Modus definiert, dieser arbeitet mit Auswertung des eigenen Zustands ohne Wiederholung. Wenn du das Attribut do auf always setzt, dann wird dein Zweig jedes Mal ausgeführt. Da du schon sehr viel in Perl programmiert hast, kannst du überlegen deine DOIF-Definition gleich im Perl-Modus zu definieren, dann brauchst du für die Wiederholung deines Programmcodes auch kein do always Attribut.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Eckat

Danke!

Stimmt, irgendwie habe ich das schon mal gelesen, dass DOIF über den eigenen Zustand sich merkt, ob er das noch mal ausführen muss.
Wirkt aber so, als ob ein DOIF mit relativen Zeitangaben dann nur so bedingt sinnvoll sind.  ;D

Das mit dem Perl-Modus ist wohl die Lösung, mir aber völlig neu. Ist wohl irgendwann mal dazu gekommen.
Ich nutze fhem schon viele Jahre, habe aber leider wenig Zeit mich über allgemeine Neuigkeiten zu informieren. Meistens nur, wenn man etwas für eine Erweiterung oder Änderung braucht.  8)

Habe jetzt den Code umgebaut und bin gespannt.
Vielleicht als Frage vorab:
In der CommandRef steht für DOIF im Perl-Modus mit relativen Zeitangaben folgendes Bsp.:
define di_save DOIF {[+01:00];fhem"save"}
Hier ist hinter "DOIF" sowohl Bedingung als auch Ausführungsblock in dem selben Paar {}, mit einem Semikolon getrennt.
Wie ist denn die korrekte Syntax, wenn man im Ausführungsblock mehrere Befehle/ Logik haben möchte?

Damian

Im Perlmodus gibt es keine Unterscheidung zwischen Bedingung und Ausführung der Art DOIF (<Bedingung>)(<Ausführung>)

Es gibt dagegen nur Perlblöcke der Art DOIF {<Block1>}{<Block2>}...

In den Perlblöcken werden Trigger in der DOIF-Syntax eingesetzt, wenn der Trigger (Ereignis- oder Zeittrigger) wahr wird, wird der Block ausgeführt. FHEM-Befehle können logischerweise im Perlmodus nur über fhem-Funktion ausgeführt werden. Alles weitere steht in der Doku zum DOIF-Perlmodus.

Für dich würde es bedeuten:

DOIF {[+00:15]; fhem"set eNiro.Text.dummy Start-1";
{
fhem("set eNiro.Text.dummy Start-2");;
my $uhrzeit = time();;
my $last_run = ReadingsVal("eNiro.DI", "last_run", 0);;
my $alter = $uhrzeit - $last_run;;

my $text = '['.strftime('%d.%m.%y - %H:%M:%S', localtime).'] DOIF - Start / Pre-Call - Alter: '.$alter;;

fhem("set eNiro.Text.dummy ".$text);;
...

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

Eckat

Hmm, unabhängig davon das ist das aus der CommandRef nicht gelesen hätte, führt folgender Code zu einem Fehler:

{[+00:15]; fhem ("set eNiro.Text.dummy Start-1");

{
fhem("set eNiro.Text.dummy Start-2");;
my $uhrzeit = time();;
my $last_run = ReadingsVal("eNiro.DI", "last_run", 0);;
my $alter = $uhrzeit - $last_run;;

my $text = '['.strftime('%d.%m.%y - %H:%M:%S', localtime).'] DOIF - Start / Pre-Call - Alter: '.$alter;;

fhem("set eNiro.Text.dummy ".$text);;

if (($alter > 900 && ReadingsVal('go_eCharger.no3_V3', 'car_state', 'NA') > 1) || $alter > 3600) {
fhem ('setreading eNiro.DI last_run '.$uhrzeit);;
system('node /home/fhem/bluelinky/kia.js &');;
$text = '['.strftime('%d.%m.%y - %H:%M:%S', localtime).'] DOIF - allowcharging: '.ReadingsVal('go_eCharger.no3_V3', 'allow_charging', 'NA').', carstate: '.ReadingsVal('go_eCharger.no3_V3', 'car_state', 'NA').', bat12V: '.ReadingsVal('eNiro', 'battery12V', 'NA').', SoC: '.ReadingsVal('eNiro', 'soc', 'NA').'% | fhem - eNiro.DI';;
if (AttrVal("eNiro.DI", "verbose", 2) > 2) {
fhem ('set CarstenPush message '.$text);;
}
fhem("set eNiro.Text.dummy ".$text);;
}
}
}

Reading block_01 hat den Inhalt "condition c01: Undefined subroutine &DOIF::strftime called, line 9." nach der Ausführung.

Eckat

Sorry, bin zu doof  :o

Bin davon ausgegangen das das Problem mit dem Umbau auf den perl-Modus zu tun hat, aber es steht ja klar in der Meldung das die subroutine strftime nicht definiert ist.
Habe die testweise rausgenommen, nun funktioniert es.

Aber grundsätzlich klappt das mit strftime. Gibt es im Perl-Modus hier Besonderheiten?

Eckat

Doppel-Sorry  :D

Hab's doch selber gefunden.
Danke, ist gelöst.