Hauptmenü

DOIF: "next timer event"

Begonnen von SGi, 19 November 2016, 16:14:30

Vorheriges Thema - Nächstes Thema

SGi

Hallo zusammen,

Damians DOIF liefert ja netterweise bei berechneten (Sonnenuntergang etc) Events die Schaltzeitpunkte mit Datum und Uhrzeit gleich als Readings. Nun würde ich gerne die Zeit des jeweils nächsten Events in meinem UI anzeigen können. Bisher war meine Überlegung, über ein notify eine Änderung eines Readings zu erkennen und dann per PERL-substr() den gekürzten Wert in einen Dummy zu schreiben, der dann letztendlich zum Anzeigen verwendet wird. Aber gibt es auch eine weniger umständliche Möglichkeit, aus timer_1_c1 = 20.11.2016 06:38:00 nur die Uhrzeit 06:38 zu machen ? 

Und als komfortable Steigerung: nur das jeweils nächste Schaltereignis in der Zukunft - und nicht einen expliziten Timer (z.B. timer1_c1) aus einem DOELSEIF-Zweig, denn wenn danach noch timer 2, 3 usw kommen, brauche ich ja für jeden möglichen Zeitpunkt jedes DOIFs einen eigenen Dummy und ein eigenes notify...

Sven
FHEM auf RasPi und FritzBox 7390 mit MAX! und HomeMatic

Ellert

ZitatAber gibt es auch eine weniger umständliche Möglichkeit, aus timer_1_c1 = 20.11.2016 06:38:00 nur die Uhrzeit 06:38 zu machen
Du kannst ein userReadings ins DOIF bauen und auf die Timer triggern, das spart den Dummy.
ZitatUnd als komfortable Steigerung: nur das jeweils nächste Schaltereignis in der Zukunft
Das geht mit der Perl-Funktion min(<Timer1>,<Timer2>,<Timer3>,...).

Damian

next_timer kommt auf die todo-Liste, da schon mehrfach danach gefragt wurde. Es wird etwas aufwändiger sein als nur sortieren, da man den Wochentag noch auswerten muss.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Ellert

#3
Zitatnur das jeweils nächste Schaltereignis in der Zukunft
Was sollte in "next timer event" berücksichtigt werden?

1. Nehmen wir an es ist 13 Uhr am 1.10.2016 und Du hast einen Timer [12:00|8].
2. Du hast eine Zeitspanne [10:00-18:00] und es ist 13 Uhr.
Zu 1. und 2.: Welche Zeit und Datum sollte nextUpdate beinhalten?

3. Sollte immer von allen Timern eines DOIF der nächste Schalttermin gebildet werden oder nur von selbstbestimmten Timer?

4.Sollte das in holiday2we angegebene Gerät vorausschauend befragt werden?

Damian

#4
Zitat von: Ellert am 20 November 2016, 06:52:21
Was sollte in "next timer event" berücksichtigt werden?

1. Nehmen wir an es ist 13 Uhr am 1.10.2016 und Du hast einen Timer [12:00|8].
2. Du hast eine Zeitspanne [10:00-18:00] und es ist 13 Uhr.
Zu 1. und 2.: Welche Zeit und Datum sollte nextUpdate beinhalten?

3. Sollte immer von allen Timern eines DOIF der nächste Schalttermin gebildet werden oder nur von selbstbestimmten Timer?

4.Sollte das in holiday2we angegebene Gerät vorausschauend befragt werden?

Das Setzen des next_timers würde ich beim Setzen eines Timers vornehmen, die einzelnen Timer sind intern als Real-Timer, also errechnete Zeit in HH:MM:SS oder sogar als echter Zeitpunkt in Sekunden abgelegt. Zum Zeitpunkt des Setzens und damit der Prüfung ist der aktuelle Wochentag bekannt, von dem man ausgehen muss. Problematisch werden natürlich die Feiertage, die man bei der Angabe "7" oder "8" jeweils für jeweiligen Zeitpunkt erst errechnen muss.

Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Per

Zitat von: Damian am 19 November 2016, 17:36:56Es wird etwas aufwändiger sein als nur sortieren, da man den Wochentag noch auswerten muss.
Wobei das eine Philosophiefrage ist: zählen die "|0-8" zur Bedingung oder zum Timer. Man müsste es meiner Ansicht nach gleich ihrem Verhalten bei checkall machen.

Damian

Zitat von: Per am 21 November 2016, 11:51:08
Wobei das eine Philosophiefrage ist: zählen die "|0-8" zur Bedingung oder zum Timer. Man müsste es meiner Ansicht nach gleich ihrem Verhalten bei checkall machen.

Die Wochentagangaben gehören immer zum jeweiligen Timer (auch bei Intervallen). Z. Zt. triggern alle Timer auch wenn sie an dem Tag nicht wahr sind - das führt ggf. zur Ausführung von DOELSE falls angegeben. Zukünftig sollen Timer nur an dem angegebenen Tag  zur Auswertung der Bedingung führen.


Ein richtiges next_Timer mit tatsächlichen Triggerzeiten ist eigentlich gar nicht realisierbar, denn bei der Angabe [08:00|[Myweekday]] ist gar nicht klar, wann der Timer zuschlägt. Man kann kurz vor 08:00 Myweekday ändern und damit die Gültigkeit des Timers verändern.

Vermutlich wird ein einfaches Sortieren der gesetzten Timer das einzig Machbare sein.





Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Per

Zitat von: Damian am 21 November 2016, 16:35:58Vermutlich wird ein einfaches Sortieren der gesetzten Timer das einzig Machbare sein.
Und bestimmt das, was 90% der User ausreichen wird.

Ellert

Zitat von: Damian am 21 November 2016, 16:35:58
Die Wochentagangaben gehören immer zum jeweiligen Timer (auch bei Intervallen). Z. Zt. triggern alle Timer auch wenn sie an dem Tag nicht wahr sind - das führt ggf. zur Ausführung von DOELSE falls angegeben. Zukünftig sollen Timer nur an dem angegebenen Tag  zur Auswertung der Bedingung führen.


Ein richtiges next_Timer mit tatsächlichen Triggerzeiten ist eigentlich gar nicht realisierbar, denn bei der Angabe [08:00|[Myweekday]] ist gar nicht klar, wann der Timer zuschlägt. Man kann kurz vor 08:00 Myweekday ändern und damit die Gültigkeit des Timers verändern.

Vermutlich wird ein einfaches Sortieren der gesetzten Timer das einzig Machbare sein.
Ich denke, dass userReadings eine gute Möglichkeit sind, die DOIF internen Timer individuell weiter zu verarbeiten, da eigentlich gar nicht klar ist, was "next Update" bzw. "next timer event" genau beinhalten sollte, individuelle Vorstellungen könnten sein, immer unter der Voraussetzung, dass zum Timer gehörende Wochentagseinschränkungen berücksichtigt werden:

-nächster Einschaltzeitpunkt eines Zweiges oder der gesamten Bedingungen
-nächster Ausschaltzeitpunkt eines Zweiges oder der ges. Bed.
-nächster Zeitpunkt aller Timer des DOIF
-nächster Zeitpunkt von einer Auswahl von Timern des DOIF

Ein 6-faches, vorausschauendes get holiday und schreiben in ein Array dauert ca. 25 ms auf einem Pi2B, das ist im Verhältnis zum Zeitbedarf des DOIF recht lang, und könnte, abhängig davon, wie es organisiert ist, die Perfomance beeinträchtigen.

Der erhöhte Zeitbedarf wäre auch gegeben, wenn die Angabe nextUpdate garnicht benötigt wird, was dagegen spricht, so eine Berechnung ins DOIF zu legen.

Damian

Zitat von: Ellert am 21 November 2016, 18:54:14
Ich denke, dass userReadings eine gute Möglichkeit sind, die DOIF internen Timer individuell weiter zu verarbeiten, da eigentlich gar nicht klar ist, was "next Update" bzw. "next timer event" genau beinhalten sollte, individuelle Vorstellungen könnten sein, immer unter der Voraussetzung, dass zum Timer gehörende Wochentagseinschränkungen berücksichtigt werden:

-nächster Einschaltzeitpunkt eines Zweiges oder der gesamten Bedingungen
-nächster Ausschaltzeitpunkt eines Zweiges oder der ges. Bed.
-nächster Zeitpunkt aller Timer des DOIF
-nächster Zeitpunkt von einer Auswahl von Timern des DOIF

Ein 6-faches, vorausschauendes get holiday und schreiben in ein Array dauert ca. 25 ms auf einem Pi2B, das ist im Verhältnis zum Zeitbedarf des DOIF recht lang, und könnte, abhängig davon, wie es organisiert ist, die Perfomance beeinträchtigen.

Der erhöhte Zeitbedarf wäre auch gegeben, wenn die Angabe nextUpdate garnicht benötigt wird, was dagegen spricht, so eine Berechnung ins DOIF zu legen.

ja, eine "richtige" next_time-Funktion kann es beim jetzigen DOIF nicht geben.

was bringt next_time ohne Wochentagauswertung z. B. bei?

[00:00-12:00|135] or [02:00-23:00|236]

nicht viel, da es meisten nicht stimmt.

wenn einer z. B. den frühsten Zeitpunkt des Tages ermitteln will, dann kann er das so machen

{(sort values %{$defs{"<mein DOIF>"}{realtime}})[0]}

den spätesten

{(reverse sort values %{$defs{"<mein DOIF>"}{realtime}})[0]}

so richtig sinnvoll ist das aber alles nicht.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Damian

hier mal ein Beispiel für den nächsten Zeitpunkt ausgehend von aktueller Zeit für eingefleischte Perl-User (und die es werden wollen):

{foreach my $t (sort values %{$defs{"mein_DOIF"}{realtime}}) {return $t if ($t gt substr(localtime,11,8))}}

könnte man im userreading unterbringen getriggert auf Änderung der Timer im DOIF-Modul einschaltbar über das Attribut timerevent.

Allerdings könnte sich die interne Darstellung im DOIF-Modul ändern, daher nur mit Vorsicht zu genießen. Auf der anderen Seite sollten DOIF-Nutzer sich mit solchen Konstrukten nicht rumschlagen müssen, davon gibt es hier im Forum mehr als genug.

Es war eher eine sportliche Herausforderung für mich dieses Problem mit einem Einzeiler zur erschlagen ;)


Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Ellert

#11
Hier ist der erste Versuch den echten nächsten Schalttermin zu ermitteln, unter Berücksichtigung von holiday2we und Wochentagsangaben. Grundlage sind die Timerreadings.
Ist leider kein Einzeiler geworden  ;) das Meiste davon stammt aus dem DOIF-Modul.

Dieser Code muss in die 99_myUtils.pm
########## für DOIF: ermittelt den nächsten echten Schalttermin aus einem TimerReading
sub nextTrigger {
use Time::Local;
my $t1 = gettimeofday();
my ($timer_str) = @_;
$timer_str =~ /(\d\d).(\d\d).(\d\d\d\d) (\d\d):(\d\d):(\d\d)\|?(.*)/;
return "$1.$2.$3 $4:$5:$6" if (length($7) == 0);
my $tdays = $7;
my $timer = timelocal($6,$5,$4,$1,$2-1,$3);
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($timer);
my $ilook = 0;
my $h2we = $attr{global}{holiday2we};
my $we;
my @days;
my $val;
my $a;
my $b;
for (my $iday = $wday; $iday < 7; $iday++) {
$we = (($iday==0 || $iday==6) ? 1 : 0);
if($h2we && !$we) {
$val = fhem "get $h2we days ".($ilook + 1), 1;
if($val) {
($a, $b) = ReplaceEventMap($h2we, [$h2we, $val], 0);
$we = 1 if($b ne "none");
}
}
if ($tdays =~ /$iday/ or ($tdays =~ /7/ and $we) or ($tdays =~ /8/ and !$we)) {
# Log 1, "Laufzeit: ".(gettimeofday()-$t1);
return strftime("%d.%m.%Y %H:%M:%S",localtime($timer + $ilook * 86400));
}
$ilook++;
}
for (my $iday = 0; $iday <= $wday; $iday++) {
$we = (($iday==0 || $iday==6) ? 1 : 0);
if($h2we && !$we) {
$val = fhem "get $h2we days ".($ilook + 1), 1;
if($val) {
($a, $b) = ReplaceEventMap($h2we, [$h2we, $val], 0);
$we = 1 if($b ne "none");
}
}
if ($tdays =~ /$iday/ or ($tdays =~ /7/ and $we) or ($tdays =~ /8/ and !$we)) {
# Log 1, "Laufzeit: ".(gettimeofday()-$t1);
return strftime("%d.%m.%Y %H:%M:%S",localtime($timer + $ilook * 86400));
}
$ilook++;
}
}


dann kann man ein userReading anlegen, z.B. für den Timer "timer_01_c01"
attr <DOIFname> userReadings next_01_c01:timer_01_c01.* {nextTrigger(ReadingsVal($name,"timer_01_c01","01.01.1970 00:00:00"))}

Edit: kleine Verbesserungen

blasterx

Das sieht schon mal gut aus und geht auch soweit aber der Sonntag (0) geht nicht.  Es wird bei

([21:55|0] or [23:00] or [14:00]) (set HMPavillon on)

next_1_c1  der  23.11.2016 21:55:00 angezeigt.
Gruß-BlasterX

Ellert

Zitat von: blasterx am 22 November 2016, 22:02:19
Das sieht schon mal gut aus und geht auch soweit aber der Sonntag (0) geht nicht.  Es wird bei

([21:55|0] or [23:00] or [14:00]) (set HMPavillon on)

next_1_c1  der  23.11.2016 21:55:00 angezeigt.
Müsste jetzt klappen, Code siehe oben.

blasterx

Habe es gerade getestet, funktioniert super. Ich Danke Dir für die schnelle Unterstützung bei meinem Problem.

Gesendet von meinem SM-G935F mit Tapatalk

Gruß-BlasterX