diff --git a/fhem/FHEM/10_RESIDENTS.pm b/fhem/FHEM/10_RESIDENTS.pm index 19792ad4c..5fc0d4c5b 100644 --- a/fhem/FHEM/10_RESIDENTS.pm +++ b/fhem/FHEM/10_RESIDENTS.pm @@ -62,7 +62,7 @@ sub RESIDENTS_Initialize($) { $hash->{NotifyFn} = "RESIDENTS_Notify"; $hash->{UndefFn} = "RESIDENTS_Undefine"; $hash->{AttrList} = - "rgr_showAllStates:0,1 rgr_states rgr_wakeupDevice " +"rgr_showAllStates:0,1 rgr_states:multiple-strict,home,gotosleep,asleep,awoken,absent,gone rgr_wakeupDevice " . $readingFnAttributes; } @@ -87,6 +87,15 @@ sub RESIDENTS_Define($$) { $attr{$name}{webCmd} = "state"; } + # Injecting AttrFn for use with RESIDENTS Toolkit + if ( !defined( $modules{dummy}{AttrFn} ) ) { + $modules{dummy}{AttrFn} = "RESIDENTStk_AttrFnDummy"; + } + elsif ( $modules{dummy}{AttrFn} ne "RESIDENTStk_AttrFnDummy" ) { + Log3 $name, 5, +"RESIDENTStk $name: concurrent AttrFn already defined for dummy module. Some attribute based functions like auto-creations will not be available."; + } + return undef; } @@ -128,7 +137,6 @@ sub RESIDENTS_Notify($$) { my ( $hash, $dev ) = @_; my $devName = $dev->{NAME}; my $hashName = $hash->{NAME}; - my $hashName_attr; # process child notifies if ( $devName ne $hashName ) { @@ -194,23 +202,72 @@ sub RESIDENTS_Notify($$) { } } - # process only registered devices for wakeup function - if ( @registeredWakeupdevs && $devName ~~ @registeredWakeupdevs ) { + # if we have registered wakeup devices + if (@registeredWakeupdevs) { - return - if ( !$dev->{CHANGED} ); # Some previous notify deleted the array. + # if this is a notification of a registered wakeup device + if ( $devName ~~ @registeredWakeupdevs ) { - foreach my $change ( @{ $dev->{CHANGED} } ) { + # Some previous notify deleted the array. + return + if ( !$dev->{CHANGED} ); - # state changed - if ( $change =~ /OFF|([0-9]{2}:[0-9]{2})/ ) { - Log3 $hash, 4, - "RESIDENTS " - . $hashName . ": " - . $devName - . ": notify about change to $change"; + foreach my $change ( @{ $dev->{CHANGED} } ) { - return RESIDENTStk_wakeupSet( $devName, $change ); + # state changed + if ( $change =~ /OFF|([0-9]{2}:[0-9]{2})/ ) { + Log3 $hash, 4, + "RESIDENTS " + . $hashName . ": " + . $devName + . ": notify about change to $change"; + + RESIDENTStk_wakeupSet( $devName, $change ); + } + else { + Log3 $hash, 5, + "RESIDENTS " + . $hashName . ": " + . $devName + . ": received unhandled notify about change $change"; + } + } + } + + # stuff for every registered wakeupdev + foreach my $wakeupDev (@registeredWakeupdevs) { + + # if this is a notification of a registered sub dummy device + # of one of our wakeup devices + if ( defined( $attr{$wakeupDev}{wakeupResetSwitcher} ) + && $attr{$wakeupDev}{wakeupResetSwitcher} eq $devName + && $defs{$devName}{TYPE} eq "dummy" ) + { + + # Some previous notify deleted the array. + return + if ( !$dev->{CHANGED} ); + + foreach my $change ( @{ $dev->{CHANGED} } ) { + + # state changed to on + if ( $change eq "auto" ) { + Log3 $hash, 4, + "RESIDENTS " + . $hashName . ": " + . $devName + . ": notify about change to $change"; + + RESIDENTStk_wakeupSet($wakeupDev); + } + else { + Log3 $hash, 5, + "RESIDENTS " + . $hashName . ": " + . $devName + . ": received unhandled notify about change $change"; + } + } } } } @@ -527,12 +584,13 @@ sub RESIDENTS_Set($@) { # 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 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 icon time_timer"; fhem "attr $wakeuptimerName room " . $attr{$name}{room} if ( defined( $attr{$name}{room} ) ); fhem @@ -556,7 +614,7 @@ sub RESIDENTS_Set($@) { $created = 1; return -"Dummy $wakeuptimerName and other pending devices created and pre-configured. You may edit Macro_$wakeuptimerName to define your wake-up actions."; +"Dummy $wakeuptimerName and other pending devices created and pre-configured. You may edit Macro_$wakeuptimerName to define your wake-up actions and at_$wakeuptimerName for optional at-device adjustments."; } } } @@ -1176,6 +1234,9 @@ sub RESIDENTS_Datetime2Timestamp($) { 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:
+
  • + wakeupAtdevice - backlink the at device (mandatory) +
  • wakeupAutosave - Triggers FHEM command 'save' after adjusting wake-up time value (defaults to 0=false)
  • @@ -1194,6 +1255,9 @@ sub RESIDENTS_Datetime2Timestamp($) {
  • 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)
  • +
  • + wakeupResetSwitcher - DUMMY device to quickly turn on/off reset function (optional, device will be auto-created/-deleted) +
  • wakeupUserdevice - backlink to RESIDENTS, ROOMMATE or GUEST device to check it's status (mandatory)
  • @@ -1402,6 +1466,9 @@ sub RESIDENTS_Datetime2Timestamp($) { 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:
    +
  • + wakeupAtdevice - Backlink zum at Gerät (notwendig) +
  • wakeupAutosave - Löst das FHEM Kommando 'save' nach einer Änderung der Weckzeit aus (Standard 0=aus)
  • @@ -1420,6 +1487,9 @@ sub RESIDENTS_Datetime2Timestamp($) {
  • 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)
  • +
  • + wakeupResetSwitcher - das DUMMY Device, welches zum schnellen ein/aus schalten der Resetfunktion verwendet wird (optional, Device wird automatisch angelegt/gelöscht) +
  • wakeupUserdevice - Backlink zum RESIDENTS, ROOMMATE oder GUEST Gerät, um dessen Status zu prüfen (notwendig)
  • diff --git a/fhem/FHEM/20_GUEST.pm b/fhem/FHEM/20_GUEST.pm index e394a7afa..5aee26684 100644 --- a/fhem/FHEM/20_GUEST.pm +++ b/fhem/FHEM/20_GUEST.pm @@ -62,7 +62,7 @@ sub GUEST_Initialize($) { $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_wakeupDevice " +"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:multiple-strict,home,gotosleep,asleep,awoken,absent,gone rg_locations rg_moods rg_moodDefault rg_moodSleepy rg_noDuration:0,1 rg_wakeupDevice " . $readingFnAttributes; } @@ -163,6 +163,15 @@ sub GUEST_Define($$) { # run timers InternalTimer( gettimeofday() + 15, "GUEST_StartInternalTimers", $hash, 0 ); + # Injecting AttrFn for use with RESIDENTS Toolkit + if ( !defined( $modules{dummy}{AttrFn} ) ) { + $modules{dummy}{AttrFn} = "RESIDENTStk_AttrFnDummy"; + } + elsif ( $modules{dummy}{AttrFn} ne "RESIDENTStk_AttrFnDummy" ) { + Log3 $name, 5, +"RESIDENTStk $name: concurrent AttrFn already defined for dummy module. Some attribute based functions like auto-creations will not be available."; + } + return undef; } @@ -197,7 +206,6 @@ sub GUEST_Notify($$) { my ( $hash, $dev ) = @_; my $devName = $dev->{NAME}; my $hashName = $hash->{NAME}; - my $hashName_attr; # process child notifies if ( $devName ne $hashName ) { @@ -206,23 +214,72 @@ sub GUEST_Notify($$) { if ( defined( $attr{$hashName}{rg_wakeupDevice} ) && $attr{$hashName}{rg_wakeupDevice} ne "" ); - # process only registered devices for wakeup function - if ( @registeredWakeupdevs && $devName ~~ @registeredWakeupdevs ) { + # if we have registered wakeup devices + if (@registeredWakeupdevs) { - return - if ( !$dev->{CHANGED} ); # Some previous notify deleted the array. + # if this is a notification of a registered wakeup device + if ( $devName ~~ @registeredWakeupdevs ) { - foreach my $change ( @{ $dev->{CHANGED} } ) { + # Some previous notify deleted the array. + return + if ( !$dev->{CHANGED} ); - # state changed - if ( $change =~ /OFF|([0-9]{2}:[0-9]{2})/ ) { - Log3 $hash, 4, - "GUEST " - . $hashName . ": " - . $devName - . ": notify about change to $change"; + foreach my $change ( @{ $dev->{CHANGED} } ) { - return RESIDENTStk_wakeupSet( $devName, $change ); + # state changed + if ( $change =~ /OFF|([0-9]{2}:[0-9]{2})/ ) { + Log3 $hash, 4, + "GUEST " + . $hashName . ": " + . $devName + . ": notify about change to $change"; + + RESIDENTStk_wakeupSet( $devName, $change ); + } + else { + Log3 $hash, 5, + "GUEST " + . $hashName . ": " + . $devName + . ": received unhandled notify about change $change"; + } + } + } + + # stuff for every registered wakeupdev + foreach my $wakeupDev (@registeredWakeupdevs) { + + # if this is a notification of a registered sub dummy device + # of one of our wakeup devices + if ( defined( $attr{$wakeupDev}{wakeupResetSwitcher} ) + && $attr{$wakeupDev}{wakeupResetSwitcher} eq $devName + && $defs{$devName}{TYPE} eq "dummy" ) + { + + # Some previous notify deleted the array. + return + if ( !$dev->{CHANGED} ); + + foreach my $change ( @{ $dev->{CHANGED} } ) { + + # state changed to on + if ( $change eq "auto" ) { + Log3 $hash, 4, + "GUEST " + . $hashName . ": " + . $devName + . ": notify about change to $change"; + + RESIDENTStk_wakeupSet($wakeupDev); + } + else { + Log3 $hash, 5, + "GUEST " + . $hashName . ": " + . $devName + . ": received unhandled notify about change $change"; + } + } } } } @@ -726,12 +783,13 @@ sub GUEST_Set($@) { # 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 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 icon time_timer"; fhem "attr $wakeuptimerName room " . $attr{$name}{room} if ( defined( $attr{$name}{room} ) ); fhem @@ -755,7 +813,7 @@ sub GUEST_Set($@) { $created = 1; return -"Dummy $wakeuptimerName and other pending devices created and pre-configured. You may edit Macro_$wakeuptimerName to define your wake-up actions."; +"Dummy $wakeuptimerName and other pending devices created and pre-configured. You may edit Macro_$wakeuptimerName to define your wake-up actions and at_$wakeuptimerName for optional at-device adjustments."; } } } diff --git a/fhem/FHEM/20_ROOMMATE.pm b/fhem/FHEM/20_ROOMMATE.pm index 2aefca873..f64366619 100644 --- a/fhem/FHEM/20_ROOMMATE.pm +++ b/fhem/FHEM/20_ROOMMATE.pm @@ -62,7 +62,7 @@ sub ROOMMATE_Initialize($) { $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_wakeupDevice " +"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:multiple-strict,home,gotosleep,asleep,awoken,absent,gone rr_locations rr_moods rr_moodDefault rr_moodSleepy rr_passPresenceTo rr_noDuration:0,1 rr_wakeupDevice " . $readingFnAttributes; } @@ -168,6 +168,15 @@ sub ROOMMATE_Define($$) { $hash, 0 ); + # Injecting AttrFn for use with RESIDENTS Toolkit + if ( !defined( $modules{dummy}{AttrFn} ) ) { + $modules{dummy}{AttrFn} = "RESIDENTStk_AttrFnDummy"; + } + elsif ( $modules{dummy}{AttrFn} ne "RESIDENTStk_AttrFnDummy" ) { + Log3 $name, 5, +"RESIDENTStk $name: concurrent AttrFn already defined for dummy module. Some attribute based functions like auto-creations will not be available."; + } + return undef; } @@ -202,7 +211,6 @@ sub ROOMMATE_Notify($$) { my ( $hash, $dev ) = @_; my $devName = $dev->{NAME}; my $hashName = $hash->{NAME}; - my $hashName_attr; # process child notifies if ( $devName ne $hashName ) { @@ -211,23 +219,72 @@ sub ROOMMATE_Notify($$) { if ( defined( $attr{$hashName}{rr_wakeupDevice} ) && $attr{$hashName}{rr_wakeupDevice} ne "" ); - # process only registered devices for wakeup function - if ( @registeredWakeupdevs && $devName ~~ @registeredWakeupdevs ) { + # if we have registered wakeup devices + if (@registeredWakeupdevs) { - return - if ( !$dev->{CHANGED} ); # Some previous notify deleted the array. + # if this is a notification of a registered wakeup device + if ( $devName ~~ @registeredWakeupdevs ) { - foreach my $change ( @{ $dev->{CHANGED} } ) { + # Some previous notify deleted the array. + return + if ( !$dev->{CHANGED} ); - # state changed - if ( $change =~ /OFF|([0-9]{2}:[0-9]{2})/ ) { - Log3 $hash, 4, - "ROOMMATE " - . $hashName . ": " - . $devName - . ": notify about change to $change"; + foreach my $change ( @{ $dev->{CHANGED} } ) { - return RESIDENTStk_wakeupSet( $devName, $change ); + # state changed + if ( $change =~ /OFF|([0-9]{2}:[0-9]{2})/ ) { + Log3 $hash, 4, + "ROOMMATE " + . $hashName . ": " + . $devName + . ": notify about change to $change"; + + RESIDENTStk_wakeupSet( $devName, $change ); + } + else { + Log3 $hash, 5, + "ROOMMATE " + . $hashName . ": " + . $devName + . ": received unhandled notify about change $change"; + } + } + } + + # stuff for every registered wakeupdev + foreach my $wakeupDev (@registeredWakeupdevs) { + + # if this is a notification of a registered sub dummy device + # of one of our wakeup devices + if ( defined( $attr{$wakeupDev}{wakeupResetSwitcher} ) + && $attr{$wakeupDev}{wakeupResetSwitcher} eq $devName + && $defs{$devName}{TYPE} eq "dummy" ) + { + + # Some previous notify deleted the array. + return + if ( !$dev->{CHANGED} ); + + foreach my $change ( @{ $dev->{CHANGED} } ) { + + # state changed to on + if ( $change eq "auto" ) { + Log3 $hash, 4, + "ROOMMATE " + . $hashName . ": " + . $devName + . ": notify about change to $change"; + + RESIDENTStk_wakeupSet($wakeupDev); + } + else { + Log3 $hash, 5, + "ROOMMATE " + . $hashName . ": " + . $devName + . ": received unhandled notify about change $change"; + } + } } } } @@ -708,12 +765,13 @@ sub ROOMMATE_Set($@) { # 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 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 icon time_timer"; fhem "attr $wakeuptimerName room " . $attr{$name}{room} if ( defined( $attr{$name}{room} ) ); fhem @@ -737,7 +795,7 @@ sub ROOMMATE_Set($@) { $created = 1; return -"Dummy $wakeuptimerName and other pending devices created and pre-configured. You may edit Macro_$wakeuptimerName to define your wake-up actions."; +"Dummy $wakeuptimerName and other pending devices created and pre-configured. You may edit Macro_$wakeuptimerName to define your wake-up actions and at_$wakeuptimerName for optional at-device adjustments."; } } } diff --git a/fhem/FHEM/RESIDENTStk.pm b/fhem/FHEM/RESIDENTStk.pm index fb736116c..32c3a2d2c 100644 --- a/fhem/FHEM/RESIDENTStk.pm +++ b/fhem/FHEM/RESIDENTStk.pm @@ -34,51 +34,97 @@ ##################################### # Enslave DUMMY device to be used for alarm clock # -sub RESIDENTStk_wakeupSet($$) { +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; + my $userattr = AttrVal( $NAME, "userattr", 0 ); + my $autosave = AttrVal( $NAME, "wakeupAutosave", 0 ); + my $wakeupDefaultTime = AttrVal( $NAME, "wakeupDefaultTime", 0 ); + my $wakeupMacro = AttrVal( $NAME, "wakeupMacro", 0 ); + my $wakeupAtdevice = AttrVal( $NAME, "wakeupAtdevice", 0 ); + my $wakeupOffset = AttrVal( $NAME, "wakeupOffset", "0" ); + my $room = AttrVal( $NAME, "room", 0 ); + my $macroName = "Macro_" . $NAME; + my $atName = "at_" . $NAME; + + if ( !$VALUE ) { + if ($wakeupDefaultTime) { + Log3 $NAME, 4, + "RESIDENTStk $NAME: Resetting based on wakeupDefaultTime"; + fhem + "set $NAME:FILTER=state!=$wakeupDefaultTime $wakeupDefaultTime"; + } + return; + } # 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"; +"wakeupOffset:slider,0,1,120 wakeupDefaultTime:time wakeupMacro wakeupUserdevice wakeupAtdevice wakeupResetSwitcher 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"; } + # check for required wakeupMacro 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 notify device + if ( !defined( $defs{$wakeupMacro} ) ) { + Log3 $NAME, 3, + "RESIDENTStk $NAME: new notify macro device $wakeupMacro created"; + fhem "define $wakeupMacro notify $wakeupMacro {}"; + fhem + "attr $wakeupMacro comment Macro auto-created by RESIDENTS Toolkit"; + 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 wakeupAtdevice attribute + if ( !$wakeupAtdevice ) { + Log3 $NAME, 3, +"RESIDENTStk $NAME: adjusting dummy device for required attribute wakeupAtdevice"; + fhem "attr $NAME wakeupAtdevice $atName"; + $wakeupAtdevice = $atName; + } + + # check for existing at device + if ( !defined( $defs{$wakeupAtdevice} ) ) { + Log3 $NAME, 3, + "RESIDENTStk $NAME: new at device $wakeupAtdevice created"; + fhem +"define $wakeupAtdevice at *08:00 { RESIDENTStk_wakeupRun(\"$NAME\") }"; + fhem "attr $wakeupAtdevice comment Auto-created by RESIDENTS Toolkit"; + if ($room) { fhem "attr $wakeupAtdevice room $room" } + } + +# Reset at device if wake-up timer was disabled and wakeupDefaultTime is present + if ( $VALUE eq "OFF" ) { + Log3 $NAME, 4, "RESIDENTStk $NAME: Wake-up timer disabled"; + if ($wakeupDefaultTime) { + $VALUE = $wakeupDefaultTime; + Log3 $NAME, 4, +"RESIDENTStk $NAME: Wake-up timer disabled and triggered at device reset"; + } + else { + Log3 $NAME, 4, "RESIDENTStk $NAME: Wake-up timer disabled"; + } + } + + # Recalculate new wake-up value if ( $VALUE ne "OFF" ) { my @time = split /:/, $VALUE; my $time_sec = $time[0] * 3600 + $time[1] * 60; @@ -88,27 +134,19 @@ sub RESIDENTStk_wakeupSet($$) { 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" ) { + if ( $defs{$wakeupAtdevice}{TYPE} ne "at" ) { Log3 $NAME, 3, -"RESIDENTStk $NAME: WARNING - defined device '$atName' is not an at device!"; +"RESIDENTStk $NAME: ERROR - defined device '$wakeupAtdevice' is not an at device!"; } else { - Log3 $NAME, 4, "RESIDENTStk $NAME: $atName modified to " + fhem "modify $wakeupAtdevice *" + . sprintf( "%02d:%02d", $hour, $min ); + + Log3 $NAME, 4, + "RESIDENTStk $NAME($wakeupAtdevice): Wake-up begin scheduled for " . 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" } @@ -122,11 +160,12 @@ sub RESIDENTStk_wakeupSet($$) { 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 $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 $wakeupResetSwitcher = AttrVal( $NAME, "wakeupResetSwitcher", 0 ); my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) = localtime(time); @@ -148,7 +187,6 @@ sub RESIDENTStk_wakeupRun($) { 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"; @@ -198,10 +236,82 @@ sub RESIDENTStk_wakeupRun($) { } } - if ( $wakeupDefaultTime && $wday ~~ @rdays ) { + my $doReset = 1; + if ( $wakeupResetSwitcher + && defined( $defs{$wakeupResetSwitcher} ) + && $defs{$wakeupResetSwitcher}{TYPE} eq "dummy" + && ReadingsVal( $wakeupResetSwitcher, "state", 0 ) eq "off" ) + { + $doReset = 0; + } + + if ( $wakeupDefaultTime && $wday ~~ @rdays && $doReset ) { Log3 $NAME, 4, "RESIDENTStk $NAME: Resetting based on wakeupDefaultTime"; - fhem "set $NAME $wakeupDefaultTime"; + fhem "set $NAME:FILTER=state!=$wakeupDefaultTime $wakeupDefaultTime"; + } + + return undef; +} + +##################################### +# AttFn for enslaved dummy devices +# +sub RESIDENTStk_AttrFnDummy(@) { + my ( $cmd, $name, $aName, $aVal ) = @_; + + # set attribute + if ( $cmd eq "set" ) { + + # wakeupResetSwitcher + if ( $aName eq "wakeupResetSwitcher" ) { + if ( !defined( $defs{$aVal} ) ) { + my $alias = AttrVal( $name, "alias", 0 ); + my $group = AttrVal( $name, "group", 0 ); + my $room = AttrVal( $name, "room", 0 ); + + fhem "define $aVal dummy"; + fhem "attr $aVal comment Auto-created by RESIDENTS Toolkit"; + if ($alias) { + fhem "attr $aVal alias $alias Reset"; + } + else { + fhem "attr $aVal alias Wake-up Timer Reset"; + } + fhem +"attr $aVal devStateIcon auto:time_automatic:off off:time_manual_mode:auto"; + if ($group) { fhem "attr $aVal group $group" } + fhem "attr $aVal icon refresh"; + if ($room) { fhem "attr $aVal room $room" } + fhem "attr $aVal setList state:auto,off"; + fhem "attr $aVal webCmd state"; + fhem "set $aVal auto"; + + Log3 $name, 3, + "RESIDENTStk $name: new slave dummy device $aVal created"; + } + elsif ( $defs{$aVal}{TYPE} ne "dummy" ) { + Log3 $name, 3, +"RESIDENTStk $name: Defined device name in attr $aName is not a dummy device"; + return "Existing device $aVal is not a dummy!"; + } + } + + } + + # del attribute + elsif ( $cmd eq "del" ) { + + # wakeupResetSwitcher + if ( $aName eq "wakeupResetSwitcher" ) { + if ( defined( $defs{$aVal} ) && $defs{$aVal}{TYPE} eq "dummy" ) { + fhem "delete $aVal"; + + Log3 $name, 3, + "RESIDENTStk $name: slave dummy device $aVal deleted"; + } + } + } return undef;