Hallo zusammen,
bin mir fast sicher das ich hier nicht im richtigen Bereich bin.
Ursprünglich wollte ich das Thema in dem Bereich "Perl-Ecke" anlegen,
doch dazu fehlt mir richtigerweise die Berechtigung.
Andererseits bin ich ja in dem Thema Perl Anfänger,
dann passt es wieder. ;)
Es dreht sich um folgendes.
Bei meinen Kalendern habe ich mir ein paar userreadings angelegt.
Damit ich nicht immer den ganzen Code bei jedem Kalender eintippen muss,
habe ich eine 99_myUtils_calendar.pm angelegt, und dort die Definitionen der userreadings vereinheitlicht.
Prinzipiell funktioniert das auch wie gewünscht.
Worum es mir geht, ob der von mir erstellte Code überhaupt den, ich sag mal, Perl-Normen entspricht.
Was das angeht, bin ich blutiger Anfänger. Seither viel mit copy->modify->paste gearbeitet.
Wenn etwas unklar war, Internetsuche ist mein Freund.
Doch wie es so ist, viele Programmierer = unterschiedliche Herangehensweise.
Mehr als eine Plausibilitätsprüfung ist daher bei mir nicht vorhanden.
Daher meine Bitte.
Könnte sich bitte ein Profi meiner annehmen, und sich den Code einmal ansehen.
Mir eventuell Tipps geben wie ich etwas besser lösen, bzw. vereinfachen könnte.
Hauptsächlich geht es mir um den Code selbst, damit ich zukünftig eine Art Vorlage hätte.
Vorab schon einmal Dankeschön für eure Mühen.
!Die hier geposteten Codes nicht verwenden!
siehe hier (https://forum.fhem.de/index.php/topic,114901.msg1092847.html#msg1092847)
Aufruf userreadings (am Beispiel eines Test-Kalenders)
defmod Cal_WoW Calendar ical url https://{USERNAME}:{PASSWORD}@192.168.78.33:31443/remote.php/dav/calendars/{USERNAME}/wow?export 43200
attr Cal_WoW DbLogExclude .*
attr Cal_WoW hideLaterThan 030d
attr Cal_WoW hideOlderThan 00:15
attr Cal_WoW room Kalender
attr Cal_WoW stateFormat Status: state T: lastUpdate<br/>\
Event in: Event_at Tag(en) Morgen: Event_tomorrow, Heute: Event_today<br/>\
Hallo in: Search_Hallo_at Tag(en) Morgen: Search_Hallo_tomorrow, Heute: Search_Hallo_today<br/>\
Ciao in: Search_Ciao_at Tag(en) Morgen: Search_Ciao_tomorrow, Heute: Search_Ciao_today
attr Cal_WoW synchronousUpdate 0
attr Cal_WoW userReadings Event_name {Cal_na($NAME)},\
Event_at {Cal_at($NAME)},\
Event_tomorrow {Cal_tm($NAME)},\
Event_today {Cal_td($NAME)},\
Search_Hallo_name {Cal_na($NAME, "Hallo")},\
Search_Hallo_at {Cal_at($NAME, "Hallo")},\
Search_Hallo_tomorrow {Cal_tm($NAME, "Hallo")},\
Search_Hallo_today {Cal_td($NAME, "Hallo")},\
Search_Ciao_name {Cal_na($NAME, "Ciao")},\
Search_Ciao_at {Cal_at($NAME, "Ciao")},\
Search_Ciao_tomorrow {Cal_tm($NAME, "Ciao")},\
Search_Ciao_today {Cal_td($NAME, "Ciao")}
99_myUtils_calendar.pm (2020-10-10 / ursprüngliche Version)
##############################################
# $Id: myUtilsTemplate.pm 7570 2015-01-14 18:31:44Z rudolfkoenig $
#
# Save this file as 99_myUtils.pm, and create your own functions in the new
# file. They are then available in every Perl expression.
#************************************************************************
# 99_myUtils_calendar.pm kst
#************************************************************************
# 2020-10-03 - Datei erstellt
# 2020-10-03 - Abfrage Tage bis zu Event hinzu
# 2020-10-03 - Nicht Ganztagestermine Zeit bis Mitternacht verechnen
# 2020-10-04 - Event Morgen/Heute hinzu
# 2020-10-05 - Event Name hinzu
#
#------------------------------------------------------------------------
package main;
use strict;
use warnings;
use POSIX;
sub
myUtils_calendar_Initialize($$)
{
my ($hash) = @_;
}
# Enter you functions below _this_ line.
##************************************************************************
## Zeit in Sekunden von Mitternacht bis aktuelle Zeit in Sekunden
##************************************************************************
## Kopie aus 57_Calendar.pm
#sub Calendar_GetSecondsFromMidnight()
#{
# my @time = localtime();
# return (($time[2] * HOURSECONDS) + ($time[1] * MINUTESECONDS) + $time[0]);
#}
#************************************************************************
# Tage bis zum anstehenden Termin
#************************************************************************
sub
Cal_at ($;$)
{
my ($cname, $sword) = @_; # Übernahmeparameter (calendername, searchword)
my $format = '"$t1"'; # $t1 Startzeit in Sekunden
my $zeit = '0'; # Parameter setzen, damit keine Warnmeldung erscheint
my $timewordoff = fhem("get $cname events format:custom=$format limit:from=0,count=1"); # Zeit in Sekunden ohne Suchwort
my $timewordon = fhem("get $cname events format:custom=$format filter:field(summary)=~'$sword' limit:from=0,count=1"); # Zeit in Sekunden mit Suchwort
if (defined $sword && length($sword) > 0) # Abfrage ob Zeit mit oder ohne Suchwort verwendet wird
{
$zeit = $timewordon;
}
else
{
$zeit = $timewordoff;
}
my $todaymidnight = Calendar_GetSecondsFromMidnight();# Zeit von Mitternacht bis aktueller Zeit in Sekunden
my $day = int(($zeit / 86400) - ((time - $todaymidnight) / 86400)); # Berechnung der Tage bis zum anstehenden Termin
if (defined $day && $day < 0) {999} else {$day}; # Übergabe der Tage bis zum anstehenden Termin (999=kein Termin)
}
#************************************************************************
# Termin Morgen
#************************************************************************
sub
Cal_tm ($;$)
{
my ($cname, $sword) = @_; # Übernahmeparameter (calendername, searchword)
my $format = '"$S"'; # $S Ereignis
my $tmwordoff = fhem("get $cname events format:custom=$format limit:when=tomorrow"); # Ereignis ohne Suchwort
my $tmwordon = fhem("get $cname events format:custom=$format filter:field(summary)=~'$sword' limit:when=tomorrow"); # Ereignis mit Suchwort
if (defined $sword && length($sword) > 0) # Abfrage ob Ereignis mit oder ohne Suchwort verwendet wird
{
if (defined $tmwordon && $tmwordon =~ m/$sword/i)
{1} else {0}; # Übergabe Status Termin mit Suchwort (0=nein/1=ja)
}
else
{
if (defined $tmwordoff && length($tmwordoff) > 0)
{1} else {0}; # Übergabe Status Termin ohne Suchwort (0=nein/1=ja)
}
}
#************************************************************************
# Termin Heute
#************************************************************************
sub
Cal_td ($;$)
{
my ($cname, $sword) = @_; # Übernahmeparameter (calendername, searchword)
my $format = '"$S"'; # $S Ereignis
my $tdwordoff = fhem("get $cname events format:custom=$format limit:when=today"); # Ereignis ohne Suchwort
my $tdwordon = fhem("get $cname events format:custom=$format filter:field(summary)=~'$sword' limit:when=today"); # Ereignis mit Suchwort
if (defined $sword && length($sword) > 0) # Abfrage ob Ereignis mit oder ohne Suchwort verwendet wird
{
if (defined $tdwordon && $tdwordon =~ m/$sword/i)
{1} else {0}; # Übergabe Status Termin mit Suchwort (0=nein/1=ja)
}
else
{
if (defined $tdwordoff && length($tdwordoff) > 0)
{1} else {0}; # Übergabe Status Termin ohne Suchwort (0=nein/1=ja)
}
}
#************************************************************************
# Name zum Termin
#************************************************************************
sub
Cal_na ($;$)
{
my ($cname, $sword) = @_; # Übernahmeparameter (calendername, searchword)
my $format = '"$S"'; # $S Ereignis
my $nawordoff = fhem("get $cname events format:custom=$format limit:from=0,count=1"); # Name ohne Suchwort
my $nawordon = fhem("get $cname events format:custom=$format filter:field(summary)=~'$sword' limit:from=0,count=1"); # Name mit Suchwort
if (defined $sword && length($sword) > 0) # Abfrage ob Name mit oder ohne Suchwort verwendet wird
{
if (defined $nawordon && length($nawordon) > 0)
{$nawordon} else {"Kein Treffer"}; # Übergabe Name mit Suchwort
}
else
{
if (defined $nawordoff && length($nawordoff) > 0)
{$nawordoff} else {"Kein Termin"}; # Übergabe Name ohne Suchwort
}
}
#************************************************************************
# Temporaer
#************************************************************************
#Feiertag_name {fhem('get Cal_Feiertage events format:custom="$S" limit:from=0,count=1',1)},
#
#Formel1_name {my $name = fhem('get Cal_Formel1 events format:custom="$S" limit:from=0,count=1',1)},
#Formel1_name_short { my @c = split ' / ',ReadingsVal($name,'Formel1_name',0);$c[1] },
#
#NFL_name {fhem('get Cal_NFL events format:custom="$S" limit:from=0,count=1',1)},
#NFL_Vikings_name {fhem('get Cal_NFL events format:custom="$S" filter:field(summary)=~"Vikings" limit:from=0,count=1',1)},
##************************************************************************
## Vorlage
##************************************************************************
#sub
#Cal_tmtd ($$;$)
#{
#}
1;
99_myUtils_calendar.pm (2020-10-11 / angepasste Version / !Zwischenstand!)
##############################################
# $Id: myUtilsTemplate.pm 7570 2015-01-14 18:31:44Z rudolfkoenig $
#
# Save this file as 99_myUtils.pm, and create your own functions in the new
# file. They are then available in every Perl expression.
#************************************************************************
# 99_myUtils_calendar.pm kst
#************************************************************************
# 2020-10-03 - Datei erstellt
# 2020-10-03 - Abfrage Tage bis zu Event hinzu
# 2020-10-03 - Nicht Ganztagestermine Zeit bis Mitternacht verechnen
# 2020-10-04 - Event Morgen/Heute hinzu
# 2020-10-05 - Event Name hinzu
# 2020-10-10 - Cal_at umformatiert nach Vorlage CoolTux (Forum)
# 2020-10-11 - Code leserlich formatiert
# - Event Morgen/Heute angepasst
# - Event Name angepasst
#
#------------------------------------------------------------------------
package main;
use strict;
use warnings;
use POSIX;
sub
myUtils_calendar_Initialize($$)
{
my ($hash) = @_;
}
# Enter you functions below _this_ line.
##************************************************************************
## Zeit in Sekunden von Mitternacht bis aktuelle Zeit in Sekunden
##************************************************************************
## Kopie aus 57_Calendar.pm
#sub Calendar_GetSecondsFromMidnight()
#{
# my @time = localtime();
# return (($time[2] * HOURSECONDS) + ($time[1] * MINUTESECONDS) + $time[0]);
#}
#************************************************************************
# Tage bis zum anstehenden Termin
#************************************************************************
sub
Cal_at {
my $cname = shift; # Uebernahmeparameter (calendername)
my $sword = shift // undef; # Uebernahmeparameter (searchword)
my $format = '"$t1"'; # $t1 Startzeit in Sekunden
my $zeit = 0; # Parameter setzen, damit keine Warnmeldung erscheint
# Zeit in Sekunden ohne Suchwort
my $timewordoff = fhem("get $cname events format:custom=$format limit:from=0,count=1");
# Zeit in Sekunden mit Suchwort
my $timewordon = fhem("get $cname events format:custom=$format filter:field(summary)=~'$sword' limit:from=0,count=1");
if ( defined $sword
&& length($sword) > 0) # Abfrage ob Zeit mit oder ohne Suchwort verwendet wird
{
$zeit = $timewordon;
}
else {
$zeit = $timewordoff;
}
# Zeit von Mitternacht bis aktueller Zeit in Sekunden
my $todaymidnight = Calendar_GetSecondsFromMidnight();
# Berechnung der Tage bis zum anstehenden Termin
my $day = int(($zeit / 86400) - ((time - $todaymidnight) / 86400));
# Uebergabe der Tage bis zum anstehenden Termin (999=kein Termin)
return ( (defined $day && $day < 0) ? 999 : $day );
}
#************************************************************************
# Termin Morgen
#************************************************************************
sub
Cal_tm {
my $cname = shift; # Uebernahmeparameter (calendername)
my $sword = shift // undef; # Uebernahmeparameter (searchword)
my $format = '"$S"'; # $S Ereignis
# Ereignis ohne Suchwort
my $tmwordoff = fhem("get $cname events format:custom=$format limit:when=tomorrow");
# Ereignis mit Suchwort
my $tmwordon = fhem("get $cname events format:custom=$format filter:field(summary)=~'$sword' limit:when=tomorrow");
if (defined $sword
&& length($sword) > 0) # Abfrage ob Ereignis mit oder ohne Suchwort verwendet wird
{
# Uebergabe Status Termin mit Suchwort (0=nein/1=ja)
return ( (defined $tmwordon && $tmwordon =~ m/$sword/i) ? 1 : 0 );
}
else{
# Uebergabe Status Termin ohne Suchwort (0=nein/1=ja)
return ( (defined $tmwordoff && length($tmwordoff) > 0) ? 1 : 0);
}
}
#************************************************************************
# Termin Heute
#************************************************************************
sub
Cal_td {
my $cname = shift; # Uebernahmeparameter (calendername)
my $sword = shift // undef; # Uebernahmeparameter (searchword)
my $format = '"$S"'; # $S Ereignis
# Ereignis ohne Suchwort
my $tdwordoff = fhem("get $cname events format:custom=$format limit:when=today");
# Ereignis mit Suchwort
my $tdwordon = fhem("get $cname events format:custom=$format filter:field(summary)=~'$sword' limit:when=today");
if (defined $sword
&& length($sword) > 0) # Abfrage ob Ereignis mit oder ohne Suchwort verwendet wird
{
# Uebergabe Status Termin mit Suchwort (0=nein/1=ja)
return ( (defined $tdwordon && $tdwordon =~ m/$sword/i) ? 1 : 0 );
}
else{
# Uebergabe Status Termin ohne Suchwort (0=nein/1=ja)
return ( (defined $tdwordoff && length($tdwordoff) > 0) ? 1 : 0);
}
}
#************************************************************************
# Name zum Termin
#************************************************************************
sub
Cal_na {
my $cname = shift; # Uebernahmeparameter (calendername)
my $sword = shift // undef; # Uebernahmeparameter (searchword)
my $format = '"$S"'; # $S Ereignis
# Name ohne Suchwort
my $nawordoff = fhem("get $cname events format:custom=$format limit:from=0,count=1");
# Name mit Suchwort
my $nawordon = fhem("get $cname events format:custom=$format filter:field(summary)=~'$sword' limit:from=0,count=1");
if (defined $sword
&& length($sword) > 0) # Abfrage ob Name mit oder ohne Suchwort verwendet wird
{
# Uebergabe Name mit Suchwort
return ( (defined $nawordon && length($nawordon) > 0) ? $nawordon : "Kein Treffer" );
}
else{
# Uebergabe Name ohne Suchwort
return ( (defined $nawordoff && length($nawordoff) > 0) ? $nawordoff : "Kein Termin" );
}
}
#************************************************************************
# Temporaer
#************************************************************************
#[erledigt]Formel1_name {my $name = fhem('get Cal_Formel1 events format:custom="$S" limit:from=0,count=1',1)},
#Formel1_name_short { my @c = split ' / ',ReadingsVal($name,'Formel1_name',0);$c[1] },
#
1;
edit: 99_myUtils_calendar.pm
- Ursprüngliche Version (Thread-Start) wieder eingefügt
- Angepasste Version (!Zwischenstand!) darunter eingefügt
Mit freundlichem Gruß
Karsten
Wie immer ist das wichtigste die Formatierung. Da müsstest Du noch mal nachbessern.
Desweiteren gehe ich davon aus das Du ja einen Rückgabewert hast. Da fehlt also ein return ganz am Ende jder Funktion gefolgt von dem was Du zurück geben willst. Solltest Du nichts zurück geben wollen schreibt man nur return.
Ich habe mir nur kurz die erste Funktion angeschaut. Willst Du da $day zurück geben?
Grüße
sub Cal_at {
my $cname = shift;
my $sword = shift; # Übernahmeparameter (calendername, searchword)
my $format = '"$t1"'; # $t1 Startzeit in Sekunden
my $zeit = 0; # Parameter setzen, damit keine Warnmeldung erscheint
my $timewordoff = fhem("get $cname events format:custom=$format limit:from=0,count=1"); # Zeit in Sekunden ohne Suchwort
my $timewordon = fhem("get $cname events format:custom=$format filter:field(summary)=~'$sword' limit:from=0,count=1"); # Zeit in Sekunden mit Suchwort
if ( defined $sword
&& length($sword) > 0 ) # Abfrage ob Zeit mit oder ohne Suchwort verwendet wird
{
$zeit = $timewordon;
}
else {
$zeit = $timewordoff;
}
my $todaymidnight = Calendar_GetSecondsFromMidnight();# Zeit von Mitternacht bis aktueller Zeit in Sekunden
my $day = int(($zeit / 86400) - ((time - $todaymidnight) / 86400)); # Berechnung der Tage bis zum anstehenden Termin
#if (defined $day && $day < 0) {999} else {$day}; # Übergabe der Tage bis zum anstehenden Termin (999=kein Termin)
return ( (defined $day && $day < 0) ? 999 : $day);
}
Ein Beispiel wäre so.
Aber wie Du schon sagtest, viele Programmierer viele Möglichkeiten. Daher gibt es das Buch PBP (Perl Best Practices)
Grüße
Hallo CoolTux,
Dankeschön für die Hinweise.
PBP (Perl Best Practices) hab ich auch schon einmal überflogen.
Jedoch nicht wirklich alles verstanden.
Deswegen hab ich einfach mal losgelegt, und dann um eure Mithilfe gebeten.
Jetzt habe ich, dank dir, schon einmal Ansätze wonach ich mich genauer informieren kann.
z.B. warum anstatt my ($cname, $sword) = @_;
my $cname = shift; my $sword = shift;
(funktioniert dann die optionale Übergabe von "$sword" noch)
oder warum ich return explizid angeben muss, dachte "{Rückgabewert}" würde ausreichen.
Werde nachher den Code in meiner 99_myUtils_calendar.pm anpassen.
Kann etwas dauern ;)
Gruß Karsten
Zitat von: hydrotec am 10 Oktober 2020, 11:09:57
z.B. warum anstatt my ($cname, $sword) = @_;
my $cname = shift; my $sword = shift;
(funktioniert dann die optionale Übergabe von "$sword" noch)
@_ verwendet man laut PBP so ab 4 Übergabewerte. Es ist ein spezial Variable.
Was die Sache mit der optionalen Übergabe an geht so kannst Du das gerne auch abfangen
my $sword = shift // undef;
Zitat von: hydrotec am 10 Oktober 2020, 11:09:57
oder warum ich return explizid angeben muss, dachte "{Rückgabewert}" würde ausreichen.
Jede Funktion muss mit einen return sauber beendet werden.
Hallo CoolTux,
mal eben schnell deine Vorschläge umgesetzt, passt einwandfrei. :)
Jetzt muss ich mir nur noch PBP zur Brust nehmen, damit ich das Umgesetzte auch wirklich verstehe.
Vielen Dank noch einmal.
Gruß Karsten
Guten Morgen Miteinander,
habe mich ein wenig über PBP (Perl Best Practices) informiert.
Das es sich um ein Buch handelt, war mir nicht wirklich bewußt.
Kann es sein, das es keine digitale Version dieses Taschenbuches zu erwerben gibt?
Über folgende Website https://perl.programmingpedia.net/en/tutorial/5919/best-practices (https://perl.programmingpedia.net/en/tutorial/5919/best-practices) bin ich auf perlcritic.com (http://perlcritic.com) gestoßen.
Ist sehr hilfreich um seinen Code analysieren zu lassen, doch ohne Buch fehlt einem der Hintergrund.
Angenehmen Sonntag noch :)
Gruß Karsten
Hallo CoolTux,
Zitat von: CoolTux am 10 Oktober 2020, 09:58:02
Wie immer ist das wichtigste die Formatierung. Da müsstest Du noch mal nachbessern.
Wo du recht hast, hast du recht.
Gelobe zukünftig Besserung. ;)
Danke nochmal für deine hilfreiche Unterstützung :)
Gruß Karsten
Zitat von: CoolTux am 10 Oktober 2020, 11:22:54
Was die Sache mit der optionalen Übergabe an geht so kannst Du das gerne auch abfangen
my $sword = shift // undef;
Dazu eine Frage: Bisher hatte ich den "defined-or"-Operator immer so interpretiert, dass man den verwendet, um das "undef" in einen anderen Wert zu überführen. Da mir das aber jüngst auch in jemand anderen's Code über den Weg gelaufen ist, würde mich interessieren, ob ich mal wieder was wesentliches übersehe.
Mein bisheriges Verständnis war eher, dass man damit u.A. auch iVm. shift eindeutigere Fehlermeldungen generieren kann (wenn man das möchte, macht shift auch bei mehr Parametern Sinn...) oder eben "echte" Defaultwerte zuweist (Auchtung: das Beispiel hier ist in dieser Form sinnlos, weil man eigentlich einfacher einen undefinierten Zustand lassen und dann direkt mit "if" arbeiten könnte):
sub Cal_at {
my $cname = shift // return "Error: we need at least one parameter!"; # ggf. carp (?) nutzen, um das als explizite Fehlerrückmeldung zu kennzeichnen zu füllen
my $sword = shift // "unknown"; # optionaler Parameter, wenn ohne aufgerufen, wird "unknown" zugewiesen)
my $format = '"$t1"'; # $t1 Startzeit in Sekunden
my $zeit = 0; # Parameter setzen, damit keine Warnmeldung erscheint
my $timewordoff = fhem("get $cname events format:custom=$format limit:from=0,count=1"); # Zeit in Sekunden ohne Suchwort
my $timewordon = fhem("get $cname events format:custom=$format filter:field(summary)=~'$sword' limit:from=0,count=1"); # Zeit in Sekunden mit Suchwort
if ( $sword ne "unknown" ) # Abfrage ob Zeit mit oder ohne Suchwort verwendet wird
[...]
Ergänzende Hinweise:
- "use POSIX;" sollte raus.
- aus hygienischen Gründen sollte man userReadings immer mit trigger definieren (hier ist es vermutlich egal, da HTTPMOD bulkUpdate verwenden dürfte und daher sowieso alles in derselben trigger-Stufe mit abgearbeitet wird).
- Für ganztägige Sachen (an anderer Stelle ging es mal um "Müll") ist der Umweg über Calendar m.E. nicht optimal, das kann man einfacher in einem holiday-Device haben...
- Im Developer-Bereich bzw. der Perl-Ecke kann afaik auch posten, wer als Tester angemeldet ist. Da sind auch noch mehr Infos zu den Fragen rund um perlcritic/perltidy zu finden (vielleicht schaust du mal den RandomTimer-Thread durch).
Hallo Beta-User,
auch dir erst einmal ein Dankeschön für deine Unterstützung. :)
Der erste Schritt um meinen Code zu optimieren ist ja schon geschehen.
Da die von mir erwünschten Funktionen erst einmal machen was sie sollen,
kann ich mir nun etwas Zeit nehmen und die einzelnen Themen explizit näher anschauen.
Zu dem Thema
my $sword = shift // undef;
Nachdem ich mich im Internet etwas schlauer gemacht habe,
muss ich dir zustimmem. Man könnte das // undef auch weg lassen und später über
if (defined $sword && length($sword) > 0)
abfangen.
Das mit dem
my $cname = shift // return "Error: we need at least one parameter!"; # ggf. carp (?) nutzen, um das als explizite Fehlerrückmeldung zu kennzeichnen zu füllen
ist eine gute Idee, muss ich mir später einmal genauer anschauen.
Zu den ergänzenden Hinweisen.
- "use POSIX;" sollte raus.
Im Wiki zu "99 myUtils anlegen", und im "myUtilsTemplate.pm" ist "use POSIX;" vorhanden.
(vermutlich nur aus Kompatibilitätsgründen, falls jemand mit POSIX Funktionen arbeitet)
Da ich diese Funktionen nicht nutze, kann ich sie auch abschalten, oder.
(aktuell "use POSIX;" gelöscht, funktioniert)
- aus hygienischen Gründen...
Da siehst du mal, so tief bin ich noch gar nicht in der Materie.
Bin, einfach so, davon ausgegangen das die userreadings mit "calendar set reload/update" getriggert werden.
Also, noch ein Punkt den ich mir bei Gelegenheit mal ansehen sollte.
- Für ganztägige Sachen...
Das ist bei mir historisch so gewachsen.
Ich verwende mobile einige Kalender in Nextcloud, und verwalte sie auch dort.
Die hatte ich dann auf FHEM verfügbar gemacht,
um sie für kleinere Schaltungen, oder zur Information zu verwenden.
Zur Information nutze ich hauptsächlich die Tage bis zum anstehenden Termin.
Bei ganztägigen Terminen werden die Tage bis zum Termin korrekt ausgegeben,
anders bei Terminen die nur einen gewissen Zeitraum am Tag einnehmen.
Da werden die Tage im 24h Format zum Termin berechnet.
Für mich sind die Tage von-bis Mitternacht relevant.
- Im Developer-Bereich...
Sollten es noch mehr Fragen in diesem Bereich geben,
werde ich mich als Tester anmelden, und gleich dort posten.
Danke für den Hinweis.
RandomTimer-Thread werde ich mir einmal anschauen.
Erst einmal noch einen angenehmen Abend 8)
Gruß Karsten
In der Tat ist ein undef eher doppelt gemoppelt nach einem //
@CoolTux:
Danke für die Rückmeldung.
Zitat von: hydrotec am 11 Oktober 2020, 19:10:03
Im Wiki zu "99 myUtils anlegen", und im "myUtilsTemplate.pm" ist "use POSIX;" vorhanden.
...dann ist dein FHEM nicht ganz aktuell: https://svn.fhem.de/trac/changeset/21509/
Im Wiki habe ich es eben auch rausgenommen, Danke für den Hinweis.
Was die "ganztägigen Kalender" angeht: Müll und Ferien kommen bei mir auch aus einem (Familien-) ical und werden dann als holiday (mit Ferien als holiday2we-Eintrag in global) eingebunden, irgendwo im Forum hatte ich dazu auch mal ein (grottiges) Code-Schnippsel veröffentlicht (muß ich mal überarbeiten und dann neu posten, aber es funktioniert ja grundsätzlich...).
Zitat von: Beta-User am 12 Oktober 2020, 11:43:14
...dann ist dein FHEM nicht ganz aktuell: https://svn.fhem.de/trac/changeset/21509/
Sorry, mein Fehler.
Auch bei mir ist "use POSIX;" in "myUtilsTemplate.pm" nicht vorhanden.
Da hatte ich wohl Augentinnitus. :-[
Kleine Rückfrage, sollte POSIX generell in den 99_myUtils... entfernt werden?
(Hab da noch ein paar ältere Versionen)
FHEM ist (fast) aktuell
Zitatfhem.pl 22894 2020-10-01 19:49:32Z rudolfkoenig
Zitat von: Beta-User am 12 Oktober 2020, 11:43:14
Was die "ganztägigen Kalender" angeht: Müll und Ferien kommen bei mir auch aus einem (Familien-) ical und werden dann als holiday (mit Ferien als holiday2we-Eintrag in global) eingebunden, irgendwo im Forum hatte ich dazu auch mal ein (grottiges) Code-Schnippsel veröffentlicht (muß ich mal überarbeiten und dann neu posten, aber es funktioniert ja grundsätzlich...).
Solltest du diesen Code noch finden, werde ich mir das gerne ansehen.
Man lernt ja nie aus. ;)
!Die hier geposteten Codes nicht verwenden!
siehe hier (https://forum.fhem.de/index.php/topic,114901.msg1092847.html#msg1092847)
Was den aktuellen Code meiner 99_myUtils_calendar.pm angeht, bin ich bis jetzt ganz glücklich damit.
calendar device (Test-Kalender)
defmod Cal_WoW Calendar ical url https://{USERNAME}:{PASSWORD}@192.168.78.33:31443/remote.php/dav/calendars/{USERNAME}/wow?export 43200
attr Cal_WoW DbLogExclude .*
attr Cal_WoW event-on-change-reading Event_.*,Search_.*
attr Cal_WoW event-on-update-reading state
attr Cal_WoW hideLaterThan 030d
attr Cal_WoW hideOlderThan 00:15
attr Cal_WoW room Kalender
attr Cal_WoW stateFormat Status: state T: lastUpdate<br/>\
Event in: Event_at Tag(en) Morgen: Event_tomorrow, Heute: Event_today<br/>\
Hallo in: Search_Hallo_at Tag(en) Morgen: Search_Hallo_tomorrow, Heute: Search_Hallo_today<br/>\
Ciao in: Search_Ciao_at Tag(en) Morgen: Search_Ciao_tomorrow, Heute: Search_Ciao_today
attr Cal_WoW synchronousUpdate 0
attr Cal_WoW userReadings Event_name {Cal_na($NAME)},\
Event_at {Cal_at($NAME)},\
Event_tomorrow {Cal_tm($NAME)},\
Event_today {Cal_td($NAME)},\
Search_Hallo_name {Cal_na($NAME, "Hallo")},\
Search_Hallo_at {Cal_at($NAME, "Hallo")},\
Search_Hallo_tomorrow {Cal_tm($NAME, "Hallo")},\
Search_Hallo_today {Cal_td($NAME, "Hallo")},\
Search_Ciao_name {Cal_na($NAME, "Ciao")},\
Search_Ciao_at {Cal_at($NAME, "Ciao")},\
Search_Ciao_tomorrow {Cal_tm($NAME, "Ciao")},\
Search_Ciao_today {Cal_td($NAME, "Ciao")}
99_myUtils_calendar.pm
##############################################
# $Id: myUtilsTemplate.pm 7570 2015-01-14 18:31:44Z rudolfkoenig $
#
# Save this file as 99_myUtils.pm, and create your own functions in the new
# file. They are then available in every Perl expression.
#************************************************************************
# 99_myUtils_calendar.pm kst
#************************************************************************
# 2020-10-03 - Datei erstellt
# 2020-10-03 - Abfrage Tage bis zu Event hinzu
# 2020-10-03 - Nicht Ganztagestermine Zeit bis Mitternacht verrechnen
# 2020-10-04 - Event Morgen/Heute hinzu
# 2020-10-05 - Event Name hinzu
# 2020-10-10 - Thread erstellt (99_myUtils_calendar - Perl Code)
# - https://forum.fhem.de/index.php/topic,114901.0.html
# - Cal_at umformatiert nach Vorlage CoolTux (Forum)
# 2020-10-11 - Code leserlich formatiert
# - Event Morgen/Heute angepasst
# - Event Name angepasst
# - use POSIX; entfernt nach Hinweis von Beta-User (Forum)
# 2020-10-12 - Bei Optionalem Parameter ($sword) " // undef" entfernt
# - (wird ueber "if (defined $sword && length($sword) > 0)" abgfragt)
# - Abfrage ob Pflichtparameter ($cname) angegeben ist
# - Rueckmeldung ueber Text im Reading verwendet, da in diesem Fall ausreichend
# - carp (?) ist eher was fuer Modulentwickler (bessere Fehlerauswertung)
# -
# -
# -
#
#------------------------------------------------------------------------
package main;
use strict;
use warnings;
#use Carp;
#use POSIX;
sub
myUtils_calendar_Initialize($$)
{
my ($hash) = @_;
}
# Enter you functions below _this_ line.
##************************************************************************
## Zeit in Sekunden von Mitternacht bis aktuelle Zeit in Sekunden
##************************************************************************
## Kopie aus 57_Calendar.pm
#sub Calendar_GetSecondsFromMidnight()
#{
# my @time = localtime();
# return (($time[2] * HOURSECONDS) + ($time[1] * MINUTESECONDS) + $time[0]);
#}
#************************************************************************
# Tage bis zum anstehenden Termin
#************************************************************************
sub
Cal_at {
# Pflicht-Uebernahmeparameter (calendername), mit Ueberpruefung
my $cname = shift // return '"Error: minimum call {Cal_at($NAME)}!"';
my $sword = shift; # Optionaler Uebernahmeparameter (searchword)
my $format = '"$t1"'; # $t1 Startzeit in Sekunden
my $zeit = 0; # Parameter setzen, damit keine Warnmeldung erscheint
# Zeit in Sekunden ohne Suchwort
my $timewordoff = fhem("get $cname events format:custom=$format limit:from=0,count=1");
# Zeit in Sekunden mit Suchwort
my $timewordon = fhem("get $cname events format:custom=$format filter:field(summary)=~'$sword' limit:from=0,count=1");
if ( defined $sword
&& length($sword) > 0) # Abfrage ob Zeit mit oder ohne Suchwort verwendet wird
{
$zeit = $timewordon;
}
else {
$zeit = $timewordoff;
}
# Zeit von Mitternacht bis aktueller Zeit in Sekunden
my $todaymidnight = Calendar_GetSecondsFromMidnight();
# Berechnung der Tage bis zum anstehenden Termin
my $day = int(($zeit / 86400) - ((time - $todaymidnight) / 86400));
# Uebergabe der Tage bis zum anstehenden Termin (999=kein Termin)
return ( (defined $day && $day < 0) ? 999 : $day );
}
#************************************************************************
# Termin Morgen
#************************************************************************
sub
Cal_tm {
# Pflicht-Uebernahmeparameter (calendername), mit Ueberpruefung
my $cname = shift // return '"Error: minimum call {Cal_tm($NAME)}!"';
my $sword = shift; # Optionaler Uebernahmeparameter (searchword)
my $format = '"$S"'; # $S Ereignis
# Ereignis ohne Suchwort
my $tmwordoff = fhem("get $cname events format:custom=$format limit:when=tomorrow");
# Ereignis mit Suchwort
my $tmwordon = fhem("get $cname events format:custom=$format filter:field(summary)=~'$sword' limit:when=tomorrow");
if (defined $sword
&& length($sword) > 0) # Abfrage ob Ereignis mit oder ohne Suchwort verwendet wird
{
# Uebergabe Status Termin mit Suchwort (0=nein/1=ja)
return ( (defined $tmwordon && $tmwordon =~ m/$sword/i) ? 1 : 0 );
}
else{
# Uebergabe Status Termin ohne Suchwort (0=nein/1=ja)
return ( (defined $tmwordoff && length($tmwordoff) > 0) ? 1 : 0);
}
}
#************************************************************************
# Termin Heute
#************************************************************************
sub
Cal_td {
# Pflicht-Uebernahmeparameter (calendername), mit Ueberpruefung
my $cname = shift // return '"Error: minimum call {Cal_td($NAME)}!"';
my $sword = shift; # Optionaler Uebernahmeparameter (searchword)
my $format = '"$S"'; # $S Ereignis
# Ereignis ohne Suchwort
my $tdwordoff = fhem("get $cname events format:custom=$format limit:when=today");
# Ereignis mit Suchwort
my $tdwordon = fhem("get $cname events format:custom=$format filter:field(summary)=~'$sword' limit:when=today");
if (defined $sword
&& length($sword) > 0) # Abfrage ob Ereignis mit oder ohne Suchwort verwendet wird
{
# Uebergabe Status Termin mit Suchwort (0=nein/1=ja)
return ( (defined $tdwordon && $tdwordon =~ m/$sword/i) ? 1 : 0 );
}
else{
# Uebergabe Status Termin ohne Suchwort (0=nein/1=ja)
return ( (defined $tdwordoff && length($tdwordoff) > 0) ? 1 : 0);
}
}
#************************************************************************
# Name zum Termin
#************************************************************************
sub
Cal_na {
# Pflicht-Uebernahmeparameter (calendername), mit Ueberpruefung
my $cname = shift // return '"Error: minimum call {Cal_na($NAME)}!"';
my $sword = shift; # Optionaler Uebernahmeparameter (searchword)
my $format = '"$S"'; # $S Ereignis
# Name ohne Suchwort
my $nawordoff = fhem("get $cname events format:custom=$format limit:from=0,count=1");
# Name mit Suchwort
my $nawordon = fhem("get $cname events format:custom=$format filter:field(summary)=~'$sword' limit:from=0,count=1");
if (defined $sword
&& length($sword) > 0) # Abfrage ob Name mit oder ohne Suchwort verwendet wird
{
# Uebergabe Name mit Suchwort
return ( (defined $nawordon && length($nawordon) > 0) ? $nawordon : "Kein Treffer" );
}
else{
# Uebergabe Name ohne Suchwort
return ( (defined $nawordoff && length($nawordoff) > 0) ? $nawordoff : "Kein Termin" );
}
}
#************************************************************************
# Temporaer
#************************************************************************
#[erledigt]Formel1_name {my $name = fhem('get Cal_Formel1 events format:custom="$S" limit:from=0,count=1',1)},
#Formel1_name_short { my @c = split ' / ',ReadingsVal($name,'Formel1_name',0);$c[1] },
#
1;
Sollten doch noch Kritikpunkte (positiv wie negativ) vorhanden sein,
gerne her damit. ;)
Mit freundlichen Grüßen, Karsten :)
Ja, POSIX sollte aus allem raus, was mit im Namespace von main rumspukt... Betrifft nicht nur myUtils-Code, sondern auch eine ganze Zahl von FHEM-Modulen (Die Diskussion dazu findest du über den svn-diff-Link).
Das ist der Link (https://forum.fhem.de/index.php/topic,85759.0.html) zu dem nämlichen Code; wie gesagt, der ist nicht in allen Punkten "auf dem aktuellen Stand der Erkenntnis".
Zu deinem Code kann ich jetzt grade wenig sagen, tendenziell würde ich mal die Lektüre von irgendwas empfehlen, was "Quotes in Perl" erläutert (und q() bzw. qq()), z.B. das hier: https://www.perlmonks.org/?node_id=401006. Da scheinen noch ein paar Workarounds zu dem Thema drin zu sein.
Wenn es in Richtung Modulentwicklung ginge, würde ich auch die fhem-Aufrufe noch ersetzen wollen, für myutils ist es m.E. aber ok.
Aber Achtung: Ich lerne auch immer noch was dazu...
Grüße, Beta-User
Hallo Beta-User,
OK, das mit POSIX glaube ich grob (ganz grob) verstanden zu haben.
Perl bringt ja im "package main" schon einige Funktionen mit.
Sollte eine Funktion nicht vorhanden sein, kann man auf das Modul POSIX zurückgreifen.
Generell wird aber nicht empfohlen das Modul komplett zu laden (use POSIX;),
sondern es soll explizit nur die benötigte Funktion aus dem Modul geladen werden (z.B.: use POSIX qw(strftime);).
Ich denke mal das ich in diesem Bereich der Programmierung noch nicht gelandet bin.
Aber gut zu wissen, das wenn einmal eine Funktion nicht wie gewünscht funktioniert,
man über diesen Punkt nachdenken sollte.
Die fhem-Aufrufe in sub(s) zu legen hatte ich mir auch schon überlegt.
Eventuell mache ich das auch noch, einfach nur zur Übung.
Doch vorher muss ich mich erst einmal mit der Materie "Anführungszeichen und Klammersetzung" auseinandersetzen.
Ist derzeit noch mehr learning by doing, als wirklich wissen wann was benötigt wird.
Habe so ein Gefühl das sich FHEM und Perl nicht immer einig sind ;)
Zu "57_Calendar2holiday.pm"
So wie ich das verstehe, ist dein Ansatz, deine (benötigten) Kalender aus dem Netz mittels 57_Calendar.pm in FHEM zur Verfügung zu stellen.
Anschließend wird einmal die Woche der betreffende Kalender in eine .holiday geschrieben.
Diese wiederum verwendest du dann um diverse "Schaltungen" zu steuern.
(z.B.: Rolladen hoch um 06:00 Uhr wenn kein Eintrag im .holiday vorhanden sein sollte, ansonsten erst um 09:00 Uhr)
Zitat von: Beta-User am 11 Januar 2019, 21:29:27
Die Vorgehenweise eignet sich eher für längerfristig planende Themen, die potentiell alle Bewohner treffen, nicht für tages- oder stundenaktuelles Reagieren...
Und dafür ist es m.E. gut geeignet.
Bei mir war der Ausgangspunkt etwas anders.
Ich wollte eine "Schaltung" die mir schon einen Tag vorher berechnet wie mein Szenario am Folgetag auszusehen hat.
Muss wohl etwas weiter ausholen (sorry für OT, aber gehört ja irgendwie doch auch zur Hintergrundinformation)
Es gibt ja im Forum und Wiki schon einige gute Lösungsansätze wie man einen dummy über einen Kalender schalten kann,
oder die verbleibenden Tage bis zur Müllverwertung berechnet werden können.
Weder das eine noch das andere war das was ich mir vorgestellt hatte.
Nur so z.B., die Lampe sollte am Vortag schon wissen wie lange sie am Abend an sein darf, weil morgen Urlaub oder kein Urlaub ist.
OK, also einen Kalender angelegt und über userreadings die Abfrage morgen/heute eingebaut.
(userreading deshalb, weil für mich die Ausgabe in dem jeweiligen Kalender mehr Sinn macht als sie woanders noch einmal extra zu definieren)
Hat wunderbar funktioniert, und ich hatte Werte mit dene ich weiter arbeiten konnte (bei mir größtenteils doif).
Weil das so reibungslos funktioniert hatte, gleich noch den Abfallkalender mit angelegt,
und dort die Abfrage der anstehenden Tage in ein userreading gepackt.
Und so kam dann ein Kalender nach dem Anderen hinzu.
Jetzt hatte jeder Kalender die für mich benötigten Berechnungen in den userreadings enthalten.
Da kam mir die Idee, die Berechnungen zu vereinheitlichen und in eine myUtils zu legen.
Prinzipiell waren es ja nur die Auswertungen
- Event morgen/heute mit/ohne Suchwort
- Name des Events (mit Einkürzen des Textes ist in Planung)
- Anzahl der Tage bis zum Event mit/ohne Suchwort
(inkl. der Verrechnung, bei Terminen die Tageszeitabhängig sind, bis 00:00:00 am selbigen Tag)
In Planung (wenn ich mal wieder Lust zum Programmieren habe)
- Einkürzen des Event-Namens parametrisieren
- Anzahl der Tage auch mit mehrtägigen Terminen
Deswegen bin ich diesen Weg, hier stark vereinfacht, gegangen.
Wie sagt man so schön, viele Wege führen nach Rom,
man muss nur das mobile bedienen können.
Grüße, Karsten
Zitat von: hydrotec am 12 Oktober 2020, 22:52:29
Perl bringt ja im "package main" schon einige Funktionen mit.
[...] (z.B.: use POSIX qw(strftime) ;) .
Das ist m.E. schief, ich versuch's mal mit meinen Worten, bin aber auch Laie, kann sein, dass das einer der Experten anders formulieren würde:
fhem.pl bestimmt zunächst mal, was im "main"-Namensraum geladen wird. Da dort schon "use POSIX;" steht, ist es bei allem weiterem Code schlicht überflüssig, der in diesen Namespace geladen wird. Sollte - aus welchen Gründen auch immer - entschieden werden, das in fhem.pl einzuschränken, würde das wirkungslos, sobald irgendein anderes Modul oder ein myUtils-Code ebenfalls diese "globale" Anweisung enthalten...
Ergo tut man an der Stelle nicht nur was überflüssiges, sondern was tendenziell auch für andere Programmteile gefährliches (da uU. unbeabsichtigt).
Wenn man diese Gefahr mehr oder weniger komplett ausschalten will, muß man mit packages arbeiten, was etwas komplizierter ist, aber auch nicht soo schwer, wenn man mal weiß, wie es geht.
Zitat
Die fhem-Aufrufe in sub(s) zu legen hatte ich mir auch schon überlegt.
Eventuell mache ich das auch noch, einfach nur zur Übung.
Da sind ein paar Missverständnisse drin:
- Es gibt in fhem.pl bereits "Direktaufrufe", die fhem("...")-Syntax ist nur ein allgemeiner Wrapper für diese Direktaufrufe, die meistens mit Command.* oder Analyze.* anfangen.
- Solange man in "main" rumfuhrwerkt, sollte man eher sparsam sein mit der Zahl der Subs, einfach weil sonst das Risiko besteht, dass es zu Überschneidungen kommt und dann plötzlich was ganz anderes passiert als erwartet, nur weil man ein weiteres Modul in Betrieb nimmt...
- und zu guter letzt erschließt sich mir nicht, was das Auslagern in eigene Subs für einen Sinn hätte.
ZitatZu "57_Calendar2holiday.pm"
So wie ich das verstehe, ist dein Ansatz,[...](z.B.: Rolladen hoch um 06:00 Uhr wenn kein Eintrag im .holiday vorhanden sein sollte, ansonsten erst um 09:00 Uhr) Und dafür ist es m.E. gut geeignet.
Bei mir war der Ausgangspunkt etwas anders.
Ich wollte eine "Schaltung" die mir schon einen Tag vorher berechnet
Genau: ein holiday-Device kennt auch "tomorrow" ;)
Da wirklich viele Wege nach Rom führen, und ich sowieso einen generischeren Ansatz für die calendar2holiday-Geschichte haben wollte, habe ich noch etwas rumgefiddelt und meinen Code überarbeitet:
sub myCalendar2Holiday {
my $calname = shift // return;
my $regexp = shift // return;
my $targetname = shift // $calname;
my $field = shift // "summary";
my $limit = shift // 10;
my $yearEndRe = shift;
my ($sec,$min,$hour,$mday,$month,$year,$wday,$yday,$isdst) = localtime(gettimeofday());
my $getstring = $calname . ' events format:custom="4 $T1 $T2 $S" timeFormat:"%m-%d" limit:count=' . $limit." filter:field($field)=~\"$regexp\"";
my @holidaysraw = split( /\n/, CommandGet( undef, "$getstring" ));
my @holidays;
for my $holiday (@holidaysraw) {
if ( !$yearEndRe || $holiday !~ m/$yearEndRe/) {
push (@holidays, $holiday);
} else { my @tokens = split (" ",$holiday);
my $lines = "4 $tokens[1] 12-31 $tokens[3]";
push (@holidays,$lines) if $month > 9;
$lines = "4 01-01 $tokens[2] $tokens[3]";
unshift (@holidays,$lines);
}
}
unshift (@holidays, "# get $getstring");
my $today = strftime "%d.%m.%y, %H:%M", localtime(time);;\
unshift (@holidays, "# Created by myCalendar2Holiday on $today");
FileWrite("./FHEM/${targetname}.holiday",@holidays);
}
Aufruf dann mit
{ myCalendar2Holiday('Familienkalender','.*[fF]erie.*','ferien','summary',10,'[Ww]eihnacht') }
oder die "Kurzversion":
{ myCalendar2Holiday('Familienkalender','.*(Bioabfall|Restmüll).*','muell') }
Aber wenn du zum einen eine funktionierende Logik mit den (immer noch ungetriggerten...) userReadings hast und zum anderen sowieso CalView2 planst und dich in Perl-Programmierung eindenken willst, ist so ein Kalenderprojekt durchaus gut geeignet :) . War für mich auch der Einstieg in FileWrite, z.B..
POSIX
Prinzipiell hab ich das so verstanden,
doch mit meinem Laienverständnis kann ich es nicht mit eigenen Worten formulieren.
Mein Fazit, ich habe mich bewusst für ein offenes System (Bezug Hausautomation) entschieden,
damit ich unter Umständen auch etwas nach meinen Bedürfnissen anpassen kann.
Dazu sollte ich die Programmiersprache von Grund auf verstehen,
nicht nur "copy&paste" anwenden, sich freuen das es funktioniert, ohne zu wissen warum es funktioniert,
und später dann wundern warum es plötzlich nicht mehr geht (oder anderweitige Probleme entstehen).
Also, Ärmel hochkrempeln, und ran an den Speck.
(Da es für mich ein Hobby ist, bin ich zeitlich nicht unter Druck etwas umzusetzen)
Zugegeben, das mit den sub(s) hatte ich wirklich komplett missverstanden.
Jetzt meine ich zu verstehen was du gemeint hast.
Ein Beispiel dazu sehe ich ja in deinem Code.
(Finger weg, ich werde das jetzt nicht kopieren, s.o.) ;)
Da du dir so viel Mühe gibst mit der calendar2holiday-Geschichte,
werde ich mir die holiday-Funktion in FHEM genauer anschauen.
Anschließend deinen Code übernehmen, um zu sehen ob das für meine Zwecke geeignet ist.
(Kann etwas dauern)
Zitat von: Beta-User am 13 Oktober 2020, 08:27:41
... funktionierende Logik mit den (immer noch ungetriggerten...) userReadings ...
Jetzt bin ich etwas verwirrt.
Um nicht wieder Missverständnissen zu unterliegen, hake ich mal nach.
Hab mir die commandref.html extra noch einmal (inkl. Verweise) angesehen.
So wie ich das verstehe ist ein trigger dafür zuständig das ein Event generiert wird.
In meinem Fall ist der trigger für die userReadings das reading state.
Sobald sich der Status des readings ändert (z.B. set Cal_ reload/update), wird userReadings getriggert,
und die userReadings erzeugen jeweils ein Event auf das man, in welcher Form auch immer (notify, doif, ...)
zugreifen/reagieren kann.
Zumindest kann man das so im Event monitor beobachten.
Damit nicht ständig alle userReadings ein Event feuern, habe ich die Attribute
event-on-update/change-reading gesetzt.
Korrigiere mich bitte wenn es sich anders verhält.
Zitat von: Beta-User am 13 Oktober 2020, 08:27:41
... sowieso CalView2 planst...
:)
Nein, das ist nicht wirklich mein Plan.
(so nebenbei, gibt es eigentlich ein copyright auf Modulnamen?) ;)
CalView hat seine Berechtigung, nutze ich selber, doch nur für FTUI.
Die drei Funktionen waren eigentlich mein Ziel.
Alles weitere, in Bezug auf calendar und userReadings, ist zu vernachlässigendes Beiwerk.
Manchmal ist man einfach nur so im flow, das man eben mehr macht als gedacht.
So in der Art, ach komm, da könnte ich doch auch noch dies oder jenes mit rein nehmen.
Geht mir auch im Geschäft so,
beim überfliegen des NC-Codes mal eben noch schnell ein paar Parameter mit eingebaut und verrechnet,
bis dann der Vorgesetzte meint, du hast doch nen Knall, das versteht doch kein Maschinenbediener mehr.
Aber egal, mir macht es Spaß, und solange es funktioniert, why not.
Ups, mal wieder etwas OT.
OK, mein Hauptanliegen war ja Programmierung und Struktur in Perl.
Dank deiner großartigen Hilfe zur Selbsthilfe bin ich hier doch einen großen Schritt vorwärts gekommen.
Sicherlich wird die ein oder andere Frage noch auftauchen,
vor allem wenn ich das bis hierhin Besprochene aufarbeite.
Ansonsten noch einen angenehmen Tag,
und Dankeschön noch einmal für deine sehr hilfreiche Unterstützung.
Freundliche Grüße, Karsten
Zitat von: hydrotec am 13 Oktober 2020, 13:00:54
Um nicht wieder Missverständnissen zu unterliegen, hake ich mal nach.
Die trigger-Angabe in userReadings hat eine komplett andere Funktion, als bei dir ankam:
- Das ganze mit userReadings wird - vereinfacht gesagt - in der Eventverarbeitung des Geräts abgearbeitet, an dem das definiert wird. Ergo gibt es bereits mind. einen Event, die Liste der geänderten Readings wird nur ggf. länger (das "bulk").
- Hat man ein Gerät (wie vermutlich Calendar), das sowieso alle Readings "per bulk" aktualisiert, ist die daraus resultierende zusätzliche Systemlast gering.
- Ist das Gerät aber so gestrickt, dass Readings (teilweise) nicht per bulk-update aktualisiert werden (z.B. wird jeder readingList-Eintrag in MQTT2_DEVICE separat behandelt oder jeder MySensors-Wert), wird auch das userReading bei jedem update ausgewertet, ganz egal, ob sich der "Bezugspunkt" geändert hat oder nicht.
Kurz: "trigger" ist in diesem Zusammenhang als Einschränkung zu lesen und spart Ressourcen.
Nochmal zu "Hygiene": Da aber die wenigsten User eine Idee haben, ob ein Device-TYPE jetzt bulk-updates macht (=> kann man sich trigger sparen) oder per single jedesmal auch indirekt den userReading-Teil aufruft, halte ich es für sinnvoll, das "immer" zu fordern und auch hinzuschreiben. Ist aber meine persönliche Meinung, und gegenteiligen Code (auch von fleißigen Helfern hier) wirst du zuhauf finden.
Zitat von: hydrotec am 13 Oktober 2020, 13:00:54
Da du dir so viel Mühe gibst mit der calendar2holiday-Geschichte,
...das wollte ich schon lange mal überarbeiten ::) ...
holiday hat halt den Vorteil, dass man es sehr gut in die "allgemeine Logik" integriert bekommt. Via global-holiday2we bekommt man es z.B. sehr simpel in alles, was IsWe() spricht ("Einzeiler", AutoShuttersControl, WeekdayTimer, (vermutlich) DOIF, ...)
Guten Morgen miteinander
@Beta-User
57_Calendar2holiday.pm habe ich mir angesehen, und schon angelegt.
Getestet, ob es etwas für mich ist, habe ich noch nicht.
Werde mir das die Tage auch noch ansehen.
Dann poste ich aber in dem passenden Thread (https://forum.fhem.de/index.php/topic,85759.msg1092165.html#msg1092165).
@all
Zwischenzeitlich habe ich mich etwas mehr in Perl eingelesen, und meinen Code noch einmal überarbeitet.
Ist ja peinlich, doch ich hatte bei der ganzen Programmiererei und anschließender Testerei,
komplett vergessen das mein verbose auf 1 eingestellt war. :-[
Mit verbose=5 wurde mir klar, mein Code ist alles andere als OK. :'(
Jetzt klappt das mit dem Nachbarn. (Log, Event monitor) ;)
Zumindest wird im Log-file kein Fehler oder Warnung ausgegeben,
und im Event monitor erscheinen nur die von mir erwünschten Events.
Selbst bei Perl::Critic (http://perlcritic.com/) übersteht der Code Severity level (3) harsh ohne Meldung.
Was ich noch nicht hinbekommen habe,
das bei der Abfrage ob Ereignis mit Suchwort die Groß- und Kleinschreibung ignoriert wird.
Ist nicht dramatisch, muss man halt etwas aufpassen das Kalendereintrag und Suchwort gleich geschrieben sind.
Folgend noch der (vermutlich) finale Stand
calendar device (Test-Kalender)
defmod Cal_WoW Calendar ical url https://{USERNAME}:{PASSWORD}@192.168.78.33:31443/remote.php/dav/calendars/{USERNAME}/wow?export 43200
attr Cal_WoW DbLogExclude .*
attr Cal_WoW event-on-change-reading Event_.*,Search_.*
attr Cal_WoW event-on-update-reading state,lastUpdate
attr Cal_WoW hideLaterThan 030d
attr Cal_WoW hideOlderThan 00:15
attr Cal_WoW room Kalender
attr Cal_WoW stateFormat Status: state T: lastUpdate<br/>\
Event in: Event_at Tag(en) Morgen: Event_tomorrow, Heute: Event_today<br/>\
Hallo in: Search_Hallo_at Tag(en) Morgen: Search_Hallo_tomorrow, Heute: Search_Hallo_today<br/>\
Ciao in: Search_Ciao_at Tag(en) Morgen: Search_Ciao_tomorrow, Heute: Search_Ciao_today
attr Cal_WoW synchronousUpdate 0
attr Cal_WoW userReadings Event_name:triggered.* {Cal_na($NAME)}, \
Event_at:triggered.* {Cal_at($NAME)}, \
Event_tomorrow:triggered.* {Cal_tm($NAME)}, \
Event_today:triggered.* {Cal_td($NAME)}, \
Search_Hallo_name:triggered.* {Cal_na($NAME, 'Hallo')}, \
Search_Hallo_at:triggered.* {Cal_at($NAME, 'Hallo')}, \
Search_Hallo_tomorrow:triggered.* {Cal_tm($NAME, 'Hallo')}, \
Search_Hallo_today:triggered.* {Cal_td($NAME, 'Hallo')}, \
Search_Ciao_name:triggered.* {Cal_na($NAME, 'Ciao')}, \
Search_Ciao_at:triggered.* {Cal_at($NAME, 'Ciao')}, \
Search_Ciao_tomorrow:triggered.* {Cal_tm($NAME, 'Ciao')}, \
Search_Ciao_today:triggered.* {Cal_td($NAME, 'Ciao')}
attr Cal_WoW verbose 5
99_myUtils_calendar.pm
#************************************************************************
# 99_myUtils_calendar.pm kst
#************************************************************************
# 2020-10-03 - Datei erstellt
# 2020-10-03 - Abfrage Tage bis zu Event hinzu
# 2020-10-03 - Nicht Ganztagestermine Zeit bis Mitternacht verrechnen
# 2020-10-04 - Event Morgen/Heute hinzu
# 2020-10-05 - Event Name hinzu
# 2020-10-10 - Thread erstellt (99_myUtils_calendar - Perl Code)
# - https://forum.fhem.de/index.php/topic,114901.0.html
# - Cal_at umformatiert nach Vorlage CoolTux (Forum)
# 2020-10-11 - Code leserlich formatiert
# - Event Morgen/Heute angepasst
# - Event Name angepasst
# - use POSIX; entfernt nach Hinweis von Beta-User (Forum)
# 2020-10-12 - Bei Optionalem Parameter ($kst_sword) " // undef" entfernt
# - (wird ueber "if (defined $kst_sword && length($kst_sword) > 0)" abgfragt)
# - Abfrage ob Pflichtparameter ($kst_cname) angegeben ist
# - Rueckmeldung ueber Text im Reading verwendet, da in diesem Fall ausreichend
# - carp (?) ist eher was fuer Modulentwickler (bessere Fehlerauswertung)
# 2020-10-14 - 57_Calendar2holiday.pm fuer Testzwecke eingefuegt
# - nach Vorlage von Beta-User (Forum)
# - (https://forum.fhem.de/index.php/topic,85759.msg1092165.html#msg1092165)
# - Aufruf (fhem("get...")) nach Abfrage mit/ohne Suchwort eingefuegt
# - (ansonsten werden beide Aufrufe angestossen)
# 2020-10-15 - Anfuehrungszeichen bei Aufruf (fhem("get...")) angepasst
# - Code nach Notepad++ formatiert
# - Abfrage ob Pflichtparameter ($kst_cname) angegeben ist
# - Rueckmeldung angepasst
# - 57_Calendar2holiday.pm in extra 99_myUtils_calendar2holiday.pm.pm eingefuegt
# -
# -
# -
#
#------------------------------------------------------------------------
package main;
use strict;
use warnings;
#use Carp;
#use POSIX;
sub
myUtils_calendar_Initialize($$)
{
my ($hash) = @_;
}
# Enter you functions below _this_ line.
##************************************************************************
## Zeit in Sekunden von Mitternacht bis aktuelle Zeit in Sekunden
##************************************************************************
## Kopie aus 57_Calendar.pm
#sub Calendar_GetSecondsFromMidnight()
#{
# my @time = localtime();
# return (($time[2] * HOURSECONDS) + ($time[1] * MINUTESECONDS) + $time[0]);
#}
#************************************************************************
# Tage bis zum anstehenden Termin
#************************************************************************
sub Cal_at {
# Pflicht-Uebernahmeparameter (calendername), mit Ueberpruefung
my $kst_cname = shift // return '!!! Error: minimum call {Cal_at($NAME)} !!!';
my $kst_sword = shift; # Optionaler Uebernahmeparameter (searchword)
my $kst_format = '$t1'; # $t1 Startzeit in Sekunden
my $kst_time = 0; # Parameter setzen, damit keine Warnmeldung erscheint
if (defined $kst_sword
&& length($kst_sword) > 0) # Abfrage ob Zeit mit oder ohne Suchwort verwendet wird
{ # Zeit in Sekunden mit Suchwort
my $kst_timewordon = fhem("get $kst_cname events format:custom=\"$kst_format\" filter:field(summary)=~\"$kst_sword\" limit:from=0,count=1");
$kst_time = $kst_timewordon;
}
else
{ # Zeit in Sekunden ohne Suchwort
my $kst_timewordoff = fhem("get $kst_cname events format:custom=\"$kst_format\" limit:from=0,count=1");
$kst_time = $kst_timewordoff;
}
# Zeit von Mitternacht bis aktueller Zeit in Sekunden
my $kst_todaymidnight = Calendar_GetSecondsFromMidnight();
# Berechnung der Tage bis zum anstehenden Termin
my $kst_day = int(($kst_time / 86400) - ((time - $kst_todaymidnight) / 86400));
# Uebergabe der Tage bis zum anstehenden Termin (999=kein Termin)
return ( (defined $kst_day && $kst_day < 0) ? 999 : $kst_day );
}
#************************************************************************
# Termin Morgen
#************************************************************************
sub Cal_tm {
# Pflicht-Uebernahmeparameter (calendername), mit Ueberpruefung
my $kst_cname = shift // return '!!! Error: minimum call {Cal_tm($NAME)} !!!';
my $kst_sword = shift; # Optionaler Uebernahmeparameter (searchword)
my $kst_format = '$S'; # $S Ereignis
if (defined $kst_sword
&& length($kst_sword) > 0) # Abfrage ob Ereignis mit oder ohne Suchwort verwendet wird
{ # Ereignis mit Suchwort
my $kst_tmwordon = fhem("get $kst_cname events format:custom=\"$kst_format\" filter:field(summary)=~\"$kst_sword\" limit:when=tomorrow");
# Uebergabe Status Termin mit Suchwort (0=nein/1=ja)
return ( (defined $kst_tmwordon && $kst_tmwordon =~ m/$kst_sword/x) ? 1 : 0 );
}
else
{ # Ereignis ohne Suchwort
my $kst_tmwordoff = fhem("get $kst_cname events format:custom=\"$kst_format\" limit:when=tomorrow");
# Uebergabe Status Termin ohne Suchwort (0=nein/1=ja)
return ( (defined $kst_tmwordoff && length($kst_tmwordoff) > 0) ? 1 : 0);
}
}
#************************************************************************
# Termin Heute
#************************************************************************
sub Cal_td {
# Pflicht-Uebernahmeparameter (calendername), mit Ueberpruefung
my $kst_cname = shift // return '!!! Error: minimum call {Cal_td($NAME)} !!!';
my $kst_sword = shift; # Optionaler Uebernahmeparameter (searchword)
my $kst_format = '$S'; # $S Ereignis
if (defined $kst_sword
&& length($kst_sword) > 0) # Abfrage ob Ereignis mit oder ohne Suchwort verwendet wird
{ # Ereignis mit Suchwort
my $kst_tdwordon = fhem("get $kst_cname events format:custom=\"$kst_format\" filter:field(summary)=~\"$kst_sword\" limit:when=today");
# Uebergabe Status Termin mit Suchwort (0=nein/1=ja)
return ( (defined $kst_tdwordon && $kst_tdwordon =~ m/$kst_sword/x) ? 1 : 0 );
}
else
{ # Ereignis ohne Suchwort
my $kst_tdwordoff = fhem("get $kst_cname events format:custom=\"$kst_format\" limit:when=today");
# Uebergabe Status Termin ohne Suchwort (0=nein/1=ja)
return ( (defined $kst_tdwordoff && length($kst_tdwordoff) > 0) ? 1 : 0);
}
}
#************************************************************************
# Name zum Termin
#************************************************************************
sub Cal_na {
# Pflicht-Uebernahmeparameter (calendername), mit Ueberpruefung
my $kst_cname = shift // return '!!! Error: minimum call {Cal_na($NAME)} !!!';
my $kst_sword = shift; # Optionaler Uebernahmeparameter (searchword)
my $kst_format = '$S'; # $S Ereignis
if (defined $kst_sword
&& length($kst_sword) > 0) # Abfrage ob Name mit oder ohne Suchwort verwendet wird
{ # Name mit Suchwort
my $kst_nawordon = fhem("get $kst_cname events format:custom=\"$kst_format\" filter:field(summary)=~\"$kst_sword\" limit:from=0,count=1");
# Uebergabe Name mit Suchwort
return ( (defined $kst_nawordon && length($kst_nawordon) > 0) ? $kst_nawordon : "Kein Treffer" );
}
else
{ # Name ohne Suchwort
my $kst_nawordoff = fhem("get $kst_cname events format:custom=\"$kst_format\" limit:from=0,count=1");
# Uebergabe Name ohne Suchwort
return ( (defined $kst_nawordoff && length($kst_nawordoff) > 0) ? $kst_nawordoff : "Kein Termin" );
}
}
#************************************************************************
# Temporaer
#************************************************************************
#
#
#
1;
Sollten doch noch Kritikpunkte (positiv wie negativ) vorhanden sein,
gerne her damit. :D
Mit freundlichen Grüßen,
Karsten
Zitat von: hydrotec am 16 Oktober 2020, 09:21:00
@Beta-User
57_Calendar2holiday.pm habe ich mir angesehen, und schon angelegt.
Ähm, das ist eigentlich "normaler" myUtils-Code und kein Modul; der Dateiname sollte daher mit 99_ beginnen, damit das automatisch geladen wird. Aber schon richtig: Fragen dazu gehören in den anderen Thread.
Ob Calendar mit dem /i-Schalter bei der regex umgehen würde, weiß ich auch grade nicht, kann durchaus sein, dass da auch in meinem Code noch Verbesserungspotential drin ist.
Zum eigentlichen Thema zurück
Was das Lernen angeht: Super Fortschritte, Hut ab :) !
Der (über-) nächste Schritt wäre dann ggf. die myUtils-Geschichten direkt auch noch in entsprechende eigene Packages einzubetten. Das macht die Sache allerdings dann im ersten Moment etwas komplizierter, allerdings hat es den Vorteil, dass man z.B. innerhalb des Packages auch Unicode aktivieren kann (https://forum.fhem.de/index.php/topic,115005.0.html), das "min/max"-Problem fixen (=> Perl-Ecke) und vieles mehr.
Falls du eine Basis suchst, wie sowas aussehen kann: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/AttrTemplate/99_attrT_ZWave_Utils.pm
@CoolTux: Eventuell sollte man das mit "myUtils2" (als package, ggf. auch in dem Wiki-Artikel dargestellt) auch in der Development-Ecke mal ventilieren, _falls_ mein gedanklicher Ansatz nicht insgesamt in die falsche Richtung geht. Aber dazu sind meine eigenen Kenntnisse nicht vertieft genug, um diese Diskussion wirklich vertieft zu führen.
Zitat von: Beta-User am 16 Oktober 2020, 12:20:11
@CoolTux: Eventuell sollte man das mit "myUtils2" (als package, ggf. auch in dem Wiki-Artikel dargestellt) auch in der Development-Ecke mal ventilieren, _falls_ mein gedanklicher Ansatz nicht insgesamt in die falsche Richtung geht. Aber dazu sind meine eigenen Kenntnisse nicht vertieft genug, um diese Diskussion wirklich vertieft zu führen.
Du meinst generell eine Vorlage als myUtils2 vor zu stellen welche auf package Basis läuft?
Zitat von: CoolTux am 16 Oktober 2020, 12:38:16
Du meinst generell eine Vorlage als myUtils2 vor zu stellen welche auf package Basis läuft?
Genau.
Und dann eben gleich als "Vorlage" "wichtige" Funktionen importiert (z.B. ReadingsVal+Num, min, max) und utf8 aktiviert. Was auch immer sinnvoll sein mag, um erst mal eine Idee zu haben, was notwendig ist und um künftige (bzw. alte) Probleme gleich zu umschiffen...?
Zitat von: Beta-User am 16 Oktober 2020, 12:53:36
Genau.
Und dann eben gleich als "Vorlage" "wichtige" Funktionen importiert (z.B. ReadingsVal+Num, min, max) und utf8 aktiviert. Was auch immer sinnvoll sein mag, um erst mal eine Idee zu haben, was notwendig ist und um künftige (bzw. alte) Probleme gleich zu umschiffen...?
Klingt gut. Ich werde es mir mal notieren auf meinem ToDo Stapel. Schauen wir mal.
Zitat von: Beta-User am 16 Oktober 2020, 12:20:11
Ähm, das ist eigentlich "normaler" myUtils-Code und kein Modul; der Dateiname sollte daher mit 99_ beginnen, damit das automatisch geladen wird. Aber schon richtig: Fragen dazu gehören in den anderen Thread.
Sorry, etwas unglücklich ausgedrückt, hätte den kompletten thread-title übernehmen sollen.
Zitat von: Beta-User am 16 Oktober 2020, 12:20:11
Was das Lernen angeht: Super Fortschritte, Hut ab :) !
Dankeschön, ein Lob kann man gerne auch einmal vertragen ;D
Andererseits, wie heißt es bei uns,
"Ned gschompfa isch gloabd gnuag" ;)
Zitat von: Beta-User am 16 Oktober 2020, 12:20:11
Der (über-) nächste Schritt wäre dann ggf. die myUtils-Geschichten direkt auch noch in entsprechende eigene Packages einzubetten.
Das ist, wenn nicht sogar der über-übernächste Schritt.
Dennoch Dankeschön für die Vorlage. :)
Zitat von: CoolTux am 16 Oktober 2020, 12:58:22
Klingt gut. Ich werde es mir mal notieren auf meinem ToDo Stapel.
Entschuldige bitte, ich wollte dir nicht noch mehr Arbeit aufdrücken. :-[
Generell sind "Vorlagen" schon eine gute Sache, andererseits, bei einem so komplexen System auch wieder gefährlich.
Man kann noch so viele Optionen berücksichtigen, und eine Dokumentation dazu bereitstellen,
wenn der Anwender nicht weiß was er da macht, kann der Schuß nach hinten losgehen.
Ich kenne da einen, der hat das erst kürzlich am eigenen Leib erfahren müssen. ::)
Wie dem auch sei, ich wünsche euch allen ein angenehmes Wochenende,
und danke noch einmal für eure Geduld und hervorragende Hilfestellung.
Grüße, Karsten