Random Time Problem mit at

Begonnen von marc2, 28 Januar 2014, 23:39:25

Vorheriges Thema - Nächstes Thema

marc2

Moin !

Ich streue viele meiner Jobs über eine kleine randtime Funktion:

sub randtime($$) {
  my ($ts,$offset) = @_;
  my ($h,$m,$s)    = split(/:/,$ts);
  my $ts_fix       = 3600*$h+60*$m+$s;
  my $offset_rand  = int(rand($offset * 60));
  my $ts_rand      = $ts_fix + $offset_rand;
  return sprintf("%02d:%02d:%02d", $ts_rand/3600, ($ts_rand/60)%60, $ts_rand%60);
}


Generell funktioniert das gut. Einen Sonderfall bekomme ich jedoch leider nicht abgefangen.  Läuft ein Job z.B. *23:10:00, so kann es sein,
dass er aufgrund der Streuung für *23:20:00 neu eingestellt wird. Eigentlich soll dies nur für den nächsten Tage gelten, läuft aber natürlich
noch am selben Tag direkt an. D.h. unter Umständen wird ein Job an einem Tag mehrfach ausgeführt.

Erst hatte ich gedacht, die Funktion so zu erweitern, dass sie diesen Zustand erkennt und für den Job "skip_next" setzt. Dumm ist nur, dass
die Ausführung von randtime  erst durch "at_define" erfolgt und der ursprüngliche Job zu dieser Zeit halt gerade gar nicht existiert.  Hat
jemand eine Idee, wie ich das mit "at" einfangen bekomme - relative Timer der Art +24:10:00 werden ja wohl nicht unterstützt oder ?

Danke & Gruß, Marc

marc2

Hi !

Da bei den relativen Angaben doch Werte > 24 Stunden angegeben werden können (z.B: 25:30:10), habe ich
auf relative Berechnung umgestellt:

sub randtime24plus($$) {
  my ($ts,$offset) = @_;
  my ($h,$m,$s)    = split(/:/,$ts);
  my @now          = localtime(time);
  my $ts_fix       = timelocal($s,$m,$h,$now[3],$now[4],$now[5]);
  my $offset_rand  = int(rand($offset * 60));
  my $delta        = $ts_fix + $offset_rand + 86400 - time;
  return sprintf("%02d:%02d:%02d", $delta/3600, ($delta/60)%60, $delta%60);
}


Und die Timer werden jetzt z.B. so eingestellt:

at +*{randtime24plus("05:45:00","20")}

Damit habe ich jetzt die Streuung, jeweils ausgehend von einem festen Zeitpunkt, aber ohne den vorherigen
Effekt einer potentiell mehrfachen Ausführung  :)

Gruß, Marc

marc2

Kleines Update ....

sub randtime24plus($$) {
  my ($ts,$offset) = @_;
  my ($h,$m,$s)    = split(/:/,$ts);
  my @now          = localtime(time);
  my $ts_fix       = timelocal($s,$m,$h,$now[3],$now[4],$now[5]);
  my $offset_rand  = int(rand($offset * 60));
  my $delta;

  if (time < $ts_fix)  { # nächster Zeitpunkt ist heute
           $delta = $ts_fix - time + $offset_rand;
  } else {               # nächster Zeitpunkt ist morgen
           $delta = $ts_fix - time + $offset_rand + 86400;
  }

  return sprintf("%02d:%02d:%02d", $delta/3600, ($delta/60)%60, $delta%60);
}


fischle

Hallo,
wenn ich deinen Code probiere,
bekomme ich folgende Fehlermeldung:

"Undefined subroutine &main::timelocal called at (eval 12985) line 1."

Irgend eine Idee?

Gruß

Fabian
RPi,
- USB RS485 Adapter für Stromzähler DRS155M und SDM630M-DC (B+G E-Tech)
- Viesmann KO2B Heizung mit selbstbau Optolink Adapter
- Mi-Light WiFi-Bridge V4, WW/CW LED-Birne

fischle

Gelöst, bei mir fehlte noch das

use Time::Local 'timelocal';

Sieht nun so aus:

sub randtime24plus($$) {
  use Time::Local 'timelocal';
  my ($ts,$offset) = @_;
  my ($h,$m,$s)    = split(/:/,$ts);
  my @now          = localtime(time);
  my $ts_fix       = timelocal($s,$m,$h,$now[3],$now[4],$now[5]);
  my $offset_rand  = int(rand($offset * 60));
  my $delta;

  if (time < $ts_fix)  { # nächster Zeitpunkt ist heute
           $delta = $ts_fix - time + $offset_rand;
  } else {               # nächster Zeitpunkt ist morgen
           $delta = $ts_fix - time + $offset_rand + 86400;
  }

  return sprintf("%02d:%02d:%02d", $delta/3600, ($delta/60)%60, $delta%60);
}
RPi,
- USB RS485 Adapter für Stromzähler DRS155M und SDM630M-DC (B+G E-Tech)
- Viesmann KO2B Heizung mit selbstbau Optolink Adapter
- Mi-Light WiFi-Bridge V4, WW/CW LED-Birne

Toto1973

#5
Das liest sich ja sehr interessant!
Damit würde ich gerne meine Rolläden steuern, so dass sie in einem Zeitfenster von 30 Minuten geöffnet und Abends wenn es Dunkel wird innerhalb von 15 Minuten, schließen.
Wenn ich das richtig sehe, ist der erste Zeitwert der Zeitpunkt, wann der Random Timer startet und der 2. Wert die Länge, also 20 Minuten. Ist das so?
Und wenn ja, geht dann auch Sunset als Zeitpunkt?
Oder könnte man den Timer auch so umbauen, das er über ein Dummy starten würde (also als Startzeit die aktuelle Zeit setzten wenn das Dummy umschaltet)?
Dann könnte man den z.b. über einen Helligkeitssensor starten...
Raspberry PI2, Rademacher DuoFern Stick, CUL, 2 x SCC,  JeeLink 868 Mhz, JeeLink 433 Mhz, 3x Magic UFO LED WiFi Controller, 4x MAX BC-RT-TRX-CyG, 2x MAX Fensterkontakt, 5x Rademacher Gurtwickler, 6x TX29DTH-it, 2x TX25-it als Helligkeitssensor, 1X HM-ES-PM, 6x Sonoff, 7x G-Homa, PIR-1000