Die von Schulferien.org zur Verfügung gestellten Kalender haben ja die Herausforderung, immer nur pro Jahr definiert zu sein.
Somit muss man sich überlegen, wie man in FHEM jeweils den richtigen Kalender automatisch erwischt.
Aus einem anderen Thread, wo diese Thema bereits gelöst wurde, der aber schon zu ist, stammt dieses Zitat:
Zitatin fhem selbst würde ich mir ein notify anlegen, das auf global:INITIALIZED reagiert und nach dem vollständigen fhem Start diese Funktion aufruft:
Wenn ich mir die Definition in der commandref von INITIALIZED anschaue, und diesen Satz lese, stellt sich mir folgende Frage:
Wie kann das funktionieren, wenn ich FHEM nur alle paar Wochen oder Monate einmal neu starten muss, da es ja rund läuft?
Muss ich nicht besser immer am 1.1. eines jeden Jahres die Funktion aufrufen, und wie könnte ein entsprechender Aufruf aussehen?
Evtl. ein notify auf den Jahreswechsel?
Theoretisch könntest Du doch auch ein at-Kommando nutzen, das einmal pro Tag (z.B. kurz nach Mitternacht) den Ferienkalender des aktuellen Jahres einstellt. Der Befehl würde zwar 364 mal im Jahr umsonst laufen, aber ressourcentechnisch wäre das, glaube ich, kein besonders großes Problem.
Da bin ich mir jetzt nicht so sicher.
Wenn ich einen define schon habe, sagen wir mal am 1.1. erstellt, dann müsste FHEM aber eigentlich meckern, wenn ich den gleichen define am 2.1. schon wieder machen will. Oder etwa nicht?
Wie's ausschaut, funktioniert die Lösung von betateilchen nur auf den ersten Blick:
Da ja mit restart noch keine Defiition vorhanden ist, sondern diese ja erst quasi beim hochfahren von FHEM erstellt wird. Somit muss zuvor auch nichts gelöscht werden.
Problem ist jedoch, das dies nur funktioniert, wenn am 1.1. um kurz nach 0:00 auch wirklich ein Restart durchgeführt wird.
Wenn dieser restart erst am 2.2. erfolgt, sind die Weihnachtsferien schon vorbei :-)
Ein zusätzlicher defineFerien(2015) am 1.1. funktioniert jedoch nicht, da schon ein Kalender für 2014 vorhanden ist. Die Defintion wird in diesem Fall nicht geändert, aber auch nicht weiter kommentiert.
Ich wewrde es einmal bei Gelegenheit mit CommandModify probieren.
Also anstatt so:
Zitatsub defineFerien($) {
my ($year) = @_;
my $url = "http://www.schulferien.org/iCal/Ferien/icals/Ferien_Bayern_$year.ics";
CommandDefine(undef, "Bayern_Ferien Calendar ical url $url 21600");
return;
}
so:
sub defineFerien($) {
my ($year) = @_;
my $url = "http://www.schulferien.org/iCal/Ferien/icals/Ferien_Bayern_$year.ics";
CommandModify(undef, "Bayern_Ferien Calendar ical url $url 21600");
return;
}
Ich hoffe, das er dann die bestehende Definition ändert, und somit über einen täglichen Aufruf aktualisiert werden kann.
Mal sehen.
Die Hoffnung stirbt zuletzt. Also gerade eben...
Leider ändert ein CommandModify ebenfalls nicht eine bestehende Definition.
Ich gebe auf und habe zwei Kalender definiert.
Jeweils für's aktuelle und Folgejahr. Ich muss nun immer manuell eingreifen und das Jahr abändern.
Schade, aber ich komme mit meinen Mitteln nicht weiter.
Mit CommandDefine() und Co habe ich noch nie gearbeitet, aber die folgende Konstruktion funktioniert bei mir ganz gut, um FHEM-Dummys oder -Funktionen ggf. neu zu definieren:
{
fhem("delete auto_weather_repeat") if (Value("auto_weather_repeat") ne "");;
fhem("define auto_weather_repeat at +00:10:00 {alertWeather(1)}");;
}
Ließe sich das evtl. so anpassen, dass es bei Dir klappt?
Baumi, Du bist mein Held :-)
So funktioniert es:
Zitatsub defineFerien($) {
my ($year) = @_;
my $url = "http://www.schulferien.org/iCal/Ferien/icals/Ferien_Bayern_$year.ics";
fhem("delete Bayern_Ferien");
CommandDefine(undef, "Bayern_Ferien Calendar ical url $url 21600");
return;
}
Auf der Basis kann man nun auch ein doif aufbauen, welches bei (jedem neustart) oder (um 0:05 Uhr am 1. eines jeden monats (hauptsächlich natürlich am 1.1.)) diese defineFerien aufruft.
Oder eben ein at für den 1. eines Monats, und ein notify wie bei betateilchen für den neustart.
Danke.
Hallo,
wenn die Frage gelöst ist dann bitte dem Betreff noch ein Gelöst vorne dran.
Danke.
Grüße
Edith: Ich muss mal meinen Bildschirm putzen ::)
Hi Pjg,
kannst Du die komplette Lösung mal posten?
Danke,
Spartacus.
fhem.cfg
Zitat# Schulferien
define Ferientag dummy
define makeFerien notify global:INITIALIZED {defineFerien($year)}
define makeFerien2 at *00:05 { if ( $mday == 1) {defineFerien($year)}}
define Job_Ferien_Check notify Ferien { fhem "set Ferientag " . (ReadingsVal("Ferien", "modeStart", "") =~ "schulferien" ? 1: 0) }
myutils
Zitatsub defineFerien($) {
my ($year) = @_;
my $url = "http://www.schulferien.org/iCal/Ferien/icals/Ferien_Rheinland_Pfalz_$year.ics";
fhem("delete Ferien");
CommandDefine(undef, "Ferien Calendar ical url $url 86400");
return;
}
Halo,
Danke für Deinen Post. Du fragst mit mday=1 den ersten Tag eines Monats ab. Müsste man hier nicht auch den Monat mon=0 für Januar abfragen? Sonst läuft Dein at doch jeden 1. eines Monats um 5 nach 12.
Oder was übersehe ich gerade....
Spartacus
Siehst Du fast richtig. $month ==1 könnte man noch rein nehmen.
Hab ich jetzt aber mal gelassen. Wird dann halt 11 mal zuviel aufgerufen.
Frohes neues Jahr an alle!
Für die Steuerung meine Rollladen habe ich die Lösung von Pjg Angewendet, das hat Funktioniert bis Jahreswechselt jetzt wird nach neues Jahr kein Feiertag erkannt.
Weiß es jemand mehr drüber?
Vielen Dank.
Hallo zusammen
das Problem von Deen habe ich auch. Der Code von oben hat einen Haken:
Wenn die Ferien um 00:05:00 Uhr an Neujahr auf das neue Kalenderjahr aktualisiert werden, dann sind die aktuellen Weihnachtsferien futsch, denn diese sind im Kalender für 2015 angegeben (22.12.2015-07.01.2016).
Hat dafür jemand eine Lösung?
Spartacus
Es müsste mit Hilfe der internen FHEM-Variablen für Tag und Monat gehen. (Nicht getestet!)
sub defineFerien($) {
my ($year) = @_;
my $url = "http://www.schulferien.org/iCal/Ferien/icals/Ferien_Rheinland_Pfalz_$year.ics";
if ($month > 1 || $mday > 15) {
fhem("delete Ferien");
CommandDefine(undef, "Ferien Calendar ical url $url 86400");
}
return;
}
(Die Kombination aus delete und CommandDefine ließe sich inzwischen auch durch ein defmod ersetzen.)
Mit dieser Routine wird (wenn ich mich nicht vertippt habe) der Kalender zwischen dem 1. und 15. Januar nicht aktualisiert. Und ich glaube, am 15.01. sind nirgendwo mehr Ferien.
Alternativ könnte man die Abfrage auch auf einen einzelnen Zeitraum beschränken (z.B. ändere das Define nur am soundsovielten Januar), aber das birgt die Gefahr, dass ausgerechnet in der Minute, in der die Funktion aufgerufen werden müsste, aus irgendwelchen Gründen gerade fhem nicht läuft und man das ganze Jahr über den falschen Kalender hat. Ein einzelnes define pro Tag kostet nicht viel Rechenzeit und beugt diesem Problem vor.
Hallo Baumi,
das ist es noch nicht ganz, denn durch:
define makeFerien notify global:INITIALIZED {defineFerien($year)}
werden die Ferien bei jedem Booten mit dem aktuellen Jahr angelegt. Das muss man noch irgendwie abfangen...
Christian
NACHTRAG:
das if ($month > 1 || $mday > 15) {
fhem("delete Ferien");
funktioniert noch nicht! Der Befehl wird ausgeführt.
Sorry, das kommt davon, wenn man mitten in der Nacht ungetesteten Code postet. :)
So funktioniert's bei mir:
sub defineFerien($$$) {
my ($year, $month, $mday) = @_;
my $url = "http://www.schulferien.org/iCal/Ferien/icals/Ferien_Rheinland_Pfalz_$year.ics";
if ($month > 1 || $mday > 15) {
fhem("delete Ferien");
CommandDefine(undef, "Ferien Calendar ical url $url 86400");
}
return;
}
Achtung: Alle defines und anderen Strukturen, die diese Funktion aufrufen, müssen dann auch geändert werden. Der Aufruf muss jeweils so aussehen:
defineFerien($year,$month,$mday);;
Dass der Befehl bei jedem Boot ausgeführt wird, sollte m. E. keinen Unterschied machen. Das Datum wird ja übergeben und während der Ausführung abgefragt, d.h. wenn das Booten Anfang Januar stattfindet, wird dabei auch nix geändert. Oder liefert FHEM während des Startvorgangs fehlerhafte Werte für $year, $month und $mday?
Hallo,
ich glaube ich habe es jetzt:
Der Knackpunkt ist, dass $month und $mday übergeben werden müssen. Sonst kann die Routine das nicht auswerten. Vielleicht hat jemand eine bessere Lösung. Aber so scheint es zu funzen.
# Neujahr um 00:01 Uhr
#
define cal.04.Schulferien.not at *00:01:00 \
set cal.01.Schulferien reload;; \
{ \
if ( $mday == 1 && $month == 1)\
{ \
defineFerien($year,$month,$mday)\
}\
}
und dann
define cal.03.Schulferien.not notify global:INITIALIZED {defineFerien($year,$month,$mday)}
und in myutils...
sub defineFerien($$$)
{
my ($year,$month,$mday) = @_;
my $url = "http://www.schulferien.org/iCal/Ferien/icals/Ferien_Nordrhein_Westfalen_$year.ics";
if ($month > 1 || $mday > 15)
{
fhem("delete cal.01.Schulferien");
CommandDefine(undef, "cal.01.Schulferien Calendar ical url $url 100000");
}
return;
}
Spartacus
8)
da warst Du eine paar Sekunden schneller!
Christian
8)
Du kannst Dir die Parameter-Übergabe natürlich auch komplett sparen, wenn Du statt dessen innerhalb der Funktion das aktuelle Datum ausliest. Allerdings musst Du die Ausgabewerte von localtime noch ein bisschen aufbereiten, um sie zu verwenden. (1900 zum Jahr addieren, und 1 zum Monat.
sub defineFerien()
{
my($sec,$min,$hour,$mday,$month,$year,$wday,$yday,$isdst) = localtime(time);
$year += 1900;
$month ++;
my $url = "http://www.schulferien.org/iCal/Ferien/icals/Ferien_Nordrhein_Westfalen_$year.ics";
if ($month > 1 || $mday > 15)
{
usw.
Dann müssten die Aufrufe in ein einfaches defineFerien();; geändert werden.
Hi Baumi,
habe jetzt Deine letzte Variante genommen. Die ist viel eleganter....
Danke Dir für Deine Hilfe..
Christian
Super! Vielen Dank!
Ich bin ein Anfänger, verstehe das richtig? Ich habe so in ".cfg angegeben:
# Neujahr um 00:01 Uhr
#
define cal.04.Schulferien.not at *20:41:00 \
set cal.01.Schulferien reload;; \
{ \
if ( $mday == 1 && $month == 1)\
{ \
defineFerien($year,$month,$mday)\
}\
}
define cal.03.Schulferien.not notify global:INITIALIZED {defineFerien($year,$month,$mday)}
# Schulferien
define Ferientag dummy
define makeFerien notify global:INITIALIZED {defineFerien($year)}
define makeFerien2 at *20:30:00 { if ( $mday == 1) {defineFerien($year)}}
define Job_Ferien_Check notify Ferien { fhem "set Ferientag " . (ReadingsVal("Ferien", "modeStart", "") =~ "schulferien" ? 1: 0) }
define K.Zimmer1 at *06:10:00 { if ( !($we) && !(Value("Ferientag")) ) { fhem("set harmony_24908328 command directionup");; } }
define K.Zimmer2 at *06:10:20 { if ( !($we) && !(Value("Ferientag")) ) { fhem("set harmony_24908328 command stop");; } }
define K.Zimmer3 at *10:00:00 { if (($we) || (Value("Ferientag"))) {fhem("set harmony_24908328 command directionup");; } }
define K.Zimmer4 at *10:00:20 { if (($we) || (Value("Ferientag"))) {fhem("set harmony_24908328 command stop");; } }
und dann in myutils:
package main;
use strict;
use warnings;
use POSIX;
sub
myUtils_Initialize($$)
{
my ($hash) = @_;
}
sub defineFerien()
{
my($sec,$min,$hour,$mday,$month,$year,$wday,$yday,$isdst) = localtime(time);
$year += 1900;
$month ++;
my $url ="http://www.schulferien.org/iCal/Ferien/icals/Ferien_Baden_Wuerttemberg_$year.ics";
if ($month > 1 || $mday > 15)
{
fhem("delete cal.01.Schulferien");
CommandDefine(undef, "cal.01.Schulferien Calendar ical url $url 100000");
}
return;
}
1;
ist so korrekt?
Vielen Dank
Hi,
im Prinzip richtig.
Du brauchst zwei Trigger für das Aktualisieren der Kalender: Einmal beim Booten und einmal an Neujahr bzw. nach den Weihnachtsferien durch ein Notify. Bei mir läuft das am 11.01. Die Abfrage auf das Datum in in der myFerien.pm verhindert, dass die neue Kalenderdatei beim booten nicht vor Ende der aktuellen Weihnachtsferien angelegt wird. Sonst gehen die Ferientage im Januar verloren. In der Regel sind die Ferien in den meisten Bundesländern spätestens am 10.01. beendet. Deshalb erstelle ich den neuen Kalender am 11.01.
Hier mein Code, den ich aus der fhem.cfg kopiert habe. Die Namen der Kalender kannst Du natürlich ändern..
booten:
define cal.03.Schulferien.not notify global:INITIALIZED {defineFerien()}
nach den Weihnachtsferien (hier 11.01.):
define cal.04.Schulferien.not at *00:01:00 \
set cal.01.Schulferien reload;; \
{ \
if ( $mday == 11 && $month == 1)\
{ \
defineFerien()\
}\
}
aus der 99_myFerien.pm
package main;
use strict;
use warnings;
use POSIX;
use Time::Local;
sub myFerien_Initialize($$)
{
my ($hash) = @_;
}
sub defineFerien()
{
my($sec,$min,$hour,$mday,$month,$year,$wday,$yday,$isdst) = localtime(time);
$year += 1900;
$month ++;
my $url = "http://www.schulferien.org/iCal/Ferien/icals/Ferien_Nordrhein_Westfalen_$year.ics";
if ($month > 1 || $mday > 10)
{
fhem("delete cal.01.Schulferien");
CommandDefine(undef, "cal.01.Schulferien Calendar ical url $url 100000");
}
fhem("set cal.01.Schulferien reload");
fhem("attr cal.01.Schulferien room 99-Dienste");
fhem("attr cal.01.Schulferien alias Ferien NRW");
fhem("attr cal.01.Schulferien group Online Kalender");
return;
}
1;
Ich hoffe, das hilft jetzt!
Spartacus
Fehlt beim Notify für den 11.01. nicht noch ein Semikolon (oder zwei) hinter "defineFerien()"?
Vielen Dank.
D. h. dass von 01.01 bis 10.1 keine Feiertagen erkannt werden oder?
mfg
Hallo,
das heißt, dass vom 01.01. bis 10.01. der alte Kalender (also 2015) gültig ist und der 2016er erst am 11.01. geladen wird. Die Weihnachtsferien (z.B.: 22.12.2015-06.01.2016) stehen immer im 2015er Kalender. Und wenn Du in der Neujahrsnacht den 2016er Kalender lädst, dann sind die Ferientage im Januar 2016 futsch!
Deshalb wird der 2016er Kalender erst geladen, wenn die Weihnachtsferien beendet sind.
Christian
Danke Christian.
Sorry für das späte aufspringen auf diesen mittlerweile gelösten Fall.
pah hatte für diese Thematik mal seine eigenen Skripte zur Verfügung gestellt, die selbiges (und noch etwas mehr) ganz vorzüglich lösen:
Ist hier zum nachlesen:
http://forum.fhem.de/index.php/topic,36244.msg299631.html#msg299631 (http://forum.fhem.de/index.php/topic,36244.msg299631.html#msg299631)