FHEM Forum

FHEM => Anfängerfragen => Thema gestartet von: TomLee am 19 April 2021, 11:03:15

Titel: userreadings -> at -> Funktionsaufruf mit setreading
Beitrag von: TomLee am 19 April 2021, 11:03:15
Hallo,

habs noch nicht getestet mit einem at (aber mit einem sleep 1 <- klappt nicht, es kommt zur prohibited-Meldung), wenn ich in userReadings ein at definiere welches eine Funktion aufruft die ein setreading im selben Device des userreadings ausführt, umgehe ich dann die Meldung oder ist es immer noch ein setreading im gleichen Device ?
Ich rufe den Code ja aus einem at auf und nicht mehr aus dem userReadings, Denkfehler oder klappt das ?

Gruß

Thomas
Titel: Antw:userreadings -> at -> Funktionsaufruf mit setreading
Beitrag von: KernSani am 19 April 2021, 11:17:44
Kannst du vielleicht mal Beispielcoding posten? Dann wird das Ganze vielleicht verständlicher...
Titel: Antw:userreadings -> at -> Funktionsaufruf mit setreading
Beitrag von: TomLee am 19 April 2021, 11:30:12
Der Code ist noch nicht fertig (mir ist noch nicht klar wie ich bereits vorhandene Readings zu vergangenen Terminen lösche falls weniger wie 5 vorhanden sind), aber er legt die Termine schonmal an:

{pc_ce2rtest($name,'5')}

sub pc_ce2rtest {
    my $name = shift;
my $nr = shift;
    my $t = fhem('get '.$name.' events format:custom="$S" limit:from=0,count='.$nr,1);
    my @a= split("\n",$t);
    for (my $i = 0;$i<=$#a;$i++)
    {my $r = sprintf("t_%03.0f", $i ).'_summary';fhem("setreading $name $r $a[$i]");}
}


Warum über userReadings ? Weil ich mir eine zusätzliche at/notify-Definition sparen möchte, sonst kann ich ja gleich wieder Calview nehmen.

edit: "_summary" noch an das $r angehängt.
Titel: Antw:userreadings -> at -> Funktionsaufruf mit setreading
Beitrag von: TomLee am 19 April 2021, 15:25:18
Zum nachstellen, einfach den Devicenamen mit dem eines bereits vorhandenen Calendar-Device ersetzen, in diesem sollten dann die nächsten 5 Termine mit den Readingnamen t00X_summary und dem Wert der Zusammenfassung angelegt werden.

Für die Kommandozeile:

{
    my $name = '<Kalendername>';;
my $nr = 5;;
    my $t = fhem('get '.$name.' events format:custom="$S" limit:from=0,count='.$nr,1);;
    my @a= split("\n",$t);;
    for (my $i = 0;;$i<=$#a;;$i++)
    {my $r = sprintf("t_%03.0f", $i + 1 ).'_summary';;fhem("setreading $name $r $a[$i]");;}
}
Titel: Antw:userreadings -> at -> Funktionsaufruf mit setreading
Beitrag von: KernSani am 19 April 2021, 15:37:59
Lustig, ich habe schon seit ewigen Zeiten "CALVIEW loswerden" auf meiner Todo-Liste ;-) Habe mir aber noch nicht überlegt, wie... Deine Idee schaue ich mir heute Abend mal im Detail an, aber dumme Frage: Warum machst du nicht 5 userreadings, die direkt über eine Sub mit dem ersten/zweiten/dritten usw... Termin fütterst (also ohne setreading?). Für "deletreading" habe ich jetzt spontan auch keine schlaue Idee... Müsste mal ausprobieren, was passiert, wenn ein userreading auf Undef oder "" gesetzt wird...
Titel: Antw:userreadings -> at -> Funktionsaufruf mit setreading
Beitrag von: TomLee am 19 April 2021, 16:31:25
ZitatWarum machst du nicht 5 userreadings, die direkt über eine Sub...

Meine Variante mit 5 userReadings hab ich hier (https://forum.fhem.de/index.php/topic,103238.msg1147496.html#msg1147496) festgehalten.

Wie du siehst wird das Attribut userReadings aber ellenlang wenn man noch weitere Readings möchte bspw. die Startzeit.

Daher der Ansatz mit setreading.

edit: für jedes zusätzliche Reading eine Funktion dacht ich mir.
Titel: Antw:userreadings -> at -> Funktionsaufruf mit setreading
Beitrag von: TomLee am 25 April 2021, 17:21:51
Also das setreading aus dem AT im userReadings klappt:

userReadings:    
ce2r:triggered {fhem("define at_c at +00:00:01 {pc_ce2rtest('cal_example1','5')}");;return 'done'}


Funktion:
sub pc_ce2rtest {
    my $name = shift;
my $nr = shift;
    my $t = fhem('get '.$name.' events format:custom="$S" limit:from=0,count='.$nr,1);
    my @a= split("\n",$t);
    for (my $i = 0;$i<=$#a;$i++)
    {my $r = sprintf("t_%03.0f", $i + 1 )._summary;fhem("setreading $name $r $a[$i]");}
}


Fragen hätt ich dazu:

1. Welche Zeit nimmt man bei der Ausführung des AT am besten, gleich ?, sowas wie $hms ?

2. Wie muss der Perl-Teil im userReadings definiert werden, das man $name (Kalendername) verwenden kann ?

Mit
ce2r:triggered {fhem(qq(define at_c at +00:00:01 {pc_ce2rtest($name,'5')}));;return 'done'}

steht im Log:
2021.04.25 17:04:30 1: ERROR evaluating {pc_ce2rtest(cal_example1,'5')}: Bareword "cal_example1" not allowed while "strict subs" in use at (eval 111042) line 1.

2021.04.25 17:04:30 3: at_c: Bareword "cal_example1" not allowed while "strict subs" in use at (eval 111042) line 1.


Mit
ce2r:triggered {fhem(q(define at_c at +00:00:01 {pc_ce2rtest($name,'5')}));;return 'done'}
kann die Variable nicht aufgelöst werden:
2021.04.25 17:07:15 1: ERROR evaluating {pc_ce2rtest($name,'5')}: Global symbol "$name" requires explicit package name (did you forget to declare "my $name"?) at (eval 111352) line 1.

2021.04.25 17:07:15 3: at_c: Global symbol "$name" requires explicit package name (did you forget to declare "my $name"?) at (eval 111352) line 1.


Dann hab noch mehrere Varianten mit verketten probiert, bekomms einfach nicht hin, denke das Problem liegt an den zusätzlichen geschweiften Klammern im Fhem-Befehl.

3. Wie/aAuf was genau prüfen bei dem fhem Befehl das man entweder sowas wie "failed" oder "done" zurückgibt.

Titel: Antw:userreadings -> at -> Funktionsaufruf mit setreading
Beitrag von: Otto123 am 26 April 2021, 13:53:30
Hi Thomas,

zu 2. das ist der Punkt wo Du anstatt  {pc_ce2rtest($name,'5')}));;return 'done'} -> {pc_ce2rtest("$name",'5')}));;return 'done'} oder  {pc_ce2rtest(\'$name\','5')}));;return 'done'} nehmen musst.
Du löst ja die Variable auf und anschließend muss es wieder ein String werden.

zu 1. sleep 0.1 willst Du nicht nehmen?

Gruß Otto
Titel: Antw:userreadings -> at -> Funktionsaufruf mit setreading
Beitrag von: TomLee am 26 April 2021, 14:20:25
ZitatDu löst ja die Variable auf und anschließend muss es wieder ein String werden.

Probier ich später aus, es ist schönes Wetter und mag was arbeiten.

Zitatsleep 0.1 willst Du nicht nehmen?

Komm nicht ganz mit, du meinst statt AT ? Dazu steht die Antwort im ersten Beitrag, das setreading muss ja aus einem anderen Device kommen.
Titel: Antw:userreadings -> at -> Funktionsaufruf mit setreading
Beitrag von: Otto123 am 26 April 2021, 14:32:19
Zitat von: TomLee am 26 April 2021, 14:20:25
Dazu steht die Antwort im ersten Beitrag, das setreading muss ja aus einem anderen Device kommen.
Habe ich schon verstanden mein Ungläubiger ;) ist das gleiche Verhalten https://commandref.fhem.de/#setreading
Titel: Antw:userreadings -> at -> Funktionsaufruf mit setreading
Beitrag von: TomLee am 26 April 2021, 17:55:00
Zwischendurch den Vorschlag getestet zu Punkt 2. DANKE, klappt.

ce2r:triggered {fhem(qq(define at_c at +00:00:01 {pc_ce2rtest("$name",'5')}));return 'done'}

ZitatDu löst ja die Variable auf und anschließend muss es wieder ein String werden.
Hab ich ehrlich gesagt noch nicht ganz verstanden, ist aber jetzt im Hinterkopf und irgendwann werd ichs schon begreifen.




Les mir später (am PC) nochmal die "Anleitung" zu setreading durch, weil ich komm immer noch nicht mit, mit sleep hats doch nicht geklappt, mit AT schon, meine auch bisher verstanden zu haben das AT nix anderes macht/ist, es klappt aber nicht mit einem einfachen sleep (dann kommt die prohibited-Meldung), AT es ist aber aus einem anderen Device.

Titel: Antw:userreadings -> at -> Funktionsaufruf mit setreading
Beitrag von: Otto123 am 26 April 2021, 18:55:40
Zitat von: TomLee am 26 April 2021, 17:55:00
einfachen sleep (dann kommt die prohibited-Meldung), AT es ist aber aus einem anderen Device.
Ich sage doch fhem sleep :) - das ist am Ende auch ein anderes "Device"
ce2r:triggered {fhem(qq(sleep 0.1;{pc_ce2rtest("$name",'5')}));return 'done'}

Du übergibst der fhem() Funktion einen String den sie ausführen soll.
Das sieht dann im zweiten Schritt so aus - nachdem die Variable $name von Perl aufgelöst wurde:
fhem("define at_c at +00:00:01 {pc_ce2rtest(cal_example1,'5')}")
Das funktioniert noch, aber das at sieht dann so aus define at_c at +00:00:01 {pc_ce2rtest(cal_example1,'5')} wenn das losrennt versucht es also deine perl Funktion aufzurufen -> {pc_ce2rtest(cal_example1,'5')} das ist natürlich falsch, weil es keine Perlfunktion cal_example1 gibt, wolltest Du auch nicht, Du wolltest den String "cal_example1" übergeben.

Zu 3. fällt mir noch ein:
ce2r:triggered {fhem(qq(define at_c at +00:00:01 {pc_ce2rtest("$name",'5')})) ? 'done':'failed'}
Aber die Ausführung der fhem() Funktion wird wohl immer wahr sein?
Titel: Antw:userreadings -> at -> Funktionsaufruf mit setreading
Beitrag von: TomLee am 26 April 2021, 22:08:14
Fuchs du, Tatsache, klappt "natürlich" auch mit sleep, so hatte ich es auch verstanden darum auch als erstes damit versucht, also wie du sagst:

ce2r:triggered {fhem(qq(sleep 0.1;{pc_ce2rtest("$name",'5')}));return 'done'}


Ich habs ehrlich gesagt zuvor mit
ce2r:triggered {fhem(qq(sleep 0.1;{pc_ce2rtest('cal_example1','5')}));return 'done'}
nicht versucht, dann wäre gleich klar gewesen das es am interpolieren (<- ::)) der Variable lag.

ZitatAber die Ausführung der fhem() Funktion wird wohl immer wahr sein?

Kann dazu noch wer was sagen ?

Und ob irgendwas dagegen spricht beim Aufruf der Funktion einfach alle t_+-Readings zu löschen, um zu verhindern das es alte/vergangene Readings gibt ?

Titel: Antw:userreadings -> at -> Funktionsaufruf mit setreading
Beitrag von: TomLee am 27 April 2021, 13:15:34
ZitatAber die Ausführung der fhem() Funktion wird wohl immer wahr sein?

Es ist nicht so das ich mir dazu zuvor keine Gedanken gemacht hätte.

Wenn man die t_.*-Readings nach dem Aufruf der Funktion gleich löscht, kann man nach dem setreading prüfen obs eines gibt oder nicht:

list cal_example1:FILTER=t_001_summary=.+

Da im userReadings diese Prüfung kombiniert mit einem if
{my $v =fhem("list cal_example1:FILTER=t_001_summary=.+");;!defined ($v) ? return 'nothing to do' : return 'done';;}
in den geschweiften Klammern/Perl des userReadings aber sofort ausgeführt wird und nicht nach dem setreading ist sie immer wahr.

Darum und dass das userReadings auch möglichst kurz bleibt also in die myUtils damit, da kann man dann auch problemlos erst nach dem setreading prüfen:
ce2r:triggered {fhem(qq(sleep 0.1;{pc_ce2rtest("$name",'5')}))}

sub pc_ce2rtest {
    my $name = shift;
my $nr = shift;
fhem ("deletereading cal_example1 t_.*",1);
    my $t = fhem('get '.$name.' events format:custom="$S" limit:from=0,count='.$nr,1);
    my @a= split("\n",$t);
    for (my $i = 0;$i<=$#a;$i++)
    {my $r = sprintf("t_%03.0f", $i + 1 )._summary;fhem("setreading $name $r $a[$i]");}
my $v =fhem("list cal_example1:FILTER=t_001_summary=.+",1);
!defined ($v) ? return 'nothing to do' : return 'done';
}


Jetzt wird aber kein userReadings (ce2r) erstellt, weil (denke ich) der Rückgabewert von dem if in dem Fhem-Befehl des userReadings zurückgegeben wird, also erfolgt die Meldung im Log (bspw. 2021.04.27 12:56:43 2: After sleep: done).

Kann ich mit leben, hab ich halt das userReadings nur missbraucht, ein Reading (ce2r) brauch ich nicht wirklich, eine Ausgabe im Log ob was angelegt wurde trotzdem hilfreich.

Was denkst du dazu ?




Mir ist jetzt erst aufgefallen das es zu einer Meldung kommt
PERL WARNING: Use of uninitialized value $t in split at ./FHEM/99_Calendar_Utils.pm line 114.
mit
    my $t = fhem('get '.$name.' events format:custom="$S" limit:from=0,count='.$nr,1);
    my @a= split("\n",$t);


wenn es gar keine Termine gibt, hast dazu eine Idee das abzufangen.
Titel: Antw:userreadings -> at -> Funktionsaufruf mit setreading
Beitrag von: Otto123 am 27 April 2021, 13:29:41
zum Letzteren:
Ich hatte das mal profan so gemacht:
my $zeit=fhem('get '.$name.' events format:custom="$t1" limit:from=0,count=1',1);
             if (!defined $zeit) {$zeit=0}

Also die Frage: was erwartest Du für eine Ausgabe wenn es keine Termine gibt.

Zum Ersteren:
mit sleep schiebst das ganze ja auch in eine andere "Dimension" deswegen landet die Rückgabe im Log. Ich würde der "guten Ordnung" halber doch noch einfach etwas zurückgeben, damit weißt Du ob das userReadings getriggert hat oder nicht. 
ce2r:triggered {fhem(qq(sleep 0.1;{pc_ce2rtest("$name",'5')}));'willi'}
Titel: Antw:userreadings -> at -> Funktionsaufruf mit setreading
Beitrag von: TomLee am 27 April 2021, 13:48:34
ZitatAlso die Frage: was erwartest Du für eine Ausgabe wenn es keine Termine gibt.

Versteh ich nicht, ein get gibt entweder was zurück oder wenns keine Termine gibt undef/nix.

Du meinst also den Teil
my @a= split("\n",$t);
    for (my $i = 0;$i<=$#a;$i++)
    {my $r = sprintf("t_%03.0f", $i + 1 )._summary;fhem("setreading $name $r $a[$i]");}

im Ausführungsteil eines if ausführen das prüft ob das get nicht undef ist.

ZitatIch würde der "guten Ordnung" halber doch noch einfach etwas zurückgeben, damit weißt Du ob das userReadings getriggert hat oder nicht.

Mir gefällts aber eigentlich sehr das es gar kein zusätzliches Reading und wenns man wissen möchte obs getriggert hat schaut man halt im Log  8)  :P
Titel: Antw:userreadings -> at -> Funktionsaufruf mit setreading
Beitrag von: Otto123 am 27 April 2021, 13:56:57
Eventuell haben wir uns doch verstanden? ich dachte so:
my $t = fhem('get '.$name.' events format:custom="$S" limit:from=0,count='.$nr,1);
if (defined $t) {
my @a= split("\n",$t)
...
}
Titel: Antw:userreadings -> at -> Funktionsaufruf mit setreading
Beitrag von: TomLee am 27 April 2021, 14:45:34
Dann hier nochmal mein bisheriger Ansatz die Zusammenfassung der nächsten 5 Termine in Readings zu schreiben, evtl. findet sich ja noch jemand der irgendwo Optimierungsbedarf oder ein No-Go sieht:

ce2r:triggered {fhem(qq(sleep 0.1;{pc_ce2rtest("$name",'5')}))}

sub pc_ce2rtest {
    my $name = shift;
my $nr = shift;
fhem ("deletereading $name t_.*",1);
    my $t = fhem('get '.$name.' events format:custom="$S" limit:from=0,count='.$nr,1);
if (defined $t) {
my @a= split("\n",$t);
for (my $i = 0;$i<=$#a;$i++)
{my $r = sprintf("t_%03.0f", $i + 1 )._summary;fhem("setreading $name $r $a[$i]");}
}
my $v =fhem("list $name:FILTER=t_001_summary=.+",1);
!defined ($v) ? return 'nothing to do' : return 'done';
}


Im Falle das es User gibt die gar kein Calendar-Device nutzen, sich aber mit der Programmierung auskennen und -evt.- es nachvollziehen möchten, hier eine RAW-Definition und im Anhang die dazugehörige .ics mit 3 Beispiel-Terminen:

defmod cal_Test Calendar ical file ./example4.ics 86400
attr cal_Test defaultFormat "$T1 $T2 $S"
attr cal_Test hideOlderThan 1
attr cal_Test room Test
attr cal_Test userReadings ce2r:triggered {fhem(qq(sleep 0.1;;{pc_ce2rtest("$name",'5')}))}

Titel: Antw:userreadings -> at -> Funktionsaufruf mit setreading
Beitrag von: Otto123 am 27 April 2021, 14:51:15
noch 2 x cal_example1 -> $name ? ;)