# $Id$ ############################################################################## # # 10_RESIDENTS.pm # An FHEM Perl module to ease resident administration. # # 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 . # ############################################################################## package main; use strict; use warnings; use Time::Local; use Data::Dumper; require RESIDENTStk; sub RESIDENTS_Set($@); sub RESIDENTS_Define($$); sub RESIDENTS_Notify($$); sub RESIDENTS_Undefine($$); ################################### sub RESIDENTS_Initialize($) { my ($hash) = @_; Log3 $hash, 5, "RESIDENTS_Initialize: Entering"; $hash->{SetFn} = "RESIDENTS_Set"; $hash->{DefFn} = "RESIDENTS_Define"; $hash->{NotifyFn} = "RESIDENTS_Notify"; $hash->{UndefFn} = "RESIDENTS_Undefine"; $hash->{AttrList} = "rgr_showAllStates:0,1 rgr_states:multiple-strict,home,gotosleep,asleep,awoken,absent,gone rgr_wakeupDevice " . $readingFnAttributes; } ################################### sub RESIDENTS_Define($$) { my ( $hash, $def ) = @_; my $name = $hash->{NAME}; my $name_attr; Log3 $name, 5, "RESIDENTS $name: called function RESIDENTS_Define()"; $hash->{TYPE} = "RESIDENTS"; # set default settings on first define if ($init_done) { $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 .*:user_unknown:home'; $attr{$name}{group} = "Home State"; $attr{$name}{icon} = "control_building_filled"; $attr{$name}{room} = "Residents"; $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; } ################################### sub RESIDENTS_Undefine($$) { my ( $hash, $name ) = @_; # delete child roommates if ( defined( $hash->{ROOMMATES} ) && $hash->{ROOMMATES} ne "" ) { my @registeredRoommates = split( /,/, $hash->{ROOMMATES} ); foreach my $child (@registeredRoommates) { fhem( "delete " . $child ); Log3 $name, 3, "RESIDENTS $name: deleted device $child"; } } # delete child guests if ( defined( $hash->{GUESTS} ) && $hash->{GUESTS} ne "" ) { my @registeredGuests = split( /,/, $hash->{GUESTS} ); foreach my $child (@registeredGuests) { fhem( "delete " . $child ); Log3 $name, 3, "RESIDENTS $name: deleted device $child"; } } return undef; } ################################### sub RESIDENTS_Notify($$) { my ( $hash, $dev ) = @_; my $devName = $dev->{NAME}; my $hashName = $hash->{NAME}; # process child notifies if ( $devName ne $hashName ) { my @registeredRoommates = split( /,/, $hash->{ROOMMATES} ) if ( defined( $hash->{ROOMMATES} ) && $hash->{ROOMMATES} ne "" ); my @registeredGuests = split( /,/, $hash->{GUESTS} ) 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 ) ) { return if ( !$dev->{CHANGED} ); # Some previous notify deleted the array. readingsBeginUpdate($hash); foreach my $change ( @{ $dev->{CHANGED} } ) { Log3 $hash, 5, "RESIDENTS " . $hashName . ": processing change $change"; # state changed if ( $change !~ /:/ || $change =~ /wayhome:/ || $change =~ /wakeup:/ ) { Log3 $hash, 4, "RESIDENTS " . $hashName . ": " . $devName . ": notify about change to $change"; RESIDENTS_UpdateReadings($hash); } # activity if ( $change !~ /:/ ) { # get user realname my $realnamesrc; if ( $dev->{TYPE} eq "GUEST" ) { $realnamesrc = ( defined( $attr{$devName}{rg_realname} ) && $attr{$devName}{rg_realname} ne "" ? $attr{$devName}{rg_realname} : "alias" ); } else { $realnamesrc = ( defined( $attr{$devName}{rr_realname} ) && $attr{$devName}{rr_realname} ne "" ? $attr{$devName}{rr_realname} : "group" ); } my $realname = ( defined( $attr{$devName}{$realnamesrc} ) && $attr{$devName}{$realnamesrc} ne "" ? $attr{$devName}{$realnamesrc} : $devName ); # update statistics readingsBulkUpdate( $hash, "lastActivity", ReadingsVal( $devName, "state", $change ) ); readingsBulkUpdate( $hash, "lastActivityBy", $realname ); readingsBulkUpdate( $hash, "lastActivityByDev", $devName ); } } readingsEndUpdate( $hash, 1 ); return; } # if we have registered wakeup devices if (@registeredWakeupdevs) { # if this is a notification of a registered wakeup device if ( $devName ~~ @registeredWakeupdevs ) { # Some previous notify deleted the array. return if ( !$dev->{CHANGED} ); foreach my $change ( @{ $dev->{CHANGED} } ) { RESIDENTStk_wakeupSet( $devName, $change ); } return; } # process sub-child notifies: *_wakeupDevice 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} } ) { RESIDENTStk_wakeupSet( $wakeupDev, $change ) if ( $change ne "off" ); } last; } } } } return; } ################################### sub RESIDENTS_Set($@) { my ( $hash, @a ) = @_; my $name = $hash->{NAME}; my $state = ReadingsVal( $name, "state", "initialized" ); my $roommates = ( $hash->{ROOMMATES} ? $hash->{ROOMMATES} : "" ); my $guests = ( $hash->{GUESTS} ? $hash->{GUESTS} : "" ); Log3 $name, 5, "RESIDENTS $name: called function RESIDENTS_Set()"; return "No Argument given" if ( !defined( $a[1] ) ); # depending on current FHEMWEB instance's allowedCommands, # restrict set commands if there is "set-user" in it my $adminMode = 1; my $FWallowedCommands = 0; $FWallowedCommands = AttrVal( $FW_wname, "allowedCommands", 0 ) if ( defined($FW_wname) ); if ( $FWallowedCommands && $FWallowedCommands =~ m/\bset-user\b/ ) { $adminMode = 0; return "Forbidden command: set " . $a[1] if ( lc( $a[1] ) eq "addroommate" || lc( $a[1] ) eq "addguest" || lc( $a[1] ) eq "removeroommate" || lc( $a[1] ) eq "removeguest" || lc( $a[1] ) eq "create" ); } # states my $states = ( defined( $attr{$name}{rgr_states} ) ? $attr{$name}{rgr_states} : ( defined( $attr{$name}{rgr_showAllStates} ) && $attr{$name}{rgr_showAllStates} == 1 ? "home,gotosleep,asleep,awoken,absent,gone" : "home,gotosleep,absent,gone" ) ); $states = $state . "," . $states if ( $state ne "initialized" && $states !~ /$state/ ); my $usage = "Unknown argument " . $a[1] . ", choose one of state:$states"; if ($adminMode) { $usage .= " addRoommate addGuest"; $usage .= " removeRoommate:" . $roommates if ( $roommates ne "" ); $usage .= " removeGuest:" . $guests if ( $guests ne "" ); $usage .= " create:wakeuptimer"; } # states if ( $a[1] eq "state" || $a[1] eq "home" || $a[1] eq "gotosleep" || $a[1] eq "asleep" || $a[1] eq "awoken" || $a[1] eq "absent" || $a[1] eq "gone" ) { my $newstate; my $presence = "absent"; # if not direct if ( $a[1] eq "state" && defined( $a[2] ) && ( $a[2] eq "home" || $a[2] eq "gotosleep" || $a[2] eq "asleep" || $a[2] eq "awoken" || $a[2] eq "absent" || $a[2] eq "gone" ) ) { $newstate = $a[2]; } elsif ( defined( $a[2] ) ) { return "Invalid 2nd argument, choose one of home gotosleep asleep awoken absent gone "; } else { $newstate = $a[1]; } Log3 $name, 2, "RESIDENTS set $name " . $newstate; # loop through every roommate if ( defined( $hash->{ROOMMATES} ) && $hash->{ROOMMATES} ne "" ) { my @registeredRoommates = split( /,/, $hash->{ROOMMATES} ); foreach my $roommate (@registeredRoommates) { fhem "set $roommate silentSet state $newstate" if ( ReadingsVal( $roommate, "state", "initialized" ) ne $newstate ); } } # loop through every guest if ( defined( $hash->{GUESTS} ) && $hash->{GUESTS} ne "" ) { $newstate = "none" if ( $newstate eq "gone" ); my @registeredGuests = split( /,/, $hash->{GUESTS} ); foreach my $guest (@registeredGuests) { fhem "set $guest silentSet state $newstate" if ( ReadingsVal( $guest, "state", "initialized" ) ne $newstate ); } } } # addRoommate elsif ( $a[1] eq "addRoommate" ) { Log3 $name, 2, "RESIDENTS set $name " . $a[1] . " " . $a[2] if ( defined( $a[2] ) ); my $rr_name; my $rr_name_attr; if ( $a[2] ne "" ) { $rr_name = "rr_" . $a[2]; # define roommate if ( !defined( $defs{$rr_name} ) ) { fhem( "define " . $rr_name . " ROOMMATE " . $name ); if ( defined( $defs{$rr_name} ) ) { fhem "set $rr_name silentSet state home"; Log3 $name, 3, "RESIDENTS $name: created new device $rr_name"; } } else { return "Can't create, device $rr_name already existing."; } } else { return "No Argument given, choose one of name "; } } # removeRoommate elsif ( $a[1] eq "removeRoommate" ) { Log3 $name, 2, "RESIDENTS set $name " . $a[1] . " " . $a[2] if ( defined( $a[2] ) ); if ( $a[2] ne "" ) { my $rr_name = $a[2]; # delete roommate if ( defined( $defs{$rr_name} ) ) { Log3 $name, 3, "RESIDENTS $name: deleted device $rr_name" if fhem( "delete " . $rr_name ); } } else { return "No Argument given, choose one of name "; } } # addGuest elsif ( $a[1] eq "addGuest" ) { Log3 $name, 2, "RESIDENTS set $name " . $a[1] . " " . $a[2] if ( defined( $a[2] ) ); my $rg_name; my $rg_name_attr; if ( $a[2] ne "" ) { $rg_name = "rg_" . $a[2]; # define guest if ( !defined( $defs{$rg_name} ) ) { fhem( "define " . $rg_name . " GUEST " . $name ); if ( defined( $defs{$rg_name} ) ) { fhem "set $rg_name silentSet state none"; Log3 $name, 3, "RESIDENTS $name: created new device $rg_name"; } } else { return "Can't create, device $rg_name already existing."; } } else { return "No Argument given, choose one of name "; } } # removeGuest elsif ( $a[1] eq "removeGuest" ) { Log3 $name, 2, "RESIDENTS set $name " . $a[1] . " " . $a[2] if ( defined( $a[2] ) ); if ( $a[2] ne "" ) { my $rg_name = $a[2]; # delete guest if ( defined( $defs{$rg_name} ) ) { Log3 $name, 3, "RESIDENTS $name: deleted device $rg_name" if fhem( "delete " . $rg_name ); } } else { return "No Argument given, choose one of name "; } } # register elsif ( $a[1] eq "register" ) { if ( defined( $a[2] ) && $a[2] ne "" ) { return "No such device " . $a[2] if ( !defined( $defs{ $a[2] } ) ); # ROOMMATE if ( $defs{ $a[2] }{TYPE} eq "ROOMMATE" ) { Log3 $name, 4, "RESIDENTS $name: " . $a[2] . " registered"; # update readings $roommates .= ( $roommates eq "" ? $a[2] : "," . $a[2] ) if ( $roommates !~ /$a[2]/ ); $hash->{ROOMMATES} = $roommates; } # GUEST elsif ( $defs{ $a[2] }{TYPE} eq "GUEST" ) { Log3 $name, 4, "RESIDENTS $name: " . $a[2] . " registered"; # update readings $guests .= ( $guests eq "" ? $a[2] : "," . $a[2] ) if ( $guests !~ /$a[2]/ ); $hash->{GUESTS} = $guests; } # unsupported else { return "Device type is not supported."; } } else { return "No Argument given, choose one of ROOMMATE GUEST "; } } # unregister elsif ( $a[1] eq "unregister" ) { if ( defined( $a[2] ) && $a[2] ne "" ) { return "No such device " . $a[2] if ( !defined( $defs{ $a[2] } ) ); # ROOMMATE if ( $defs{ $a[2] }{TYPE} eq "ROOMMATE" ) { Log3 $name, 4, "RESIDENTS $name: " . $a[2] . " unregistered"; # update readings my $replace = "," . $a[2]; $roommates =~ s/$replace//g; $replace = $a[2] . ","; $roommates =~ s/^$replace//g; $roommates =~ s/^$a[2]//g; $hash->{ROOMMATES} = $roommates; } # GUEST elsif ( $defs{ $a[2] }{TYPE} eq "GUEST" ) { Log3 $name, 4, "RESIDENTS $name: " . $a[2] . " unregistered"; # update readings my $replace = "," . $a[2]; $guests =~ s/$replace//g; $replace = $a[2] . ","; $guests =~ s/^$replace//g; $guests =~ s/^$a[2]//g; $hash->{GUESTS} = $guests; } # unsupported else { return "Device type is not supported."; } } else { return "No Argument given, choose one of ROOMMATE GUEST "; } readingsBeginUpdate($hash); RESIDENTS_UpdateReadings($hash); readingsEndUpdate( $hash, 1 ); } # 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 { my $sortby = AttrVal( $name, "sortby", -1 ); $sortby++; # 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:reset running:general_an\@green:stop .*:general_an\@orange:nextRun%20OFF"; fhem "attr $wakeuptimerName group " . $attr{$name}{group} if ( defined( $attr{$name}{group} ) ); fhem "attr $wakeuptimerName icon time_timer"; fhem "attr $wakeuptimerName room " . $attr{$name}{room} if ( defined( $attr{$name}{room} ) ); fhem "attr $wakeuptimerName setList nextRun: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 reset:noArg trigger:noArg start:noArg stop:noArg end:noArg"; fhem "attr $wakeuptimerName userattr wakeupUserdevice"; fhem "attr $wakeuptimerName sortby " . $sortby if ($sortby); fhem "attr $wakeuptimerName wakeupUserdevice $name"; fhem "attr $wakeuptimerName webCmd nextRun"; # register slave device my $wakeupDevice = AttrVal( $name, "rgr_wakeupDevice", 0 ); if ( !$wakeupDevice ) { fhem "attr $name rgr_wakeupDevice $wakeuptimerName"; } elsif ( $wakeupDevice !~ /(.*,?)($wakeuptimerName)(.*,?)/ ) { fhem "attr $name rgr_wakeupDevice " . $wakeupDevice . ",$wakeuptimerName"; } # trigger first update fhem "set $wakeuptimerName nextRun OFF"; $created = 1; } } return "Dummy $wakeuptimerName and other pending devices created and pre-configured.\nYou may edit Macro_$wakeuptimerName to define your wake-up actions\nand at_$wakeuptimerName for optional at-device adjustments."; } else { return "Invalid 2nd argument, choose one of wakeuptimer "; } } # return usage hint else { return $usage; } return undef; } ############################################################################################################ # # Begin of helper functions # ############################################################################################################ sub RESIDENTS_UpdateReadings (@) { my ($hash) = @_; my $name = $hash->{NAME}; my $state = ReadingsVal( $name, "state", "none" ); my $presence = ReadingsVal( $name, "presence", "absent" ); my $state_home = 0; my $state_gotosleep = 0; my $state_asleep = 0; my $state_awoken = 0; my $state_absent = 0; my $state_gone = 0; my $state_total = 0; my $state_totalPresent = 0; my $state_totalAbsent = 0; my $state_totalGuests = 0; my $state_totalGuestsPresent = 0; my $state_totalGuestsAbsent = 0; my $state_totalRoommates = 0; my $state_totalRoommatesPresent = 0; my $state_totalRoommatesAbsent = 0; my $state_guestDev = 0; my $residentsDevs_home = "-"; my $residentsDevs_absent = "-"; my $residentsDevs_asleep = "-"; my $residentsDevs_awoken = "-"; my $residentsDevs_gone = "-"; my $residentsDevs_gotosleep = "-"; my $residentsDevs_wakeup = "-"; my $residentsDevs_wayhome = "-"; my $residentsDevs_wayhomeDelayed = "-"; my $residentsDevs_totalAbsent = "-"; my $residentsDevs_totalPresent = "-"; my $residentsDevs_totalAbsentGuest = "-"; my $residentsDevs_totalPresentGuest = "-"; my $residentsDevs_totalAbsentRoommates = "-"; my $residentsDevs_totalPresentRoommates = "-"; my $residents_home = "-"; my $residents_absent = "-"; my $residents_asleep = "-"; my $residents_awoken = "-"; my $residents_gone = "-"; my $residents_gotosleep = "-"; my $residents_wakeup = "-"; my $residents_wayhome = "-"; my $residents_wayhomeDelayed = "-"; my $residents_totalAbsent = "-"; my $residents_totalPresent = "-"; my $residents_totalAbsentGuest = "-"; my $residents_totalPresentGuest = "-"; my $residents_totalAbsentRoommates = "-"; my $residents_totalPresentRoommates = "-"; my $wayhome = 0; my $wayhomeDelayed = 0; my $wakeup = 0; my $newstate; my @registeredRoommates = split( /,/, $hash->{ROOMMATES} ) if ( defined( $hash->{ROOMMATES} ) && $hash->{ROOMMATES} ne "" ); my @registeredGuests = split( /,/, $hash->{GUESTS} ) if ( defined( $hash->{GUESTS} ) && $hash->{GUESTS} ne "" ); # count child states for ROOMMATE devices foreach my $roommate (@registeredRoommates) { $state_total++; $state_totalRoommates++; my $roommateName = AttrVal( $roommate, AttrVal( $roommate, "rr_realname", "alias" ), "" ); Log3 $name, 5, "RESIDENTS $name: considering $roommate for state change"; if ( ReadingsVal( $roommate, "state", "initialized" ) eq "home" ) { $state_home++; $residentsDevs_home .= "," . $roommate if ( $residentsDevs_home ne "-" ); $residentsDevs_home = $roommate if ( $residentsDevs_home eq "-" ); $residents_home .= ", " . $roommateName if ( $roommateName ne "" && $residents_home ne "-" ); $residents_home = $roommateName if ( $roommateName ne "" && $residents_home eq "-" ); $state_totalPresent++; $state_totalRoommatesPresent++; $residentsDevs_totalPresent .= "," . $roommate if ( $residentsDevs_totalPresent ne "-" ); $residentsDevs_totalPresent = $roommate if ( $residentsDevs_totalPresent eq "-" ); $residentsDevs_totalPresentRoommates .= "," . $roommate if ( $residentsDevs_totalPresentRoommates ne "-" ); $residentsDevs_totalPresentRoommates = $roommate if ( $residentsDevs_totalPresentRoommates eq "-" ); $residents_totalPresent .= ", " . $roommateName if ( $roommateName ne "" && $residents_totalPresent ne "-" ); $residents_totalPresent = $roommateName if ( $roommateName ne "" && $residents_totalPresent eq "-" ); $residents_totalPresentRoommates .= ", " . $roommateName if ( $roommateName ne "" && $residents_totalPresentRoommates ne "-" ); $residents_totalPresentRoommates = $roommateName if ( $roommateName ne "" && $residents_totalPresentRoommates eq "-" ); } elsif ( ReadingsVal( $roommate, "state", "initialized" ) eq "gotosleep" ) { $state_gotosleep++; $residentsDevs_gotosleep .= "," . $roommate if ( $residentsDevs_gotosleep ne "-" ); $residentsDevs_gotosleep = $roommate if ( $residentsDevs_gotosleep eq "-" ); $residents_gotosleep .= ", " . $roommateName if ( $roommateName ne "" && $residents_gotosleep ne "-" ); $residents_gotosleep = $roommateName if ( $roommateName ne "" && $residents_gotosleep eq "-" ); $state_totalPresent++; $state_totalRoommatesPresent++; $residentsDevs_totalPresent .= "," . $roommate if ( $residentsDevs_totalPresent ne "-" ); $residentsDevs_totalPresent = $roommate if ( $residentsDevs_totalPresent eq "-" ); $residentsDevs_totalPresentRoommates .= "," . $roommate if ( $residentsDevs_totalPresentRoommates ne "-" ); $residentsDevs_totalPresentRoommates = $roommate if ( $residentsDevs_totalPresentRoommates eq "-" ); $residents_totalPresent .= ", " . $roommateName if ( $roommateName ne "" && $residents_totalPresent ne "-" ); $residents_totalPresent = $roommateName if ( $roommateName ne "" && $residents_totalPresent eq "-" ); $residents_totalPresentRoommates .= ", " . $roommateName if ( $roommateName ne "" && $residents_totalPresentRoommates ne "-" ); $residents_totalPresentRoommates = $roommateName if ( $roommateName ne "" && $residents_totalPresentRoommates eq "-" ); } elsif ( ReadingsVal( $roommate, "state", "initialized" ) eq "asleep" ) { $state_asleep++; $residentsDevs_asleep .= "," . $roommate if ( $residentsDevs_asleep ne "-" ); $residentsDevs_asleep = $roommate if ( $residentsDevs_asleep eq "-" ); $residents_asleep .= ", " . $roommateName if ( $roommateName ne "" && $residents_asleep ne "-" ); $residents_asleep = $roommateName if ( $roommateName ne "" && $residents_asleep eq "-" ); $state_totalPresent++; $state_totalRoommatesPresent++; $residentsDevs_totalPresent .= "," . $roommate if ( $residentsDevs_totalPresent ne "-" ); $residentsDevs_totalPresent = $roommate if ( $residentsDevs_totalPresent eq "-" ); $residentsDevs_totalPresentRoommates .= "," . $roommate if ( $residentsDevs_totalPresentRoommates ne "-" ); $residentsDevs_totalPresentRoommates = $roommate if ( $residentsDevs_totalPresentRoommates eq "-" ); $residents_totalPresent .= ", " . $roommateName if ( $roommateName ne "" && $residents_totalPresent ne "-" ); $residents_totalPresent = $roommateName if ( $roommateName ne "" && $residents_totalPresent eq "-" ); $residents_totalPresentRoommates .= ", " . $roommateName if ( $roommateName ne "" && $residents_totalPresentRoommates ne "-" ); $residents_totalPresentRoommates = $roommateName if ( $roommateName ne "" && $residents_totalPresentRoommates eq "-" ); } elsif ( ReadingsVal( $roommate, "state", "initialized" ) eq "awoken" ) { $state_awoken++; $residentsDevs_awoken .= "," . $roommate if ( $residentsDevs_awoken ne "-" ); $residentsDevs_awoken = $roommate if ( $residentsDevs_awoken eq "-" ); $residents_awoken .= ", " . $roommateName if ( $roommateName ne "" && $residents_awoken ne "-" ); $residents_awoken = $roommateName if ( $roommateName ne "" && $residents_awoken eq "-" ); $state_totalPresent++; $state_totalRoommatesPresent++; $residentsDevs_totalPresent .= "," . $roommate if ( $residentsDevs_totalPresent ne "-" ); $residentsDevs_totalPresent = $roommate if ( $residentsDevs_totalPresent eq "-" ); $residentsDevs_totalPresentRoommates .= "," . $roommate if ( $residentsDevs_totalPresentRoommates ne "-" ); $residentsDevs_totalPresentRoommates = $roommate if ( $residentsDevs_totalPresentRoommates eq "-" ); $residents_totalPresent .= ", " . $roommateName if ( $roommateName ne "" && $residents_totalPresent ne "-" ); $residents_totalPresent = $roommateName if ( $roommateName ne "" && $residents_totalPresent eq "-" ); $residents_totalPresentRoommates .= ", " . $roommateName if ( $roommateName ne "" && $residents_totalPresentRoommates ne "-" ); $residents_totalPresentRoommates = $roommateName if ( $roommateName ne "" && $residents_totalPresentRoommates eq "-" ); } elsif ( ReadingsVal( $roommate, "state", "initialized" ) eq "absent" ) { $state_absent++; $residentsDevs_absent .= "," . $roommate if ( $residentsDevs_absent ne "-" ); $residentsDevs_absent = $roommate if ( $residentsDevs_absent eq "-" ); $residents_absent .= ", " . $roommateName if ( $roommateName ne "" && $residents_absent ne "-" ); $residents_absent = $roommateName if ( $roommateName ne "" && $residents_absent eq "-" ); $state_totalAbsent++; $state_totalRoommatesAbsent++; $residentsDevs_totalAbsent .= "," . $roommate if ( $residentsDevs_totalAbsent ne "-" ); $residentsDevs_totalAbsent = $roommate if ( $residentsDevs_totalAbsent eq "-" ); $residentsDevs_totalAbsentRoommates .= "," . $roommate if ( $residentsDevs_totalAbsentRoommates ne "-" ); $residentsDevs_totalAbsentRoommates = $roommate if ( $residentsDevs_totalAbsentRoommates eq "-" ); $residents_totalAbsent .= ", " . $roommateName if ( $roommateName ne "" && $residents_totalAbsent ne "-" ); $residents_totalAbsent = $roommateName if ( $roommateName ne "" && $residents_totalAbsent eq "-" ); $residents_totalAbsentRoommates .= ", " . $roommateName if ( $roommateName ne "" && $residents_totalAbsentRoommates ne "-" ); $residents_totalAbsentRoommates = $roommateName if ( $roommateName ne "" && $residents_totalAbsentRoommates eq "-" ); } elsif ( ReadingsVal( $roommate, "state", "initialized" ) eq "gone" ) { $state_gone++; $residentsDevs_gone .= "," . $roommate if ( $residentsDevs_gone ne "-" ); $residentsDevs_gone = $roommate if ( $residentsDevs_gone eq "-" ); $residents_gone .= ", " . $roommateName if ( $roommateName ne "" && $residents_gone ne "-" ); $residents_gone = $roommateName if ( $roommateName ne "" && $residents_gone eq "-" ); $state_totalAbsent++; $state_totalRoommatesAbsent++; $residentsDevs_totalAbsent .= "," . $roommate if ( $residentsDevs_totalAbsent ne "-" ); $residentsDevs_totalAbsent = $roommate if ( $residentsDevs_totalAbsent eq "-" ); $residentsDevs_totalAbsentRoommates .= "," . $roommate if ( $residentsDevs_totalAbsentRoommates ne "-" ); $residentsDevs_totalAbsentRoommates = $roommate if ( $residentsDevs_totalAbsentRoommates eq "-" ); $residents_totalAbsent .= ", " . $roommateName if ( $roommateName ne "" && $residents_totalAbsent ne "-" ); $residents_totalAbsent = $roommateName if ( $roommateName ne "" && $residents_totalAbsent eq "-" ); $residents_totalAbsentRoommates .= ", " . $roommateName if ( $roommateName ne "" && $residents_totalAbsentRoommates ne "-" ); $residents_totalAbsentRoommates = $roommateName if ( $roommateName ne "" && $residents_totalAbsentRoommates eq "-" ); } if ( ReadingsVal( $roommate, "wakeup", "0" ) > 0 ) { $wakeup++; $residentsDevs_wakeup .= "," . $roommate if ( $residentsDevs_wakeup ne "-" ); $residentsDevs_wakeup = $roommate if ( $residentsDevs_wakeup eq "-" ); $residents_wakeup .= ", " . $roommateName if ( $roommateName ne "" && $residents_wakeup ne "-" ); $residents_wakeup = $roommateName if ( $roommateName ne "" && $residents_wakeup eq "-" ); } if ( ReadingsVal( $roommate, "wayhome", "0" ) > 0 ) { $wayhome++; $residentsDevs_wayhome .= "," . $roommate if ( $residentsDevs_wayhome ne "-" ); $residentsDevs_wayhome = $roommate if ( $residentsDevs_wayhome eq "-" ); $residents_wayhome .= ", " . $roommateName if ( $roommateName ne "" && $residents_wayhome ne "-" ); $residents_wayhome = $roommateName if ( $roommateName ne "" && $residents_wayhome eq "-" ); if ( ReadingsVal( $roommate, "wayhome", "0" ) == 2 ) { $wayhomeDelayed++; $residentsDevs_wayhomeDelayed .= "," . $roommate if ( $residentsDevs_wayhomeDelayed ne "-" ); $residentsDevs_wayhomeDelayed = $roommate if ( $residentsDevs_wayhomeDelayed eq "-" ); $residents_wayhomeDelayed .= ", " . $roommateName if ( $roommateName ne "" && $residents_wayhomeDelayed ne "-" ); $residents_wayhomeDelayed = $roommateName if ( $roommateName ne "" && $residents_wayhomeDelayed eq "-" ); } } } # count child states for GUEST devices foreach my $guest (@registeredGuests) { $state_guestDev++; my $guestName = AttrVal( $guest, AttrVal( $guest, "rg_realname", "alias" ), "" ); Log3 $name, 5, "RESIDENTS $name: considering $guest for state change"; if ( ReadingsVal( $guest, "state", "initialized" ) eq "home" ) { $state_home++; $state_totalPresent++; $state_totalGuestsPresent++; $state_totalGuests++; $state_total++; $residentsDevs_totalPresentGuest .= "," . $guest if ( $residentsDevs_totalPresentGuest ne "-" ); $residentsDevs_totalPresentGuest = $guest if ( $residentsDevs_totalPresentGuest eq "-" ); $residents_totalPresentGuest .= ", " . $guestName if ( $guestName ne "" && $residents_totalPresentGuest ne "-" ); $residents_totalPresentGuest = $guestName if ( $guestName ne "" && $residents_totalPresentGuest eq "-" ); $residentsDevs_totalPresent .= "," . $guest if ( $residentsDevs_totalPresent ne "-" ); $residentsDevs_totalPresent = $guest if ( $residentsDevs_totalPresent eq "-" ); $residents_totalPresent .= ", " . $guestName if ( $guestName ne "" && $residents_totalPresent ne "-" ); $residents_totalPresent = $guestName if ( $guestName ne "" && $residents_totalPresent eq "-" ); } elsif ( ReadingsVal( $guest, "state", "initialized" ) eq "gotosleep" ) { $state_gotosleep++; $state_totalPresent++; $state_totalGuestsPresent++; $state_totalGuests++; $state_total++; $residentsDevs_totalPresentGuest .= "," . $guest if ( $residentsDevs_totalPresentGuest ne "-" ); $residentsDevs_totalPresentGuest = $guest if ( $residentsDevs_totalPresentGuest eq "-" ); $residents_totalPresentGuest .= ", " . $guestName if ( $guestName ne "" && $residents_totalPresentGuest ne "-" ); $residents_totalPresentGuest = $guestName if ( $guestName ne "" && $residents_totalPresentGuest eq "-" ); $residentsDevs_totalPresent .= "," . $guest if ( $residentsDevs_totalPresent ne "-" ); $residentsDevs_totalPresent = $guest if ( $residentsDevs_totalPresent eq "-" ); $residents_totalPresent .= ", " . $guestName if ( $guestName ne "" && $residents_totalPresent ne "-" ); $residents_totalPresent = $guestName if ( $guestName ne "" && $residents_totalPresent eq "-" ); } elsif ( ReadingsVal( $guest, "state", "initialized" ) eq "asleep" ) { $state_asleep++; $state_totalPresent++; $state_totalGuestsPresent++; $state_totalGuests++; $state_total++; $residentsDevs_totalPresentGuest .= "," . $guest if ( $residentsDevs_totalPresentGuest ne "-" ); $residentsDevs_totalPresentGuest = $guest if ( $residentsDevs_totalPresentGuest eq "-" ); $residents_totalPresentGuest .= ", " . $guestName if ( $guestName ne "" && $residents_totalPresentGuest ne "-" ); $residents_totalPresentGuest = $guestName if ( $guestName ne "" && $residents_totalPresentGuest eq "-" ); $residentsDevs_totalPresent .= "," . $guest if ( $residentsDevs_totalPresent ne "-" ); $residentsDevs_totalPresent = $guest if ( $residentsDevs_totalPresent eq "-" ); $residents_totalPresent .= ", " . $guestName if ( $guestName ne "" && $residents_totalPresent ne "-" ); $residents_totalPresent = $guestName if ( $guestName ne "" && $residents_totalPresent eq "-" ); } elsif ( ReadingsVal( $guest, "state", "initialized" ) eq "awoken" ) { $state_awoken++; $state_totalPresent++; $state_totalGuestsPresent++; $state_totalGuests++; $state_total++; $residentsDevs_totalPresentGuest .= "," . $guest if ( $residentsDevs_totalPresentGuest ne "-" ); $residentsDevs_totalPresentGuest = $guest if ( $residentsDevs_totalPresentGuest eq "-" ); $residents_totalPresentGuest .= ", " . $guestName if ( $guestName ne "" && $residents_totalPresentGuest ne "-" ); $residents_totalPresentGuest = $guestName if ( $guestName ne "" && $residents_totalPresentGuest eq "-" ); $residentsDevs_totalPresent .= "," . $guest if ( $residentsDevs_totalPresent ne "-" ); $residentsDevs_totalPresent = $guest if ( $residentsDevs_totalPresent eq "-" ); $residents_totalPresent .= ", " . $guestName if ( $guestName ne "" && $residents_totalPresent ne "-" ); $residents_totalPresent = $guestName if ( $guestName ne "" && $residents_totalPresent eq "-" ); } elsif ( ReadingsVal( $guest, "state", "initialized" ) eq "absent" ) { $state_absent++; $state_totalAbsent++; $state_totalGuestsAbsent++; $state_totalGuests++; $state_total++; $residentsDevs_totalAbsentGuest .= "," . $guest if ( $residentsDevs_totalAbsentGuest ne "-" ); $residentsDevs_totalAbsentGuest = $guest if ( $residentsDevs_totalAbsentGuest eq "-" ); $residents_totalAbsentGuest .= ", " . $guestName if ( $guestName ne "" && $residents_totalAbsentGuest ne "-" ); $residents_totalAbsentGuest = $guestName if ( $guestName ne "" && $residents_totalAbsentGuest eq "-" ); $residentsDevs_totalAbsent .= "," . $guest if ( $residentsDevs_totalAbsent ne "-" ); $residentsDevs_totalAbsent = $guest if ( $residentsDevs_totalAbsent eq "-" ); $residents_totalAbsent .= ", " . $guestName if ( $guestName ne "" && $residents_totalAbsent ne "-" ); $residents_totalAbsent = $guestName if ( $guestName ne "" && $residents_totalAbsent eq "-" ); } if ( ReadingsVal( $guest, "wakeup", "0" ) > 0 ) { $wakeup++; $residentsDevs_wakeup .= "," . $guest if ( $residentsDevs_wakeup ne "-" ); $residentsDevs_wakeup = $guest if ( $residentsDevs_wakeup eq "-" ); $residents_wakeup .= ", " . $guestName if ( $guestName ne "" && $residents_wakeup ne "-" ); $residents_wakeup = $guestName if ( $guestName ne "" && $residents_wakeup eq "-" ); } if ( ReadingsVal( $guest, "wayhome", "0" ) > 0 ) { $wayhome++; $residents_wayhome .= "," . $guest if ( $residents_wayhome ne "-" ); $residents_wayhome = $guest if ( $residents_wayhome eq "-" ); $residents_wayhome .= ", " . $guestName if ( $guestName ne "" && $residents_wayhome ne "-" ); $residents_wayhome = $guestName if ( $guestName ne "" && $residents_wayhome eq "-" ); if ( ReadingsVal( $guest, "wayhome", "0" ) == 2 ) { $wayhomeDelayed++; $residentsDevs_wayhomeDelayed .= "," . $guest if ( $residentsDevs_wayhomeDelayed ne "-" ); $residentsDevs_wayhomeDelayed = $guest if ( $residentsDevs_wayhomeDelayed eq "-" ); $residents_wayhomeDelayed .= ", " . $guestName if ( $guestName ne "" && $residents_wayhomeDelayed ne "-" ); $residents_wayhomeDelayed = $guestName if ( $guestName ne "" && $residents_wayhomeDelayed eq "-" ); } } } # update counter readingsBulkUpdate( $hash, "residentsTotal", $state_total ) if ( ReadingsVal( $name, "residentsTotal", "" ) ne $state_total ); readingsBulkUpdate( $hash, "residentsTotalGuests", $state_totalGuests ) if ( ReadingsVal( $name, "residentsTotalGuests", "" ) ne $state_totalGuests ); readingsBulkUpdate( $hash, "residentsTotalGuestsPresent", $state_totalGuestsPresent ) if ( ReadingsVal( $name, "residentsTotalGuestsPresent", "" ) ne $state_totalGuestsPresent ); readingsBulkUpdate( $hash, "residentsTotalGuestsPresentDevs", $residentsDevs_totalPresentGuest ) if ( ReadingsVal( $name, "residentsTotalGuestsPresentDevs", "" ) ne $residentsDevs_totalPresentGuest ); readingsBulkUpdate( $hash, "residentsTotalGuestsPresentNames", $residents_totalPresentGuest ) if ( ReadingsVal( $name, "residentsTotalGuestsPresentNames", "" ) ne $residents_totalPresentGuest ); readingsBulkUpdate( $hash, "residentsTotalGuestsAbsent", $state_totalGuestsAbsent ) if ( ReadingsVal( $name, "residentsTotalGuestsAbsent", "" ) ne $state_totalGuestsAbsent ); readingsBulkUpdate( $hash, "residentsTotalGuestsAbsentDevs", $residentsDevs_totalAbsentGuest ) if ( ReadingsVal( $name, "residentsTotalGuestsAbsentDevs", "" ) ne $residentsDevs_totalAbsentGuest ); readingsBulkUpdate( $hash, "residentsTotalGuestsAbsentNames", $residents_totalAbsentGuest ) if ( ReadingsVal( $name, "residentsTotalGuestsAbsentNames", "" ) ne $residents_totalAbsentGuest ); readingsBulkUpdate( $hash, "residentsTotalRoommates", $state_totalRoommates ) if ( ReadingsVal( $name, "residentsTotalRoommates", "" ) ne $state_totalRoommates ); readingsBulkUpdate( $hash, "residentsTotalRoommatesPresent", $state_totalRoommatesPresent ) if ( ReadingsVal( $name, "residentsTotalRoommatesPresent", "" ) ne $state_totalRoommatesPresent ); readingsBulkUpdate( $hash, "residentsTotalRoommatesPresentDevs", $residentsDevs_totalPresentRoommates ) if ( ReadingsVal( $name, "residentsTotalRoommatesPresentDevs", "" ) ne $residentsDevs_totalPresentRoommates ); readingsBulkUpdate( $hash, "residentsTotalRoommatesPresentNames", $residents_totalPresentRoommates ) if ( ReadingsVal( $name, "residentsTotalRoommatesPresentNames", "" ) ne $residents_totalPresentRoommates ); readingsBulkUpdate( $hash, "residentsTotalRoommatesAbsent", $state_totalRoommatesAbsent ) if ( ReadingsVal( $name, "residentsTotalRoommatesAbsent", "" ) ne $state_totalRoommatesAbsent ); readingsBulkUpdate( $hash, "residentsTotalRoommatesAbsentDevs", $residentsDevs_totalAbsentRoommates ) if ( ReadingsVal( $name, "residentsTotalRoommatesAbsentDevs", "" ) ne $residentsDevs_totalAbsentRoommates ); readingsBulkUpdate( $hash, "residentsTotalRoommatesAbsentNames", $residents_totalAbsentRoommates ) if ( ReadingsVal( $name, "residentsTotalRoommatesAbsentNames", "" ) ne $residents_totalAbsentRoommates ); readingsBulkUpdate( $hash, "residentsTotalPresent", $state_totalPresent ) if ( ReadingsVal( $name, "residentsTotalPresent", "" ) ne $state_totalPresent ); readingsBulkUpdate( $hash, "residentsTotalPresentDevs", $residentsDevs_totalPresent ) if ( ReadingsVal( $name, "residentsTotalPresentDevs", "" ) ne $residentsDevs_totalPresent ); readingsBulkUpdate( $hash, "residentsTotalPresentNames", $residents_totalPresent ) if ( ReadingsVal( $name, "residentsTotalPresentNames", "" ) ne $residents_totalPresent ); readingsBulkUpdate( $hash, "residentsTotalAbsent", $state_totalAbsent ) if ( ReadingsVal( $name, "residentsTotalAbsent", "" ) ne $state_totalAbsent ); readingsBulkUpdate( $hash, "residentsTotalAbsentDevs", $residentsDevs_totalAbsent ) if ( ReadingsVal( $name, "residentsTotalAbsentDevs", "" ) ne $residentsDevs_totalAbsent ); readingsBulkUpdate( $hash, "residentsTotalAbsentNames", $residents_totalAbsent ) if ( ReadingsVal( $name, "residentsTotalAbsentNames", "" ) ne $residents_totalAbsent ); readingsBulkUpdate( $hash, "residentsHome", $state_home ) if ( ReadingsVal( $name, "residentsHome", "" ) ne $state_home ); readingsBulkUpdate( $hash, "residentsHomeDevs", $residentsDevs_home ) if ( ReadingsVal( $name, "residentsHomeDevs", "" ) ne $residentsDevs_home ); readingsBulkUpdate( $hash, "residentsHomeNames", $residents_home ) if ( ReadingsVal( $name, "residentsHomeNames", "" ) ne $residents_home ); readingsBulkUpdate( $hash, "residentsGotosleep", $state_gotosleep ) if ( ReadingsVal( $name, "residentsGotosleep", "" ) ne $state_gotosleep ); readingsBulkUpdate( $hash, "residentsGotosleepDevs", $residentsDevs_gotosleep ) if ( ReadingsVal( $name, "residentsGotosleepDevs", "" ) ne $residentsDevs_gotosleep ); readingsBulkUpdate( $hash, "residentsGotosleepNames", $residents_gotosleep ) if ( ReadingsVal( $name, "residentsGotosleepNames", "" ) ne $residents_gotosleep ); readingsBulkUpdate( $hash, "residentsAsleep", $state_asleep ) if ( ReadingsVal( $name, "residentsAsleep", "" ) ne $state_asleep ); readingsBulkUpdate( $hash, "residentsAsleepDevs", $residentsDevs_asleep ) if ( ReadingsVal( $name, "residentsAsleepDevs", "" ) ne $residentsDevs_asleep ); readingsBulkUpdate( $hash, "residentsAsleepNames", $residents_asleep ) if ( ReadingsVal( $name, "residentsAsleepNames", "" ) ne $residents_asleep ); readingsBulkUpdate( $hash, "residentsAwoken", $state_awoken ) if ( ReadingsVal( $name, "residentsAwoken", "" ) ne $state_awoken ); readingsBulkUpdate( $hash, "residentsAwokenDevs", $residentsDevs_awoken ) if ( ReadingsVal( $name, "residentsAwokenDevs", "" ) ne $residentsDevs_awoken ); readingsBulkUpdate( $hash, "residentsAwokenNames", $residents_awoken ) if ( ReadingsVal( $name, "residentsAwokenNames", "" ) ne $residents_awoken ); readingsBulkUpdate( $hash, "residentsAbsent", $state_absent ) if ( ReadingsVal( $name, "residentsAbsent", "" ) ne $state_absent ); readingsBulkUpdate( $hash, "residentsAbsentDevs", $residentsDevs_absent ) if ( ReadingsVal( $name, "residentsAbsentDevs", "" ) ne $residentsDevs_absent ); readingsBulkUpdate( $hash, "residentsAbsentNames", $residents_absent ) if ( ReadingsVal( $name, "residentsAbsentNames", "" ) ne $residents_absent ); readingsBulkUpdate( $hash, "residentsGone", $state_gone ) if ( ReadingsVal( $name, "residentsGone", "" ) ne $state_gone ); readingsBulkUpdate( $hash, "residentsGoneDevs", $residentsDevs_gone ) if ( ReadingsVal( $name, "residentsGoneDevs", "" ) ne $residentsDevs_gone ); readingsBulkUpdate( $hash, "residentsGoneNames", $residents_gone ) if ( ReadingsVal( $name, "residentsGoneNames", "" ) ne $residents_gone ); readingsBulkUpdate( $hash, "residentsTotalWakeup", $wakeup ) if ( ReadingsVal( $name, "residentsTotalWakeup", "" ) ne $wakeup ); readingsBulkUpdate( $hash, "residentsTotalWakeupDevs", $residentsDevs_wakeup ) if ( ReadingsVal( $name, "residentsTotalWakeupDevs", "" ) ne $residentsDevs_wakeup ); readingsBulkUpdate( $hash, "residentsTotalWakeupNames", $residents_wakeup ) if ( ReadingsVal( $name, "residentsTotalWakeupNames", "" ) ne $residents_wakeup ); readingsBulkUpdate( $hash, "residentsTotalWayhome", $wayhome ) if ( ReadingsVal( $name, "residentsTotalWayhome", "" ) ne $wayhome ); readingsBulkUpdate( $hash, "residentsTotalWayhomeDevs", $residentsDevs_wayhome ) if ( ReadingsVal( $name, "residentsTotalWayhomeDevs", "" ) ne $residentsDevs_wayhome ); readingsBulkUpdate( $hash, "residentsTotalWayhomeNames", $residents_wayhome ) if ( ReadingsVal( $name, "residentsTotalWayhomeNames", "" ) ne $residents_wayhome ); readingsBulkUpdate( $hash, "residentsTotalWayhomeDelayed", $wayhomeDelayed ) if ( ReadingsVal( $name, "residentsTotalWayhomeDelayed", "" ) ne $wayhomeDelayed ); readingsBulkUpdate( $hash, "residentsTotalWayhomeDelayedDevs", $residentsDevs_wayhomeDelayed ) if ( ReadingsVal( $name, "residentsTotalWayhomeDelayedDevs", "" ) ne $residentsDevs_wayhomeDelayed ); readingsBulkUpdate( $hash, "residentsTotalWayhomeDelayedNames", $residents_wayhomeDelayed ) if ( ReadingsVal( $name, "residentsTotalWayhomeDelayedNames", "" ) ne $residents_wayhomeDelayed ); # # state calculation # # gotosleep if ( $state_home == 0 && $state_gotosleep > 0 && $state_asleep >= 0 && $state_awoken == 0 ) { $newstate = "gotosleep"; } # asleep elsif ($state_home == 0 && $state_gotosleep == 0 && $state_asleep > 0 && $state_awoken == 0 ) { $newstate = "asleep"; } # awoken elsif ($state_home == 0 && $state_gotosleep >= 0 && $state_asleep >= 0 && $state_awoken > 0 ) { $newstate = "awoken"; } # general presence elsif ($state_home > 0 || $state_gotosleep > 0 || $state_asleep > 0 || $state_awoken > 0 ) { $newstate = "home"; } # absent elsif ($state_absent > 0 && $state_home == 0 && $state_gotosleep == 0 && $state_asleep == 0 && $state_awoken == 0 ) { $newstate = "absent"; } # gone elsif ($state_gone > 0 && $state_absent == 0 && $state_home == 0 && $state_gotosleep == 0 && $state_asleep == 0 && $state_awoken == 0 ) { $newstate = "gone"; } # none elsif ($state_totalGuests == 0 && $state_totalRoommates == 0 && $state_gone == 0 && $state_absent == 0 && $state_home == 0 && $state_gotosleep == 0 && $state_asleep == 0 && $state_awoken == 0 ) { $newstate = "none"; } # unspecified; this should not happen else { $newstate = "unspecified"; } # calculate presence state my $newpresence = ( $newstate ne "none" && $newstate ne "gone" && $newstate ne "absent" ) ? "present" : "absent"; Log3 $name, 4, "RESIDENTS $name: calculation result - residentsTotal:$state_total residentsTotalRoommates:$state_totalRoommates residentsTotalRoommatesPresent:$state_totalRoommatesPresent residentsTotalRoommatesAbsent:$state_totalRoommatesAbsent residentsTotalGuests:$state_totalGuests residentsTotalGuestsPresent:$state_totalGuestsPresent residentsTotalGuestsAbsent:$state_totalGuestsAbsent residentsTotalPresent:$state_totalPresent residentsTotalAbsent:$state_totalAbsent residentsHome:$state_home residentsGotosleep:$state_gotosleep residentsAsleep:$state_asleep residentsAwoken:$state_awoken residentsAbsent:$state_absent residentsGone:$state_gone presence:$newpresence state:$newstate"; # safe current time my $datetime = FmtDateTime(time); # if state changed if ( $state ne $newstate ) { # stop any running wakeup-timers in case state changed my $wakeupState = AttrVal( $name, "wakeup", 0 ); if ($wakeupState) { my $wakeupDeviceList = AttrVal( $name, "rgr_wakeupDevice", 0 ); for my $wakeupDevice ( split /,/, $wakeupDeviceList ) { next if !$wakeupDevice; if ( defined( $defs{$wakeupDevice} ) && $defs{$wakeupDevice}{TYPE} eq "dummy" ) { # forced-stop only if resident is not present anymore if ( $newpresence eq "present" ) { fhem "set $wakeupDevice:FILTER=running!=0 end"; } else { fhem "set $wakeupDevice:FILTER=running!=0 stop"; } } } } # if newstate is asleep, start sleep timer readingsBulkUpdate( $hash, "lastSleep", $datetime ) if ( $newstate eq "asleep" ); # if prior state was asleep, update sleep statistics if ( $state eq "asleep" && ReadingsVal( $name, "lastSleep", "" ) ne "" ) { readingsBulkUpdate( $hash, "lastAwake", $datetime ); readingsBulkUpdate( $hash, "lastDurSleep", RESIDENTStk_TimeDiff( $datetime, ReadingsVal( $name, "lastSleep", "" ) ) ); readingsBulkUpdate( $hash, "lastDurSleep_cr", RESIDENTStk_TimeDiff( $datetime, ReadingsVal( $name, "lastSleep", "" ), "min" ) ); } readingsBulkUpdate( $hash, "lastState", ReadingsVal( $name, "state", "initialized" ) ); readingsBulkUpdate( $hash, "state", $newstate ); } # if presence changed if ( $newpresence ne $presence ) { readingsBulkUpdate( $hash, "presence", $newpresence ); # update statistics if ( $newpresence eq "present" ) { readingsBulkUpdate( $hash, "lastArrival", $datetime ); # absence duration if ( ReadingsVal( $name, "lastDeparture", "-" ) ne "-" ) { readingsBulkUpdate( $hash, "lastDurAbsence", RESIDENTStk_TimeDiff( $datetime, ReadingsVal( $name, "lastDeparture", "-" ) ) ); readingsBulkUpdate( $hash, "lastDurAbsence_cr", RESIDENTStk_TimeDiff( $datetime, ReadingsVal( $name, "lastDeparture", "-" ), "min" ) ); } } else { readingsBulkUpdate( $hash, "lastDeparture", $datetime ); # presence duration if ( ReadingsVal( $name, "lastArrival", "-" ) ne "-" ) { readingsBulkUpdate( $hash, "lastDurPresence", RESIDENTStk_TimeDiff( $datetime, ReadingsVal( $name, "lastArrival", "-" ) ) ); readingsBulkUpdate( $hash, "lastDurPresence_cr", RESIDENTStk_TimeDiff( $datetime, ReadingsVal( $name, "lastArrival", "-" ), "min" ) ); } } } } 1; =pod =item helper =begin html

RESIDENTS

=end html =begin html_DE

RESIDENTS

=end html_DE =cut