//Lösung unten
Hallo,
ich bin gerade dabei einen Button für alle Lichter zu machen welcher wie ein Sleeptimer funktionieren soll.
Beispiel:
- BettLampe on|off|timer
on => Lampe wird eingeschaltet
off => Lampe wird ausgeschaltet
timer => Lampe wird eingeschaltet mit einem Timer von 5min. Drückt man nochmals auf "timer" wird der Timer auf 10min erhöht, usw.
Wie lässt sich so etwas am besten abbilden? Ich dachte daran eine Funktion in Utils zu schreiben mit (Pseudocode)
timer_funktion($lampe, $aktuellerwert) {
if ($aktuellerwert = 5min) {
set $lampe off at +0:10:0
}
...
}
und die rufe ich dann im Notify auf. Nur wo kann ich den aktuellen Wert speichern!?
Gruß
dominik
--
Hier meine Lösung
99_myUtils.pm
sub Timerfunktion ($$)
{
my ($Device) = $_[0];
my ($Schalter) = $_[1];
my ($TimerIntervall) = 10;
my ($currentValue) = ReadingsVal($Device, "timerValue", 0);
my ($currentState) = ReadingsVal($Device, "state", "off");
#Nur einschalten wenn zuvor "off"
if ($currentState ne "on") {
fhem("set $Device on");
$currentValue = 0;
}
#Sleeptimer hochzählen. Max=180 Minuten
$currentValue = $currentValue + 10;
if ($currentValue > 180) {
$currentValue = 0;
}
my $timerValue = sprintf("%02d:%02d:%02d", (gmtime($currentValue*60))[2,1,0]);
#Schalter state ändern
fhem("set $Schalter $currentValue");
#Aktuellen Sleeptimer schreiben
fhem("setreading $Device timerValue $currentValue");
#Alten Timer löschen
fhem("delete $Device.timer");
#Neuen Timer setzen bzw. ausschalten wenn 0
if ($currentValue > 0) {
fhem("define $Device.timer at +$timerValue set $Device off;;setreading $Device timerValue 0");
} else {
fhem("set $Device off");
}
}
fhem.conf (EingangsLampe ist das zu schaltende Element in diesem Fall)
define EingangsLampeTimer dummy
attr EingangsLampeTimer alias EingangsLampe Timer
attr EingangsLampeTimer group Beleuchtung
attr EingangsLampeTimer room Wohnzimmer
attr EingangsLampeTimer webCmd timer
define NEingangsLampeTimer notify EingangsLampeTimer:timer { Timerfunktion("EingangsLampe", "EingangsLampeTimer") }
...und damit der Timer beim Ausschalten wieder gelöscht wird noch folgendes:
99_myUtils.pm
sub deleteDeviceTimers ($) {
my ($device) = @_;
fhem("delete $device.timer");
}
sub notifyOnOff ($$) {
my ($device, $event) = @_;
if ($event eq "off") {
deleteDeviceTimers($device);
}
}
fhem.conf
define Neingangslampe_onoff notify EingangsLampe:* {notifyOnOff($NAME,$EVENT)}
Bugs (wer hat Lösungen? :))
- FIXED: Wird das Device in der Zwischenzeit aus und wieder eingeschalten, so bleibt der Timer dennoch erhalten
- FIXED: Limitiert auf einen maximalen Timer von 60 Minuten => ist nun auf 180 Minuten Maximum eingestellt
Hallo Dominik,
ich hatte so was ähnliches als Frage vor Kurzem.
Mit einem DOIF so in der Art (nur DEF):
([Test2] eq "on") (set SD3 on) DOELSEIF ([8:00 -20:00] and [+:05] and ([Test2] eq "intervall")) (set SD3 on-for-timer 5) DOELSEIF (([Test2] eq "countdown")) (set SD3 on-for-timer 10)
Nur die Timerverlängerung musst Du dir einfallen lassen.
Gruß Otto
Danke Otto123.
Das DOIF ist in meinem Fall glaub ich nicht passend. Ich möchte nämlich per Timer Button den Sleeptimer setzen, von daher muss ich den per Notify abfragen. on-for-timer dachte ich auch schon, aber der funktioniert mit pilight nicht. Daher werde ich wohl auf at +... als Funktion zurückgreifen.
Meine Idee war gerade folgende
sub Timerfunktion ($)
{
my ($Device) = $_[0];
my ($currentValue) = Value($Device);
$currentValue = $currentValue + 10;
fhem("set $Device $currentValue");
}
Zumindest um mal irgendwo die aktuell gesetzte Zeit zu speichern. Obwohl ich das nicht unbedingt im "state" machen möchte. Und dann plane ich ein Notify auf den state und verwende $EVENT als at +0:$EVENT:00.
Aktuell schlägt der Code oben aber schon fehl. Weil ich den state nicht ausgelesen bekomm...ich dachte der Sleeptimer geht einfacher :)
Zitat von: dominik am 19 Juli 2015, 20:32:31
Ich möchte nämlich per Timer Button den Sleeptimer setzen, von daher muss ich den per Notify abfragen. on-for-timer dachte ich auch schon, aber der funktioniert mit pilight nicht.
Schau Dir mal http://www.fhemwiki.de/wiki/ReadingsProxy#setExtensions_f.C3.BCr_Ger.C3.A4te_implementieren an. Mit einem ReadingsProxy-Device bekommt man "on-for-timer"
Der ReadingProxy wird ja nur verwendet wenn standardmäßig kein on,off state gesetzt wird, oder? In meinem Fall arbeitet pilight bereits mit on,off states. Daher macht es dann keinen Unterschied.
Wo speichert man mit fhem normal Variablen zum Device wenn das nicht in state hinterlegt werden soll? Bei der Verwendung von setreading... und danach ReadingsVal() bekomm ich das Reading in Perl leider auch nicht ausgelesen. Glaub sobald ich eine Variable hab die ich hochzählen kann, sollte der Rest nicht mehr so schwer sein :-[
ZitatGlaub sobald ich eine Variable hab die ich hochzählen kann, sollte der Rest nicht mehr so schwer sein :-[
Hier bitte.
Mach ich seit gut einem Jahr so und funktioniert einwandfrei.
Zitat
my $Wert=ReadingsVal("OG_Zimmer_Licht2","counter",0);
...
$Wert = $Wert+1;
fhem("setreading OG_Zimmer_Licht2 counter $Wert");
Danke Puschel74!!
So...hier nun mein aktueller Code:
sub Timerfunktion ($)
{
my ($Device) = $_[0];
my ($currentValue) = ReadingsVal($Device, "timerValue", 0);
#FIXME hier wird leider immer "timer" als state eingelesen
my ($currentState) = ReadingsVal($Device, "state", "off");
#FIXME sollte nur eingeschalten werden wenn zuvor "off"
fhem("set $Device on");
#Sleeptimer hochzählen. Max=60 Minuten
$currentValue = $currentValue + 10;
if ($currentValue > 60) {
$currentValue = 0;
}
#Aktuellen Sleeptimer schreiben
fhem("setreading $Device timerValue $currentValue");
#Alten Timer löschen
fhem("delete $Device.timer");
#Neuen Timer setzen bzw. ausschalten wenn 0
if ($currentValue > 0) {
fhem("define $Device.timer at +0:$currentValue:00 set $Device off");
} else {
fhem("set $Device off");
}
}
Folgende Konfiguration ist in FHEM nötig:
attr Lampe webCmd on:off:timer
define Nbettlampesleep notify Lampe:timer { Timerfunktion("Lampe") }
Bugs:
- Lampe schaltet noch bei jedem "timer" Klick kurz aus und wieder ein, der "timer" webCmd sollte nicht als state gesetzt werden. Jemand eine Idee wie man das umgehen kann? :)
- Aktuell max. 60 Minuten Sleeptimer
Zitat von: dominik am 19 Juli 2015, 20:44:55
Der ReadingProxy wird ja nur verwendet wenn standardmäßig kein on,off state gesetzt wird, oder? In meinem Fall arbeitet pilight bereits mit on,off states. Daher macht es dann keinen Unterschied.
Nein.
Mit readingsProxy solltest Du eigentlich jedem Original-Device, das von sich aus keine setExtensions (u.a. auch on-for-timer) unterstützt, das beibringen können.
Aber Du hast ja auch so schon eine Lösung. Viele Wege...
Ah, jetzt versteh ich es. Ich dachte on-for-timer ist eine fhem interne Funktion die nur on/off der Devices aufruft. Danke für die Klarstellung.
ZitatSo...hier nun mein aktueller Code:
Der nicht funktioniert - sorry.
Das
fhem("define $Device.timer at +0:$currentValue:00 set $Device off");
von dir wurde von mir abgeändert damit ich was damit anfangen kann.
Das
Zitatfhem("define $NAME.timer at +0:$EVENT:00 set Sender off");
kommt dabei raus und liefert das im Logfile
Zitat2015.07.19 21:43:36 3: define Sendepause.timer at +0:8:00 set Sender off : Wrong timespec 0:8:00: either HH:MM:SS or {perlcode}
Eigenartig das du diese Meldung nicht im Log bekommst wenn du das notify triggerst ???
Sollte ich wirklich so weit daneben liegen :o
Du dürftest statt 10 Minuten 8 verwendet haben. Probier es mal mit 10, vielleicht braucht at die Minuten wirklich 2-stellig.
Ok, ich geh immer von mir aus das die "unmöglichen Sachen" auch funktionieren.
Mit 53 Minuten klappt es aber mit 4 nicht - das ist richtig.
Einfach eine 0 vor die einstelligen und dann erst erstellen hilft dabei ;)
Nicht schön aber ich behelf mir bei sowas damit
if ($Smin < "10") {
$Smin = "0".$Smin;
}
Zitat von: dominik am 19 Juli 2015, 17:36:24
Hallo,
ich bin gerade dabei einen Button für alle Lichter zu machen welcher wie ein Sleeptimer funktionieren soll.
Beispiel:
- BettLampe on|off|timer
on => Lampe wird eingeschaltet
off => Lampe wird ausgeschaltet
timer => Lampe wird eingeschaltet mit einem Timer von 5min. Drückt man nochmals auf "timer" wird der Timer auf 10min erhöht, usw.
Wie lässt sich so etwas am besten abbilden? Ich dachte daran eine Funktion in Utils zu schreiben mit (Pseudocode)
timer_funktion($lampe, $aktuellerwert) {
if ($aktuellerwert = 5min) {
set $lampe off at +0:10:0
}
...
}
und die rufe ich dann im Notify auf. Nur wo kann ich den aktuellen Wert speichern!?
Gruß
dominik
define di_on_for_timer DOIF ([BettLampe:?on])
(set lamp on)
DOELSEIF ([BettLampe:?off])
(set lamp off)
DOELSEIF ([BettLampe:?timer])
(set lamp on)
(set lamp off)
attr di_on_for_timer do resetwait
attr di_on_for_timer wait 0:0:0,300
siehe http://forum.fhem.de/index.php/topic,39070.msg312029.html#msg312029
Gruß
Damian
@Damian
Und nun noch den timer in das Attribut wait übergeben ;)
Aber so wie ich dich kenne geht das mittlerweile auch ::)
Sorry ich benutz kein DOIF daher kenn ich die commandref dazu nicht
@Damian
Hab ich es richtig verstanden, dass der Timer verlängert wird? Also wenn dort 300 steht (5 Minuten) und ich 2x Timer drücke, dann erhalte ich einen Timer von 10 Minuten?
Weil in deinem Post lese ich es eher so, als ob der Timer nochmals mit 0 beginnt und wieder 5 Minuten läuft.
Zitat von: dominik am 19 Juli 2015, 23:17:50
@Damian
Hab ich es richtig verstanden, dass der Timer verlängert wird? Also wenn dort 300 steht (5 Minuten) und ich 2x Timer drücke, dann erhalte ich einen Timer von 10 Minuten?
Weil in deinem Post lese ich es eher so, als ob der Timer nochmals mit 0 beginnt und wieder 5 Minuten läuft.
ja, hier wird ab dem wiederholten Tastendruck um 5 Minuten verlängert. Ein Doppelklick lässt sich mit dem Attribut waitsame realisieren, siehe Commandref zu DOIF.
Gruß
Damian
Sogar noch eins drauf gesetzt und noch besser gemacht 8)
Hab mir mal die commandref dazu durchgelesen, aber so wie ich das verstehe, kann ich damit nicht wirklich verlängern, sondern nur den timer wieder auf 0 setzen.
Ich möchte nämlich, dass wenn ich 1x timer drücke nach 10 Minuten die Lampe aus geht. 2x timer drücken => 20 Minuten, 3x => 30 Minuten, usw.
Ich werde jetzt mal dein neues Modul installieren und es ausprobieren ;)
Zitat von: dominik am 19 Juli 2015, 23:47:12
Hab mir mal die commandref dazu durchgelesen, aber so wie ich das verstehe, kann ich damit nicht wirklich verlängern, sondern nur den timer wieder auf 0 setzen.
Ich möchte nämlich, dass wenn ich 1x timer drücke nach 10 Minuten die Lampe aus geht. 2x timer drücken => 20 Minuten, 3x => 30 Minuten, usw.
Ich werde jetzt mal dein neues Modul installieren und es ausprobieren ;)
Bei x-mal drücken musst du auch jeweils Zeitspannen programmieren, wann weiter gezählt wird und wann nicht. Dann sollte dein System auch performant genug sein und sich keine Zeitpausen gönnen, sonst kommst du beim Zählen durcheinander.
Gruß
Damian
Ich habe jetzt mal meinen Code belassen, denn damit funktioniert es ja :)
Mich stört nur, dass wenn ich "timer" drücke, die Lampe gleich "timer" als state übernimmt und sich damit kurz ausschaltet. Kann man ein webCmd an einem Device auch absetzen ohne dass sich das webCmd gleich als state hinterlegt?
Hab mal testweise einen dummy Schalter gebaut und dort die "timer" Funktionalität integriert. Da funktioniert es dann prima, da die Lampe nicht auf "timer" gesetzt wird sondern immer schön auf on oder off bleibt.
Wie handhabt ihr das generell im Webinterface? Erstellt ihr dummy Schalter im WebIf oder schaltet ihr direkt an den Devices? Was ist da die Empfehlung? Nachdem ich keine Hardware Schalter habe, steuer ich zur Zeit alles über das WebIf bzw. lasse die Devices zeitgesteuert agieren.
Hab meine Lösung auf der ersten Seite angepasst. Nun läuft der Sleeptimer einwandfrei und lässt sich auch sehr leicht auf weitere Geräte erweitern.
Btw, nutzt ihr eigentlich viel Perl Code oder eher mehr fhem.conf Befehle? Mache gerade die Erfahrung, dass ich viel besser zurecht komme, wenn ich die Befehle wie notify gleich auf Perl Code umleite und dort dann mit entsprechenden Funktionen arbeiten. Hat auch den Charm, dass ich dort die Funktionen wiederverwenden kann. Ist das auch Best Practice?