Folgende Definition habe ich im DOIF
DOELSEIF ([23:59]){
my $timePrefixMonth = qx"date -d 'today' +'%Y_%m'";
my $monthThermicEnergy = (split(/\s/,(ReadingsVal("GPIO3","statGesamtWaermemenge",0))))[5];
fhem("setreading GPIO3 ${timePrefixMonth}_TEST ${monthThermicEnergy});
}
Verwende ich diese Syntax im DOIF, wird der Wert "277" (aus Variable monthThermicEnergy) in Form von "_TEST 277" für das Reading gesetzt. Das "_TEST" wird also nicht an den Reading-Namen der Variable timePrefixMonth als Präfix gesetzt, sondern an den Wert gehangen.
Falsch: Reading "2021_08" hat den Wert "_TEST 277"
Richtig: Reading "2021_08_TEST" hat den Wert "277"
Setze ich die Variable timePrefixMonth vom qx manuell auf "2021_08", funktioniert das Verketten mit fhem("setreading ...") korrekt. qx scheint also einen Wert mitzuliefern, der durch das setreading anders interpretiert wird. Führe ich
{qx(date -d 'today' +'%Y_%m')}
auf der Webkonsole aus, bekomme ich "2021_08" angezeigt. Kann mir das bitte jemand erklären? Vielen Dank! :-)
Vermutlich habe ich die Ursache gefunden.
Das "qx" scheint durch das "date" einen Zeilenumbruch als Rückgabewert mit zu erhalten. So funktioniert es jetzt bei mir mit Hilfe von chomp() (https://perldoc.perl.org/functions/chomp).
DOELSEIF ([23:59]){
my $timePrefixMonth = qx"date -d 'today' +'%Y_%m'";
chomp($timePrefixMonth)
my $monthThermicEnergy = (split(/\s/,(ReadingsVal("GPIO3","statGesamtWaermemenge",0))))[5];
fhem("setreading GPIO3 ${timePrefixMonth}_TEST ${monthThermicEnergy}");
}
Hallo,
versuch mal so:
{
my $v = (split(/\s/,(ReadingsVal("GPIO3","statGesamtWaermemenge",0))))[5];
my $tpm = qx"date -d 'today' +'%Y_%m'";
$tpm .= "_TEST $v"
fhem("setreading GPIO3 $tpm);
}
Ich verstehe die geschweiften Klammern bei den Variablen nicht, sollten die beim DOIF gebraucht werden musst die noch ergänzen.
Gruß
Thomas
edit:
edit:
Ok, wenn es an dem Zeilenumbruch liegt, dann trotzdem etwas kürzer auch mit chomp, ungetestet:
{
my $v = (split(/\s/,(ReadingsVal("GPIO3","statGesamtWaermemenge",0))))[5];
my $tpm = chomp(qx"date -d 'today' +'%Y_%m'");
$tpm .= "_TEST $v"
fhem("setreading GPIO3 $tpm);
}
Hast du
my $tpm = chomp(qx"date -d 'today' +'%Y_%m'");
getestet? Ich bekomme dort den Fehler
Can't modify quoted execution (``, qx) in chomp at (eval 9557149) line 1, near "qx"date -d 'today -1 month' +'%Y_%m'")"
Das hatte ich auch erst so, aber es funktioniert bei mir erst nach dem qx den Wert in die Variable geschrieben hat.
Die geschweiften Klammern sind eine Syntax-Variante in Perl, um Variablen in Strings anstatt z.B. den "." zu verwenden. So hab ich es verstanden.
Hi,
anstatt des Umweges über die Shell:
my $timePrefixMonth = strftime('%Y_%m',localtime())
Gruß Otto
Danke euch für eure Rückmeldungen. :-)
Den Umweg über die Shell habe ich gemacht, weil ich auch den Vormonat benötige. Das ging mit
qx(date -d 'today -1 month' +'%Y_%m')
fixer.
Oder gibt es in Perl was Ähnliches, ohne das Thema mit dem Dezember / Januar abzufangen?
Zitat... das Thema mit dem Dezember / Januar abzufangen?
Da werden mehrere die Hände überm Kopf zusammenschlagen, aber es wäre eine Lösung:
Mit dem ternären Operator, kurz und knapp, prüfen ob
my $v = strftime(%m',localtime())
eins ergibt und dann 12 zurückgeben, sonst den Rückgabewert mit sprintf (mit führender Null
edit: wenn nicht schon zweistellig) ausgeben ?
Schau mal hier: https://wiki.fhem.de/wiki/Zeitangaben,_rechnen_mit
Auf die Schnelle zum Anschauen in der FHEM Kommandozeile:
{strftime('%Y_%m',localtime(time-60*60*24*31))}
Thema mit dem Dezember / Januar ist damit abgefangen aber wegen exakt einem Monat, der hat ja nicht immer 31 Tage - da gibt es sicher etwas.
Zitataber wegen exakt einem Monat, der hat ja nicht immer 31 Tage - da gibt es sicher etwas.
Deswegen der Vorschlag von gerade eben.
Eigentlich liefert localtime eine Liste / einzelnen Elemente:
{my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();;return $mon}
$mon liefert den Monat - 1, der aktuelle Monat ist also $mon+1, der Vormonat ist $mon
Oder lieg ich da falsch?
ZitatOder lieg ich da falsch?
Kann leider nicht folgen wie die Frage jetzt gemeint ist, wenns um
rechnen mit Zeiten geht war ich bisher froh das du da warst :)
Verstehe nicht warum $mon den letzten Monat zurückgibt.
Meinetwegen nimmt man mit meinem obigen Vorschlag auch einfach $month.
edit:
Achso, du meinst $mon könnte man hier jetzt verwenden weil bei null angefangen wird zu zählen ?
Zitat von: Otto123 am 31 August 2021, 21:17:34
Eigentlich liefert localtime eine Liste / einzelnen Elemente:
{my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();;return $mon}
$mon liefert den Monat - 1, der aktuelle Monat ist also $mon+1, der Vormonat ist $mon
Oder lieg ich da falsch?
Da liegst du richtig. Ich muss dann aber trotzdem Dezember (11) und Januar (0) prüfen.
Passt jetzt aber alles und konnte mein Problem mit dem qx ja lösen. Vielen Dank nochmal.
Und warum mit qx und nicht mit einem Systemaufruf der nicht blockierend sein kann ? Zumindest hab ich es bisher so verstanden .
Zitat von: h002 am 31 August 2021, 22:24:49
Da liegst du richtig. Ich muss dann aber trotzdem Dezember (11) und Januar (0) prüfen.
Dezember verstehe ich nicht. Bei 0 hast Recht.
system() liefert die Ausgabe nicht zurück.
Zitat von: Otto123 am 31 August 2021, 23:04:18
Dezember verstehe ich nicht. Bei 0 hast Recht.
Die IT'ler nehmen es wieder sehr genau. Im Kopf habe ich nur überlegt, dass ich beim Jahreswechsel was beachten muss. Darum habe ich Dezember und Januar erwähnt. Das es kein Problem mit dem Vormonat vom Dezember gibt, ist mir klar. ;-)
Ich hab mal wo mitgenommen das man so einen qx-Aufruf bspw.
qx(date -d 'today -1 month' +'%Y_%m')
in der Kommandozeile einfach nur in doppelten Quotes angeben kann und der Aufruf ist nicht blockierend.
Also so:
"date -d 'today' +'%Y_%m'"
Hier sind wir ja aber in Perl, dachte wenn ich den Aufruf in einen Fhem-Befehl stecke klappt das evtl. auch, tuts aber nicht.
Aber wenn ich den Aufruf in `` packe schon.
Frage an die "Experten", ist das dann das gleiche wie aus der Kommandozeile (nicht blockierend) oder nicht ?
{
my $v = (split(/\s/,(ReadingsVal("GPIO3","statGesamtWaermemenge",0))))[5];
my $tpm = `date -d 'today' +'%Y_%m'`;
chomp($tpm);;
$tpm .= "_TEST $v";
fhem("setreading GPIO3 $tpm);
}
Im DOIF-Perlmodus geht es einfacher (da sind die entsprechenden Variablen schon vorhanden)
DOIF {
[23:59];
my $monthThermicEnergy = (split(/\s/,(ReadingsVal("GPIO3","statGesamtWaermemenge",0))))[5];
fhem("setreading GPIO3 ${year}_${month}_TEST $monthThermicEnergy");
}
Den Vormontag kann man aus $month natürlich entsprechend bestimmen.
Zitat von: Damian am 01 September 2021, 07:49:05
Den Vormontag kann man aus $month natürlich entsprechend bestimmen.
;D wobei wir wieder beim Knackpunkt sind ;D
@TomLee
qx(date -d 'today -1 month' +'%Y_%m') und `date -d 'today' +'%Y_%m'` (also backticks) sind faktisch das Gleiche siehe https://perldoc.perl.org/perlop#Quote-Like-Operators
Der Aufruf "date -d 'today' +'%Y_%m'" in der FHEM Kommandozeile schreibt die Ausgabe in das LogFile.
Dein letzter Codeblock ist also auch blockierend, was bei date keine Rolle spielen dürfte.
Den Vormonat kann man ja einfach berechnen:
my $premonth=($month==1 ? 12 : $month-1);
Ich würde mir die ganzen Systemaufrufe sparen.
ZitatIm DOIF-Perlmodus geht es einfacher
Was genau meinst du damit ? Nur die Zeit-Angabe ([23:59];) in Perl oder auch die Zeitvariablen, weil die sind doch nicht DOIF-spezifisch, das sind doch "normale, einfache FHEM-Variablen" ?
Die Variabeln $month, $year usw. gibt es in Perl nicht. Es handelt sich um lokale Variablen, die entweder in fhem.pl deklariert wurden oder im DOIF oder sonst in irgend einem Modul, wenn sie dort definiert wurde.
Im DOIF z. B. werden sie in der Abarbeitung der Bedingung im FHEM-Modus oder im Perl-Block im Perlmodus deklariert und mit aktuellen Werten belegt.
Dann mal noch ein Vorschlag für den Kompletten String wie im Ausgangspost. Nur mit Verwendung von Variablen :)
Für aktuellen und Vormonat
{strftime('%Y_%m',$sec,$min,$hour,$mday,$month-1,$year-1900)}
{$month==1 ? strftime('%Y_%m',$sec,$min,$hour,$mday,11,$year-1901) : strftime('%Y_%m',$sec,$min,$hour,$mday,$month-2,$year-1900)}
Sollte in FHEM einzeilern gehen ;) nicht in myUtils dort braucht man vorher die korrekte Zuweisung in der Art (nur als Ansatz):
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime()
Siehe auch https://commandref.fhem.de/#perl