diff --git a/fhem/CHANGED b/fhem/CHANGED index 2d43dc312..c7a77b074 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,7 @@ # 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: 73_AutoShuttersControl: new major release 0.6, add wind support, + chnage code and Attribut style - feature: 93_DbLog: V4.1.0 from contrib, write function rewritten, new attr bulkInsert, fix reconnect behavior of MySQL-Forum: #99719 - change: 74_GardenaSmartDevice: change output for illigal year diff --git a/fhem/FHEM/73_AutoShuttersControl.pm b/fhem/FHEM/73_AutoShuttersControl.pm index 12c0dd095..74846f098 100644 --- a/fhem/FHEM/73_AutoShuttersControl.pm +++ b/fhem/FHEM/73_AutoShuttersControl.pm @@ -35,40 +35,49 @@ ### Notizen # - Feststellen ob ein Rolladen fährt oder nicht +# !!!!! - Innerhalb einer Shutterschleife kein CommandAttr verwenden. Bring Fehler!!! Kommen Raumnamen in die Shutterliste !!!!!! +# package main; use strict; use warnings; +use FHEM::Meta; -my $version = '0.4.0.9'; +my $version = '0.6.0'; sub AutoShuttersControl_Initialize($) { my ($hash) = @_; -## Da ich mit package arbeite müssen in die Initialize für die jeweiligen hash Fn Funktionen der Funktionsname - # und davor mit :: getrennt der eigentliche package Name des Modules - $hash->{SetFn} = 'AutoShuttersControl::Set'; - $hash->{GetFn} = 'AutoShuttersControl::Get'; - $hash->{DefFn} = 'AutoShuttersControl::Define'; - $hash->{NotifyFn} = 'AutoShuttersControl::Notify'; - $hash->{UndefFn} = 'AutoShuttersControl::Undef'; - $hash->{AttrFn} = 'AutoShuttersControl::Attr'; - $hash->{AttrList} = - 'ASC_guestPresence:on,off ' - . 'ASC_temperatureSensor ' + ### alte Attribute welche entfernt werden + my $oldAttr = + 'ASC_temperatureSensor ' . 'ASC_temperatureReading ' - . 'ASC_brightnessMinVal ' - . 'ASC_brightnessMaxVal ' - . 'ASC_autoShuttersControlMorning:on,off ' - . 'ASC_autoShuttersControlEvening:on,off ' - . 'ASC_autoShuttersControlShading:on,off ' - . 'ASC_autoShuttersControlComfort:on,off ' . 'ASC_residentsDevice ' . 'ASC_residentsDeviceReading ' . 'ASC_rainSensorDevice ' . 'ASC_rainSensorReading ' . 'ASC_rainSensorShuttersClosedPos:0,10,20,30,40,50,60,70,80,90,100 ' + . 'ASC_brightnessMinVal ' + . 'ASC_brightnessMaxVal '; + +## Da ich mit package arbeite müssen in die Initialize für die jeweiligen hash Fn Funktionen der Funktionsname + # und davor mit :: getrennt der eigentliche package Name des Modules + $hash->{SetFn} = 'FHEM::AutoShuttersControl::Set'; + $hash->{GetFn} = 'FHEM::AutoShuttersControl::Get'; + $hash->{DefFn} = 'FHEM::AutoShuttersControl::Define'; + $hash->{NotifyFn} = 'FHEM::AutoShuttersControl::Notify'; + $hash->{UndefFn} = 'FHEM::AutoShuttersControl::Undef'; + $hash->{AttrFn} = 'FHEM::AutoShuttersControl::Attr'; + $hash->{AttrList} = + 'ASC_tempSensor ' + . 'ASC_brightnessDriveUpDown ' + . 'ASC_autoShuttersControlMorning:on,off ' + . 'ASC_autoShuttersControlEvening:on,off ' + . 'ASC_autoShuttersControlShading:on,off ' + . 'ASC_autoShuttersControlComfort:on,off ' + . 'ASC_residentsDev ' + . 'ASC_rainSensor ' . 'ASC_autoAstroModeMorning:REAL,CIVIL,NAUTIC,ASTRONOMIC,HORIZON ' . 'ASC_autoAstroModeMorningHorizon:-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9 ' . 'ASC_autoAstroModeEvening:REAL,CIVIL,NAUTIC,ASTRONOMIC,HORIZON ' @@ -76,23 +85,24 @@ sub AutoShuttersControl_Initialize($) { . 'ASC_freezeTemp:-5,-4,-3,-2,-1,0,1,2,3,4,5 ' . 'ASC_shuttersDriveOffset ' . 'ASC_twilightDevice ' + . 'ASC_windSensor ' . 'ASC_expert:1 ' + . 'ASC_blockAscDrivesAfterManual:0,1 ' + . 'ASC_debug:1 ' + . $oldAttr . $readingFnAttributes; $hash->{NotifyOrderPrefix} = '51-'; # Order Nummer für NotifyFn -## Ist nur damit sich bei einem reload auch die Versionsnummer erneuert. -# foreach my $d ( sort keys %{ $modules{AutoShuttersControl}{defptr} } ) { -# my $hash = $modules{AutoShuttersControl}{defptr}{$d}; -# $hash->{VERSION} = $version; -# } + return FHEM::Meta::InitMod( __FILE__, $hash ); } ## unserer packagename -package AutoShuttersControl; +package FHEM::AutoShuttersControl; use strict; use warnings; use POSIX; +use FHEM::Meta; use GPUtils qw(:all) ; # wird für den Import der FHEM Funktionen aus der fhem.pl benötigt @@ -141,65 +151,61 @@ BEGIN { ## Die Attributsliste welche an die Rolläden verteilt wird. Zusammen mit Default Werten my %userAttrList = ( - 'ASC_Mode_Up:absent,always,off,home' => 'always', - 'ASC_Mode_Down:absent,always,off,home' => 'always', - 'ASC_Up:time,astro,brightness' => 'astro', - 'ASC_Down:time,astro,brightness' => 'astro', - 'ASC_AutoAstroModeMorning:REAL,CIVIL,NAUTIC,ASTRONOMIC,HORIZON' => 'none', + 'ASC_Mode_Up:absent,always,off,home' => '-', + 'ASC_Mode_Down:absent,always,off,home' => '-', + 'ASC_Up:time,astro,brightness' => '-', + 'ASC_Down:time,astro,brightness' => '-', + 'ASC_AutoAstroModeMorning:REAL,CIVIL,NAUTIC,ASTRONOMIC,HORIZON' => '-', 'ASC_AutoAstroModeMorningHorizon:-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9' - => 'none', - 'ASC_AutoAstroModeEvening:REAL,CIVIL,NAUTIC,ASTRONOMIC,HORIZON' => 'none', + => '-', + 'ASC_AutoAstroModeEvening:REAL,CIVIL,NAUTIC,ASTRONOMIC,HORIZON' => '-', 'ASC_AutoAstroModeEveningHorizon:-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9' - => 'none', + => '-', 'ASC_Open_Pos:0,10,20,30,40,50,60,70,80,90,100' => [ '', 0, 100 ], 'ASC_Closed_Pos:0,10,20,30,40,50,60,70,80,90,100' => [ '', 100, 0 ], 'ASC_Pos_Reading' => [ '', 'position', 'pct' ], - 'ASC_Time_Up_Early' => '04:30', - 'ASC_Time_Up_Late' => '09:00', - 'ASC_Time_Up_WE_Holiday' => '08:30', - 'ASC_Time_Down_Early' => '15:30', - 'ASC_Time_Down_Late' => '22:30', - 'ASC_PrivacyDownTime_beforNightClose' => -1, - 'ASC_PrivacyDown_Pos' => 50, - 'ASC_WindowRec' => 'none', - 'ASC_Ventilate_Window_Open:on,off' => 'on', - 'ASC_LockOut:soft,hard,off' => 'off', - 'ASC_LockOut_Cmd:inhibit,blocked,protection' => 'none', - 'ASC_BlockingTime_afterManual' => 1200, - 'ASC_BlockingTime_beforNightClose' => 3600, - 'ASC_BlockingTime_beforDayOpen' => 3600, - 'ASC_Brightness_Sensor' => 'none', - 'ASC_Brightness_Reading' => 'brightness', - 'ASC_Shading_Direction' => 180, - 'ASC_Shading_Pos:10,20,30,40,50,60,70,80,90,100' => [ '', 80, 20 ], - 'ASC_Shading_Mode:absent,always,off,home' => 'off', - 'ASC_Shading_Angle_Left' => 75, - 'ASC_Shading_Angle_Right' => 75, - 'ASC_Shading_StateChange_Sunny' => 35000, - 'ASC_Shading_StateChange_Cloudy' => 20000, - 'ASC_Shading_Min_Elevation' => 25.0, - 'ASC_Shading_Min_OutsideTemperature' => 18, - 'ASC_Shading_WaitingPeriod' => 1200, - - # 'ASC_Shading_Fast_Open:on,off' => 'none', - # 'ASC_Shading_Fast_Close:on,off' => 'none', - 'ASC_Drive_Offset' => -1, - 'ASC_Drive_OffsetStart' => -1, - 'ASC_WindowRec_subType:twostate,threestate' => 'twostate', - 'ASC_ShuttersPlace:window,terrace' => 'window', + 'ASC_Time_Up_Early' => '-', + 'ASC_Time_Up_Late' => '-', + 'ASC_Time_Up_WE_Holiday' => '-', + 'ASC_Time_Down_Early' => '-', + 'ASC_Time_Down_Late' => '-', + 'ASC_PrivacyDownTime_beforNightClose' => '-', + 'ASC_PrivacyDown_Pos' => '-', + 'ASC_WindowRec' => '-', + 'ASC_Ventilate_Window_Open:on,off' => '-', + 'ASC_LockOut:soft,hard,off' => '-', + 'ASC_LockOut_Cmd:inhibit,blocked,protection' => '-', + 'ASC_BlockingTime_afterManual' => '-', + 'ASC_BlockingTime_beforNightClose' => '-', + 'ASC_BlockingTime_beforDayOpen' => '-', + 'ASC_BrightnessSensor' => '-', + 'ASC_Shading_Direction' => '-', + 'ASC_Shading_Pos:10,20,30,40,50,60,70,80,90,100' => [ '', 80, 20 ], + 'ASC_Shading_Mode:absent,always,off,home' => '-', + 'ASC_Shading_Angle_Left' => '-', + 'ASC_Shading_Angle_Right' => '-', + 'ASC_Shading_StateChange_Sunny' => '-', + 'ASC_Shading_StateChange_Cloudy' => '-', + 'ASC_Shading_Min_Elevation' => '-', + 'ASC_Shading_Min_OutsideTemperature' => '-', + 'ASC_Shading_WaitingPeriod' => '-', + 'ASC_Drive_Offset' => '-', + 'ASC_Drive_OffsetStart' => '-', + 'ASC_WindowRec_subType:twostate,threestate' => '-', + 'ASC_ShuttersPlace:window,terrace' => '-', 'ASC_Ventilate_Pos:10,20,30,40,50,60,70,80,90,100' => [ '', 70, 30 ], 'ASC_ComfortOpen_Pos:0,10,20,30,40,50,60,70,80,90,100' => [ '', 20, 80 ], - 'ASC_GuestRoom:on,off' => 'none', - 'ASC_Antifreeze:off,soft,hard,am,pm' => 'off', + 'ASC_GuestRoom:on,off' => '-', + 'ASC_Antifreeze:off,soft,hard,am,pm' => '-', 'ASC_Antifreeze_Pos:5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100' => [ '', 85, 15 ], - 'ASC_Partymode:on,off' => 'off', - 'ASC_Roommate_Device' => 'none', - 'ASC_Roommate_Reading' => 'state', - 'ASC_Self_Defense_Exclude:on,off' => 'off', - 'ASC_BrightnessMinVal' => -1, - 'ASC_BrightnessMaxVal' => -1, - 'ASC_WiggleValue' => 5, + 'ASC_Partymode:on,off' => '-', + 'ASC_Roommate_Device' => '-', + 'ASC_Roommate_Reading' => '-', + 'ASC_Self_Defense_Exclude:on,off' => '-', + 'ASC_WiggleValue' => '-', + 'ASC_WindParameters' => '-', + 'ASC_DriveUpMaxDuration' => '-', ); my %posSetCmds = ( @@ -221,6 +227,7 @@ sub Define($$) { my ( $hash, $def ) = @_; my @a = split( '[ \t][ \t]*', $def ); + return $@ unless ( FHEM::Meta::SetInternals($hash) ); return 'only one AutoShuttersControl instance allowed' if ( devspec2array('TYPE=AutoShuttersControl') > 1 ) ; # es wird geprüft ob bereits eine Instanz unseres Modules existiert,wenn ja wird abgebrochen @@ -260,10 +267,6 @@ sub Define($$) { if ( $ascDev->getAutoShuttersControlMorning eq 'none' ); CommandAttr( undef, $name . ' ASC_autoShuttersControlEvening on' ) if ( $ascDev->getAutoShuttersControlEvening eq 'none' ); - CommandAttr( undef, $name . ' ASC_temperatureReading temperature' ) - if ( $ascDev->getTempReading eq 'none' ); - CommandAttr( undef, $name . ' ASC_freezeTemp 3' ) - if ( $ascDev->getFreezeTemp eq 'none' ); CommandAttr( undef, $name . ' devStateIcon selfeDefense.terrace:fts_door_tilt created.new.drive.timer:clock .*asleep:scene_sleeping roommate.(awoken|home):user_available residents.(home|awoken):status_available manual:fts_shutter_manual selfeDefense.active:status_locked selfeDefense.inactive:status_open day.open:scene_day night.close:scene_night shading.in:weather_sun shading.out:weather_cloudy' @@ -340,10 +343,6 @@ sub Notify($$) { readingsSingleUpdate( $hash, 'selfDefense', 'off', 0 ) if ( $ascDev->getSelfDefense eq 'none' ); - CommandDeleteReading( undef, $name . ' lockOut' ) - if ( ReadingsVal( $name, 'lockOut', 'none' ) ne 'none' ) - ; # temporär ab Version 0.2.2 - # Ist der Event ein globaler und passt zum Rest der Abfrage oben wird nach neuen Rolläden Devices gescannt und eine Liste im Rolladenmodul sortiert nach Raum generiert ShuttersDeviceScan($hash) unless ( ReadingsVal( $name, 'userAttrList', 'none' ) eq 'none' ); @@ -360,10 +359,10 @@ sub Notify($$) { WriteReadingsShuttersList($hash); UserAttributs_Readings_ForShutters( $hash, 'add' ); InternalTimer( gettimeofday() + 3, - 'AutoShuttersControl::RenewSunRiseSetShuttersTimer', + 'FHEM::AutoShuttersControl::RenewSunRiseSetShuttersTimer', $hash ); InternalTimer( gettimeofday() + 5, - 'AutoShuttersControl::AutoSearchTwilightDev', $hash ); + 'FHEM::AutoShuttersControl::AutoSearchTwilightDev', $hash ); } } elsif ( grep /^partyMode:.off$/, @{$events} ) { @@ -377,15 +376,7 @@ sub Notify($$) { { # Kommt ein globales Event und beinhaltet folgende Syntax wird die Funktion zur Verarbeitung aufgerufen if ( grep -/^(ATTR|DELETEATTR)\s(.*ASC_Roommate_Device|.*ASC_WindowRec|.*ASC_residentsDevice|.*ASC_rainSensorDevice|.*ASC_Brightness_Sensor|.*ASC_twilightDevice)(\s.*|$)/, - @{$events} - ) - { - EventProcessingGeneral( $hash, undef, join( ' ', @{$events} ) ); - } - elsif ( - grep -/^(ATTR|DELETEATTR)\s(.*ASC_Time_Up_WE_Holiday|.*ASC_Up|.*ASC_Down|.*ASC_AutoAstroModeMorning|.*ASC_AutoAstroModeMorningHorizon|.*ASC_AutoAstroModeEvening|.*ASC_AutoAstroModeEveningHorizon|.*ASC_Time_Up_Early|.*ASC_Time_Up_Late|.*ASC_Time_Down_Early|.*ASC_Time_Down_Late|.*ASC_autoAstroModeMorning|.*ASC_autoAstroModeMorningHorizon|.*ASC_PrivacyDownTime_beforNightClose|.*ASC_autoAstroModeEvening|.*ASC_autoAstroModeEveningHorizon)(\s.*|$)/, +/^(ATTR|DELETEATTR)\s(.*ASC_Time_Up_WE_Holiday|.*ASC_Up|.*ASC_Down|.*ASC_AutoAstroModeMorning|.*ASC_AutoAstroModeMorningHorizon|.*ASC_AutoAstroModeEvening|.*ASC_AutoAstroModeEveningHorizon|.*ASC_Time_Up_Early|.*ASC_Time_Up_Late|.*ASC_Time_Down_Early|.*ASC_Time_Down_Late|.*ASC_autoAstroModeMorning|.*ASC_autoAstroModeMorningHorizon|.*ASC_PrivacyDownTime_beforNightClose|.*ASC_autoAstroModeEvening|.*ASC_autoAstroModeEveningHorizon|.*ASC_Roommate_Device|.*ASC_WindowRec|.*ASC_residentsDev|.*ASC_rainSensor|.*ASC_windSensor|.*ASC_BrightnessSensor|.*ASC_twilightDevice)(\s.*|$)/, @{$events} ) { @@ -418,31 +409,33 @@ sub EventProcessingGeneral($$$) { if ( $deviceAttr eq 'ASC_Roommate_Device' ) ; # ist es ein Bewohner Device wird diese Funktion gestartet EventProcessingResidents( $hash, $device, $events ) - if ( $deviceAttr eq 'ASC_residentsDevice' ); + if ( $deviceAttr eq 'ASC_residentsDev' ); EventProcessingRain( $hash, $device, $events ) - if ( $deviceAttr eq 'ASC_rainSensorDevice' ); + if ( $deviceAttr eq 'ASC_rainSensor' ); + EventProcessingWind( $hash, $device, $events ) + if ( $deviceAttr eq 'ASC_windSensor' ); EventProcessingTwilightDevice( $hash, $device, $events ) if ( $deviceAttr eq 'ASC_twilightDevice' ); $shutters->setShuttersDev($device) - if ( $deviceAttr eq 'ASC_Brightness_Sensor' ); + if ( $deviceAttr eq 'ASC_BrightnessSensor' ); if ( - $deviceAttr eq 'ASC_Brightness_Sensor' + $deviceAttr eq 'ASC_BrightnessSensor' and ( $shutters->getDown eq 'brightness' or $shutters->getUp eq 'brightness' ) ) { EventProcessingBrightness( $hash, $device, $events ); } - elsif ( $deviceAttr eq 'ASC_Brightness_Sensor' ) { + elsif ( $deviceAttr eq 'ASC_BrightnessSensor' ) { EventProcessingShadingBrightness( $hash, $device, $events ); } } } else { # alles was kein Devicenamen mit übergeben hat landet hier if ( $events =~ -m#^ATTR\s(.*)\s(ASC_Roommate_Device|ASC_WindowRec|ASC_residentsDevice|ASC_rainSensorDevice|ASC_Brightness_Sensor|ASC_twilightDevice)\s(.*)$# +m#^ATTR\s(.*)\s(ASC_Roommate_Device|ASC_WindowRec|ASC_residentsDev|ASC_rainSensor|ASC_windSensor|ASC_BrightnessSensor|ASC_twilightDevice)\s(.*)$# ) { # wurde den Attributen unserer Rolläden ein Wert zugewiesen ? AddNotifyDev( $hash, $3, $1, $2 ) if ( $3 ne 'none' ); @@ -450,7 +443,7 @@ m#^ATTR\s(.*)\s(ASC_Roommate_Device|ASC_WindowRec|ASC_residentsDevice|ASC_rainSe "AutoShuttersControl ($name) - EventProcessing: ATTR" ); } elsif ( $events =~ -m#^DELETEATTR\s(.*)\s(ASC_Roommate_Device|ASC_WindowRec|ASC_residentsDevice|ASC_rainSensorDevice|ASC_Brightness_Sensor|ASC_twilightDevice)$# +m#^DELETEATTR\s(.*)\s(ASC_Roommate_Device|ASC_WindowRec|ASC_residentsDev|ASC_rainSensor|ASC_windSensor|ASC_BrightnessSensor|ASC_twilightDevice)$# ) { # wurde das Attribut unserer Rolläden gelöscht ? Log3( $name, 4, @@ -496,7 +489,7 @@ sub Set($$@) { elsif ( lc $cmd eq 'partymode' ) { return "usage: $cmd" if ( @args > 1 ); readingsSingleUpdate( $hash, $cmd, join( ' ', @args ), 1 ) - if ( join( ' ', @args ) ne ReadingsVal($name,'partyMode',0) ); + if ( join( ' ', @args ) ne ReadingsVal( $name, 'partyMode', 0 ) ); } elsif ( lc $cmd eq 'hardlockout' ) { return "usage: $cmd" if ( @args > 1 ); @@ -581,31 +574,14 @@ sub ShuttersDeviceScan($) { push( @{ $hash->{helper}{shuttersList} }, $_ ) ; ## einem Hash wird ein Array zugewiesen welches die Liste der erkannten Rollos beinhaltet - delFromDevAttrList( $_, 'ASC_lock-out:soft,hard' ) - ; # temporär muss später gelöscht werden ab Version 0.2.0.6 - delFromDevAttrList( $_, 'ASC_lock-outCmd:inhibit,blocked' ) - ; # temporär muss später gelöscht werden ab Version 0.2.0.6 - delFromDevAttrList( $_, - 'ASC_Pos_after_ComfortOpen:0,10,20,30,40,50,60,70,80,90,100' ) - ; # temporär muss später gelöscht werden ab Version 0.2.0.6 - - delFromDevAttrList( $_, 'ASC_Antifreeze:off,on' ) - if ( AttrVal( $_, 'ASC_Antifreeze', 'on' ) eq 'on' - or AttrVal( $_, 'ASC_Antifreeze', 'on' ) eq 'off' ) - ; # temporär muss später gelöscht werden ab Version 0.2.0.6 - - delFromDevAttrList( $_, -'ASC_AntifreezePos:5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100' - ); # temporär muss später gelöscht werden ab Version 0.2.0.7 - - delFromDevAttrList( $_, 'ASC_LockOut_Cmd:inhibit,blocked' ) - if ( AttrVal( $_, 'ASC_LockOut_Cmd', 'none' ) eq 'none' ) - ; # temporär muss später gelöscht werden ab Version 0.2.0.10 - - delFromDevAttrList( $_, 'ASC_Shading_Brightness_Sensor' ) - ; # temporär muss später gelöscht werden ab Version 0.2.0.12 - delFromDevAttrList( $_, 'ASC_Shading_Brightness_Reading' ) - ; # temporär muss später gelöscht werden ab Version 0.2.0.12 + delFromDevAttrList( $_, 'ASC_Wind_SensorDevice' ) + ; # temporär muss später gelöscht werden ab Version 0.4.0.10 + delFromDevAttrList( $_, 'ASC_Wind_SensorReading' ) + ; # temporär muss später gelöscht werden ab Version 0.4.0.10 + delFromDevAttrList( $_, 'ASC_Wind_minMaxSpeed' ) + ; # temporär muss später gelöscht werden ab Version 0.4.11beta6 + delFromDevAttrList( $_, 'ASC_Wind_Pos' ) + ; # temporär muss später gelöscht werden ab Version 0.4.11beta6 $shuttersList = $shuttersList . ',' . $_; $shutters->setShuttersDev($_); @@ -614,10 +590,58 @@ sub ShuttersDeviceScan($) { $shutters->setDelayCmd('none'); $shutters->setNoOffset(0); $shutters->setPosSetCmd( $posSetCmds{ $defs{$_}->{TYPE} } ); - $shutters->setShading('out'); + $shutters->setShadingStatus( + ( $shutters->getStatus != $shutters->getShadingPos ? 'out' : 'in' ) + ); } - # $hash->{NOTIFYDEV} = $hash->{NOTIFYDEV} . $shuttersList; + ### Temporär und muss später entfernt werden + CommandAttr( undef, + $name + . ' ASC_tempSensor ' + . AttrVal( $name, 'ASC_temperatureSensor', 'none' ) . ':' + . AttrVal( $name, 'ASC_temperatureReading', 'temperature' ) ) + if ( AttrVal( $name, 'ASC_temperatureSensor', 'none' ) ne 'none' ); + CommandAttr( undef, + $name + . ' ASC_residentsDev ' + . AttrVal( $name, 'ASC_residentsDevice', 'none' ) . ':' + . AttrVal( $name, 'ASC_residentsDeviceReading', 'state' ) ) + if ( AttrVal( $name, 'ASC_residentsDevice', 'none' ) ne 'none' ); + CommandAttr( undef, + $name + . ' ASC_rainSensor ' + . AttrVal( $name, 'ASC_rainSensorDevice', 'none' ) . ':' + . AttrVal( $name, 'ASC_rainSensorReading', 'rain' ) . ' 100 ' + . AttrVal( $name, 'ASC_rainSensorShuttersClosedPos', 50 ) ) + if ( AttrVal( $name, 'ASC_rainSensorDevice', 'none' ) ne 'none' ); + CommandAttr( undef, + $name + . ' ASC_brightnessDriveUpDown ' + . AttrVal( $name, 'ASC_brightnessMinVal', 500 ) . ':' + . AttrVal( $name, 'ASC_brightnessMaxVal', 800 ) ) + if ( AttrVal( $name, 'ASC_brightnessMinVal', 'none' ) ne 'none' ); + + CommandDeleteAttr( undef, $name . ' ASC_temperatureSensor' ) + if ( AttrVal( $name, 'ASC_temperatureSensor', 'none' ) ne 'none' ); + CommandDeleteAttr( undef, $name . ' ASC_temperatureReading' ) + if ( AttrVal( $name, 'ASC_temperatureReading', 'none' ) ne 'none' ); + CommandDeleteAttr( undef, $name . ' ASC_residentsDevice' ) + if ( AttrVal( $name, 'ASC_residentsDevice', 'none' ) ne 'none' ); + CommandDeleteAttr( undef, $name . ' ASC_residentsDeviceReading' ) + if ( AttrVal( $name, 'ASC_residentsDeviceReading', 'none' ) ne 'none' ); + CommandDeleteAttr( undef, $name . ' ASC_rainSensorDevice' ) + if ( AttrVal( $name, 'ASC_rainSensorDevice', 'none' ) ne 'none' ); + CommandDeleteAttr( undef, $name . ' ASC_rainSensorReading' ) + if ( AttrVal( $name, 'ASC_rainSensorReading', 'none' ) ne 'none' ); + CommandDeleteAttr( undef, $name . ' ASC_rainSensorShuttersClosedPos' ) + if ( + AttrVal( $name, 'ASC_rainSensorShuttersClosedPos', 'none' ) ne 'none' ); + CommandDeleteAttr( undef, $name . ' ASC_brightnessMinVal' ) + if ( AttrVal( $name, 'ASC_brightnessMinVal', 'none' ) ne 'none' ); + CommandDeleteAttr( undef, $name . ' ASC_brightnessMaxVal' ) + if ( AttrVal( $name, 'ASC_brightnessMaxVal', 'none' ) ne 'none' ); + $hash->{NOTIFYDEV} = "global," . $name . $shuttersList; if ( $ascDev->getMonitoredDevs ne 'none' ) { @@ -683,22 +707,24 @@ sub UserAttributs_Readings_ForShutters($$) { addToDevAttrList( $_, $attrib ) ; ## fhem.pl bietet eine Funktion um ein userAttr Attribut zu befüllen. Wir schreiben also in den Attribut userAttr alle unsere Attribute rein. Pro Rolladen immer ein Attribut pro Durchlauf ## Danach werden die Attribute die im userAttr stehen gesetzt und mit default Werten befüllt + ## CommandAttr hat nicht funktioniert. Führte zu Problemen + ## https://github.com/LeonGaultier/fhem-AutoShuttersControl/commit/e33d3cc7815031b087736c1054b98c57817e7083 if ( $cmd eq 'add' ) { if ( ref($attribValue) ne 'ARRAY' ) { $attr{$_}{ ( split( ':', $attrib ) )[0] } = $attribValue if ( - not - defined( $attr{$_}{ ( split( ':', $attrib ) )[0] } ) ); + not defined( $attr{$_}{ ( split( ':', $attrib ) )[0] } ) + and $attribValue ne '-' ); } else { $attr{$_}{ ( split( ':', $attrib ) )[0] } = $attribValue->[ AttrVal( $_, 'ASC', 2 ) ] if ( - not - defined( $attr{$_}{ ( split( ':', $attrib ) )[0] } ) ); + not defined( $attr{$_}{ ( split( ':', $attrib ) )[0] } ) + and $attrib eq 'ASC_Pos_Reading' ); } - ## Oder das Attribut wird wieder gelöscht. } + ## Oder das Attribut wird wieder gelöscht. elsif ( $cmd eq 'del' ) { $shutters->setShuttersDev($_); @@ -714,13 +740,20 @@ sub UserAttributs_Readings_ForShutters($$) { ## Fügt dem NOTIFYDEV Hash weitere Devices hinzu sub AddNotifyDev($@) { + ### Beispielaufruf: AddNotifyDev( $hash, $3, $1, $2 ) if ( $3 ne 'none' ); my ( $hash, $dev, $shuttersDev, $shuttersAttr ) = @_; + + $dev = ( split( ':', $dev ) )[0]; + my ( $key, $value ) = split( ':', ( split( ' ', $dev ) )[0], 2 ) + ; ## Wir versuchen die Device Attribute anders zu setzen. device=DEVICE reading=READING + $dev = $key; + my $name = $hash->{NAME}; my $notifyDev = $hash->{NOTIFYDEV}; - $notifyDev = "" if ( !$notifyDev ); - my %hash; + $notifyDev = '' if ( !$notifyDev ); + my %hash; %hash = map { ( $_ => 1 ) } split( ",", "$notifyDev,$dev" ); @@ -770,8 +803,11 @@ 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:\s(open(ed)?|closed|tilted)# # weitere mögliche Events (opened / closed) + and IsAfterShuttersManualBlocking($shuttersDev) + ) { $shutters->setShuttersDev($shuttersDev); my $homemode = $shutters->getRoommatesStatus; @@ -781,9 +817,8 @@ sub EventProcessingWindowRec($@) { $shutters->setHardLockOut('off') if ( $1 eq 'closed' and $shutters->getShuttersPlace eq 'terrace' ); $shutters->setHardLockOut('on') - if ( ($1 eq 'open' or $1 eq 'opened') and $shutters->getShuttersPlace eq 'terrace' ); - - $shutters->setNoOffset(1); + if ( ( $1 eq 'open' or $1 eq 'opened' ) + and $shutters->getShuttersPlace eq 'terrace' ); my $queryShuttersPosWinRecTilted = ( $shutters->getShuttersPosCmdValueNegate @@ -796,71 +831,83 @@ sub EventProcessingWindowRec($@) { : $shutters->getStatus < $shutters->getComfortOpenPos ); -# ## Wird erstmal deaktiviert da es Sinnlos ist in meinen Augen -# if ( $shutters->getDelayCmd ne 'none' and $1 eq 'closed' ) -# { # Es wird geschaut ob wärend der Fenster offen Phase ein Fahrbefehl über das Modul kam,wenn ja wird dieser aus geführt -# $shutters->setLastDrive('delayed drive - window closed'); -# ShuttersCommandSet( $hash, $shuttersDev, $shutters->getDelayCmd ); -# } - if ( $1 eq 'closed' - and IsAfterShuttersTimeBlocking( $hash, $shuttersDev ) - and ($shutters->getModeDown eq $homemode - or ( $shutters->getModeDown eq 'absent' - and $homemode eq 'gone' ) - or $shutters->getModeDown eq 'always') ) - { - if ( $shutters->getStatus == $shutters->getVentilatePos + if ( + $1 eq 'closed' + and IsAfterShuttersTimeBlocking($shuttersDev) + and ( $shutters->getStatus == $shutters->getVentilatePos or $shutters->getStatus == $shutters->getComfortOpenPos or $shutters->getStatus == $shutters->getOpenPos ) + ) + { + my $homemode = $shutters->getRoommatesStatus; + $homemode = $ascDev->getResidentsStatus + if ( $homemode eq 'none' ); + + if ( + IsDay($shuttersDev) + and $shutters->getStatus != $shutters->getOpenPos + and ( $homemode ne 'asleep' + or $homemode ne 'gotosleep' + or $homemode eq 'none' ) + ) { - my $homemode = $shutters->getRoommatesStatus; - $homemode = $ascDev->getResidentsStatus - if ( $homemode eq 'none' ); + $shutters->setLastDrive('window day closed'); + $shutters->setNoOffset(1); + $shutters->setDriveCmd( + ( + $shutters->getLastPos != $shutters->getClosedPos + ? $shutters->getLastPos + : $shutters->getOpenPos + ) + ); + } - if ( - IsDay( $hash, $shuttersDev ) - and $shutters->getStatus != $shutters->getOpenPos - and ( $homemode ne 'asleep' - or $homemode ne 'gotosleep' - or $homemode eq 'none' ) - ) - { - $shutters->setLastDrive('window day closed'); - ShuttersCommandSet( $hash, $shuttersDev, - $shutters->getLastPos ); - } - - elsif (not IsDay( $hash, $shuttersDev ) - or $homemode eq 'asleep' - or $homemode eq 'gotosleep' ) - { - $shutters->setLastDrive('window night closed'); - ShuttersCommandSet( $hash, $shuttersDev, - $shutters->getClosedPos ); - } + elsif (not IsDay($shuttersDev) + or $homemode eq 'asleep' + or $homemode eq 'gotosleep' ) + { + $shutters->setLastDrive('window night closed'); + $shutters->setNoOffset(1); + $shutters->setDriveCmd( $shutters->getClosedPos ); } } elsif ( ( $1 eq 'tilted' - or ( ($1 eq 'open' or $1 eq 'opened') and $shutters->getSubTyp eq 'twostate' ) + or ( ( $1 eq 'open' or $1 eq 'opened' ) + and $shutters->getSubTyp eq 'twostate' ) ) and $shutters->getVentilateOpen eq 'on' and $queryShuttersPosWinRecTilted ) { $shutters->setLastDrive('ventilate - window open'); - ShuttersCommandSet( $hash, $shuttersDev, - $shutters->getVentilatePos ); + $shutters->setNoOffset(1); + $shutters->setDriveCmd( $shutters->getVentilatePos ); } - elsif ( ($1 eq 'open' or $1 eq 'opened') - and $shutters->getSubTyp eq 'threestate' - and $ascDev->getAutoShuttersControlComfort eq 'on' - and $queryShuttersPosWinRecComfort ) + elsif ( ( $1 eq 'open' or $1 eq 'opened' ) + and $shutters->getSubTyp eq 'threestate' ) { - $shutters->setLastDrive('comfort - window open'); - ShuttersCommandSet( $hash, $shuttersDev, - $shutters->getComfortOpenPos ); + my $posValue; + my $setLastDrive; + if ( $ascDev->getAutoShuttersControlComfort eq 'on' + and $queryShuttersPosWinRecComfort ) + { + $posValue = $shutters->getComfortOpenPos; + $setLastDrive = 'comfort - window open'; + } + elsif ( $queryShuttersPosWinRecTilted + and $shutters->getVentilateOpen eq 'on' ) + { + $posValue = $shutters->getVentilatePos; + $setLastDrive = 'ventilate - window open'; + } + + if ( defined($posValue) and $posValue ) { + $shutters->setLastDrive($setLastDrive); + $shutters->setNoOffset(1); + $shutters->setDriveCmd($posValue); + } } } } @@ -881,14 +928,20 @@ sub EventProcessingRoommate($@) { "AutoShuttersControl ($name) - EventProcessingRoommate: $shuttersDev und Events $events" ); + my $getModeUp = $shutters->getModeUp; + my $getModeDown = $shutters->getModeDown; + my $getRoommatesLastStatus = $shutters->getRoommatesLastStatus; + if ( ( $1 eq 'home' or $1 eq 'awoken' ) and ( $shutters->getRoommatesStatus eq 'home' or $shutters->getRoommatesStatus eq 'awoken' ) and $ascDev->getAutoShuttersControlMorning eq 'on' - - and ( $shutters->getModeUp eq 'always' - or $shutters->getModeUp eq 'home' ) + and ( $getModeUp eq 'home' + or $getModeUp eq 'always' + or $getModeDown eq 'home' + or $getModeDown eq 'always' ) + and IsAfterShuttersManualBlocking($shuttersDev) ) { Log3( $name, 4, @@ -896,11 +949,13 @@ sub EventProcessingRoommate($@) { ); if ( ( - $shutters->getRoommatesLastStatus eq 'asleep' - or $shutters->getRoommatesLastStatus eq 'awoken' + $getRoommatesLastStatus eq 'asleep' + or $getRoommatesLastStatus eq 'awoken' ) - and IsDay( $hash, $shuttersDev ) - and IsAfterShuttersTimeBlocking( $hash, $shuttersDev ) + and IsDay($shuttersDev) + and IsAfterShuttersTimeBlocking($shuttersDev) + and ( $getModeUp eq 'home' + or $getModeUp eq 'always' ) ) { Log3( $name, 4, @@ -913,19 +968,20 @@ sub EventProcessingRoommate($@) { if ( ( - $shutters->getRoommatesLastStatus eq 'absent' - or $shutters->getRoommatesLastStatus eq 'gone' - or $shutters->getRoommatesLastStatus eq 'home' + $getRoommatesLastStatus eq 'absent' + or $getRoommatesLastStatus eq 'gone' + + # or $getRoommatesLastStatus eq 'home' ) - and ( $shutters->getModeUp eq 'home' - or $shutters->getModeUp eq 'always' - or $shutters->getModeDown eq 'home' - or $shutters->getModeDown eq 'always' ) and $shutters->getRoommatesStatus eq 'home' ) { - if ( not IsDay( $hash, $shuttersDev ) - and IsAfterShuttersTimeBlocking( $hash, $shuttersDev ) ) + if ( + not IsDay($shuttersDev) + and IsAfterShuttersTimeBlocking($shuttersDev) + and ( $getModeDown eq 'home' + or $getModeDown eq 'always' ) + ) { my $position; $shutters->setLastDrive('roommate home'); @@ -943,9 +999,14 @@ sub EventProcessingRoommate($@) { ShuttersCommandSet( $hash, $shuttersDev, $position ); } - elsif ( IsDay( $hash, $shuttersDev ) + elsif ( + IsDay($shuttersDev) and $shutters->getStatus == $shutters->getClosedPos - and IsAfterShuttersTimeBlocking( $hash, $shuttersDev ) ) + and IsAfterShuttersTimeBlocking($shuttersDev) + and ( $getModeUp eq 'home' + or $getModeUp eq 'always' ) + and not $shutters->getIfInShading + ) { $shutters->setLastDrive('roommate home'); ShuttersCommandSet( $hash, $shuttersDev, @@ -955,11 +1016,12 @@ sub EventProcessingRoommate($@) { } elsif ( ( - $shutters->getModeDown eq 'always' - or $shutters->getModeDown eq 'home' + $getModeDown eq 'always' + or $getModeDown eq 'home' ) and ( $1 eq 'gotosleep' or $1 eq 'asleep' ) and $ascDev->getAutoShuttersControlEvening eq 'on' + and IsAfterShuttersManualBlocking($shuttersDev) ) { my $position; @@ -978,9 +1040,9 @@ sub EventProcessingRoommate($@) { ShuttersCommandSet( $hash, $shuttersDev, $position ); } - elsif ( $shutters->getModeDown eq 'absent' + elsif ( $getModeDown eq 'absent' and $1 eq 'absent' - and not IsDay( $hash, $shuttersDev ) ) + and not IsDay($shuttersDev) ) { $shutters->setLastDrive('roommate absent'); ShuttersCommandSet( $hash, $shuttersDev, $shutters->getClosedPos ); @@ -991,12 +1053,15 @@ sub EventProcessingRoommate($@) { sub EventProcessingResidents($@) { my ( $hash, $device, $events ) = @_; - my $name = $device; - my $reading = $ascDev->getResidentsReading; + my $name = $device; + my $reading = $ascDev->getResidentsReading; + my $getResidentsLastStatus = $ascDev->getResidentsLastStatus; if ( $events =~ m#$reading:\s(absent)# ) { foreach my $shuttersDev ( @{ $hash->{helper}{shuttersList} } ) { $shutters->setShuttersDev($shuttersDev); + my $getModeUp = $shutters->getModeUp; + my $getModeDown = $shutters->getModeDown; $shutters->setHardLockOut('off'); if ( CheckIfShuttersWindowRecOpen($shuttersDev) != 0 @@ -1004,11 +1069,11 @@ sub EventProcessingResidents($@) { and $shutters->getSelfDefenseExclude eq 'off' or ( ( - $shutters->getModeDown eq 'absent' - or $shutters->getModeDown eq 'always' + $getModeDown eq 'absent' + or $getModeDown eq 'always' ) - and not IsDay( $hash, $shuttersDev ) - and IsAfterShuttersTimeBlocking( $hash, $shuttersDev ) + and not IsDay($shuttersDev) + and IsAfterShuttersTimeBlocking($shuttersDev) ) ) { @@ -1029,6 +1094,8 @@ sub EventProcessingResidents($@) { { foreach my $shuttersDev ( @{ $hash->{helper}{shuttersList} } ) { $shutters->setShuttersDev($shuttersDev); + my $getModeUp = $shutters->getModeUp; + my $getModeDown = $shutters->getModeDown; $shutters->setHardLockOut('off'); if ( $shutters->getShuttersPlace eq 'terrace' ) { $shutters->setLastDrive('selfeDefense terrace'); @@ -1038,24 +1105,26 @@ sub EventProcessingResidents($@) { } elsif ( $events =~ m#$reading:\s(home)# - and ( $ascDev->getResidentsLastStatus eq 'absent' - or $ascDev->getResidentsLastStatus eq 'gone' - or $ascDev->getResidentsLastStatus eq 'asleep' - or $ascDev->getResidentsLastStatus eq 'awoken' ) + and ( $getResidentsLastStatus eq 'absent' + or $getResidentsLastStatus eq 'gone' + or $getResidentsLastStatus eq 'asleep' + or $getResidentsLastStatus eq 'awoken' ) ) { foreach my $shuttersDev ( @{ $hash->{helper}{shuttersList} } ) { $shutters->setShuttersDev($shuttersDev); + my $getModeUp = $shutters->getModeUp; + my $getModeDown = $shutters->getModeDown; if ( $shutters->getStatus != $shutters->getClosedPos - and not IsDay( $hash, $shuttersDev ) + and not IsDay($shuttersDev) and $shutters->getRoommatesStatus eq 'none' - and ( $shutters->getModeDown eq 'home' - or $shutters->getModeDown eq 'always' ) - and ( $ascDev->getResidentsLastStatus ne 'asleep' - or $ascDev->getResidentsLastStatus ne 'awoken' ) - and IsAfterShuttersTimeBlocking( $hash, $shuttersDev ) + and ( $getModeDown eq 'home' + or $getModeDown eq 'always' ) + and ( $getResidentsLastStatus ne 'asleep' + or $getResidentsLastStatus ne 'awoken' ) + and IsAfterShuttersTimeBlocking($shuttersDev) ) { $shutters->setLastDrive('residents home'); @@ -1065,10 +1134,11 @@ sub EventProcessingResidents($@) { $ascDev->getSelfDefense eq 'on' and CheckIfShuttersWindowRecOpen($shuttersDev) != 0 and $shutters->getSelfDefenseExclude eq 'off' - or ( $ascDev->getResidentsLastStatus eq 'gone' + or ( $getResidentsLastStatus eq 'gone' and $shutters->getShuttersPlace eq 'terrace' ) - and ( $shutters->getModeUp eq 'absent' - or $shutters->getModeUp eq 'off' ) + and ( $getModeUp eq 'absent' + or $getModeUp eq 'off' ) + and not $shutters->getIfInShading ) { $shutters->setLastDrive('selfeDefense inactive'); @@ -1079,15 +1149,16 @@ sub EventProcessingResidents($@) { } elsif ( $shutters->getStatus == $shutters->getClosedPos - and IsDay( $hash, $shuttersDev ) + and IsDay($shuttersDev) and $shutters->getRoommatesStatus eq 'none' - and ( $shutters->getModeUp eq 'home' - or $shutters->getModeUp eq 'always' ) - and IsAfterShuttersTimeBlocking( $hash, $shuttersDev ) + and ( $getModeUp eq 'home' + or $getModeUp eq 'always' ) + and IsAfterShuttersTimeBlocking($shuttersDev) + and not $shutters->getIfInShading ) { - if ( $ascDev->getResidentsLastStatus eq 'asleep' - or $ascDev->getResidentsLastStatus eq 'awoken' ) + if ( $getResidentsLastStatus eq 'asleep' + or $getResidentsLastStatus eq 'awoken' ) { $shutters->setLastDrive('residents awoken'); } @@ -1102,26 +1173,29 @@ sub EventProcessingRain($@) { my ( $hash, $device, $events ) = @_; my $name = $device; my $reading = $ascDev->getRainSensorReading; - my $val; if ( $events =~ m#$reading:\s(\d+|rain|dry)# ) { - if ( $1 eq 'rain' ) { $val = 1000 } - elsif ( $1 eq 'dry' ) { $val = 0 } + my $val; + my $triggerMax = $ascDev->getRainTriggerMax; + my $triggerMin = $ascDev->getRainTriggerMin; + my $closedPos = $ascDev->getRainSensorShuttersClosedPos; + + if ( $1 eq 'rain' ) { $val = $triggerMax + 1 } + elsif ( $1 eq 'dry' ) { $val = $triggerMin } else { $val = $1 } foreach my $shuttersDev ( @{ $hash->{helper}{shuttersList} } ) { $shutters->setShuttersDev($shuttersDev); - if ( $val > 100 - and $shutters->getStatus != - $ascDev->getRainSensorShuttersClosedPos ) + if ( $val > $triggerMax + and $shutters->getStatus != $closedPos + and IsAfterShuttersManualBlocking($shuttersDev) ) { $shutters->setLastDrive('rain protection'); - $shutters->setDriveCmd( - $ascDev->getRainSensorShuttersClosedPos ); + $shutters->setDriveCmd($closedPos); } - elsif ( $val == 0 - and $shutters->getStatus == - $ascDev->getRainSensorShuttersClosedPos ) + elsif ( ( $val == 0 or $val < $triggerMax ) + and $shutters->getStatus == $closedPos + and IsAfterShuttersManualBlocking($shuttersDev) ) { $shutters->setLastDrive('rain un-protection'); $shutters->setDriveCmd( $shutters->getLastPos ); @@ -1130,23 +1204,110 @@ sub EventProcessingRain($@) { } } +sub EventProcessingWind($@) { + my ( $hash, $shuttersDev, $events ) = @_; + my $name = $hash->{NAME}; + $shutters->setShuttersDev($shuttersDev); + + my $reading = $ascDev->getWindSensorReading; + if ( $events =~ m#$reading:\s(\d+)# ) { + foreach my $shuttersDev ( @{ $hash->{helper}{shuttersList} } ) { + $shutters->setShuttersDev($shuttersDev); + + ASC_Debug( 'EventProcessingWind: ' + . $shutters->getShuttersDev + . ' - WindProtection1: ' + . $shutters->getWindProtection + . ' WindMax1: ' + . $shutters->getWindMax + . ' WindMin1: ' + . $shutters->getWindMin + . ' Bekommender Wert1: ' + . $1 ); + + $shutters->setWindProtection('unprotection') + if ( not defined( $shutters->getWindProtection ) + or not $shutters->getWindProtection ); + + next + if ( CheckIfShuttersWindowRecOpen($shuttersDev) != 0 + and $shutters->getShuttersPlace eq 'terrace' ); + + if ( $1 > $shutters->getWindMax + and $shutters->getWindProtection eq 'unprotection' ) + { + $shutters->setLastDrive('wind protection'); + $shutters->setDriveCmd( $shutters->getWindPos ); + $shutters->setWindProtection('protection'); + } + elsif ( $1 < $shutters->getWindMin + and $shutters->getWindProtection eq 'protection' ) + { + $shutters->setLastDrive('wind un-protection'); + $shutters->setDriveCmd( $shutters->getLastPos ); + $shutters->setWindProtection('unprotection'); + } + + ASC_Debug( 'EventProcessingWind: ' + . $shutters->getShuttersDev + . ' - WindProtection2: ' + . $shutters->getWindProtection + . ' WindMax2: ' + . $shutters->getWindMax + . ' WindMin2: ' + . $shutters->getWindMin + . ' Bekommender Wert2: ' + . $1 ); + } + } +} +########## + sub EventProcessingBrightness($@) { my ( $hash, $shuttersDev, $events ) = @_; my $name = $hash->{NAME}; $shutters->setShuttersDev($shuttersDev); + ASC_Debug( 'EventProcessingBrightness: ' + . $shutters->getShuttersDev + . ' - Event von einem Helligkeitssensor erkannt. Verarbeitung läuft. Sollten keine weitere Meldungen aus der Funktion kommen, so befindet sich die aktuelle Zeit nicht innerhalb der Verarbeitungszeit für Sunset oder Sunrise' + ); + return EventProcessingShadingBrightness( $hash, $shuttersDev, $events ) unless ( - int( gettimeofday() / 86400 ) != - int( computeAlignTime( '24:00', $shutters->getTimeUpEarly ) / 86400 ) - and int( gettimeofday() / 86400 ) == - int( computeAlignTime( '24:00', $shutters->getTimeUpLate ) / 86400 ) - or int( gettimeofday() / 86400 ) != - int( computeAlignTime( '24:00', $shutters->getTimeDownEarly ) / 86400 ) - and int( gettimeofday() / 86400 ) == - int( computeAlignTime( '24:00', $shutters->getTimeDownLate ) / 86400 ) + ( + $shutters->getModeDown eq 'brightness' + or $shutters->getModeUp eq 'brightness' + ) + or ( + ( + int( gettimeofday() / 86400 ) != int( + computeAlignTime( '24:00', $shutters->getTimeUpEarly ) / + 86400 + ) + and int( gettimeofday() / 86400 ) == int( + computeAlignTime( '24:00', $shutters->getTimeUpLate ) / + 86400 + ) + ) + or ( + int( gettimeofday() / 86400 ) != int( + computeAlignTime( '24:00', $shutters->getTimeDownEarly ) / + 86400 + ) + and int( gettimeofday() / 86400 ) == int( + computeAlignTime( '24:00', $shutters->getTimeDownLate ) / + 86400 + ) + ) + ) ); + ASC_Debug( 'EventProcessingBrightness: ' + . $shutters->getShuttersDev + . ' - Die aktuelle Zeit befindet sich innerhalb der Sunset/Sunrise Brightness Verarbeitungszeit. Also zwischen Time Early und Time Late' + ); + my $reading = $shutters->getBrightnessReading; if ( $events =~ m#$reading:\s(\d+)# ) { my $brightnessMinVal; @@ -1165,6 +1326,16 @@ sub EventProcessingBrightness($@) { $brightnessMaxVal = $ascDev->getBrightnessMaxVal; } + ASC_Debug( 'EventProcessingBrightness: ' + . $shutters->getShuttersDev + . ' - Es wird geprüft ob Sunset oder Sunrise gefahren werden soll und der aktuelle übergebene Brightness-Wert: ' + . $1 + . ' Größer dem eingestellten Sunrise-Wert: ' + . $brightnessMaxVal + . ' oder kleiner dem eingestellten Sunset-Wert: ' + . $brightnessMinVal + . ' ist' ); + if ( int( gettimeofday() / 86400 ) != int( computeAlignTime( '24:00', $shutters->getTimeUpEarly ) / 86400 @@ -1174,11 +1345,18 @@ sub EventProcessingBrightness($@) { ) and $1 > $brightnessMaxVal and $shutters->getUp eq 'brightness' + and not $shutters->getSunrise ) { Log3( $name, 4, "AutoShuttersControl ($shuttersDev) - EventProcessingBrightness: Steuerung für Morgens" ); + + ASC_Debug( 'EventProcessingBrightness: ' + . $shutters->getShuttersDev + . ' - Verarbeitungszeit für Sunrise wurd erkannt. Prüfe Status der Roommates' + ); + my $homemode = $shutters->getRoommatesStatus; $homemode = $ascDev->getResidentsStatus if ( $homemode eq 'none' ); @@ -1204,12 +1382,23 @@ sub EventProcessingBrightness($@) { and CheckIfShuttersWindowRecOpen($shuttersDev) == 0 ) ) { + $shutters->setSunrise(1); + $shutters->setSunset(0); ShuttersCommandSet( $hash, $shuttersDev, $shutters->getOpenPos ); + + ASC_Debug( 'EventProcessingBrightness: ' + . $shutters->getShuttersDev + . ' - Verarbeitung für Sunrise. Roommatestatus korrekt zum fahren. Fahrbefehl wird an die Funktion FnShuttersCommandSet gesendet. Grund des fahrens: ' + . $shutters->getLastDrive ); } else { EventProcessingShadingBrightness( $hash, $shuttersDev, $events ); + ASC_Debug( 'EventProcessingBrightness: ' + . $shutters->getShuttersDev + . ' - Verarbeitung für Sunrise. Roommatestatus nicht zum hochfahren oder Fenster sind offen. Fahrbebehl bleibt aus!!! Es wird an die Event verarbeitende Beschattungsfunktion weiter gereicht' + ); } } } @@ -1222,6 +1411,7 @@ sub EventProcessingBrightness($@) { ) and $1 < $brightnessMinVal and $shutters->getDown eq 'brightness' + and not $shutters->getSunset and IsAfterShuttersManualBlocking($shuttersDev) ) { @@ -1229,6 +1419,11 @@ sub EventProcessingBrightness($@) { "AutoShuttersControl ($shuttersDev) - EventProcessingBrightness: Steuerung für Abends" ); + ASC_Debug( 'EventProcessingBrightness: ' + . $shutters->getShuttersDev + . ' - Verarbeitungszeit für Sunset wurd erkannt. Prüfe Status der Roommates' + ); + my $posValue; if ( CheckIfShuttersWindowRecOpen($shuttersDev) == 2 and $shutters->getSubTyp eq 'threestate' @@ -1255,15 +1450,41 @@ sub EventProcessingBrightness($@) { or $shutters->getModeDown eq 'always' ) { + $shutters->setSunrise(0); + $shutters->setSunset(1); ShuttersCommandSet( $hash, $shuttersDev, $posValue ); + + ASC_Debug( 'EventProcessingBrightness: ' + . $shutters->getShuttersDev + . ' - Verarbeitung für Sunset. Roommatestatus korrekt zum fahren. Fahrbefehl wird an die Funktion FnShuttersCommandSet gesendet. Zielposition: ' + . $posValue + . ' Grund des fahrens: ' + . $shutters->getLastDrive ); } else { EventProcessingShadingBrightness( $hash, $shuttersDev, $events ); + ASC_Debug( 'EventProcessingBrightness: ' + . $shutters->getShuttersDev + . ' - Verarbeitung für Sunset. Roommatestatus nicht zum runter fahren. Fahrbebehl bleibt aus!!! Es wird an die Event verarbeitende Beschattungsfunktion weiter gereicht' + ); } } + else { + ASC_Debug( 'EventProcessingBrightness: ' + . $shutters->getShuttersDev + . ' - Brightness Event kam nicht innerhalb der Verarbeitungszeit für Sunset oder Sunris oder aber für beide wurden die entsprechendne Verarbeitungsschwellen nicht erreicht.' + ); + } + } + ### Wenn es kein Brightness Reading ist muss auch die Shading Funktion nicht aufgerufen werden. +# else { EventProcessingShadingBrightness( $hash, $shuttersDev, $events ); } + else { + ASC_Debug( 'EventProcessingBrightness: ' + . $shutters->getShuttersDev + . ' - Leider konnte kein Korrekter Brightnesswert aus dem Event erkannt werden. Entweder passt das Reading oder der tatsächliche nummerishce Wert des Events nicht' + ); } - else { EventProcessingShadingBrightness( $hash, $shuttersDev, $events ); } } sub EventProcessingShadingBrightness($@) { @@ -1272,25 +1493,55 @@ sub EventProcessingShadingBrightness($@) { $shutters->setShuttersDev($shuttersDev); my $reading = $shutters->getBrightnessReading; + Log3( $name, 4, + "AutoShuttersControl ($shuttersDev) - EventProcessingShadingBrightness" + ); + + ASC_Debug( 'EventProcessingShadingBrightness: ' + . $shutters->getShuttersDev + . ' - Es wird nun geprüft ob der übergebene Event ein nummerischer Wert vom Brightnessreading ist.' + ); + if ( $events =~ m#$reading:\s(\d+)# ) { + Log3( + $name, 4, +"AutoShuttersControl ($shuttersDev) - EventProcessingShadingBrightness + Brightness: " . $1 + ); + + ASC_Debug( 'EventProcessingShadingBrightness: ' + . $shutters->getShuttersDev + . ' - Nummerischer Brightness-Wert wurde erkannt. Der Wert ist: ' + . $1 ); + my $homemode = $shutters->getRoommatesStatus; $homemode = $ascDev->getResidentsStatus if ( $homemode eq 'none' ); - ShadingProcessing( - $hash, $shuttersDev, - $ascDev->getAzimuth, $ascDev->getElevation, - $1, $ascDev->getOutTemp, - $shutters->getDirection, $shutters->getShadingAngleLeft, - $shutters->getShadingAngleRight - ) - - if ( + if ( ( $shutters->getShadingMode eq 'always' or $shutters->getShadingMode eq $homemode ) - and IsDay( $hash, $shuttersDev ) - ); + and IsDay($shuttersDev) + ) + { + ShadingProcessing( + $hash, + $shuttersDev, + $ascDev->getAzimuth, + $ascDev->getElevation, + $1, + $ascDev->getOutTemp, + $shutters->getDirection, + $shutters->getShadingAngleLeft, + $shutters->getShadingAngleRight + ); + + ASC_Debug( 'EventProcessingShadingBrightness: ' + . $shutters->getShuttersDev + . ' - Alle Bedingungen zur weiteren Beschattungsverarbeitung sind erfüllt. Es wird nun die eigentliche Beschattungsfunktion aufgerufen' + ); + } } } @@ -1305,11 +1556,16 @@ sub EventProcessingTwilightDevice($@) { # SunAz = azimuth = Sonnenwinkel # SunAlt = elevation = Sonnenhöhe + ASC_Debug( 'EventProcessingTwilightDevice: ' + . $shutters->getShuttersDev + . ' - Event vom Astro oder Twilight Device wurde erkannt. Event wird verarbeitet' + ); + if ( $events =~ m#(azimuth|elevation|SunAz|SunAlt):\s(\d+.\d+)# ) { my $name = $device; my ( $azimuth, $elevation ); - $azimuth = $2 if ( $1 eq 'azimuth' or $1 eq 'SunAz' ); + $azimuth = $2 if ( $1 eq 'azimuth' or $1 eq 'SunAz' ); $elevation = $2 if ( $1 eq 'elevation' or $1 eq 'SunAlt' ); $azimuth = $ascDev->getAzimuth @@ -1317,30 +1573,46 @@ sub EventProcessingTwilightDevice($@) { $elevation = $ascDev->getElevation if ( not defined($elevation) and not $elevation ); + ASC_Debug( 'EventProcessingTwilightDevice: ' + . $name + . ' - Passendes Event wurde erkannt. Verarbeitung über alle Rolllos beginnt' + ); + foreach my $shuttersDev ( @{ $hash->{helper}{shuttersList} } ) { $shutters->setShuttersDev($shuttersDev); my $homemode = $shutters->getRoommatesStatus; $homemode = $ascDev->getResidentsStatus if ( $homemode eq 'none' ); - ShadingProcessing( - $hash, - $shuttersDev, - $azimuth, - $elevation, - $shutters->getBrightness, - $ascDev->getOutTemp, - $shutters->getDirection, - $shutters->getShadingAngleLeft, - $shutters->getShadingAngleRight - ) - if ( + if ( ( $shutters->getShadingMode eq 'always' or $shutters->getShadingMode eq $homemode ) - and IsDay( $hash, $shuttersDev ) - ); + and IsDay($shuttersDev) + ) + { + ShadingProcessing( + $hash, + $shuttersDev, + $azimuth, + $elevation, + $shutters->getBrightness, + $ascDev->getOutTemp, + $shutters->getDirection, + $shutters->getShadingAngleLeft, + $shutters->getShadingAngleRight + ); + + ASC_Debug( 'EventProcessingTwilightDevice: ' + . $shutters->getShuttersDev + . ' - Alle Bedingungen zur weiteren Beschattungsverarbeitung sind erfüllt. Es wird nun die Beschattungsfunktion ausgeführt' + ); + } + + $shutters->setShadingStatus('out') + if ( not IsDay($shuttersDev) + and $shutters->getShadingStatus ne 'out' ); } } } @@ -1355,9 +1627,38 @@ sub ShadingProcessing($@) { ) = @_; my $name = $hash->{NAME}; $shutters->setShuttersDev($shuttersDev); - $shutters->setShading('out') - if ( not IsDay( $hash, $shuttersDev ) - and $shutters->getShading ne 'out' ); + + ASC_Debug( + 'ShadingProcessing: ' + . $shutters->getShuttersDev + . ' - Übergebende Werte - Azimuth:' + . $azimuth + . ', Elevation: ' + . $elevation + . ', Brightness: ' + . $brightness + . ', OutTemp: ' + . $outTemp + . ', Fenster Position: ' + . $winPos + . ', Winkel Links: ' + . $angleMinus + . ', Winkel Rechts: ' + . $anglePlus + . ', Ist es nach der Zeitblockadezeit: ' + . ( IsAfterShuttersTimeBlocking($shuttersDev) ? 'JA' : 'NEIN' ) + . ', Ist es nach der manuellen Blockadezeit: ' + . ( IsAfterShuttersManualBlocking($shuttersDev) ? 'JA' : 'NEIN' ) + . ', Ist es nach der Hälfte der Beschattungswartezeit: ' + . ( + ( int( gettimeofday() ) - $shutters->getShadingStatusTimestamp ) < + ( $shutters->getShadingWaitingPeriod / 2 ) ? 'NEIN' : 'JA' + ) + ); + + $shutters->setShadingStatus('out') + if ( not IsDay($shuttersDev) + and $shutters->getShadingStatus ne 'out' ); Log3( $name, 4, "AutoShuttersControl ($name) - Shading Processing, Rollladen: " @@ -1376,17 +1677,49 @@ sub ShadingProcessing($@) { or $elevation == -1 or $brightness == -1 or $outTemp == -100 - or $outTemp < $shutters->getShadingMinOutsideTemperature - or not IsDay( $hash, $shuttersDev ) - or ( int( gettimeofday() ) - $shutters->getShadingTimestamp ) < + or ( int( gettimeofday() ) - $shutters->getShadingStatusTimestamp ) < ( $shutters->getShadingWaitingPeriod / 2 ) - or not IsAfterShuttersTimeBlocking( $hash, $shuttersDev ) ); + or not IsAfterShuttersTimeBlocking($shuttersDev) + or not IsAfterShuttersManualBlocking($shuttersDev) ); Log3( $name, 4, "AutoShuttersControl ($name) - Shading Processing, Rollladen: " . $shuttersDev . " Nach dem return" ); + my $getShadingPos = $shutters->getShadingPos; + my $getStatus = $shutters->getStatus; + my $oldShadingStatus = $shutters->getShadingStatus; + + ASC_Debug( 'ShadingProcessing: ' + . $shutters->getShuttersDev + . ' - Alle Werte für die weitere Verarbeitung sind korrekt vorhanden und es wird nun mit der Beschattungsverarbeitung begonnen' + ); + + if ( + ( + $outTemp < $shutters->getShadingMinOutsideTemperature - 3 + or not IsDay($shuttersDev) + ) + and $shutters->getShadingStatus ne 'out' + and $getStatus != $getShadingPos + ) + { + $shutters->setShadingStatus('out'); + $shutters->setLastDrive('shading out'); + + ShuttersCommandSet( $hash, $shuttersDev, $shutters->getLastPos ); + + ASC_Debug( 'ShadingProcessing: ' + . $shutters->getShuttersDev + . ' - Es ist Nacht oder die Aussentemperatur unterhalb der Shading Temperatur. Die Beschattung wird Zwangsbeendet' + ); + + return Log3( $name, 4, +"AutoShuttersControl ($name) - Shading Processing - Es ist Sonnenuntergang vorbei oder die Aussentemperatur unterhalb der Shading Temperatur " + ); + } + # minimalen und maximalen Winkel des Fensters bestimmen. wenn die aktuelle Sonnenposition z.B. bei 205° läge und der Wert für angleMin/Max 85° wäre, dann würden zwischen 120° und 290° beschattet. my $winPosMin = $winPos - $angleMinus; my $winPosMax = $winPos + $anglePlus; @@ -1394,74 +1727,129 @@ sub ShadingProcessing($@) { if ( $azimuth < $winPosMin or $azimuth > $winPosMax or $elevation < $shutters->getShadingMinElevation - or $brightness <= $shutters->getShadingStateChangeCloudy ) + or $brightness < $shutters->getShadingStateChangeCloudy + or $outTemp < $shutters->getShadingMinOutsideTemperature ) { - $shutters->setShading('out reserved') - if ( $shutters->getShading eq 'in' - or $shutters->getShading eq 'in reserved' ); + $shutters->setShadingStatus('out reserved') + if ( $shutters->getShadingStatus eq 'in' + or $shutters->getShadingStatus eq 'in reserved' ); - $shutters->setShading('out') - if ( $shutters->getShading eq 'out reserved' - and ( int( gettimeofday() ) - $shutters->getShadingTimestamp ) >= - $shutters->getShadingWaitingPeriod ); + $shutters->setShadingStatus('out') + if ( + ( + $shutters->getShadingStatus eq 'out reserved' + and + ( int( gettimeofday() ) - $shutters->getShadingStatusTimestamp ) + > $shutters->getShadingWaitingPeriod + ) + or $azimuth > $winPosMax + ); Log3( $name, 4, "AutoShuttersControl ($name) - Shading Processing, Rollladen: " . $shuttersDev . " In der Out Abfrage, Shadingwert: " - . $shutters->getShading + . $shutters->getShadingStatus . ", Zeitstempel: " - . $shutters->getShadingTimestamp ); - } - elsif ( $azimuth >= $winPosMin - and $azimuth <= $winPosMax - and $elevation >= $shutters->getShadingMinElevation - and $brightness >= $shutters->getShadingStateChangeSunny ) - { - $shutters->setShading('in reserved') - if ( $shutters->getShading eq 'out' - or $shutters->getShading eq 'out reserved' ); + . $shutters->getShadingStatusTimestamp ); - $shutters->setShading('in') - if ( $shutters->getShading eq 'in reserved' - and ( int( gettimeofday() ) - $shutters->getShadingTimestamp ) >= + ASC_Debug( 'ShadingProcessing: ' + . $shutters->getShuttersDev + . ' - Einer der Beschattungsbedingungen wird nicht mehr erfüllt und somit wird der Beschattungsstatus um eine Stufe reduziert. Alter Status: ' + . $oldShadingStatus + . ' Neuer Status: ' + . $shutters->getShadingStatus ); + } + elsif ( $azimuth > $winPosMin + and $azimuth < $winPosMax + and $elevation > $shutters->getShadingMinElevation + and $brightness > $shutters->getShadingStateChangeSunny + and $outTemp > $shutters->getShadingMinOutsideTemperature ) + { + $shutters->setShadingStatus('in reserved') + if ( $shutters->getShadingStatus eq 'out' + or $shutters->getShadingStatus eq 'out reserved' ); + + $shutters->setShadingStatus('in') + if ( $shutters->getShadingStatus eq 'in reserved' + and + ( int( gettimeofday() ) - $shutters->getShadingStatusTimestamp ) > ( $shutters->getShadingWaitingPeriod / 2 ) ); Log3( $name, 4, "AutoShuttersControl ($name) - Shading Processing, Rollladen: " . $shuttersDev . " In der In Abfrage, Shadingwert: " - . $shutters->getShading + . $shutters->getShadingStatus . ", Zeitstempel: " - . $shutters->getShadingTimestamp ); + . $shutters->getShadingStatusTimestamp ); + + ASC_Debug( 'ShadingProcessing: ' + . $shutters->getShuttersDev + . ' - Alle Beschattungsbedingungen wurden erfüllt und somit wird der Beschattungsstatus um eine Stufe angehoben. Alter Status: ' + . $oldShadingStatus + . ' Neuer Status: ' + . $shutters->getShadingStatus ); } - if ( $shutters->getShading eq 'out' or $shutters->getShading eq 'in' ) { - $shutters->setShading( $shutters->getShading ) - if ( ( int( gettimeofday() ) - $shutters->getShadingTimestamp ) >= + if ( $shutters->getShadingStatus eq 'out' + or $shutters->getShadingStatus eq 'in' ) + { + ### 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 ) ); - if ( $shutters->getShading eq 'in' - and $shutters->getShadingPos != $shutters->getStatus ) + if ( $shutters->getShadingStatus eq 'in' + and $getShadingPos != $getStatus ) { my $queryShuttersShadingPos = ( $shutters->getShuttersPosCmdValueNegate - ? $shutters->getStatus > $shutters->getShadingPos - : $shutters->getStatus < $shutters->getShadingPos + ? $getStatus > $getShadingPos + : $getStatus < $getShadingPos ); - $shutters->setLastDrive('shading in'); - ShuttersCommandSet( $hash, $shuttersDev, $shutters->getShadingPos ) - if ( not $queryShuttersShadingPos ); + if ( not $queryShuttersShadingPos ) { + $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->getShading eq 'out' - and $shutters->getShadingPos == $shutters->getStatus ) + elsif ( $shutters->getShadingStatus eq 'out' + and $getShadingPos == $getStatus ) { $shutters->setLastDrive('shading out'); ShuttersCommandSet( $hash, $shuttersDev, $shutters->getLastPos ); + + ASC_Debug( 'ShadingProcessing: ' + . $shutters->getShuttersDev + . ' - Der aktuelle Beschattungsstatus ist: ' + . $shutters->getShadingStatus + . ' 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->getShading ); + . $shutters->getShadingStatus ); + + ASC_Debug( + 'ShadingProcessing: ' + . $shutters->getShuttersDev + . ' - Der aktuelle Beschattungsstatus ist: ' + . $shutters->getShadingStatus + . ', Beschattungsstatus Zeitstempel: ' + . strftime( + "%Y.%m.%e %T", localtime( $shutters->getShadingStatusTimestamp ) + ) + ); } } @@ -1471,8 +1859,9 @@ sub EventProcessingPartyMode($) { foreach my $shuttersDev ( @{ $hash->{helper}{shuttersList} } ) { $shutters->setShuttersDev($shuttersDev); - if ( not IsDay( $hash, $shuttersDev ) - and $shutters->getModeDown ne 'off' ) + if ( not IsDay($shuttersDev) + and $shutters->getModeDown ne 'off' + and IsAfterShuttersManualBlocking($shuttersDev) ) { if ( CheckIfShuttersWindowRecOpen($shuttersDev) == 2 and $shutters->getSubTyp eq 'threestate' ) @@ -1501,7 +1890,9 @@ sub EventProcessingPartyMode($) { ); } } - elsif ( IsDay( $hash, $shuttersDev ) ) { + elsif ( IsDay($shuttersDev) + and IsAfterShuttersManualBlocking($shuttersDev) ) + { $shutters->setLastDrive('drive after party mode'); ShuttersCommandSet( $hash, $shuttersDev, $shutters->getDelayCmd ); } @@ -1515,7 +1906,8 @@ sub EventProcessingShutters($@) { if ( $events =~ m#.*:\s(\d+)# ) { $shutters->setShuttersDev($shuttersDev); $ascDev->setPosReading; - if ( ( int( gettimeofday() ) - $shutters->getLastPosTimestamp ) > 60 + if ( ( int( gettimeofday() ) - $shutters->getLastPosTimestamp ) > + $shutters->getDriveUpMaxDuration and $shutters->getLastPos != $shutters->getStatus ) { $shutters->setLastDrive('manual'); @@ -1539,10 +1931,7 @@ sub ShuttersCommandSet($$$) { ); if ( - ( - $posValue != $shutters->getShadingPos - or $shutters->getShuttersPlace eq 'terrace' - ) + $posValue != $shutters->getShadingPos and ( ( $shutters->getPartyMode eq 'on' @@ -1562,13 +1951,22 @@ sub ShuttersCommandSet($$$) { and $ascDev->getHardLockOut eq 'on' and not $queryShuttersPosValue ) + or ( CheckIfShuttersWindowRecOpen($shuttersDev) == 2 + and $shutters->getShuttersPlace eq 'terrace' + and not $queryShuttersPosValue ) ) ) { $shutters->setDelayCmd($posValue); $ascDev->setDelayCmdReading; + $shutters->setNoOffset(0); Log3( $name, 4, "AutoShuttersControl ($name) - ShuttersCommandSet in Delay" ); + + ASC_Debug( 'FnShuttersCommandSet: ' + . $shutters->getShuttersDev + . ' - Die Fahrt wird zurückgestellt. Grund kann ein geöffnetes Fenster sein oder ein aktivierter Party Modus' + ); } else { $shutters->setDriveCmd($posValue); @@ -1579,6 +1977,11 @@ sub ShuttersCommandSet($$$) { Log3( $name, 4, "AutoShuttersControl ($name) - ShuttersCommandSet setDriveCmd wird aufgerufen" ); + + ASC_Debug( 'FnShuttersCommandSet: ' + . $shutters->getShuttersDev + . ' - Das Rollo wird gefahren. Kein Partymodus aktiv und das zugordnete Fenster ist entweder nicht offen oder keine Terassentür' + ); } } @@ -1591,10 +1994,8 @@ sub CreateSunRiseSetShuttersTimer($$) { return if ( IsDisabled($name) ); - my $shuttersSunriseUnixtime = - ShuttersSunrise( $hash, $shuttersDev, 'unix' ) + 1; - my $shuttersSunsetUnixtime = - ShuttersSunset( $hash, $shuttersDev, 'unix' ) + 1; + my $shuttersSunriseUnixtime = ShuttersSunrise( $shuttersDev, 'unix' ) + 1; + my $shuttersSunsetUnixtime = ShuttersSunset( $shuttersDev, 'unix' ) + 1; $shutters->setSunriseUnixTime($shuttersSunriseUnixtime); $shutters->setSunsetUnixTime($shuttersSunsetUnixtime); @@ -1675,10 +2076,10 @@ sub CreateSunRiseSetShuttersTimer($$) { } InternalTimer( $shuttersSunsetUnixtime, - 'AutoShuttersControl::SunSetShuttersAfterTimerFn', \%funcHash ) + 'FHEM::AutoShuttersControl::SunSetShuttersAfterTimerFn', \%funcHash ) if ( $ascDev->getAutoShuttersControlEvening eq 'on' ); InternalTimer( $shuttersSunriseUnixtime, - 'AutoShuttersControl::SunRiseShuttersAfterTimerFn', \%funcHash ) + 'FHEM::AutoShuttersControl::SunRiseShuttersAfterTimerFn', \%funcHash ) if ( $ascDev->getAutoShuttersControlMorning eq 'on' ); $ascDev->setStateReading('created new drive timer'); @@ -1694,6 +2095,26 @@ sub RenewSunRiseSetShuttersTimer($) { RemoveInternalTimer( $shutters->getInTimerFuncHash ); $shutters->setInTimerFuncHash(undef); CreateSunRiseSetShuttersTimer( $hash, $_ ); + + ### Temporär angelegt damit die neue Attributs Parameter Syntax verteilt werden kann +# CommandAttr(undef, $_ . ' ASC_BrightnessSensor '.AttrVal($_, 'ASC_Brightness_Sensor', 'none').':'.AttrVal($_, 'ASC_Brightness_Reading', 'brightness').' '.AttrVal($_, 'ASC_BrightnessMinVal', 500).':'.AttrVal($_, 'ASC_BrightnessMaxVal', 700)) if ( AttrVal($_, 'ASC_Brightness_Sensor', 'none') ne 'none' ); + + $attr{$_}{'ASC_BrightnessSensor'} = + AttrVal( $_, 'ASC_Brightness_Sensor', 'none' ) . ':' + . AttrVal( $_, 'ASC_Brightness_Reading', 'brightness' ) . ' ' + . AttrVal( $_, 'ASC_BrightnessMinVal', 500 ) . ':' + . AttrVal( $_, 'ASC_BrightnessMaxVal', 700 ) + if ( AttrVal( $_, 'ASC_Brightness_Sensor', 'none' ) ne 'none' ); + + delFromDevAttrList( $_, 'ASC_Brightness_Sensor' ) + ; # temporär muss später gelöscht werden ab Version 0.4.11beta9 + delFromDevAttrList( $_, 'ASC_Brightness_Reading' ) + ; # temporär muss später gelöscht werden ab Version 0.4.11beta9 + delFromDevAttrList( $_, 'ASC_BrightnessMinVal' ) + ; # temporär muss später gelöscht werden ab Version 0.4.11beta9 + delFromDevAttrList( $_, 'ASC_BrightnessMaxVal' ) + ; # temporär muss später gelöscht werden ab Version 0.4.11beta9 + } } @@ -1748,7 +2169,8 @@ sub wiggle($$) { } } - InternalTimer( gettimeofday() + 60, 'AutoShuttersControl::SetCmdFn', \%h ); + InternalTimer( gettimeofday() + 60, + 'FHEM::AutoShuttersControl::SetCmdFn', \%h ); } #### @@ -1780,22 +2202,24 @@ sub SunSetShuttersAfterTimerFn($) { and IsAfterShuttersManualBlocking($shuttersDev) ) { - $shutters->setLastDrive( - ( - $funcHash->{privacyMode} == 1 - ? 'privacy position' - : 'night close' - ) - ); - ShuttersCommandSet( - $hash, - $shuttersDev, - ( - $funcHash->{privacyMode} == 1 - ? $shutters->getPrivacyDownPos - : $posValue - ) + my $queryShuttersPosPrivacyDown = ( + $shutters->getShuttersPosCmdValueNegate + ? $shutters->getStatus > $shutters->getPrivacyDownPos + : $shutters->getStatus < $shutters->getPrivacyDownPos ); + + if ( $funcHash->{privacyMode} == 1 + and not $queryShuttersPosPrivacyDown ) + { + $shutters->setLastDrive('privacy position'); + ShuttersCommandSet( $hash, $shuttersDev, + $shutters->getPrivacyDownPos ); + } + elsif ( $funcHash->{privacyMode} == 0 ) { + $shutters->setSunset(1); + $shutters->setLastDrive('night close'); + ShuttersCommandSet( $hash, $shuttersDev, $posValue ); + } } CreateSunRiseSetShuttersTimer( $hash, $shuttersDev ); @@ -1834,6 +2258,7 @@ sub SunRiseShuttersAfterTimerFn($) { ) { $shutters->setLastDrive('day open'); + $shutters->setSunrise(1); ShuttersCommandSet( $hash, $shuttersDev, $shutters->getOpenPos ); } } @@ -1856,20 +2281,26 @@ sub CreateNewNotifyDev($) { AddNotifyDev( $hash, AttrVal( $_, 'ASC_WindowRec', 'none' ), $_, 'ASC_WindowRec' ) if ( AttrVal( $_, 'ASC_WindowRec', 'none' ) ne 'none' ); - AddNotifyDev( $hash, AttrVal( $_, 'ASC_Brightness_Sensor', 'none' ), - $_, 'ASC_Brightness_Sensor' ) - if ( AttrVal( $_, 'ASC_Brightness_Sensor', 'none' ) ne 'none' ); + AddNotifyDev( $hash, AttrVal( $_, 'ASC_BrightnessSensor', 'none' ), + $_, 'ASC_BrightnessSensor' ) + if ( AttrVal( $_, 'ASC_BrightnessSensor', 'none' ) ne 'none' ); + $shuttersList = $shuttersList . ',' . $_; } - AddNotifyDev( $hash, AttrVal( $name, 'ASC_residentsDevice', 'none' ), - $name, 'ASC_residentsDevice' ) - if ( AttrVal( $name, 'ASC_residentsDevice', 'none' ) ne 'none' ); - AddNotifyDev( $hash, AttrVal( $name, 'ASC_rainSensorDevice', 'none' ), - $name, 'ASC_rainSensorDevice' ) - if ( AttrVal( $name, 'ASC_rainSensorDevice', 'none' ) ne 'none' ); + + AddNotifyDev( $hash, AttrVal( $name, 'ASC_residentsDev', 'none' ), + $name, 'ASC_residentsDev' ) + if ( AttrVal( $name, 'ASC_residentsDev', 'none' ) ne 'none' ); + AddNotifyDev( $hash, AttrVal( $name, 'ASC_rainSensor', 'none' ), + $name, 'ASC_rainSensor' ) + if ( AttrVal( $name, 'ASC_rainSensor', 'none' ) ne 'none' ); AddNotifyDev( $hash, AttrVal( $name, 'ASC_twilightDevice', 'none' ), $name, 'ASC_twilightDevice' ) if ( AttrVal( $name, 'ASC_twilightDevice', 'none' ) ne 'none' ); + AddNotifyDev( $hash, AttrVal( $name, 'ASC_windSensor', 'none' ), + $name, 'ASC_windSensor' ) + if ( AttrVal( $name, 'ASC_windSensor', 'none' ) ne 'none' ); + $hash->{NOTIFYDEV} = $hash->{NOTIFYDEV} . $shuttersList; } @@ -1901,6 +2332,8 @@ sub GetShuttersInformation($) { $ret .= "