Neues Modul 98_alarmclock ein Fhem Wecker

Begonnen von FlorianZ, 18 Dezember 2016, 19:03:23

Vorheriges Thema - Nächstes Thema

martins

ich hätte da einen Wunsch, kann man einen set Befehl äquivalent zum EventForAlarmOff Attribut einbauen?
set <name> StopAlarm
Dieser sollte dann den gleichen Effekt haben als wenn das Modul durch ein EventForAlarmOff getriggert wird.

Wäre dies möglich?

Gruß
Martin

FlorianZ

Hallo Martin

Ich habe set <name> stop Alarm in das Modul integriert.
Ab morgen im update oder jetzt im svn.

Gruß
Florian

Prof. Dr. Peter Henning

Der Codeblock zum Lesen des HolidayDevice ist ein wenig umständloich. Außerdem sollte es egal sein, ob es sich um ein "Holiday-Device" mit dem vom Modulautor selbst erfundenen Datenformat handelt, oder um ein Calendar Device.

Anbei - zum Anpassen nach Wunsch - ein Codeblock aus einem in Arbeit befindlichen Modul:

#########################################################################################
#
# YAAHM_GetDayStatus
#
# Parameter hash = hash of device addressed
#
#########################################################################################

sub YAAHM_GetDayStatus($) {
  my ($hash) = @_;
   
  my $name = $hash->{NAME};
  my $lang = ($attr{global}{language} ? $attr{global}{language} : "EN");
 
  my ($ret,$line,$fline,$date);
  my (@lines,@chunks,@tday,@eday,@sday,@tmor);
  my ($stoday,$todaydesc,$todaytype,$stom,$tomdesc,$tomtype);
 
  #-- workday has lowest priority
  $todaytype = "workday";
  $hash->{DATA}{"DD"}[0]{"isWeekend"} = 0;

  $tomtype = "workday";
  $hash->{DATA}{"DD"}[1]{"isWeekend"} = 0;

  #-- vacation = vacdays has higher priority
  my $vacdayDevs = AttrVal( $name, "vacationDevices", "" );
  foreach my $vacdayDev ( split( /,/, $vacdayDevs ) ) {
    #-- device of type holiday
    if( IsDevice( $vacdayDev, "holiday" )){     
      $stoday = strftime('%2m-%2d', localtime(time));
      $stom   = strftime('%2m-%2d', localtime(time+86400));
      my $tod = holiday_refresh( $vacdayDev, $stoday );
      if ( $tod ne "none" ) {
        $todaydesc = $tod;
        $todaytype = "vacday";
        Log3 $name, 1,"[YAAHM] found today=vacation \"$todaydesc\" in holiday $vacdayDev";
      }
      $tod = holiday_refresh( $vacdayDev, $stom );
      if ( $tod ne "none" ) {
        $tomdesc = $tod;
        $tomtype = "vacday";
        Log3 $name, 1,"[YAAHM] found tomorrow=vacation \"$tomdesc\" in holiday $vacdayDev";
      }
    #-- device of type calendar
    }elsif( IsDevice($vacdayDev, "Calendar" )){
      $stoday  = strftime('%2d.%2m.%2y', localtime(time));
      $stom    = strftime('%2d.%2m.%2y', localtime(time+86400));
      @tday  = split('\.',$stoday);
      @tmor  = split('\.',$stom);
      #-- more complicated to check here
      $fline=Calendar_Get($defs{$vacdayDev},"get","full","mode=alarm|start|upcoming");
      if($line){
        #chomp($fline);
        @lines = split('\n',$fline);
        foreach $fline (@lines){
          chomp($fline);
          @chunks = split(' ',$fline);
          @sday   = split('\.',$chunks[2]);
          @eday   = split('\.',substr($chunks[3],9,10));
          #-- today
          my $rets  = ($sday[2]-$tday[2]-2000)*365+($sday[1]-$tday[1])*31+($sday[0]-$tday[0]);
          my $rete  = ($eday[2]-$tday[2]-2000)*365+($eday[1]-$tday[1])*31+($eday[0]-$tday[0]);
          if( ($rete>=0) && ($rets<=0) ){
            $todaydesc = $chunks[5];
            $todaytype = "vacation";
            Log3 $name, 1,"[YAAHM] found today=vacation \"$todaydesc\" in calendar $vacdayDev";
          }   
          $rets  = ($sday[2]-$tmor[2]-2000)*365+($sday[1]-$tmor[1])*31+($sday[0]-$tmor[0]);
          $rete  = ($eday[2]-$tmor[2]-2000)*365+($eday[1]-$tmor[1])*31+($eday[0]-$tmor[0]);
          if( ($rete>=0) && ($rets<=0) ){
            $tomdesc = $chunks[5];
            $tomtype = "vacation";
            Log3 $name, 1,"[YAAHM] found tomorrow=vacation \"$tomdesc\" in calendar $vacdayDev";
          }
        }
      } 
    }
  }
  #-- put into readings
  if( $todaytype eq "vacation" ){
    $hash->{DATA}{"DD"}[0]{"isVacation"} = 1;
    $hash->{DATA}{"DD"}[0]{"vDesc"} = $todaydesc;
  }else{
    $hash->{DATA}{"DD"}[0]{"isVacation"} = 0;
    $hash->{DATA}{"DD"}[0]{"vDesc"} = "";
  }
  if( $tomtype eq "vacation" ){
    $hash->{DATA}{"DD"}[1]{"isVacation"} = 1;
    $hash->{DATA}{"DD"}[1]{"vDesc"} = $tomdesc;
  }else{
    $hash->{DATA}{"DD"}[1]{"isVacation"} = 0;
    $hash->{DATA}{"DD"}[1]{"vDesc"} = "";
  }
 
  #-- weekend has higher priority
   if( strftime('%u', localtime(time)) > 5){
    $todaytype = "weekend";
    $hash->{DATA}{"DD"}[0]{"isWeekend"} = 1;
  }
 
  if( strftime('%u', localtime(time+86400)) > 5){
    $tomtype = "weekend";
    $hash->{DATA}{"DD"}[1]{"isWeekend"} = 1;
  }
   
  #-- holidays have the highest priority
  my $holidayDevs = AttrVal( $name, "holidayDevices", "" );
  foreach my $holidayDev ( split( /,/, $holidayDevs ) ) {
 
    #-- device of type holiday
    if( IsDevice( $holidayDev, "holiday" )){     
      $stoday = strftime('%2m-%2d', localtime(time));
      $stom   = strftime('%2m-%2d', localtime(time+86400));
      my $tod = holiday_refresh( $holidayDev, $stoday );
      if ( $tod ne "none" ) {
        $todaydesc = $tod;
        $todaytype = "holiday";
        Log3 $name, 1,"[YAAHM] found today=holiday \"$todaydesc\" in holiday $holidayDev";
      }
      $tod = holiday_refresh( $holidayDev, $stom );
      if ( $tod ne "none" ) {
        $tomdesc = $tod;
        $tomtype = "holiday";
        Log3 $name, 1,"[YAAHM] found tomorrow=holiday \"$tomdesc\" in holiday $holidayDev";
      }
       
    #-- device of type calendar
    }elsif( IsDevice($holidayDev, "Calendar" )){
      $stoday  = strftime('%2d.%2m.%2y', localtime(time));
      $stom    = strftime('%2d.%2m.%2y', localtime(time+86400));
      $line=Calendar_Get($defs{$holidayDev},"get","text","mode=alarm|start|upcoming");
      if($line){
        chomp($line);
        @lines = split('\n',$line);
        foreach $line (@lines){
          chomp($line);
          $date  = substr($line,0,8);
          if( $date eq $stoday ){
            $todaydesc = substr($line,15);
            $todaytype = "holiday";
            Log3 $name, 1,"[YAAHM] found today=holiday \"$todaydesc\" in calendar $holidayDev";
          }
          if( $date eq $stom ){
            $tomdesc = substr($line,15);
            $tomtype = "holiday";
            Log3 $name, 1,"[YAAHM] found tomorrow=holiday \"$tomdesc\" in calendar $holidayDev";
          }
        }
      }
    }     
  }
  #-- put into readings
  if( $todaytype eq "holiday" ){
    $hash->{DATA}{"DD"}[0]{"isHoliday"} = 1;
    $hash->{DATA}{"DD"}[0]{"hDesc"} = $todaydesc;
  }else{
    $hash->{DATA}{"DD"}[0]{"isHoliday"} = 0;
    $hash->{DATA}{"DD"}[0]{"hDesc"} = "";
  }
  if( $tomtype eq "holiday" ){
    $hash->{DATA}{"DD"}[1]{"isHoliday"} = 1;
    $hash->{DATA}{"DD"}[1]{"hDesc"} = $tomdesc;
  }else{
    $hash->{DATA}{"DD"}[1]{"isHoliday"} = 0;
    $hash->{DATA}{"DD"}[1]{"hDesc"} = "";
  }
   
  #--
  readingsBeginUpdate($hash);
  readingsBulkUpdateIfChanged( $hash, "todayType",$todaytype );
  if( $todaytype eq "workday"){
    readingsBulkUpdateIfChanged( $hash, "todayDesc","--" )
  }elsif( $todaytype eq "vacation"){
    readingsBulkUpdateIfChanged( $hash, "todayDesc",$hash->{DATA}{"DD"}[0]{"vDesc"} )
  }elsif( $todaytype eq "weekend"){
    readingsBulkUpdateIfChanged( $hash, "todayDesc","--" )
  }else{
    readingsBulkUpdateIfChanged( $hash, "todayDesc",$hash->{DATA}{"DD"}[0]{"hDesc"} )
  }
  readingsBulkUpdateIfChanged( $hash, "tomorrowType",$tomtype );
  if( $tomtype eq "workday"){
    readingsBulkUpdateIfChanged( $hash, "tomorrowDesc","--" )
  }elsif( $tomtype eq "vacation"){
    readingsBulkUpdateIfChanged( $hash, "tomorrowDesc",$hash->{DATA}{"DD"}[1]{"vDesc"} )
  }elsif( $tomtype eq "weekend"){
    readingsBulkUpdateIfChanged( $hash, "tomorrowDesc","--" )
  }else{
    readingsBulkUpdateIfChanged( $hash, "tomorrowDesc",$hash->{DATA}{"DD"}[1]{"hDesc"} )
  }
  readingsEndUpdate($hash,1);
  return undef;

}


Bei Übernahme von Teilen dieses Codeblocks: Bitte gemäß GPL meinen Namen dazuschreiben.

LG

pah

FlorianZ

Hallo pah,

vielen Dank für deinen Codeblock.
Da habe ich ja am Wochenende gut was zu studieren.  ;)

Gruß
Florian

martins

Hallo Florian,

Danke für das schnelle integrieren.

Gruß
Martin


FlorianZ

Hallo,

ich konnte HolidayDevice und VacationDevice um die automatische Erkennung des Typ holiday und Typ Calendar bzw.
Auswertung von Calendar dank des Codes von Prof. Dr. Peter Henning erweitern.

Um einen Kalender des Typ Calendar oder Typ holiday als HolidayDevice bzw VacationDevice zu nutzen:

attr <name> HolidayDevice <devicename>
attr <name> VacationDevice <devicename>

Alle anderen Möglichkeiten wie beispielsweise ein Dummy als HolidayDevice bleiben auch weiterhin bestehen.

attr <name> HolidayDevice <devicename>:<value>
attr <name> HolidayDevice <devicename>:<readingname>: <value>
attr <name> VacationDevice <devicename>:<value>
attr <name> VacationDevice <devicename>:<readingname>: <value>

Mehrfachnennung getrennt mit Pipe |

Ein Calendar als HolidayDevice wertet nur Einträge im Kalender aus,
die einen Tag dauern und sollte für Feiertage genutzt werden.
Ein Calendar als VacationDevice wertet auch Einträge über mehrere Tage
aus, und ist so für Urlaub/Ferien geeignet.

Das HolidayDevice wird gegenüber des VacationDevice priorisiert.

@pah
Ist die Angabe deines Namen in 98_alarmclock so in deinem Sinne?
Wie checkst du in deinem Modul, ob nach einen Neustart von Fhem das
Modul Calendar fertig geladen hat?
Ich habe es unter anderem mit:

$hash->{NotifyOrderPrefix} = "51-";

versucht. Ist aber nicht ausreichend.
Problem aktuell ist, dass die sub alarmclock_createtimer durchläuft bevor
das Calendar Modul fertig geladen hat. Mit dem Modul holiday gibt es da keine Probleme.

Gruß
Florian

FlorianZ

Ich entwickle gerade ein neues Feature für alarmclock.
Um optional für jeden Tag bzw. Typ des Tages eine unterschiedliche AlarmRoutine/PreAlarmRoutine/RepRoutine/AlarmRoutineOff wie von
pah vorgeschlagen zu ermöglichen, würde ich eine Art Variable für die Routinen einführen.
Die AlarmRoutine könnte folgendermaßen aussehen:

%AlarmTime:1|2|3|4|5%
set licht1 on;
%AlarmTime:6|7%
set licht1 on;
set licht2 on;
%AlarmTime:8%
set licht3 on;
%AlarmTime:9%
set licht4 on;


Wie sind eure Meinungen oder Anregungen hierzu?

Gruß
Florian

pwlr

Hallo Florian,

ich habe seit einiger Zeit Dein Modul im Test und bin begeistert  :) Danke für Deine Arbeit !
Allerdings musste ich feststellen, dass mein Tagesablauf wesentlich unstrukturierter abläuft als die Regeln und Definitionen im Modul...  Ich möchte also einen neuen set-Befehl anregen, etwas wie :

set <name> NextAlarm hh:mm

Also einfach nur die nächste Weckzeit, die in der Prio vor allen Listen steht und nur einmalig ausgeführt wird.
Es wäre auch praktisch, wenn man im attr für EventForAlarmOff und EventForSnooze mehrere Devices definieren kann, die jeweils per ODER miteinander verknüpft sind. Dann könnte der Wecker praktischerweise von jeder Bettseite bedient werden. Erhöht den WAF, auch von wegen "Gleichberechtigung"  :)

Vielleicht geht das ja ?
Vielen Dank nochmals
Bernd



FlorianZ

Hallo Bernd,

vielen Dank für dein Feedback.

Die Mehrfachangabe für EventForAlarmOff und EventForSnooze kann ich kurzfristig mit einbauen.
Kommt mit dem nächsten Update.

Die Idee für eine einmalige priorisierte Alarmzeit gefällt mir gut. Dazu muss ich mir aber erstmal Gedanken machen bezüglich Umsetzung.

Gruß
Florian

P.A.Trick

Hi Florian, gibt's eigentlich eine Möglichkeit den nächsten Alarm in einem reading zur Verfügung zu stellen?
LG
Patrick
Cubietruck,RPI,QNAP Ts-419p+, FS20, FRITZ!DECT200, 7 MAX! Thermostate, 3 MAX! Fensterkontakte, Kodi, CUL V3.3, EM1000S, LW12, LD382, HUE, HM-CFG-USB-2, 1x HM-LC-SW1-FM, 2x HM-LC-SW2-FM, 2x HM-LC-Sw1PBU-FM, 3xHM-LC-Bl1PBU-FM,HM-SEC-RHS, 2xHM-SEC-SD,HM-WDS30-T-O, 3x HM-LC-Dim1TPBU-FM, RPI+AddOn

FlorianZ

Hallo Patrick,

nur die Weckzeit des aktuellen Tages. Das Modul prüft kurz nach Mitternacht ob Holiday oder Vacation für den heutigen Tag
zutrifft und setzt anschließend die Weckzeit. Die Weckzeit für morgen oder übermorgen ist dem Modul sozusagen noch unbekannt.
Mit größeren Aufwand (für mich) wäre es möglich, die nächsten Weckzeiten zu überprüfen, solange man keine Dummy oder ähnliches
zur Holiday und Vacation Identifikation einsetzt.Kurzfristig könnte ich nur anbieten, die heutige Weckzeit in ein seperates Reading zu
schreiben.

Gruß
Florian

P.A.Trick

Zitat von: FlorianZ am 08 Juni 2017, 12:46:14
Hallo Patrick,

nur die Weckzeit des aktuellen Tages. Das Modul prüft kurz nach Mitternacht ob Holiday oder Vacation für den heutigen Tag
zutrifft und setzt anschließend die Weckzeit. Die Weckzeit für morgen oder übermorgen ist dem Modul sozusagen noch unbekannt.
Mit größeren Aufwand (für mich) wäre es möglich, die nächsten Weckzeiten zu überprüfen, solange man keine Dummy oder ähnliches
zur Holiday und Vacation Identifikation einsetzt.Kurzfristig könnte ich nur anbieten, die heutige Weckzeit in ein seperates Reading zu
schreiben.

Gruß
Florian

Heutige Weckzeit in einem Reading wäre schon mal klasse! Hintergrund: Ich wollte mir abends ansagen wann der nächste Alarm (also am nächsten Tag) ist. Vielleicht kannst du es ja auf die Wunschliste setzen, würde mich freuen.
Vielen Dank im Voraus für deine Mühe und das tolle Modul!
VG
Patrick
Cubietruck,RPI,QNAP Ts-419p+, FS20, FRITZ!DECT200, 7 MAX! Thermostate, 3 MAX! Fensterkontakte, Kodi, CUL V3.3, EM1000S, LW12, LD382, HUE, HM-CFG-USB-2, 1x HM-LC-SW1-FM, 2x HM-LC-SW2-FM, 2x HM-LC-Sw1PBU-FM, 3xHM-LC-Bl1PBU-FM,HM-SEC-RHS, 2xHM-SEC-SD,HM-WDS30-T-O, 3x HM-LC-Dim1TPBU-FM, RPI+AddOn

pwlr

Hi Patrick,

ich habe das mit einem userReading time gelöst :
time {my$state=(ReadingsVal("Wecker_01","state","none"));
my$time="none";
if ($state =~ "next Alarm at") {$time=(substr $state,14,5)};
return $time;}


Vielleicht hilf es Dir erstmal. Ist aber, wie Florian geschrieben hat, nur die nächste Weckzeit des aktuellen Tages.
Wecker_01 ist der Devicename meines Weckers und müsstest Du gegen Deinen Wert ersetzen.
Bernd

P.A.Trick

Zitat von: pwlr am 08 Juni 2017, 12:52:10
Hi Patrick,

ich habe das mit einem userReading time gelöst :
time {my$state=(ReadingsVal("Wecker_01","state","none"));
my$time="none";
if ($state =~ "next Alarm at") {$time=(substr $state,14,5)};
return $time;}


Vielleicht hilf es Dir erstmal. Ist aber, wie Florian geschrieben hat, nur die nächste Weckzeit des aktuellen Tages.
Wecker_01 ist der Devicename meines Weckers und müsstest Du gegen Deinen Wert ersetzen.
Bernd

Danke Bernd - perfekt!
Cubietruck,RPI,QNAP Ts-419p+, FS20, FRITZ!DECT200, 7 MAX! Thermostate, 3 MAX! Fensterkontakte, Kodi, CUL V3.3, EM1000S, LW12, LD382, HUE, HM-CFG-USB-2, 1x HM-LC-SW1-FM, 2x HM-LC-SW2-FM, 2x HM-LC-Sw1PBU-FM, 3xHM-LC-Bl1PBU-FM,HM-SEC-RHS, 2xHM-SEC-SD,HM-WDS30-T-O, 3x HM-LC-Dim1TPBU-FM, RPI+AddOn

FlorianZ

Habe gerade eine neue Version eingecheckt.

Neu ist:

- Möglichkeit der Mehrfachangabe für EventForAlarmOff und EventForSnooze.
  Trenner ist Pipe |

- Neues Reading: AlarmToday
  Zeigt die heutige Weckzeit. Holiday und Vacation werden ausgewertet.

- Neues Reading: AlarmTomorrow
  Zeigt die morgige Weckzeit. Holiday und Vacation werden ausgewertet, wenn
  HolidayDevice und VacationDevice vom Typ holiday oder Calendar sind.

Gruß
Florian