Hallo Gemeinde,
ich war lange auf der Suche nach einem Modul, das mir eine Zufallszeit erzeugt.
Als Beispiel: Ich schalte eine Lampe mit der Dämmerung ein und sie soll zufällig zwischen 23:50 und 0:20 ausgehen. Mit dem rt Kommando habe ich es nicht realisiert bekommen.
Nun habe ich mir für meine 99_MyUtils.pm ein Kommando geschrieben:
sub
randomtime($)
{
my ($MeH,$MeM,$MeB) = split(",", shift);
my $ZtA = int($MeH*3600 + $MeM*60 + rand($MeB*60));
my $ZtH = int($ZtA/3600);
my $ZtM = int(($ZtA-$ZtH*3600)/60);
my $ZtS = int($ZtA-($ZtH*3600+$ZtM*60));
return sprintf("%2.2d:%2.2d:%2.2d",$ZtH,$ZtM,$ZtS);
}
Ich übergebe die Startzeit zb. 23:50Uhr und das Zeitfenster in Minuten, hier 30, an randomtime. Nun kann ich mit
define AmAbend at * {sunset("REAL",0,"16:00","23:00")} setLampe on-till {randomtime("23,50,30")}
meine Lampe zur Dämmerung einschalten und sie schaltet sich zwischen 23:50 und 0:20, 30 Minuten Fenster, wieder aus.
Oder mit
define AmMorgen at *03:10:00 {my $SonnenAG = sunrise("REAL");
my $Zeit = randomtime("5,30,45");
if ((!isday("REAL")) && (!$we)) {fhem("set SD_Teddy intervals $Zeit-$SonnenAG")}}
meine Lampe zwischen 5:30 und 6:15 einschalten , 45 Minuten Fenster, und zum Sonnenaufgang wieder ausschalten.
Vielleicht kann jemand dieses Modul ja gebrauchen.
Grüße
depe1999
das randomtimer modul hat nicht getan was du wolltest?
gruß
andre
Hallo Andre.
Zitatdas randomtimer modul hat nicht getan was du wolltest?
Mich stört an dem randomtimer das er beim Start schon schaltet und erst danach den Zufall schalten läßt. Wenn man mehrere Schaltvorgänge in einem Zeitraum haben will, ist es ok. Aber ich brauche ja nur einen Schaltvorgang, bzw. eine zufällige Zeit.
Kann natürlich auch sein, dass ich die Vorgehensweise des randomtimer total missverstanden habe. ;D
Gruß
Detlef
wenn du das onCmd und offCmd passend setzt kannst du z.b. onCmd nichts tun lassen und offCmd ein schalten lassen. dann wird unterm strich genau ein mal zu einer zufälligen zeit ein geschaltet.
gruss
andre
Depe, danke dir, ein nützlicher Codeschnipsel und schön dokumentiert - bei mir ab sofort im Produktiveinsatz und irgendwie einfacher/flexibler/geradliniger als mit dem randomTimer! Klasse!
Hallo,
ist es auch möglich zufällig/variabel bei Sonnenuntergang zu schalten (z.B. innerhalb 30 min vor bis 30min nach Sonnenuntergang)?
Wenn ja, könntest du auch schreiben wie.
Vielen Dank
Mario
hallo,
dann like ich das mal!
mit der bestehenden funktion bin ich schon mit der anleitung nicht zurecht gekommen. vielleicht weil ich keinen sinn erkannt habe innerhalb einer gewissen zeit mehrfach zu schalten. die erläuterung on-/offcmd hier macht es jetzt sicherlich deutlicher, aber die hier vorgestellte funktion/definition konnte ich auf anhieb verstehen und verwenden. vielen dank dafür!
harry
Wenn ich das richtig verstehe, müsste man die Sunset Zeit auch zerlegen um sie dann an randomtime übergeben zu können. Das müsste als in der Sub-Routine passieren.
Ich wäre an der Funktion Sunset + - Zeit als Zufallszeit auch interessiert.
Aber leider kenne ich mit da mit dem Pearl zu wenig aus, um so was zu bauen.
Ich hab mir jetzt doch mal das Modul RandomTimer angesehen und werde jetzt mal das Verhalten testen. Es ist nämlich Möglich, eine Zeitspanne zu erzeugen *{sunset(-1300)} <DEVICE> {sunset(-400)} 900.
Das würde bedeuten, das wenn es dunkel wird, minus 22 Minuten bis wenn es dunkel wird, minus 7 Minuten. Das ergibt eine Zeitspanne von 15 Minuten, in der der Timer aktiv wäre. Ich hoffe nun, das ich mit der Zeitangabe von 900 (15 Minuten) den Effekt erzielen kann, das er genau einmal ein schaltet und dann innerhalb der Zeitspanne einmal aus geht. Und wenn er aus geht, dann soll er den Befehl pct 100 an meinen Rollladen senden.
Über onCmd habe ich als Befehl pct 0 eingetragen (der Rollladen bleibt oben) und bei offCmd als Befehl pct 100 (Rollladen fährt nach unten).
Mit der Variable switchmode müsste man das Schaltverhalten noch etwas beeinflussen können, so das wirklich nur einmal aus geschaltet wird!
Ich bin gespannt, ob es klappt!
Hallo depe1999!
Ich hab Dein Modul nun mal in ein DOIF Befehl reingepackt, um meine Rollläden abhängig von Schicht und Wochenende morgens öffnen zu lassen.
Es klappt 1A!
Danke dafür...
define rolladen_auf DOIF ([?Schicht_dummy:state] eq "Frueh" and [{randomtime("08,00,30")}|8]) (set sz_Fenster pct 0) DOELSEIF ([?Schicht_dummy:state] eq "Mittel" and [{randomtime("07,45,30")}|8]) (set sz_Fenster pct 0) DOELSEIF ([{randomtime("09,00,30")}|7]) (set sz_Fenster pct 0)
Hi depe1999,
ich habe deine Funktion noch etwas erweitert, weil ich das für eine Funktion benötigte:
sub randomtime_with_realtime($;$;$)
{
my $ZtA;
my ($MeH,$MeM,$MeS)=split(':',shift(@_));
my $MeB=shift(@_);
my $MeD=shift(@_);
if ($MeD eq '+') {$ZtA = int($MeH*3600 + $MeM*60 + rand($MeB*60) + $MeS);} # Minuten addieren
else {$ZtA = int($MeH*3600 + $MeM*60 - rand($MeB*60) + $MeS);} # Minuten subtrahiern
my $ZtH = int($ZtA/3600);
my $ZtM = int(($ZtA-$ZtH*3600)/60);
my $ZtS = int($ZtA-($ZtH*3600+$ZtM*60));
return sprintf("%2.2d:%2.2d:%2.2d",$ZtH,$ZtM,$ZtS);
}
Man kann dann z.B. folgendes übergeben:
randomtime_with_realtime("22:15:23","15","-")
Nur aus Neugier.
Hätte man die Minuten nicht einfach negativ übergeben können?
:o
Super Idee - da hätte ich Hirni auch selber drauf kommen können. Manchmal sieht man den Wald vor lauter Bäumen nicht...
Aber ehrlich gesagt weiß ich nicht (und kann es grade nicht testen), ob "rand(x)" auch mit negativen Zahlen läuft. Egal - ich wollte eh die Funktion so abändern, dass ich direkt einen Uhrzeit im Format hh:mm:ss übergeben kann aus einem Reading. Jetzt ist es bei mir so drin und ich lass es so - müsste sonst wieder einige Aufrufe ändern.
Danke an depe1999 und Cluni. Bei mir läuft Cluni's Version, leicht abgeändert, so dass die Minuten standardmäßig addiert werden.
Hi,
ich habe das Problem, wenn die zeit nach 00:00 Uhr berechnet wird, das sich die Lampe nicht einschaltet.
Weil dann wahrscheinlich eigentlich ein on-till-overnight kommen müsste, wie habt ihr das Problem gelöst?
danke
Zitat von: Jack-Luck am 13 September 2018, 11:58:44
Hi,
ich habe das Problem, wenn die zeit nach 00:00 Uhr berechnet wird, das sich die Lampe nicht einschaltet.
Weil dann wahrscheinlich eigentlich ein on-till-overnight kommen müsste, wie habt ihr das Problem gelöst?
danke
Bei DOIF sollte es kein Problem sein, da ist die Funktion überflüssig. Die Funktionalität lässt sich mit Boardmitteln erledigen:
das untere Beispiel z. B.
define rolladen_auf DOIF ([?Schicht_dummy:state] eq "Frueh" and [{randomtime("08,00,30")}|8]) ....
lässt sich genauso gut mit:
define rolladen_auf DOIF ([?Schicht_dummy:state] eq "Frueh" and [([08:00]+rand(1800))|8]) ....
definieren.
Auch
define rolladen_auf DOIF ([?Schicht_dummy:state] eq "Frueh" and [([00:00]+rand(1800))|8]) ....
sollte kein Thema sein.
Ich habe das mit einem "at" befehl:
define at_licht at *{sunset("REAL",0,"16:00","24:00")} set FS_Wohnzimmer on-till {randomtime("23,45,60")}
aber wie gesagt, wenn die Zeit nach 0 Uhr ist geht die Lampe nicht mal an.
Hallo,
man kann die Funktion unter Verwendung von modulo (%) auch kürzer schreiben
sub
randomtime($)
{
my ($MeH,$MeM,$MeB) = split(",", shift);
my $T = (int($MeH*3600 + $MeM*60 + rand($MeB*60+1)))%86400;
# rand erzeugt eine floating point Zahl, int rundet nach unten
return sprintf("%2.2d:%2.2d:%2.2d",$T/3600,($T/60)%60,$T%60);
}
und löst zugleich auch das Problem, dass die erzeugte Uhrzeit nicht größer als 23:59 wird.
Will man für den Zufallsbereich $MeB auch negative Werte in Minuten zulassen, kann man die elegante Sign-Funktion
SGN = $MeB <=> 0
verwenden, die 1 oder 0 oder -1 liefert, je nachdem ob $MeB gößer/gleich/kleiner als 0 ist
sub
randomtime2($)
{
my ($MeH,$MeM,$MeB) = split(",", shift);
my $SGN = ($MeB<=>0);
my $T = (int($MeH*3600 + $MeM*60 + ($MeB*60+$SGN)*rand()))%86400;
# - rand erzeugt eine floating point Zahl, ist aber bei negativen Zahlen nicht eindeutig definiert,
# deshalb verwenden wir lieber -x*rand()
# - int rundet in Richtung 0
# - modulo sorgt auch bei neg. Zahlen dafür, dass das Ergebnis [0..86400] ist
return sprintf("%2.2d:%2.2d:%2.2d",$T/3600,($T/60)%60,$T%60);
}
Ja, das verkürzt das Ganze!
Habe meine Version von randomtime_with_realtime danach umgebaut:
sub randomtime_with_realtime($;$)
{
my ($MeH,$MeM,$MeS)=split(':',shift(@_));
my $MeB=shift(@_);
my $SGN = ($MeB<=>0);
my $T = (int($MeH*3600 + $MeM*60 + $MeS + ($MeB*60+$SGN)*rand()))%86400;
# - rand erzeugt eine floating point Zahl, ist aber bei negativen Zahlen nicht eindeutig definiert,
# deshalb verwenden wir lieber -x*rand()
# - int rundet in Richtung 0
# - modulo sorgt auch bei neg. Zahlen dafür, dass das Ergebnis [0..86400] ist
return sprintf("%2.2d:%2.2d:%2.2d",$T/3600,($T/60)%60,$T%60);
}
1;
:)