Unnötige triggerung von userReadings in Calendar?

Begonnen von Otto123, 08 Januar 2020, 12:17:34

Vorheriges Thema - Nächstes Thema

Otto123

Hallo Boris,

Ausgangspunkt war diese Definition:
define AbfallKalender Calendar ical url https://calendar.google.com/calendar/ical/bumf5n64fr8s8f99vlfu06a87k%40group.calendar.google.com/private-058f78026c3b29446a489b2202aa3f53/basic.ics 604800‬
attr AbfallKalender cutoffOlderThan 0
attr AbfallKalender hideOlderThan 0
attr AbfallKalender onCreateEvent { $e->{alarm}= $e->{start}-43200 }
attr AbfallKalender room Abfall
attr AbfallKalender userReadings nextWasteDays {my $day = int((fhem('get '.$name.' events format:custom="$t1" limit:from=0,count=1',1) + 86399 - time)/86400);;\
                  $day?eval{$day>1?$day:"morgen"}:"heute"},\
Tonne {fhem('get '.$name.' events format:custom="$S" limit:from=0,count=1',1)}

Damit gibt es bei jedem Neustart von FHEM oder modify zwei Perl Warnmeldungen:
2020.01.08 11:29:55 4: Calendar AbfallKalender: Wakeup
2020.01.08 11:29:55 4: Calendar AbfallKalender: Updating...
2020.01.08 11:29:55 4: Calendar AbfallKalender: Getting data from URL <hidden>
2020.01.08 11:29:55 5: Calendar AbfallKalender: HTTP response code 200
2020.01.08 11:29:55 1: PERL WARNING: Use of uninitialized value in addition (+) at (eval 1869) line 1.
2020.01.08 11:29:55 3: eval: {my $day = int((fhem('get '.$name.' events format:custom="$t1" limit:from=0,count=1',1) + 86399 - time)/86400);
                  $day?eval{$day>1?$day:"morgen"}:"heute"}
2020.01.08 11:29:55 4: Calendar AbfallKalender: parsing data asynchronously (PID= 30952)
2020.01.08 11:29:55 5: Calendar AbfallKalender: control passed back to main loop.
2020.01.08 11:29:56 4: Calendar AbfallKalender: got result from asynchronous parsing.
2020.01.08 11:29:56 4: Calendar AbfallKalender: asynchronous parsing finished.
2020.01.08 11:29:56 1: PERL WARNING: Use of uninitialized value in addition (+) at (eval 1876) line 1.
2020.01.08 11:29:56 3: eval: {my $day = int((fhem('get '.$name.' events format:custom="$t1" limit:from=0,count=1',1) + 86399 - time)/86400);
                  $day?eval{$day>1?$day:"morgen"}:"heute"}
2020.01.08 11:29:56 4: Calendar AbfallKalender: merging data
2020.01.08 11:29:56 4: Calendar AbfallKalender: 38 records processed, 38 new, 0 known, 0 modified, 0 changed.
2020.01.08 11:29:56 4: Calendar AbfallKalender: creating calendar events
2020.01.08 11:29:57 4: Calendar AbfallKalender: Checking times...
2020.01.08 11:29:57 4: Calendar AbfallKalender: process ended.

Das Problem scheint die Abfrage von Events zu sein. Wenn ich den Code im userReading so ab ändere:
attr AbfallKalender userReadings nextWasteDays {my $zeit=fhem('get '.$name.' events format:custom="$t1" limit:from=0,count=1',1);;\
             if (!defined $zeit) {$zeit=0} \
             my $day = int(($zeit + 86399 - time)/86400);;\
             $day?eval{$day>1?$day:"morgen"}:"heute"},\
Tonne {fhem('get '.$name.' events format:custom="$S" limit:from=0,count=1',1)}
sieht alles gut aus:
2020.01.08 11:47:39 4: Calendar AbfallKalender: Wakeup
2020.01.08 11:47:39 4: Calendar AbfallKalender: Updating...
2020.01.08 11:47:39 4: Calendar AbfallKalender: Getting data from URL <hidden>
2020.01.08 11:47:40 5: Calendar AbfallKalender: HTTP response code 200
2020.01.08 11:47:40 4: Calendar AbfallKalender: parsing data asynchronously (PID= 1476)
2020.01.08 11:47:40 5: Calendar AbfallKalender: control passed back to main loop.
2020.01.08 11:47:41 4: Calendar AbfallKalender: got result from asynchronous parsing.
2020.01.08 11:47:41 4: Calendar AbfallKalender: asynchronous parsing finished.
2020.01.08 11:47:41 4: Calendar AbfallKalender: merging data
2020.01.08 11:47:41 4: Calendar AbfallKalender: 38 records processed, 38 new, 0 known, 0 modified, 0 changed.
2020.01.08 11:47:41 4: Calendar AbfallKalender: creating calendar events
2020.01.08 11:47:41 4: Calendar AbfallKalender: Checking times...
2020.01.08 11:47:41 4: Calendar AbfallKalender: process ended.

Die userReadings werden mit beiden Codevarianten letztlich immer richtig gesetzt!
Mir scheint es aber, als ob die userReadings nach einem modify mindestens 3 mal getriggert werden, zweimal ohne Erfolg.
Kein wirkliches Problem, aber liegt da noch Optimierungspotential für Deinen Code?
Die Quelle für diese Frage war hier

Liebe Grüße
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

Dr. Boris Neubert

Boah, das ist verwickelt und ich bin schon soooo müde.

Was mir auffällt, ist der rekursive Aufruf von fhem() im userReading. Um herauszufinden, wie da die Trigger-Kaskade aussieht, ist erst mal lange Codebeschau nötig.

Perliger wird das ganze, wenn man get events mit ReturnType aufruft und dann die Werte aus dem Hash pickt.

Ich nehme mir den Punkt mal auf die Merkliste.

Viele Grüße
Boris
Globaler Moderator, Developer, aktives Mitglied des FHEM e.V. (Marketing, Verwaltung)
Bitte keine unaufgeforderten privaten Nachrichten!

Otto123

Hallo Boris,

hat aus meiner Sicht keine Eile. Und wenn Du mir sagst, wie ich das besser machen sollte wäre das auch toll :)
Ich weiß halt nicht: wie soll ich es anders machen um an die Termine zu kommen?
Ist ja eigentlich so nach Deiner "Vorgabe" ;)

Viele Grüße
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

eddy242

Hallo Boris,

könntest Du mir bitte einen kleinen Anschub geben. Ich frage mit diesem Code ab (pure Perl).
@events= fhem('get '.$geraet.' events filter:mode=="upcoming" limit:when=tomorrow returnType:@event');
Ohne die Angabe von Returntype kommen (in meinem Falle erwartungsgemäß) 2 Zeilen heraus.

Wie genau komme ich an den Content des Arrays ran. Ich habe in den Sourcecode Deines Moduls geschaut aber so weit bin ich noch nicht in Perl als dass ich verstehen würde, wie ich die Hash-Werte in meinen Code einbaue. Z.B. ein Sample was ich codieren muss um an die summary von event1 ranzukommen würde mir schon reichen, den rest erschließe ich mir. Danke!

Danke!

betateilchen

@eddy242: Deine Frage hat aber mal so gar nichts mit dem eigentlichen Thema dieses Threads zu tun.

Wenn die events in Deinem array namens "@events" stehen, musst Du über dieses Array einen loop bauen, um an die einzelnen Elemente zu kommen.

https://www.perl.com/article/perl-foreach-loops/

Und bitte bringe "array" und "hash" nicht durcheinander, das sind in perl zwei völlig unterschiedliche Dinge.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

eddy242

Hallo betateilchen,

ja das ist für diesen Thread off topic, ich habe aber nirgendwo einen anderen Thread gefunden wo ein griffiges Beispiel mit den verschiedenen Returntypes gezeigt wird. Ich würde mich als Perl-Anfänger bezeichnen, mit Hashes beginne ich erst. Ich habe das Problem für mich folgendermaßen gelöst, würde aber gerne die elegantere Variante mit den Hashs nutzen um weiter zu kommen - alleine das Know How fehlt:


          ...
  @events= split(/\n/,fhem('get '.$geraet.' events filter:mode=="upcoming" format:custom="$S\|$T1\|$T2" limit:when=tomorrow timeFormat:"%H:%M" '));
 
  foreach my $thisevent (@events) {
    ($summary,$calstartshort,$calendshort)=split(/\|/,$thisevent);
             ...
          }


betateilchen

Ich glaube, ich muss jetzt mal selbst in die Doku schauen, weil ich immer noch nicht verstehe, was Du mit hash meinst.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

Zitat von: eddy242 am 29 Oktober 2020, 17:54:56
ja das ist für diesen Thread off topic, ich habe aber nirgendwo einen anderen Thread gefunden wo ein griffiges Beispiel mit den verschiedenen Returntypes gezeigt wird.

Du hättest einfach einen neuen Thread aufmachen können.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Dr. Boris Neubert

Hallo eddy242,

@events ist ein Array, wie Betateilchen richtig anmerkt, auch wenn ich im Januar vor lauter Müdigkeit Hash geschrieben habe.

Die Schleife sieht richtig aus. In der Schleife kannst Du nun was mit den gelieferten Events anfangen.

Grüße
Boris
Globaler Moderator, Developer, aktives Mitglied des FHEM e.V. (Marketing, Verwaltung)
Bitte keine unaufgeforderten privaten Nachrichten!

betateilchen

Hallo Boris,

in der Doku steht "@event   an array of Calendar::Event hashes"

das könnte ja Sinn machen, weil mit @texts schon ein Array von strings geliefert wird.
Ich glaube, ich werde mal ein bisschen testen, was wirklich passiert.

@eddy242: wenn es wirklich ein array of hashes ist, hast Du Dir ziemlich das komplexeste ausgesucht, das einem als perl Anfänger begegnen kann. Als Anfänger würde ich Dir gerne eine "einfachere" Lösung nahelegen, mit Deinem Code bist Du doch auf einem guten Weg.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Dr. Boris Neubert

uiuiui, habe gerade in den Code geguckt.

@events ist ein Array von event-Hashes. Siehe package Calendar::Event ab Zeile 396 im Code.

Du bekommst mit $thisevent eine Referenz auf ein Hash zurück. %$thisevent ist dann das Hash. Deswegen kannst Du $thisevent->start() usw. benutzen.
Globaler Moderator, Developer, aktives Mitglied des FHEM e.V. (Marketing, Verwaltung)
Bitte keine unaufgeforderten privaten Nachrichten!

betateilchen

Zitat von: Dr. Boris Neubert am 29 Oktober 2020, 18:25:43
uiuiui, habe gerade in den Code geguckt.

@events ist ein Array von event-Hashes.

Ja, das habe ich gerade rausgefunden, dies Funktionalität von returnType war mir bis heute völlig unbekannt.

In der Doku steht übrigens fälschlicherweise "@event" anstatt "@events" bei den möglichen returnTypes.

-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

Zitat von: Dr. Boris Neubert am 29 Oktober 2020, 18:25:43
@events ist ein Array von event-Hashes. Siehe package Calendar::Event ab Zeile 396 im Code.
Du bekommst mit $thisevent eine Referenz auf ein Hash zurück.

Hast Du das mal ausprobiert? Inzwischen habe ich ca. 1 Stunde damit experimentiert und bin noch zu keinem sinnvollen Ergebnis gekommen.

-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

@Boris: kannst Du den Diskussionsteil zu den returnTypes aus dem Thread mal abtrennen und in einen eigenen Thread packen?
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

eddy242

Also nach den o.a. Erläuterungen sollte dieser Code funktionieren?
  sub subtesthash {
        my @events;
my $thisevent;
@events= fhem('get calendar_anton events filter:mode=="upcoming" limit:when=tomorrow returnType:@events');
$thisevent=@events[0];  ## line for debugging
set_Reading("debug.hash.start",$thisevent->start());  ## line for debugging
  }


Da kommt dann zur execution time (in einem DOIF im PERL-Mode):
condition c05: Can't locate object method "start" via package "0" (perhaps you forgot to load "0"?), line 40.