From a35f2d79df1e102eb357532ecbc25dfb18906f7b Mon Sep 17 00:00:00 2001 From: jpawlowski Date: Wed, 11 Mar 2015 14:16:05 +0000 Subject: [PATCH] RESIDENTStk: Add RESIDENTS toolkit and wakeuptimer function git-svn-id: https://svn.fhem.de/fhem/trunk@8194 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 4 + fhem/FHEM/10_RESIDENTS.pm | 189 +++++++++++++++++++++++-- fhem/FHEM/20_GUEST.pm | 284 ++++++++++++++++++++++++++------------ fhem/FHEM/20_ROOMMATE.pm | 283 +++++++++++++++++++++++++------------ fhem/FHEM/RESIDENTStk.pm | 210 ++++++++++++++++++++++++++++ fhem/HISTORY | 4 + fhem/MAINTAINER.txt | 1 + 7 files changed, 792 insertions(+), 183 deletions(-) mode change 100755 => 100644 fhem/FHEM/10_RESIDENTS.pm mode change 100755 => 100644 fhem/FHEM/20_GUEST.pm mode change 100755 => 100644 fhem/FHEM/20_ROOMMATE.pm create mode 100644 fhem/FHEM/RESIDENTStk.pm diff --git a/fhem/CHANGED b/fhem/CHANGED index 8d374af63..776807598 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,9 @@ # Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Do not insert empty lines here, update check depends on it. + - feature: GUEST: added support for RESIDENTS toolkit + - feature: ROOMMATE: added support for RESIDENTS toolkit + - feature: RESIDENTS: added support for RESIDENTS toolkit + - added: RESIDENTStk: new RESIDENTS toolkit and first function wakeuptimer - bugfix: 37_SHC: go back to last release version v0.9.0 (rr2000) - change: SYSMON: prevent some warnings - bugfix: SYSMON: ethernet readings on bbb (thx to nesges) diff --git a/fhem/FHEM/10_RESIDENTS.pm b/fhem/FHEM/10_RESIDENTS.pm old mode 100755 new mode 100644 index 1d8d25569..f67cdcffb --- a/fhem/FHEM/10_RESIDENTS.pm +++ b/fhem/FHEM/10_RESIDENTS.pm @@ -23,9 +23,12 @@ # along with fhem. If not, see . # # -# Version: 1.1.0 +# Version: 1.2.0 # # Major Version History: +# - 1.2.0 - 2015-03-11 +# -- add RESIDENTStoolkit support +# # - 1.1.0 - 2014-04-07 # -- new readings in computer readable format (*_cr) # -- format of readings durTimer readings changed from minutes to HH:MM:ss @@ -41,6 +44,7 @@ use strict; use warnings; use Time::Local; use Data::Dumper; +require RESIDENTStk; sub RESIDENTS_Set($@); sub RESIDENTS_Define($$); @@ -58,7 +62,8 @@ sub RESIDENTS_Initialize($) { $hash->{NotifyFn} = "RESIDENTS_Notify"; $hash->{UndefFn} = "RESIDENTS_Undefine"; $hash->{AttrList} = - "rgr_showAllStates:0,1 rgr_states " . $readingFnAttributes; + "rgr_showAllStates:0,1 rgr_states rgr_wakeupDevice " + . $readingFnAttributes; } ################################### @@ -73,13 +78,13 @@ sub RESIDENTS_Define($$) { # set default settings on first define if ($init_done) { - $attr{$name}{alias} = "Residents"; - $attr{$name}{devStateIcon} = + $attr{$name}{alias} = "Residents"; + $attr{$name}{devStateIcon} = '.*home:status_available:absent .*absent:status_away_1:home .*gone:status_standby:home .*none:control_building_empty .*gotosleep:status_night:asleep .*asleep:status_night:awoken .*awoken:status_available:home'; - $attr{$name}{group} = "Home State"; - $attr{$name}{icon} = "control_building_filled"; - $attr{$name}{room} = "Residents"; - $attr{$name}{webCmd} = "state"; + $attr{$name}{group} = "Home State"; + $attr{$name}{icon} = "control_building_filled"; + $attr{$name}{room} = "Residents"; + $attr{$name}{webCmd} = "state"; } return undef; @@ -137,6 +142,11 @@ sub RESIDENTS_Notify($$) { if ( defined( $hash->{GUESTS} ) && $hash->{GUESTS} ne "" ); + my @registeredWakeupdevs = + split( /,/, $attr{$hashName}{rgr_wakeupDevice} ) + if ( defined( $attr{$hashName}{rgr_wakeupDevice} ) + && $attr{$hashName}{rgr_wakeupDevice} ne "" ); + # process only registered ROOMMATE or GUEST devices if ( ( @registeredRoommates && $devName ~~ @registeredRoommates ) || ( @registeredGuests && $devName ~~ @registeredGuests ) ) @@ -183,6 +193,27 @@ sub RESIDENTS_Notify($$) { } } } + + # process only registered devices for wakeup function + if ( @registeredWakeupdevs && $devName ~~ @registeredWakeupdevs ) { + + return + if ( !$dev->{CHANGED} ); # Some previous notify deleted the array. + + foreach my $change ( @{ $dev->{CHANGED} } ) { + + # state changed + if ( $change =~ /OFF|([0-9]{2}:[0-9]{2})/ ) { + Log3 $hash, 4, + "RESIDENTS " + . $hashName . ": " + . $devName + . ": notify about change to $change"; + + return RESIDENTStk_wakeupSet( $devName, $change ); + } + } + } } return; @@ -221,6 +252,7 @@ sub RESIDENTS_Set($@) { $usage .= " state:$states"; $usage .= " removeRoommate:" . $roommates if ( $roommates ne "" ); $usage .= " removeGuest:" . $guests if ( $guests ne "" ); + $usage .= " create:wakeuptimer"; # states if ( $a[1] eq "state" @@ -478,6 +510,61 @@ sub RESIDENTS_Set($@) { RESIDENTS_UpdateReadings($hash); } + # create + elsif ( $a[1] eq "create" ) { + if ( defined( $a[2] ) && $a[2] eq "wakeuptimer" ) { + my $i = "1"; + my $wakeuptimerName = $name . "_wakeuptimer" . $i; + my $created = 0; + + until ($created) { + if ( defined( $defs{$wakeuptimerName} ) ) { + $i++; + $wakeuptimerName = $name . "_wakeuptimer" . $i; + } + else { + + # create new dummy device + fhem "define $wakeuptimerName dummy"; + fhem "attr $wakeuptimerName alias Wake-up Timer $i"; + fhem "attr $wakeuptimerName comment Auto-created by RESIDENTS module for use with RESIDENTS Toolkit"; + fhem +"attr $wakeuptimerName devStateIcon OFF:general_aus\@red .*:general_an\@green:OFF"; + fhem "attr $wakeuptimerName group " . $attr{$name}{group} + if ( defined( $attr{$name}{group} ) ); + fhem "attr $wakeuptimerName icon time_clock"; + fhem "attr $wakeuptimerName room " . $attr{$name}{room} + if ( defined( $attr{$name}{room} ) ); + fhem +"attr $wakeuptimerName setList state:OFF,00:00,00:15,00:30,00:45,01:00,01:15,01:30,01:45,02:00,02:15,02:30,02:45,03:00,03:15,03:30,03:45,04:00,04:15,04:30,04:45,05:00,05:15,05:30,05:45,06:00,06:15,06:30,06:45,07:00,07:15,07:30,07:45,08:00,08:15,08:30,08:45,09:00,09:15,09:30,09:45,10:00,10:15,10:30,10:45,11:00,11:15,11:30,11:45,12:00,12:15,12:30,12:45,13:00,13:15,13:30,13:45,14:00,14:15,14:30,14:45,15:00,15:15,15:30,15:45,16:00,16:15,16:30,16:45,17:00,17:15,17:30,17:45,18:00,18:15,18:30,18:45,19:00,19:15,19:30,19:45,20:00,20:15,20:30,20:45,21:00,21:15,21:30,21:45,22:00,22:15,22:30,22:45,23:00,23:15,23:30,23:45"; + fhem "attr $wakeuptimerName userattr wakeupUserdevice"; + fhem "attr $wakeuptimerName wakeupUserdevice $name"; + fhem "attr $wakeuptimerName webCmd state"; + + # register slave device + if ( defined( $attr{$name}{rgr_wakeupDevice} ) ) { + fhem "attr $name rgr_wakeupDevice " + . $attr{$name}{rgr_wakeupDevice} + . ",$wakeuptimerName"; + } + else { + fhem "attr $name rgr_wakeupDevice $wakeuptimerName"; + } + + # trigger first update + fhem "set $wakeuptimerName OFF"; + + $created = 1; + return +"Dummy $wakeuptimerName and other pending devices created and pre-configured. You may edit Macro_$wakeuptimerName to define your wake-up actions."; + } + } + } + else { + return "Invalid 2nd argument, choose one of wakeuptimer "; + } + } + # return usage hint else { return $usage; @@ -841,7 +928,7 @@ sub RESIDENTS_UpdateReadings (@) { } - readingsEndUpdate($hash, 1); + readingsEndUpdate( $hash, 1 ); } ################################### @@ -936,6 +1023,9 @@ sub RESIDENTS_Datetime2Timestamp($) {
  • state   home,gotosleep,asleep,awoken,absent,gone   switch between states for all group members at once; see attribute rgr_states to adjust list shown in FHEMWEB
  • +
  • + create   wakeuptimer   add several pre-configurations provided by RESIDENTS Toolkit. See separate section for details. +


  • @@ -1069,6 +1159,45 @@ sub RESIDENTS_Datetime2Timestamp($) { +
    +
    + RESIDENTS Toolkit
    +
    +
      + Using set-command create you may add pre-configured configurations to your RESIDENTS, ROOMMATE or GUEST devices for your convenience.
      + The following commands are currently available:
      +
      +
    • + wakeuptimer   -   adds a wake-up timer dummy device with enhanced functions to start with wake-up automations +
        + A notify device is created to be used as a Macro to carry out your actual automations. The macro is triggered by a normal at device you may customize as well. However, a special RESIDENTS Toolkit function is handling the wake-up trigger event for you.
        +
        + The wake-up behaviour may be influenced by the following device attributes:
        +
      • + wakeupAutosave - Triggers FHEM command 'save' after adjusting wake-up time value (defaults to 0=false) +
      • +
      • + wakeupDays - only trigger macro at these days. Mon=1,Tue=2,Wed=3,Thu=4,Fri=5,Sat=6,Sun=0 (optional) +
      • +
      • + wakeupDefaultTime - after triggering macro reset the wake-up time to this default value (optional) +
      • +
      • + wakeupMacro - name of the notify macro device (mandatory) +
      • +
      • + wakeupOffset - value in minutes to trigger your macro earlier than the user requested to be woken up, e.g. if you have a complex wake-up program over 30 minutes (defaults to 0) +
      • +
      • + wakeupResetdays - if wakeupDefaultTime is set you may restrict timer reset to specific days only. Mon=1,Tue=2,Wed=3,Thu=4,Fri=5,Sat=6,Sun=0 (optional) +
      • +
      • + wakeupUserdevice - backlink to RESIDENTS, ROOMMATE or GUEST device to check it's status (mandatory) +
      • +
      +
    • +
    +
    =end html @@ -1117,6 +1246,9 @@ sub RESIDENTS_Datetime2Timestamp($) {
  • state   home,gotosleep,asleep,awoken,absent,gone   wechselt den Status für alle Gruppenmitglieder gleichzeitig; siehe Attribut rgr_states, um die angezeigte Liste in FHEMWEB abzuändern
  • +
  • + create   wakeuptimer   fügt diverse Vorkonfigurationen auf Basis von RESIDENTS Toolkit hinzu. Siehe separate Sektion. +


  • @@ -1250,6 +1382,45 @@ sub RESIDENTS_Datetime2Timestamp($) { +
    +
    + RESIDENTS Toolkit
    +
    +
      + Mit dem set-Kommando create können zur Vereinfachung vorkonfigurierte Konfigurationen zu RESIDENTS, ROOMMATE oder GUEST Geräten hinzugefügt werden.
      + The folgenden Kommandos sind momentan verfügbar:
      +
      +
    • + wakeuptimer   -   fügt ein Dummy Gerät mit erweiterten Funktionen als Wecker hinzu, um darauf Weck-Automationen aufzubauen. +
        + Ein notify Gerät wird als Makro erstellt, um die eigentliche Automation auszuführen. Das Makro wird durch ein normales at-Gerät ausgelöst und kann ebenfalls angepasst werden. Die Hauptfunktion wird dabei trotzdem von einer speziellen RESIDENTS Toolkit funktion gehandhabt.
        +
        + Die Weckfunktion kann wie folgt über Attribute beinflusst werden:
        +
      • + wakeupAutosave - Löst das FHEM Kommando 'save' nach einer Änderung der Weckzeit aus (Standard 0=aus) +
      • +
      • + wakeupDays - Makro nur an bestimmten Tagen auslösen. Mon=1,Di=2,Mi=3,Do=4,Fr=5,Sa=6,So=0 (optional) +
      • +
      • + wakeupDefaultTime - Stellt die Weckzeit nach dem auslösen zurück auf diesen Standardwert (optional) +
      • +
      • + wakeupMacro - Name des notify Makro Gerätes (notwendig) +
      • +
      • + wakeupOffset - Wert in Minuten, die das Makro früher ausgelöst werden soll, z.B. bei komplexen Weckprogrammen über einen Zeitraum von 30 Minuten (Standard ist 0) +
      • +
      • + wakeupResetdays - sofern wakeupDefaultTime gesetzt ist, kann der Reset hier auf betimmte Tage begrenzt werden. Mon=1,Di=2,Mi=3,Do=4,Fr=5,Sa=6,So=0 (optional) +
      • +
      • + wakeupUserdevice - Backlink zum RESIDENTS, ROOMMATE oder GUEST Gerät, um dessen Status zu prüfen (notwendig) +
      • +
      +
    • +
    +
    =end html_DE diff --git a/fhem/FHEM/20_GUEST.pm b/fhem/FHEM/20_GUEST.pm old mode 100755 new mode 100644 index 9b779cc51..f77fe63cb --- a/fhem/FHEM/20_GUEST.pm +++ b/fhem/FHEM/20_GUEST.pm @@ -23,9 +23,12 @@ # along with fhem. If not, see . # # -# Version: 1.1.0 +# Version: 1.2.0 # # Major Version History: +# - 1.2.0 - 2015-03-11 +# -- add RESIDENTStoolkit support +# # - 1.1.0 - 2014-04-07 # -- new readings in computer readable format (*_cr) # -- format of readings durTimer readings changed from minutes to HH:MM:ss @@ -41,9 +44,11 @@ use strict; use warnings; use Time::Local; use Data::Dumper; +require RESIDENTStk; sub GUEST_Set($@); sub GUEST_Define($$); +sub GUEST_Notify($$); sub GUEST_Undefine($$); ################################### @@ -52,11 +57,12 @@ sub GUEST_Initialize($) { Log3 $hash, 5, "GUEST_Initialize: Entering"; - $hash->{SetFn} = "GUEST_Set"; - $hash->{DefFn} = "GUEST_Define"; - $hash->{UndefFn} = "GUEST_Undefine"; + $hash->{SetFn} = "GUEST_Set"; + $hash->{DefFn} = "GUEST_Define"; + $hash->{NotifyFn} = "GUEST_Notify"; + $hash->{UndefFn} = "GUEST_Undefine"; $hash->{AttrList} = -"rg_locationHome rg_locationWayhome rg_locationUnderway rg_autoGoneAfter:12,16,24,26,28,30,36,48,60 rg_showAllStates:0,1 rg_realname:group,alias rg_states rg_locations rg_moods rg_moodDefault rg_moodSleepy rg_noDuration:0,1 " +"rg_locationHome rg_locationWayhome rg_locationUnderway rg_autoGoneAfter:12,16,24,26,28,30,36,48,60 rg_showAllStates:0,1 rg_realname:group,alias rg_states rg_locations rg_moods rg_moodDefault rg_moodSleepy rg_noDuration:0,1 rg_wakeupDevice " . $readingFnAttributes; } @@ -134,16 +140,17 @@ sub GUEST_Define($$) { $aliasname =~ s/^rg_//; $attr{$name}{alias} = $aliasname; - $attr{$name}{devStateIcon} = + $attr{$name}{devStateIcon} = ".*home:user_available:absent .*absent:user_away:home .*none:control_building_empty:home .*gotosleep:scene_toilet:asleep .*asleep:scene_sleeping:awoken .*awoken:scene_sleeping_alternat:home .*:user_unknown"; - $attr{$name}{group} = "Guests"; - $attr{$name}{icon} = "scene_visit_guests"; - $attr{$name}{rg_realname} = "alias"; - $attr{$name}{sortby} = "1"; - $attr{$name}{webCmd} = "state"; + $attr{$name}{group} = "Guests"; + $attr{$name}{icon} = "scene_visit_guests"; + $attr{$name}{rg_realname} = "alias"; + $attr{$name}{sortby} = "1"; + $attr{$name}{webCmd} = "state"; - $attr{$name}{room} = $attr{ $registeredResidentgroups[0] }{room} - if (@registeredResidentgroups && exists($attr{$registeredResidentgroups[0]}{room})); + $attr{$name}{room} = $attr{ $registeredResidentgroups[0] }{room} + if ( @registeredResidentgroups + && exists( $attr{ $registeredResidentgroups[0] }{room} ) ); } # trigger for modified objects @@ -185,6 +192,45 @@ sub GUEST_Undefine($$) { return undef; } +################################### +sub GUEST_Notify($$) { + my ( $hash, $dev ) = @_; + my $devName = $dev->{NAME}; + my $hashName = $hash->{NAME}; + my $hashName_attr; + + # process child notifies + if ( $devName ne $hashName ) { + my @registeredWakeupdevs = + split( /,/, $attr{$hashName}{rg_wakeupDevice} ) + if ( defined( $attr{$hashName}{rg_wakeupDevice} ) + && $attr{$hashName}{rg_wakeupDevice} ne "" ); + + # process only registered devices for wakeup function + if ( @registeredWakeupdevs && $devName ~~ @registeredWakeupdevs ) { + + return + if ( !$dev->{CHANGED} ); # Some previous notify deleted the array. + + foreach my $change ( @{ $dev->{CHANGED} } ) { + + # state changed + if ( $change =~ /OFF|([0-9]{2}:[0-9]{2})/ ) { + Log3 $hash, 4, + "GUEST " + . $hashName . ": " + . $devName + . ": notify about change to $change"; + + return RESIDENTStk_wakeupSet( $devName, $change ); + } + } + } + } + + return; +} + ################################### sub GUEST_Set($@) { my ( $hash, @a ) = @_; @@ -253,10 +299,9 @@ sub GUEST_Set($@) { $usage .= " state:$states"; $usage .= " mood:$moods"; $usage .= " location$locations"; + $usage .= " create:wakeuptimer"; -# $usage .= -#" create:wuTimerWd,wuTimerWe,wuTimerMon,wuTimerTue,wuTimerWed,wuTimerThu,wuTimerFri,wuTimerSat,wuTimerSun"; -# $usage .= " compactMode:noArg largeMode:noArg"; + # $usage .= " compactMode:noArg largeMode:noArg"; # silentSet if ( $a[1] eq "silentSet" ) { @@ -664,6 +709,61 @@ sub GUEST_Set($@) { } } + # create + elsif ( $a[1] eq "create" ) { + if ( defined( $a[2] ) && $a[2] eq "wakeuptimer" ) { + my $i = "1"; + my $wakeuptimerName = $name . "_wakeuptimer" . $i; + my $created = 0; + + until ($created) { + if ( defined( $defs{$wakeuptimerName} ) ) { + $i++; + $wakeuptimerName = $name . "_wakeuptimer" . $i; + } + else { + + # create new dummy device + fhem "define $wakeuptimerName dummy"; + fhem "attr $wakeuptimerName alias Wake-up Timer $i"; + fhem "attr $wakeuptimerName comment Auto-created by GUEST module for use with RESIDENTS Toolkit"; + fhem +"attr $wakeuptimerName devStateIcon OFF:general_aus\@red .*:general_an\@green:OFF"; + fhem "attr $wakeuptimerName group " . $attr{$name}{group} + if ( defined( $attr{$name}{group} ) ); + fhem "attr $wakeuptimerName icon time_clock"; + fhem "attr $wakeuptimerName room " . $attr{$name}{room} + if ( defined( $attr{$name}{room} ) ); + fhem +"attr $wakeuptimerName setList state:OFF,00:00,00:15,00:30,00:45,01:00,01:15,01:30,01:45,02:00,02:15,02:30,02:45,03:00,03:15,03:30,03:45,04:00,04:15,04:30,04:45,05:00,05:15,05:30,05:45,06:00,06:15,06:30,06:45,07:00,07:15,07:30,07:45,08:00,08:15,08:30,08:45,09:00,09:15,09:30,09:45,10:00,10:15,10:30,10:45,11:00,11:15,11:30,11:45,12:00,12:15,12:30,12:45,13:00,13:15,13:30,13:45,14:00,14:15,14:30,14:45,15:00,15:15,15:30,15:45,16:00,16:15,16:30,16:45,17:00,17:15,17:30,17:45,18:00,18:15,18:30,18:45,19:00,19:15,19:30,19:45,20:00,20:15,20:30,20:45,21:00,21:15,21:30,21:45,22:00,22:15,22:30,22:45,23:00,23:15,23:30,23:45"; + fhem "attr $wakeuptimerName userattr wakeupUserdevice"; + fhem "attr $wakeuptimerName wakeupUserdevice $name"; + fhem "attr $wakeuptimerName webCmd state"; + + # register slave device + if ( defined( $attr{$name}{rg_wakeupDevice} ) ) { + fhem "attr $name rg_wakeupDevice " + . $attr{$name}{rg_wakeupDevice} + . ",$wakeuptimerName"; + } + else { + fhem "attr $name rg_wakeupDevice $wakeuptimerName"; + } + + # trigger first update + fhem "set $wakeuptimerName OFF"; + + $created = 1; + return +"Dummy $wakeuptimerName and other pending devices created and pre-configured. You may edit Macro_$wakeuptimerName to define your wake-up actions."; + } + } + } + else { + return "Invalid 2nd argument, choose one of wakeuptimer "; + } + } + # return usage hint else { return $usage; @@ -739,82 +839,86 @@ sub GUEST_DurationTimer($;$) { GUEST_RemoveInternalTimer( "DurationTimer", $hash ); - if ( !defined($attr{$name}{rg_noDuration}) || $attr{$name}{rg_noDuration} == 0 ) { + if ( !defined( $attr{$name}{rg_noDuration} ) + || $attr{$name}{rg_noDuration} == 0 ) + { - # presence timer - if ( defined( $hash->{READINGS}{presence}{VAL} ) - && $hash->{READINGS}{presence}{VAL} eq "present" ) - { - if ( defined( $hash->{READINGS}{lastArrival}{VAL} ) - && $hash->{READINGS}{lastArrival}{VAL} ne "-" ) - { - $durPresence = - $timestampNow - - GUEST_Datetime2Timestamp( $hash->{READINGS}{lastArrival}{VAL} ); - } - } + # presence timer + if ( defined( $hash->{READINGS}{presence}{VAL} ) + && $hash->{READINGS}{presence}{VAL} eq "present" ) + { + if ( defined( $hash->{READINGS}{lastArrival}{VAL} ) + && $hash->{READINGS}{lastArrival}{VAL} ne "-" ) + { + $durPresence = + $timestampNow - + GUEST_Datetime2Timestamp( + $hash->{READINGS}{lastArrival}{VAL} ); + } + } - # absence timer - if ( defined( $hash->{READINGS}{presence}{VAL} ) - && $hash->{READINGS}{presence}{VAL} eq "absent" - && defined( $hash->{READINGS}{state}{VAL} ) - && $hash->{READINGS}{state}{VAL} eq "absent" ) - { - if ( defined( $hash->{READINGS}{lastDeparture}{VAL} ) - && $hash->{READINGS}{lastDeparture}{VAL} ne "-" ) - { - $durAbsence = - $timestampNow - - GUEST_Datetime2Timestamp( $hash->{READINGS}{lastDeparture}{VAL} ); - } - } + # absence timer + if ( defined( $hash->{READINGS}{presence}{VAL} ) + && $hash->{READINGS}{presence}{VAL} eq "absent" + && defined( $hash->{READINGS}{state}{VAL} ) + && $hash->{READINGS}{state}{VAL} eq "absent" ) + { + if ( defined( $hash->{READINGS}{lastDeparture}{VAL} ) + && $hash->{READINGS}{lastDeparture}{VAL} ne "-" ) + { + $durAbsence = + $timestampNow - + GUEST_Datetime2Timestamp( + $hash->{READINGS}{lastDeparture}{VAL} ); + } + } - # sleep timer - if ( defined( $hash->{READINGS}{state}{VAL} ) - && $hash->{READINGS}{state}{VAL} eq "asleep" ) - { - if ( defined( $hash->{READINGS}{lastSleep}{VAL} ) - && $hash->{READINGS}{lastSleep}{VAL} ne "-" ) - { - $durSleep = - $timestampNow - - GUEST_Datetime2Timestamp( $hash->{READINGS}{lastSleep}{VAL} ); - } - } + # sleep timer + if ( defined( $hash->{READINGS}{state}{VAL} ) + && $hash->{READINGS}{state}{VAL} eq "asleep" ) + { + if ( defined( $hash->{READINGS}{lastSleep}{VAL} ) + && $hash->{READINGS}{lastSleep}{VAL} ne "-" ) + { + $durSleep = + $timestampNow - + GUEST_Datetime2Timestamp( $hash->{READINGS}{lastSleep}{VAL} ); + } + } - my $durPresence_hr = - ( $durPresence > 0 ) ? GUEST_sec2time($durPresence) : "00:00:00"; - my $durPresence_cr = - ( $durPresence > 60 ) ? int( $durPresence / 60 + 0.5 ) : 0; - my $durAbsence_hr = - ( $durAbsence > 0 ) ? GUEST_sec2time($durAbsence) : "00:00:00"; - my $durAbsence_cr = - ( $durAbsence > 60 ) ? int( $durAbsence / 60 + 0.5 ) : 0; - my $durSleep_hr = - ( $durSleep > 0 ) ? GUEST_sec2time($durSleep) : "00:00:00"; - my $durSleep_cr = ( $durSleep > 60 ) ? int( $durSleep / 60 + 0.5 ) : 0; + my $durPresence_hr = + ( $durPresence > 0 ) ? GUEST_sec2time($durPresence) : "00:00:00"; + my $durPresence_cr = + ( $durPresence > 60 ) ? int( $durPresence / 60 + 0.5 ) : 0; + my $durAbsence_hr = + ( $durAbsence > 0 ) ? GUEST_sec2time($durAbsence) : "00:00:00"; + my $durAbsence_cr = + ( $durAbsence > 60 ) ? int( $durAbsence / 60 + 0.5 ) : 0; + my $durSleep_hr = + ( $durSleep > 0 ) ? GUEST_sec2time($durSleep) : "00:00:00"; + my $durSleep_cr = ( $durSleep > 60 ) ? int( $durSleep / 60 + 0.5 ) : 0; - readingsBeginUpdate($hash) if ( !$silent ); - readingsBulkUpdate( $hash, "durTimerPresence_cr", $durPresence_cr ) - if ( !defined( $hash->{READINGS}{durTimerPresence_cr}{VAL} ) - || $hash->{READINGS}{durTimerPresence_cr}{VAL} ne $durPresence_cr ); - readingsBulkUpdate( $hash, "durTimerPresence", $durPresence_hr ) - if ( !defined( $hash->{READINGS}{durTimerPresence}{VAL} ) - || $hash->{READINGS}{durTimerPresence}{VAL} ne $durPresence_hr ); - readingsBulkUpdate( $hash, "durTimerAbsence_cr", $durAbsence_cr ) - if ( !defined( $hash->{READINGS}{durTimerAbsence_cr}{VAL} ) - || $hash->{READINGS}{durTimerAbsence_cr}{VAL} ne $durAbsence_cr ); - readingsBulkUpdate( $hash, "durTimerAbsence", $durAbsence_hr ) - if ( !defined( $hash->{READINGS}{durTimerAbsence}{VAL} ) - || $hash->{READINGS}{durTimerAbsence}{VAL} ne $durAbsence_hr ); - readingsBulkUpdate( $hash, "durTimerSleep_cr", $durSleep_cr ) - if ( !defined( $hash->{READINGS}{durTimerSleep_cr}{VAL} ) - || $hash->{READINGS}{durTimerSleep_cr}{VAL} ne $durSleep_cr ); - readingsBulkUpdate( $hash, "durTimerSleep", $durSleep_hr ) - if ( !defined( $hash->{READINGS}{durTimerSleep}{VAL} ) - || $hash->{READINGS}{durTimerSleep}{VAL} ne $durSleep_hr ); - readingsEndUpdate( $hash, 1 ) if ( !$silent ); - } + readingsBeginUpdate($hash) if ( !$silent ); + readingsBulkUpdate( $hash, "durTimerPresence_cr", $durPresence_cr ) + if ( !defined( $hash->{READINGS}{durTimerPresence_cr}{VAL} ) + || $hash->{READINGS}{durTimerPresence_cr}{VAL} ne $durPresence_cr ); + readingsBulkUpdate( $hash, "durTimerPresence", $durPresence_hr ) + if ( !defined( $hash->{READINGS}{durTimerPresence}{VAL} ) + || $hash->{READINGS}{durTimerPresence}{VAL} ne $durPresence_hr ); + readingsBulkUpdate( $hash, "durTimerAbsence_cr", $durAbsence_cr ) + if ( !defined( $hash->{READINGS}{durTimerAbsence_cr}{VAL} ) + || $hash->{READINGS}{durTimerAbsence_cr}{VAL} ne $durAbsence_cr ); + readingsBulkUpdate( $hash, "durTimerAbsence", $durAbsence_hr ) + if ( !defined( $hash->{READINGS}{durTimerAbsence}{VAL} ) + || $hash->{READINGS}{durTimerAbsence}{VAL} ne $durAbsence_hr ); + readingsBulkUpdate( $hash, "durTimerSleep_cr", $durSleep_cr ) + if ( !defined( $hash->{READINGS}{durTimerSleep_cr}{VAL} ) + || $hash->{READINGS}{durTimerSleep_cr}{VAL} ne $durSleep_cr ); + readingsBulkUpdate( $hash, "durTimerSleep", $durSleep_hr ) + if ( !defined( $hash->{READINGS}{durTimerSleep}{VAL} ) + || $hash->{READINGS}{durTimerSleep}{VAL} ne $durSleep_hr ); + readingsEndUpdate( $hash, 1 ) if ( !$silent ); + } GUEST_InternalTimer( "DurationTimer", $timestampNow + 60, "GUEST_DurationTimer", $hash, 1 ) @@ -987,6 +1091,9 @@ sub GUEST_StartInternalTimers($$) {
  • state   home,gotosleep,asleep,awoken,absent,none   switch between states; see attribute rg_states to adjust list shown in FHEMWEB
  • +
  • + create   wakeuptimer   add several pre-configurations provided by RESIDENTS Toolkit. See separate section in RESIDENTS module commandref for details. +


  • @@ -1257,6 +1364,9 @@ sub GUEST_StartInternalTimers($$) {
  • state   home,gotosleep,asleep,awoken,absent,gone   wechselt den Status; siehe auch Attribut rg_states, um die in FHEMWEB angezeigte Liste anzupassen
  • +
  • + create   wakeuptimer   fügt diverse Vorkonfigurationen auf Basis von RESIDENTS Toolkit hinzu. Siehe separate Sektion in der RESIDENTS Modul Kommandoreferenz. +


  • diff --git a/fhem/FHEM/20_ROOMMATE.pm b/fhem/FHEM/20_ROOMMATE.pm old mode 100755 new mode 100644 index 775e8fbfc..552b66c4d --- a/fhem/FHEM/20_ROOMMATE.pm +++ b/fhem/FHEM/20_ROOMMATE.pm @@ -23,9 +23,12 @@ # along with fhem. If not, see . # # -# Version: 1.1.0 +# Version: 1.2.0 # # Major Version History: +# - 1.2.0 - 2015-03-11 +# -- add RESIDENTStoolkit support +# # - 1.1.0 - 2014-04-07 # -- new readings in computer readable format (*_cr) # -- format of readings durTimer readings changed from minutes to HH:MM:ss @@ -41,9 +44,11 @@ use strict; use warnings; use Time::Local; use Data::Dumper; +require RESIDENTStk; sub ROOMMATE_Set($@); sub ROOMMATE_Define($$); +sub ROOMMATE_Notify($$); sub ROOMMATE_Undefine($$); ################################### @@ -52,11 +57,12 @@ sub ROOMMATE_Initialize($) { Log3 $hash, 5, "ROOMMATE_Initialize: Entering"; - $hash->{SetFn} = "ROOMMATE_Set"; - $hash->{DefFn} = "ROOMMATE_Define"; - $hash->{UndefFn} = "ROOMMATE_Undefine"; + $hash->{SetFn} = "ROOMMATE_Set"; + $hash->{DefFn} = "ROOMMATE_Define"; + $hash->{NotifyFn} = "ROOMMATE_Notify"; + $hash->{UndefFn} = "ROOMMATE_Undefine"; $hash->{AttrList} = -"rr_locationHome rr_locationWayhome rr_locationUnderway rr_autoGoneAfter:12,16,24,26,28,30,36,48,60 rr_showAllStates:0,1 rr_realname:group,alias rr_states rr_locations rr_moods rr_moodDefault rr_moodSleepy rr_passPresenceTo rr_noDuration:0,1 " +"rr_locationHome rr_locationWayhome rr_locationUnderway rr_autoGoneAfter:12,16,24,26,28,30,36,48,60 rr_showAllStates:0,1 rr_realname:group,alias rr_states rr_locations rr_moods rr_moodDefault rr_moodSleepy rr_passPresenceTo rr_noDuration:0,1 rr_wakeupDevice " . $readingFnAttributes; } @@ -135,16 +141,17 @@ sub ROOMMATE_Define($$) { $groupname =~ s/^rr_//; $attr{$name}{group} = $groupname; - $attr{$name}{alias} = "Status"; - $attr{$name}{devStateIcon} = + $attr{$name}{alias} = "Status"; + $attr{$name}{devStateIcon} = ".*home:user_available:absent .*absent:user_away:home .*gone:user_ext_away:home .*gotosleep:scene_toilet:asleep .*asleep:scene_sleeping:awoken .*awoken:scene_sleeping_alternat:home .*:user_unknown"; - $attr{$name}{icon} = "people_sensor"; - $attr{$name}{rr_realname} = "alias"; - $attr{$name}{sortby} = "1"; - $attr{$name}{webCmd} = "state"; + $attr{$name}{icon} = "people_sensor"; + $attr{$name}{rr_realname} = "alias"; + $attr{$name}{sortby} = "1"; + $attr{$name}{webCmd} = "state"; - $attr{$name}{room} = $attr{ $registeredResidentgroups[0] }{room} - if (@registeredResidentgroups && exists($attr{$registeredResidentgroups[0]}{room})); + $attr{$name}{room} = $attr{ $registeredResidentgroups[0] }{room} + if ( @registeredResidentgroups + && exists( $attr{ $registeredResidentgroups[0] }{room} ) ); } # trigger for modified objects @@ -190,6 +197,45 @@ sub ROOMMATE_Undefine($$) { return undef; } +################################### +sub ROOMMATE_Notify($$) { + my ( $hash, $dev ) = @_; + my $devName = $dev->{NAME}; + my $hashName = $hash->{NAME}; + my $hashName_attr; + + # process child notifies + if ( $devName ne $hashName ) { + my @registeredWakeupdevs = + split( /,/, $attr{$hashName}{rr_wakeupDevice} ) + if ( defined( $attr{$hashName}{rr_wakeupDevice} ) + && $attr{$hashName}{rr_wakeupDevice} ne "" ); + + # process only registered devices for wakeup function + if ( @registeredWakeupdevs && $devName ~~ @registeredWakeupdevs ) { + + return + if ( !$dev->{CHANGED} ); # Some previous notify deleted the array. + + foreach my $change ( @{ $dev->{CHANGED} } ) { + + # state changed + if ( $change =~ /OFF|([0-9]{2}:[0-9]{2})/ ) { + Log3 $hash, 4, + "ROOMMATE " + . $hashName . ": " + . $devName + . ": notify about change to $change"; + + return RESIDENTStk_wakeupSet( $devName, $change ); + } + } + } + } + + return; +} + ################################### sub ROOMMATE_Set($@) { my ( $hash, @a ) = @_; @@ -258,10 +304,9 @@ sub ROOMMATE_Set($@) { $usage .= " state:$states"; $usage .= " mood:$moods"; $usage .= " location$locations"; + $usage .= " create:wakeuptimer"; -# $usage .= -#" create:wuTimerWd,wuTimerWe,wuTimerMon,wuTimerTue,wuTimerWed,wuTimerThu,wuTimerFri,wuTimerSat,wuTimerSun"; -# $usage .= " compactMode:noArg largeMode:noArg"; + # $usage .= " compactMode:noArg largeMode:noArg"; # silentSet if ( $a[1] eq "silentSet" ) { @@ -646,6 +691,61 @@ sub ROOMMATE_Set($@) { } } + # create + elsif ( $a[1] eq "create" ) { + if ( defined( $a[2] ) && $a[2] eq "wakeuptimer" ) { + my $i = "1"; + my $wakeuptimerName = $name . "_wakeuptimer" . $i; + my $created = 0; + + until ($created) { + if ( defined( $defs{$wakeuptimerName} ) ) { + $i++; + $wakeuptimerName = $name . "_wakeuptimer" . $i; + } + else { + + # create new dummy device + fhem "define $wakeuptimerName dummy"; + fhem "attr $wakeuptimerName alias Wake-up Timer $i"; + fhem "attr $wakeuptimerName comment Auto-created by ROOMMATE module for use with RESIDENTS Toolkit"; + fhem +"attr $wakeuptimerName devStateIcon OFF:general_aus\@red .*:general_an\@green:OFF"; + fhem "attr $wakeuptimerName group " . $attr{$name}{group} + if ( defined( $attr{$name}{group} ) ); + fhem "attr $wakeuptimerName icon time_clock"; + fhem "attr $wakeuptimerName room " . $attr{$name}{room} + if ( defined( $attr{$name}{room} ) ); + fhem +"attr $wakeuptimerName setList state:OFF,00:00,00:15,00:30,00:45,01:00,01:15,01:30,01:45,02:00,02:15,02:30,02:45,03:00,03:15,03:30,03:45,04:00,04:15,04:30,04:45,05:00,05:15,05:30,05:45,06:00,06:15,06:30,06:45,07:00,07:15,07:30,07:45,08:00,08:15,08:30,08:45,09:00,09:15,09:30,09:45,10:00,10:15,10:30,10:45,11:00,11:15,11:30,11:45,12:00,12:15,12:30,12:45,13:00,13:15,13:30,13:45,14:00,14:15,14:30,14:45,15:00,15:15,15:30,15:45,16:00,16:15,16:30,16:45,17:00,17:15,17:30,17:45,18:00,18:15,18:30,18:45,19:00,19:15,19:30,19:45,20:00,20:15,20:30,20:45,21:00,21:15,21:30,21:45,22:00,22:15,22:30,22:45,23:00,23:15,23:30,23:45"; + fhem "attr $wakeuptimerName userattr wakeupUserdevice"; + fhem "attr $wakeuptimerName wakeupUserdevice $name"; + fhem "attr $wakeuptimerName webCmd state"; + + # register slave device + if ( defined( $attr{$name}{rr_wakeupDevice} ) ) { + fhem "attr $name rr_wakeupDevice " + . $attr{$name}{rr_wakeupDevice} + . ",$wakeuptimerName"; + } + else { + fhem "attr $name rr_wakeupDevice $wakeuptimerName"; + } + + # trigger first update + fhem "set $wakeuptimerName OFF"; + + $created = 1; + return +"Dummy $wakeuptimerName and other pending devices created and pre-configured. You may edit Macro_$wakeuptimerName to define your wake-up actions."; + } + } + } + else { + return "Invalid 2nd argument, choose one of wakeuptimer "; + } + } + # return usage hint else { return $usage; @@ -717,82 +817,85 @@ sub ROOMMATE_DurationTimer($;$) { ROOMMATE_RemoveInternalTimer( "DurationTimer", $hash ); - if ( !defined($attr{$name}{rr_noDuration}) || $attr{$name}{rr_noDuration} == 0 ) { + if ( !defined( $attr{$name}{rr_noDuration} ) + || $attr{$name}{rr_noDuration} == 0 ) + { - # presence timer - if ( defined( $hash->{READINGS}{presence}{VAL} ) - && $hash->{READINGS}{presence}{VAL} eq "present" ) - { - if ( defined( $hash->{READINGS}{lastArrival}{VAL} ) - && $hash->{READINGS}{lastArrival}{VAL} ne "-" ) - { - $durPresence = - $timestampNow - - ROOMMATE_Datetime2Timestamp( - $hash->{READINGS}{lastArrival}{VAL} ); - } - } + # presence timer + if ( defined( $hash->{READINGS}{presence}{VAL} ) + && $hash->{READINGS}{presence}{VAL} eq "present" ) + { + if ( defined( $hash->{READINGS}{lastArrival}{VAL} ) + && $hash->{READINGS}{lastArrival}{VAL} ne "-" ) + { + $durPresence = + $timestampNow - + ROOMMATE_Datetime2Timestamp( + $hash->{READINGS}{lastArrival}{VAL} ); + } + } - # absence timer - if ( defined( $hash->{READINGS}{presence}{VAL} ) - && $hash->{READINGS}{presence}{VAL} eq "absent" ) - { - if ( defined( $hash->{READINGS}{lastDeparture}{VAL} ) - && $hash->{READINGS}{lastDeparture}{VAL} ne "-" ) - { - $durAbsence = - $timestampNow - - ROOMMATE_Datetime2Timestamp( - $hash->{READINGS}{lastDeparture}{VAL} ); - } - } + # absence timer + if ( defined( $hash->{READINGS}{presence}{VAL} ) + && $hash->{READINGS}{presence}{VAL} eq "absent" ) + { + if ( defined( $hash->{READINGS}{lastDeparture}{VAL} ) + && $hash->{READINGS}{lastDeparture}{VAL} ne "-" ) + { + $durAbsence = + $timestampNow - + ROOMMATE_Datetime2Timestamp( + $hash->{READINGS}{lastDeparture}{VAL} ); + } + } - # sleep timer - if ( defined( $hash->{READINGS}{state}{VAL} ) - && $hash->{READINGS}{state}{VAL} eq "asleep" ) - { - if ( defined( $hash->{READINGS}{lastSleep}{VAL} ) - && $hash->{READINGS}{lastSleep}{VAL} ne "-" ) - { - $durSleep = - $timestampNow - - ROOMMATE_Datetime2Timestamp( $hash->{READINGS}{lastSleep}{VAL} ); - } - } + # sleep timer + if ( defined( $hash->{READINGS}{state}{VAL} ) + && $hash->{READINGS}{state}{VAL} eq "asleep" ) + { + if ( defined( $hash->{READINGS}{lastSleep}{VAL} ) + && $hash->{READINGS}{lastSleep}{VAL} ne "-" ) + { + $durSleep = + $timestampNow - + ROOMMATE_Datetime2Timestamp( + $hash->{READINGS}{lastSleep}{VAL} ); + } + } - my $durPresence_hr = - ( $durPresence > 0 ) ? ROOMMATE_sec2time($durPresence) : "00:00:00"; - my $durPresence_cr = - ( $durPresence > 60 ) ? int( $durPresence / 60 + 0.5 ) : 0; - my $durAbsence_hr = - ( $durAbsence > 0 ) ? ROOMMATE_sec2time($durAbsence) : "00:00:00"; - my $durAbsence_cr = - ( $durAbsence > 60 ) ? int( $durAbsence / 60 + 0.5 ) : 0; - my $durSleep_hr = - ( $durSleep > 0 ) ? ROOMMATE_sec2time($durSleep) : "00:00:00"; - my $durSleep_cr = ( $durSleep > 60 ) ? int( $durSleep / 60 + 0.5 ) : 0; + my $durPresence_hr = + ( $durPresence > 0 ) ? ROOMMATE_sec2time($durPresence) : "00:00:00"; + my $durPresence_cr = + ( $durPresence > 60 ) ? int( $durPresence / 60 + 0.5 ) : 0; + my $durAbsence_hr = + ( $durAbsence > 0 ) ? ROOMMATE_sec2time($durAbsence) : "00:00:00"; + my $durAbsence_cr = + ( $durAbsence > 60 ) ? int( $durAbsence / 60 + 0.5 ) : 0; + my $durSleep_hr = + ( $durSleep > 0 ) ? ROOMMATE_sec2time($durSleep) : "00:00:00"; + my $durSleep_cr = ( $durSleep > 60 ) ? int( $durSleep / 60 + 0.5 ) : 0; - readingsBeginUpdate($hash) if ( !$silent ); - readingsBulkUpdate( $hash, "durTimerPresence_cr", $durPresence_cr ) - if ( !defined( $hash->{READINGS}{durTimerPresence_cr}{VAL} ) - || $hash->{READINGS}{durTimerPresence_cr}{VAL} ne $durPresence_cr ); - readingsBulkUpdate( $hash, "durTimerPresence", $durPresence_hr ) - if ( !defined( $hash->{READINGS}{durTimerPresence}{VAL} ) - || $hash->{READINGS}{durTimerPresence}{VAL} ne $durPresence_hr ); - readingsBulkUpdate( $hash, "durTimerAbsence_cr", $durAbsence_cr ) - if ( !defined( $hash->{READINGS}{durTimerAbsence_cr}{VAL} ) - || $hash->{READINGS}{durTimerAbsence_cr}{VAL} ne $durAbsence_cr ); - readingsBulkUpdate( $hash, "durTimerAbsence", $durAbsence_hr ) - if ( !defined( $hash->{READINGS}{durTimerAbsence}{VAL} ) - || $hash->{READINGS}{durTimerAbsence}{VAL} ne $durAbsence_hr ); - readingsBulkUpdate( $hash, "durTimerSleep_cr", $durSleep_cr ) - if ( !defined( $hash->{READINGS}{durTimerSleep_cr}{VAL} ) - || $hash->{READINGS}{durTimerSleep_cr}{VAL} ne $durSleep_cr ); - readingsBulkUpdate( $hash, "durTimerSleep", $durSleep_hr ) - if ( !defined( $hash->{READINGS}{durTimerSleep}{VAL} ) - || $hash->{READINGS}{durTimerSleep}{VAL} ne $durSleep_hr ); - readingsEndUpdate( $hash, 1 ) if ( !$silent ); - } + readingsBeginUpdate($hash) if ( !$silent ); + readingsBulkUpdate( $hash, "durTimerPresence_cr", $durPresence_cr ) + if ( !defined( $hash->{READINGS}{durTimerPresence_cr}{VAL} ) + || $hash->{READINGS}{durTimerPresence_cr}{VAL} ne $durPresence_cr ); + readingsBulkUpdate( $hash, "durTimerPresence", $durPresence_hr ) + if ( !defined( $hash->{READINGS}{durTimerPresence}{VAL} ) + || $hash->{READINGS}{durTimerPresence}{VAL} ne $durPresence_hr ); + readingsBulkUpdate( $hash, "durTimerAbsence_cr", $durAbsence_cr ) + if ( !defined( $hash->{READINGS}{durTimerAbsence_cr}{VAL} ) + || $hash->{READINGS}{durTimerAbsence_cr}{VAL} ne $durAbsence_cr ); + readingsBulkUpdate( $hash, "durTimerAbsence", $durAbsence_hr ) + if ( !defined( $hash->{READINGS}{durTimerAbsence}{VAL} ) + || $hash->{READINGS}{durTimerAbsence}{VAL} ne $durAbsence_hr ); + readingsBulkUpdate( $hash, "durTimerSleep_cr", $durSleep_cr ) + if ( !defined( $hash->{READINGS}{durTimerSleep_cr}{VAL} ) + || $hash->{READINGS}{durTimerSleep_cr}{VAL} ne $durSleep_cr ); + readingsBulkUpdate( $hash, "durTimerSleep", $durSleep_hr ) + if ( !defined( $hash->{READINGS}{durTimerSleep}{VAL} ) + || $hash->{READINGS}{durTimerSleep}{VAL} ne $durSleep_hr ); + readingsEndUpdate( $hash, 1 ) if ( !$silent ); + } ROOMMATE_InternalTimer( "DurationTimer", $timestampNow + 60, "ROOMMATE_DurationTimer", $hash, 1 ); @@ -970,6 +1073,9 @@ sub ROOMMATE_StartInternalTimers($$) {
  • state   home,gotosleep,asleep,awoken,absent,gone   switch between states; see attribute rr_states to adjust list shown in FHEMWEB
  • +
  • + create   wakeuptimer   add several pre-configurations provided by RESIDENTS Toolkit. See separate section in RESIDENTS module commandref for details. +


  • @@ -1240,6 +1346,9 @@ sub ROOMMATE_StartInternalTimers($$) {
  • state   home,gotosleep,asleep,awoken,absent,gone   wechselt den Status; siehe auch Attribut rr_states, um die in FHEMWEB angezeigte Liste anzupassen
  • +
  • + create   wakeuptimer   fügt diverse Vorkonfigurationen auf Basis von RESIDENTS Toolkit hinzu. Siehe separate Sektion in der RESIDENTS Modul Kommandoreferenz. +


  • diff --git a/fhem/FHEM/RESIDENTStk.pm b/fhem/FHEM/RESIDENTStk.pm new file mode 100644 index 000000000..fb736116c --- /dev/null +++ b/fhem/FHEM/RESIDENTStk.pm @@ -0,0 +1,210 @@ +# $Id$ +############################################################################## +# +# RESIDENTStk.pm +# Additional functions for 10_RESIDENTS.pm, 20_ROOMMATE.pm, 20_GUEST.pm +# +# Copyright by Julian Pawlowski +# e-mail: julian.pawlowski at gmail.com +# +# This file is part of fhem. +# +# Fhem is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# Fhem is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with fhem. If not, see . +# +# +# Version: 1.0.0 +# +# Version History: +# - 1.0.0 - 2015-03-11 +# -- First release +# +############################################################################## + +##################################### +# Enslave DUMMY device to be used for alarm clock +# +sub RESIDENTStk_wakeupSet($$) { + my ( $NAME, $VALUE ) = @_; + my $userattr = AttrVal( $NAME, "userattr", 0 ); + my $autosave = AttrVal( $NAME, "wakeupAutosave", 0 ); + my $wakeupMacro = AttrVal( $NAME, "wakeupMacro", 0 ); + my $wakeupOffset = AttrVal( $NAME, "wakeupOffset", "0" ); + my $room = AttrVal( $NAME, "room", "" ); + my $atName = "at_" . $NAME; + my $macroName = "Macro_" . $NAME; + + # check for required userattr attribute + my $userattributes = +"wakeupOffset:slider,0,1,120 wakeupDefaultTime:time wakeupMacro wakeupUserdevice wakeupResetdays:multiple-strict,0,1,2,3,4,5,6 wakeupDays:multiple-strict,0,1,2,3,4,5,6 wakeupAutosave:1,0"; + if ( !$userattr || $userattr ne $userattributes ) { + Log3 $NAME, 3, +"RESIDENTStk $NAME: adjusting dummy device for required attribute userattr"; + fhem "attr $NAME userattr $userattributes"; + } + + # check for required macro attribute + if ( !$wakeupMacro ) { + Log3 $NAME, 3, +"RESIDENTStk $NAME: adjusting dummy device for required attribute wakeupMacro"; + fhem "attr $NAME wakeupMacro $macroName"; + $wakeupMacro = $macroName; + } + + # check for existing macro + if ( !defined( $defs{$wakeupMacro} ) ) { + Log3 $NAME, 3, + "RESIDENTStk $NAME: new notify macro device $wakeupMacro created"; + fhem "define $wakeupMacro notify $wakeupMacro {}"; + if ($room) { fhem "attr $wakeupMacro room $room" } + } + elsif ( $defs{$wakeupMacro}{TYPE} ne "notify" ) { + Log3 $NAME, 3, +"RESIDENTStk $NAME: WARNING - defined macro device '$wakeupMacro' is not a notify device!"; + } + + # check for required userdevice attribute + if ( !AttrVal( $NAME, "wakeupUserdevice", 0 ) ) { + Log3 $NAME, 3, +"RESIDENTStk $NAME: WARNING - set attribute wakeupUserdevice before running wakeup function"; + } + + if ( $VALUE ne "OFF" ) { + my @time = split /:/, $VALUE; + my $time_sec = $time[0] * 3600 + $time[1] * 60; + my $begin = $time_sec - $wakeupOffset * 60; + my $hour = int( $begin / 3600 ); + my $leftover = $begin % 3600; + my $min = int( $leftover / 60 ); + if ( $time_sec < 1800 && $wakeupOffset > 0 ) { $hour = 23 } + + if ( !defined( $defs{$atName} ) ) { + Log3 $NAME, 3, "RESIDENTStk $NAME: $atName created and set to " + . sprintf( "%02d:%02d", $hour, $min ); + fhem "define $atName at *" + . sprintf( "%02d:%02d", $hour, $min ) + . " { RESIDENTStk_wakeupRun(\"$NAME\") }"; + if ($room) { fhem "attr $atName room $room" } + } + elsif ( $defs{$atName}{TYPE} ne "at" ) { + Log3 $NAME, 3, +"RESIDENTStk $NAME: WARNING - defined device '$atName' is not an at device!"; + } + else { + Log3 $NAME, 4, "RESIDENTStk $NAME: $atName modified to " + . sprintf( "%02d:%02d", $hour, $min ); + fhem "modify $atName *" . sprintf( "%02d:%02d", $hour, $min ); + } + } + else { + Log3 $NAME, 4, "RESIDENTStk $NAME: alarm set to OFF"; + } + + # autosave + if ($autosave) { fhem "save" } + + return undef; +} + +##################################### +# Use DUMMY device to run wakup event +# +sub RESIDENTStk_wakeupRun($) { + my ($NAME) = @_; + + my $wakeupMacro = AttrVal( $NAME, "wakeupMacro", 0 ); + my $wakeupDefaultTime = AttrVal( $NAME, "wakeupDefaultTime", 0 ); + my $wakeupUserdevice = AttrVal( $NAME, "wakeupUserdevice", 0 ); + my $wakeupDays = AttrVal( $NAME, "wakeupDays", 0 ); + my $wakeupResetdays = AttrVal( $NAME, "wakeupResetdays", 0 ); + + my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) = + localtime(time); + + my @days = ($wday); + if ($wakeupDays) { + @days = split /,/, $wakeupDays; + } + + my @rdays = ($wday); + if ($wakeupResetdays) { + @rdays = split /,/, $wakeupResetdays; + } + + if ( !defined( $defs{$NAME} ) ) { + Log3 $NAME, 3, "RESIDENTStk $NAME: Non existing device"; + return "$NAME: Non existing device"; + } + elsif ( ReadingsVal( $NAME, "state", "OFF" ) eq "OFF" ) { + Log3 $NAME, 4, + "RESIDENTStk $NAME: alarm set to OFF - not running any action"; + return; + } + elsif ( !$wakeupUserdevice ) { + Log3 $NAME, 4, "RESIDENTStk $NAME: missing attribute wakeupUserdevice"; + return "$NAME: missing attribute wakeupUserdevice"; + } + elsif ( !defined( $defs{$wakeupUserdevice} ) ) { + Log3 $NAME, 4, + "RESIDENTStk $NAME: Non existing wakeupUserdevice $wakeupUserdevice"; + return "$NAME: Non existing wakeupUserdevice $wakeupUserdevice"; + } + elsif ($defs{$wakeupUserdevice}{TYPE} ne "ROOMMATE" + && $defs{$wakeupUserdevice}{TYPE} ne "GUEST" ) + { + Log3 $NAME, 4, +"RESIDENTStk $NAME: device $wakeupUserdevice is not of type ROOMMATE or GUEST"; + return + "$NAME: device $wakeupUserdevice is not of type ROOMMATE or GUEST"; + } + elsif ( $defs{$wakeupUserdevice}{TYPE} eq "GUEST" + && ReadingsVal( $wakeupUserdevice, "state", "" ) eq "none" ) + { + fhem "set $NAME OFF"; + return; + } + elsif ($wday ~~ @days + && ReadingsVal( $wakeupUserdevice, "state", "" ) ne "absent" + && ReadingsVal( $wakeupUserdevice, "state", "" ) ne "gone" ) + { + if ( !$wakeupMacro ) { + Log3 $NAME, 2, "RESIDENTStk $NAME: missing attribute wakeupMacro"; + return "$NAME: missing attribute wakeupMacro"; + } + elsif ( !defined( $defs{$wakeupMacro} ) ) { + Log3 $NAME, 2, +"RESIDENTStk $NAME: notify macro $wakeupMacro not found - no wakeup actions defined!"; + return +"$NAME: notify macro $wakeupMacro not found - no wakeup actions defined!"; + } + elsif ( $defs{$wakeupMacro}{TYPE} ne "notify" ) { + Log3 $NAME, 2, + "RESIDENTStk $NAME: device $wakeupMacro is not of type notify"; + return "$NAME: device $wakeupMacro is not of type notify"; + } + else { + Log3 $NAME, 4, "RESIDENTStk $NAME: trigger $wakeupMacro"; + fhem "trigger $wakeupMacro"; + } + } + + if ( $wakeupDefaultTime && $wday ~~ @rdays ) { + Log3 $NAME, 4, + "RESIDENTStk $NAME: Resetting based on wakeupDefaultTime"; + fhem "set $NAME $wakeupDefaultTime"; + } + + return undef; +} + +1; diff --git a/fhem/HISTORY b/fhem/HISTORY index 4b4d90953..685b40173 100644 --- a/fhem/HISTORY +++ b/fhem/HISTORY @@ -613,3 +613,7 @@ - Fri Jan 30 2015 (fhainz) - added new module 70_Pushbullet + +- Wed Mar 11 2015 (loredo) + - added new RESIDENTS toolkit functions for RESIDENTS, ROOMMMATE and GUEST devices + first function: wakeuptimer diff --git a/fhem/MAINTAINER.txt b/fhem/MAINTAINER.txt index fae3307fa..5dc2c6737 100644 --- a/fhem/MAINTAINER.txt +++ b/fhem/MAINTAINER.txt @@ -302,6 +302,7 @@ FHEM/OWX_DS2480.pm ntruchsess http://forum.fhem.de 1Wire FHEM/OWX_DS9097.pm ntruchsess http://forum.fhem.de 1Wire FHEM/OWX_FRM.pm ntruchsess http://forum.fhem.de 1Wire FHEM/OWX_SER.pm ntruchsess http://forum.fhem.de 1Wire +FHEM/RESIDENTStk.pm loredo http://forum.fhem.de Automatisierung FHEM/SetExtensions.pm rudolfkoenig http://forum.fhem.de Automatisierung FHEM/SHC_datafields.pm rr2000 http://forum.fhem.de Sonstige Systeme FHEM/SHC_parser.pm rr2000 http://forum.fhem.de Sonstige Systeme