userreadings -> at -> Funktionsaufruf mit setreading

Begonnen von TomLee, 19 April 2021, 11:03:15

Vorheriges Thema - Nächstes Thema

TomLee

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

KernSani

Kannst du vielleicht mal Beispielcoding posten? Dann wird das Ganze vielleicht verständlicher...
RasPi: RFXTRX, HM, zigbee2mqtt, mySensors, JeeLink, miLight, squeezbox, Alexa, Siri, ...

TomLee

#2
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.

TomLee

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]");;}
}

KernSani

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...
RasPi: RFXTRX, HM, zigbee2mqtt, mySensors, JeeLink, miLight, squeezbox, Alexa, Siri, ...

TomLee

#5
ZitatWarum machst du nicht 5 userreadings, die direkt über eine Sub...

Meine Variante mit 5 userReadings hab ich hier 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.

TomLee

#6
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.


Otto123

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
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

TomLee

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.

Otto123

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
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

TomLee

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.


Otto123

#11
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?
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

TomLee

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 ?


TomLee

#13
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.

Otto123

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'}
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz