diff --git a/CHANGED b/CHANGED index 0e3ff0a14..02d063b40 100644 --- a/CHANGED +++ b/CHANGED @@ -1,5 +1,6 @@ # 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. + - bugfix: 73_AutoShuttersControl: fix bugs and add patches - feature: 30_HUEBridge, 31HUEDevice: scenes can be given by name scene dropdown in FHEMWEB show light names for scenes and groups diff --git a/FHEM/73_AutoShuttersControl.pm b/FHEM/73_AutoShuttersControl.pm index d1ca03cd1..7b2f5af4c 100644 --- a/FHEM/73_AutoShuttersControl.pm +++ b/FHEM/73_AutoShuttersControl.pm @@ -12,6 +12,8 @@ # - FunkOdyssey commandref style # - sledge fix many typo in commandref # - many User that use with modul and report bugs +# - Christoph (christoph.kaiser.in) Patch that expand RegEx for Window Events +# - Julian (Loredo) expand Residents Events for new Residents functions # # # This script is free software; you can redistribute it and/or modify @@ -45,7 +47,7 @@ use strict; use warnings; use FHEM::Meta; -my $version = '0.6.12'; +my $version = '0.6.14'; sub AutoShuttersControl_Initialize($) { my ($hash) = @_; @@ -471,18 +473,18 @@ m#^DELETEATTR\s(.*)\s(ASC_Roommate_Device|ASC_WindowRec|ASC_residentsDev|ASC_rai DeleteNotifyDev( $hash, $1, $2 ); } elsif ( $events =~ -m#^ATTR\s(.*)\s(ASC_Time_Up_WE_Holiday|ASC_Up|ASC_Down|ASC_AutoAstroModeMorning|ASC_AutoAstroModeMorningHorizon|ASC_PrivacyDownTime_beforNightClose|ASC_AutoAstroModeEvening|ASC_AutoAstroModeEveningHorizon|ASC_Time_Up_Early|ASC_Time_Up_Late|ASC_Time_Down_Early|ASC_Time_Down_Late)\s(.*)$# +m#^(DELETEATTR|ATTR)\s(.*)\s(ASC_Time_Up_WE_Holiday|ASC_Up|ASC_Down|ASC_AutoAstroModeMorning|ASC_AutoAstroModeMorningHorizon|ASC_PrivacyDownTime_beforNightClose|ASC_AutoAstroModeEvening|ASC_AutoAstroModeEveningHorizon|ASC_Time_Up_Early|ASC_Time_Up_Late|ASC_Time_Down_Early|ASC_Time_Down_Late)(.*)?# ) { - CreateSunRiseSetShuttersTimer( $hash, $1 ) + CreateSunRiseSetShuttersTimer( $hash, $2 ) if ( - $2 ne 'ASC_Time_Up_WE_Holiday' - or ( $2 eq 'ASC_Time_Up_WE_Holiday' + $3 ne 'ASC_Time_Up_WE_Holiday' + or ( $3 eq 'ASC_Time_Up_WE_Holiday' and $ascDev->getSunriseTimeWeHoliday eq 'on' ) ); } elsif ( $events =~ -m#^ATTR\s(.*)\s(ASC_autoAstroModeMorning|ASC_autoAstroModeMorningHorizon|ASC_autoAstroModeEvening|ASC_autoAstroModeEveningHorizon)\s(.*)$# +m#^(DELETEATTR|ATTR)\s(.*)\s(ASC_autoAstroModeMorning|ASC_autoAstroModeMorningHorizon|ASC_autoAstroModeEvening|ASC_autoAstroModeEveningHorizon)(.*)?# ) { RenewSunRiseSetShuttersTimer($hash); @@ -839,6 +841,8 @@ sub AddNotifyDev($@) { %hash = map { ( $_ => 1 ) } split( ',', "$notifyDev,$dev" ); + my $match + ; # CK: added local variable to save matched event type (open|opened|close|closed|tilt|tilted) $hash->{NOTIFYDEV} = join( ',', sort keys %hash ); my @devs = split( ',', $dev ); @@ -885,21 +889,29 @@ sub EventProcessingWindowRec($@) { my ( $hash, $shuttersDev, $events ) = @_; my $name = $hash->{NAME}; - if ( - $events =~ - m#state:\s(open(ed)?|closed|tilted)# # weitere mögliche Events (opened / closed) - and IsAfterShuttersManualBlocking($shuttersDev) - ) + if ( $events =~ m#.*state:.*(open(?>ed)?|closed?|tilt(?>ed)?)# + and IsAfterShuttersManualBlocking($shuttersDev) ) { + my $match = $1; + + ASC_Debug( 'EventProcessingWindowRec: ' + . $shutters->getShuttersDev + . ' - RECEIVED EVENT: ' + . $events + . ' - IDENTIFIED EVENT: ' + . $1 + . ' - STORED EVENT: ' + . $match ); + $shutters->setShuttersDev($shuttersDev); my $homemode = $shutters->getRoommatesStatus; $homemode = $ascDev->getResidentsStatus if ( $homemode eq 'none' ); #### Hardware Lock der Rollläden $shutters->setHardLockOut('off') - if ( $1 eq 'closed' and $shutters->getShuttersPlace eq 'terrace' ); + if ( $match =~ /close/ and $shutters->getShuttersPlace eq 'terrace' ); $shutters->setHardLockOut('on') - if ( ( $1 eq 'open' or $1 eq 'opened' ) + if ( $match =~ /open/ and $shutters->getShuttersPlace eq 'terrace' ); my $queryShuttersPosWinRecTilted = ( @@ -917,13 +929,13 @@ sub EventProcessingWindowRec($@) { . $shutters->getShuttersDev . ' - HOMEMODE: ' . $homemode - . ' : QueryShuttersPosWinRecTilted' + . ' QueryShuttersPosWinRecTilted:' . $queryShuttersPosWinRecTilted . ' QueryShuttersPosWinRecComfort: ' . $queryShuttersPosWinRecComfort ); if ( - $1 eq 'closed' + $match =~ /close/ and IsAfterShuttersTimeBlocking($shuttersDev) and ( $shutters->getStatus == $shutters->getVentilatePos or $shutters->getStatus == $shutters->getComfortOpenPos @@ -974,8 +986,8 @@ sub EventProcessingWindowRec($@) { } elsif ( ( - $1 eq 'tilted' - or ( ( $1 eq 'open' or $1 eq 'opened' ) + $match =~ /tilt/ + or ( $match =~ /open/ and $shutters->getSubTyp eq 'twostate' ) ) and $shutters->getVentilateOpen eq 'on' @@ -986,7 +998,7 @@ sub EventProcessingWindowRec($@) { $shutters->setNoOffset(1); $shutters->setDriveCmd( $shutters->getVentilatePos ); } - elsif ( ( $1 eq 'open' or $1 eq 'opened' ) + elsif ( $match =~ /open/ and $shutters->getSubTyp eq 'threestate' ) { my $posValue; @@ -1158,7 +1170,7 @@ sub EventProcessingResidents($@) { my $reading = $ascDev->getResidentsReading; my $getResidentsLastStatus = $ascDev->getResidentsLastStatus; - if ( $events =~ m#$reading:\s(absent)# ) { + if ( $events =~ m#$reading:\s((?:pet_[a-z]+)|(?:absent))# ) { foreach my $shuttersDev ( @{ $hash->{helper}{shuttersList} } ) { $shutters->setShuttersDev($shuttersDev); my $getModeUp = $shutters->getModeUp; @@ -1205,7 +1217,7 @@ sub EventProcessingResidents($@) { } } elsif ( - $events =~ m#$reading:\s(home)# + $events =~ m#$reading:\s((?:[a-z]+_)?home)# and ( $getResidentsLastStatus eq 'absent' or $getResidentsLastStatus eq 'gone' or $getResidentsLastStatus eq 'asleep' @@ -1243,6 +1255,18 @@ sub EventProcessingResidents($@) { $shutters->setLastDrive('shading in'); $shutters->setDriveCmd( $shutters->getShadingPos ); } + elsif ( + $shutters->getShadingMode eq 'absent' + and IsDay($shuttersDev) + and $shutters->getIfInShading + and $shutters->getStatus == $shutters->getShadingPos + and not( CheckIfShuttersWindowRecOpen($shuttersDev) == 2 + and $shutters->getShuttersPlace eq 'terrace' ) + ) + { + $shutters->setLastDrive('shading out'); + $shutters->setDriveCmd( $shutters->getLastPos ); + } elsif ( $ascDev->getSelfDefense eq 'on' and CheckIfShuttersWindowRecOpen($shuttersDev) != 0 @@ -1717,6 +1741,14 @@ sub EventProcessingShadingBrightness($@) { . ' - Alle Bedingungen zur weiteren Beschattungsverarbeitung sind erfüllt. Es wird nun die eigentliche Beschattungsfunktion aufgerufen' ); } + elsif ( $shutters->getShadingStatus eq 'in' + and $shutters->getShadingMode ne $homemode + and $shutters->getRainProtectionStatus eq 'unprotection' + and $shutters->getWindProtectionStatus eq 'unprotection' ) + { + $shutters->setShadingStatus('out'); + ShadingProcessingDriveCommand( $hash, $shuttersDev ); + } } } @@ -1977,47 +2009,42 @@ sub ShadingProcessing($@) { . $shutters->getShadingStatus ); } - if ( $shutters->getShadingStatus eq 'out' - or $shutters->getShadingStatus eq 'in' ) + ShadingProcessingDriveCommand( $hash, $shuttersDev ) + if ( $shutters->getShadingStatus eq 'out' + or $shutters->getShadingStatus eq 'in' ); +} + +sub ShadingProcessingDriveCommand($$) { + my ( $hash, $shuttersDev ) = @_; + + my $name = $hash->{NAME}; + $shutters->setShuttersDev($shuttersDev); + + my $getShadingPos = $shutters->getShadingPos; + my $getStatus = $shutters->getStatus; + + $shutters->setShadingStatus( $shutters->getShadingStatus ) + if ( + ( int( gettimeofday() ) - $shutters->getShadingStatusTimestamp ) > + ( $shutters->getShadingWaitingPeriod / 2 ) ); + + if ( $shutters->getShadingStatus eq 'in' + and $getShadingPos != $getStatus ) { - ### Erstmal rausgenommen könnte Grund für nicht mehr reinfahren in die Beschattung sein - $shutters->setShadingStatus( $shutters->getShadingStatus ) - if ( - ( int( gettimeofday() ) - $shutters->getShadingStatusTimestamp ) > - ( $shutters->getShadingWaitingPeriod / 2 ) ); + my $queryShuttersShadingPos = ( + $shutters->getShuttersPosCmdValueNegate + ? $getStatus > $getShadingPos + : $getStatus < $getShadingPos + ); - if ( $shutters->getShadingStatus eq 'in' - and $getShadingPos != $getStatus ) + if ( + not $queryShuttersShadingPos + and not( CheckIfShuttersWindowRecOpen($shuttersDev) == 2 + and $shutters->getShuttersPlace eq 'terrace' ) + ) { - my $queryShuttersShadingPos = ( - $shutters->getShuttersPosCmdValueNegate - ? $getStatus > $getShadingPos - : $getStatus < $getShadingPos - ); - - if ( - not $queryShuttersShadingPos - and not( CheckIfShuttersWindowRecOpen($shuttersDev) == 2 - and $shutters->getShuttersPlace eq 'terrace' ) - ) - { - $shutters->setLastDrive('shading in'); - ShuttersCommandSet( $hash, $shuttersDev, $getShadingPos ); - - ASC_Debug( 'ShadingProcessing: ' - . $shutters->getShuttersDev - . ' - Der aktuelle Beschattungsstatus ist: ' - . $shutters->getShadingStatus - . ' und somit wird nun in die Position: ' - . $getShadingPos - . ' zum Beschatten gefahren' ); - } - } - elsif ( $shutters->getShadingStatus eq 'out' - and $getShadingPos == $getStatus ) - { - $shutters->setLastDrive('shading out'); - ShuttersCommandSet( $hash, $shuttersDev, $shutters->getLastPos ); + $shutters->setLastDrive('shading in'); + ShuttersCommandSet( $hash, $shuttersDev, $getShadingPos ); ASC_Debug( 'ShadingProcessing: ' . $shutters->getShuttersDev @@ -2025,24 +2052,46 @@ sub ShadingProcessing($@) { . $shutters->getShadingStatus . ' und somit wird nun in die Position: ' . $getShadingPos - . ' zum beenden der Beschattung gefahren' ); + . ' zum Beschatten gefahren' ); } + } + elsif ( $shutters->getShadingStatus eq 'out' + and $getShadingPos == $getStatus ) + { + $shutters->setLastDrive('shading out'); + ShuttersCommandSet( + $hash, + $shuttersDev, + ( + $shutters->getShadingPos == $shutters->getLastPos + ? $shutters->getOpenPos + : $shutters->getLastPos + ) + ); - Log3( $name, 4, -"AutoShuttersControl ($name) - Shading Processing - In der Routine zum fahren der Rollläden, Shading Wert: " - . $shutters->getShadingStatus ); - - ASC_Debug( - 'ShadingProcessing: ' + ASC_Debug( 'ShadingProcessing: ' . $shutters->getShuttersDev . ' - Der aktuelle Beschattungsstatus ist: ' . $shutters->getShadingStatus - . ', Beschattungsstatus Zeitstempel: ' - . strftime( - "%Y.%m.%e %T", localtime( $shutters->getShadingStatusTimestamp ) - ) - ); + . ' und somit wird nun in die Position: ' + . $getShadingPos + . ' zum beenden der Beschattung gefahren' ); } + + Log3( $name, 4, +"AutoShuttersControl ($name) - Shading Processing - In der Routine zum fahren der Rollläden, Shading Wert: " + . $shutters->getShadingStatus ); + + ASC_Debug( + 'ShadingProcessing: ' + . $shutters->getShuttersDev + . ' - Der aktuelle Beschattungsstatus ist: ' + . $shutters->getShadingStatus + . ', Beschattungsstatus Zeitstempel: ' + . strftime( + "%Y.%m.%e %T", localtime( $shutters->getShadingStatusTimestamp ) + ) + ); } sub EventProcessingPartyMode($) { @@ -2475,6 +2524,7 @@ sub SunRiseShuttersAfterTimerFn($) { or ( $ascDev->getSelfDefense eq 'on' and CheckIfShuttersWindowRecOpen($shuttersDev) == 0 ) ) + and $shutters->getShadingStatus ne 'in' ) { $shutters->setLastDrive('day open'); @@ -3092,8 +3142,7 @@ sub ShuttersSunrise($$) { { if ( not IsWeTomorrow() ) { if ( - IsWe() - and int( gettimeofday() / 86400 ) == int( + int( gettimeofday() / 86400 ) == int( computeAlignTime( '24:00', $shutters->getTimeUpWeHoliday ) / 86400 ) @@ -3108,11 +3157,12 @@ sub ShuttersSunrise($$) { computeAlignTime( '24:00', $shutters->getTimeUpEarly ) / 86400 ) + and $shutters->getSunrise ) { $shuttersSunriseUnixtime = - computeAlignTime( '24:00', - $shutters->getTimeUpWeHoliday ); + computeAlignTime( '24:00', $shutters->getTimeUpEarly ) + + 86400; } else { $shuttersSunriseUnixtime = @@ -3144,6 +3194,17 @@ sub ShuttersSunrise($$) { computeAlignTime( '24:00', $shutters->getTimeUpEarly ); } + elsif ( + int( gettimeofday() / 86400 ) != int( + computeAlignTime( '24:00', + $shutters->getTimeUpWeHoliday ) / 86400 + ) + ) + { + $shuttersSunriseUnixtime = + computeAlignTime( '24:00', + $shutters->getTimeUpWeHoliday ); + } else { $shuttersSunriseUnixtime = computeAlignTime( '24:00', @@ -3283,17 +3344,18 @@ sub CheckIfShuttersWindowRecOpen($) { my $shuttersDev = shift; $shutters->setShuttersDev($shuttersDev); - if ( $shutters->getWinStatus eq 'open' - or $shutters->getWinStatus eq 'opened' ) + if ( $shutters->getWinStatus =~ /open/ ) # CK: covers: open|opened { return 2; } - elsif ( $shutters->getWinStatus eq 'tilted' - and $shutters->getSubTyp eq 'threestate' ) + elsif ( $shutters->getWinStatus =~ /tilt/ + and $shutters->getSubTyp eq 'threestate' ) # CK: covers: tilt|tilted { return 1; } - elsif ( $shutters->getWinStatus eq 'closed' ) { return 0; } + elsif ( $shutters->getWinStatus =~ /close/ ) { + return 0; + } # CK: covers: close|closed } sub makeReadingName($) { @@ -4666,15 +4728,46 @@ sub getOutTemp { sub getResidentsStatus { my $self = shift; - - return ReadingsVal( $ascDev->_getResidentsDev, $ascDev->getResidentsReading, + my $val = + ReadingsVal( $ascDev->_getResidentsDev, $ascDev->getResidentsReading, 'none' ); + + if ( $val =~ m/^(?:(.+)_)?(.+)$/ ) { + return ( $1, $2 ) if (wantarray); + return $1 && $1 eq 'pet' ? 'absent' : $2; + } + elsif ( + ReadingsVal( $ascDev->_getResidentsDev, 'homealoneType', '-' ) eq + 'PET' ) + { + return ( 'pet', 'absent' ) if (wantarray); + return 'absent'; + } + else { + return ( undef, $val ) if (wantarray); + return $val; + } } sub getResidentsLastStatus { my $self = shift; + my $val = ReadingsVal( $ascDev->_getResidentsDev, 'lastState', 'none' ); - return ReadingsVal( $ascDev->_getResidentsDev, 'lastState', 'none' ); + if ( $val =~ m/^(?:(.+)_)?(.+)$/ ) { + return ( $1, $2 ) if (wantarray); + return $1 && $1 eq 'pet' ? 'absent' : $2; + } + elsif ( + ReadingsVal( $ascDev->_getResidentsDev, 'lastHomealoneType', '-' ) eq + 'PET' ) + { + return ( 'pet', 'absent' ) if (wantarray); + return 'absent'; + } + else { + return ( undef, $val ) if (wantarray); + return $val; + } } sub getAutoShuttersControlShading { @@ -5048,254 +5141,513 @@ sub getblockAscDrivesAfterManual {

AutoShuttersControl