###############################################################################
#
# Developed with Kate
#
# (c) 2018-2020 Copyright: Marko Oldenburg (leongaultier at gmail dot com)
# All rights reserved
#
# Special thanks goes to:
# - Bernd (Cluni) this module is based on the logic of his script "Rollladensteuerung für HM/ROLLO inkl. Abschattung und Komfortfunktionen in Perl" (https://forum.fhem.de/index.php/topic,73964.0.html)
# - Beta-User for many tests, many suggestions and good discussions
# - pc1246 write english commandref
# - 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
# - Christoph (Christoph Morrison) for fix Commandref, many suggestions and good discussions
#
#
# This script 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
# any later version.
#
# The GNU General Public License can be found at
# http://www.gnu.org/copyleft/gpl.html.
# A copy is found in the textfile GPL.txt and important notices to the license
# from the author is found in LICENSE.txt distributed with these scripts.
#
# This script 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.
#
#
# $Id$
#
###############################################################################
### Notizen
# !!!!! - Innerhalb einer Shutterschleife kein CommandAttr verwenden. Bring Fehler!!! Kommen Raumnamen in die Shutterliste !!!!!!
#
package main;
use strict;
use warnings;
sub ascAPIget($@) {
my ( $getCommand, $shutterDev, $value ) = @_;
return AutoShuttersControl_ascAPIget( $getCommand, $shutterDev, $value );
}
## unserer packagename
package FHEM::AutoShuttersControl;
use strict;
use warnings;
use POSIX;
use utf8;
use Encode;
use FHEM::Meta;
use GPUtils qw(GP_Import GP_Export);
use Data::Dumper; #only for Debugging
use Date::Parse;
# try to use JSON::MaybeXS wrapper
# for chance of better performance + open code
eval {
require JSON::MaybeXS;
import JSON::MaybeXS qw( decode_json encode_json );
1;
};
if ($@) {
$@ = undef;
# try to use JSON wrapper
# for chance of better performance
eval {
# JSON preference order
local $ENV{PERL_JSON_BACKEND} =
'Cpanel::JSON::XS,JSON::XS,JSON::PP,JSON::backportPP'
unless ( defined( $ENV{PERL_JSON_BACKEND} ) );
require JSON;
import JSON qw( decode_json encode_json );
1;
};
if ($@) {
$@ = undef;
# In rare cases, Cpanel::JSON::XS may
# be installed but JSON|JSON::MaybeXS not ...
eval {
require Cpanel::JSON::XS;
import Cpanel::JSON::XS qw(decode_json encode_json);
1;
};
if ($@) {
$@ = undef;
# In rare cases, JSON::XS may
# be installed but JSON not ...
eval {
require JSON::XS;
import JSON::XS qw(decode_json encode_json);
1;
};
if ($@) {
$@ = undef;
# Fallback to built-in JSON which SHOULD
# be available since 5.014 ...
eval {
require JSON::PP;
import JSON::PP qw(decode_json encode_json);
1;
};
if ($@) {
$@ = undef;
# Fallback to JSON::backportPP in really rare cases
require JSON::backportPP;
import JSON::backportPP qw(decode_json encode_json);
1;
}
}
}
}
}
## Import der FHEM Funktionen
#-- Run before package compilation
BEGIN {
# Import from main context
GP_Import(
qw(
devspec2array
readingsSingleUpdate
readingsBulkUpdate
readingsBulkUpdateIfChanged
readingsBeginUpdate
readingsEndUpdate
defs
modules
Log3
CommandAttr
attr
CommandDeleteAttr
CommandDeleteReading
CommandSet
readingFnAttributes
AttrVal
ReadingsVal
IsDisabled
deviceEvents
init_done
addToDevAttrList
addToAttrList
delFromDevAttrList
delFromAttrList
gettimeofday
sunset
sunset_abs
sunrise
sunrise_abs
InternalTimer
RemoveInternalTimer
computeAlignTime
ReplaceEventMap)
);
}
#-- Export to main context with different name
GP_Export(
qw(
Initialize
ascAPIget
DevStateIcon
)
);
## Die Attributsliste welche an die Rolläden verteilt wird. Zusammen mit Default Werten
my %userAttrList = (
'ASC_Mode_Up:absent,always,off,home' => '-',
'ASC_Mode_Down:absent,always,off,home' => '-',
'ASC_Up:time,astro,brightness,roommate' => '-',
'ASC_Down:time,astro,brightness,roommate' => '-',
'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' => '-',
'ASC_AutoAstroModeEveningHorizon:-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9'
=> '-',
'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_Sleep_Pos:0,10,20,30,40,50,60,70,80,90,100' => '-',
'ASC_Pos_Reading' => [ '', 'position', 'pct' ],
'ASC_Time_Up_Early' => '-',
'ASC_Time_Up_Late' => '-',
'ASC_Time_Up_WE_Holiday' => '-',
'ASC_Time_Down_Early' => '-',
'ASC_Time_Down_Late' => '-',
'ASC_PrivacyUpValue_beforeDayOpen' => '-',
'ASC_PrivacyDownValue_beforeNightClose' => '-',
'ASC_PrivacyUp_Pos' => '-',
'ASC_PrivacyDown_Pos' => '-',
'ASC_TempSensor' => '-',
'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_Pos:10,20,30,40,50,60,70,80,90,100' => [ '', 80, 20 ],
'ASC_Shading_Mode:absent,always,off,home' => '-',
'ASC_Shading_InOutAzimuth' => '-',
'ASC_Shading_StateChange_SunnyCloudy' => '-',
'ASC_Shading_MinMax_Elevation' => '-',
'ASC_Shading_Min_OutsideTemperature' => '-',
'ASC_Shading_WaitingPeriod' => '-',
'ASC_Drive_Delay' => '-',
'ASC_Drive_DelayStart' => '-',
'ASC_Shutter_IdleDetection' => '-',
'ASC_WindowRec' => '-',
'ASC_WindowRec_subType:twostate,threestate' => '-',
'ASC_WindowRec_PosAfterDayClosed:open,lastManual' => '-',
'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' => '-',
'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' => '-',
'ASC_Roommate_Device' => '-',
'ASC_Roommate_Reading' => '-',
'ASC_Self_Defense_Mode:absent,gone,off' => '-',
'ASC_Self_Defense_AbsentDelay' => '-',
'ASC_WiggleValue' => '-',
'ASC_WindParameters' => '-',
'ASC_DriveUpMaxDuration' => '-',
'ASC_WindProtection:on,off' => '-',
'ASC_RainProtection:on,off' => '-',
'ASC_ExternalTrigger' => '-',
'ASC_Adv:on,off' => '-'
);
my %posSetCmds = (
ZWave => 'dim',
Siro => 'pct',
CUL_HM => 'pct',
ROLLO => 'pct',
SOMFY => 'position',
tahoma => 'dim',
KLF200Node => 'pct',
DUOFERN => 'position',
HM485 => 'level',
SELVECommeo => 'position',
SELVE => 'position',
EnOcean => 'position',
);
my $shutters = new ASC_Shutters();
my $ascDev = new ASC_Dev();
sub ascAPIget($@) {
my ( $getCommand, $shutterDev, $value ) = @_;
my $getter = 'get' . $getCommand;
if ( defined($value) and $value ) {
$shutters->setShuttersDev($shutterDev);
return $shutters->$getter($value);
}
elsif ( defined($shutterDev) and $shutterDev ) {
$shutters->setShuttersDev($shutterDev);
return $shutters->$getter;
}
else {
return $ascDev->$getter;
}
}
sub 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} = '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_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 '
. 'ASC_autoAstroModeEveningHorizon:-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9 '
. 'ASC_freezeTemp:-5,-4,-3,-2,-1,0,1,2,3,4,5 '
. 'ASC_shuttersDriveDelay '
. 'ASC_twilightDevice '
. 'ASC_windSensor '
. 'ASC_expert:1 '
. 'ASC_blockAscDrivesAfterManual:0,1 '
. 'ASC_debug:1 '
. $readingFnAttributes;
$hash->{NotifyOrderPrefix} = '51-'; # Order Nummer für NotifyFn
$hash->{FW_detailFn} = 'FHEM::AutoShuttersControl::ShuttersInformation';
return FHEM::Meta::InitMod( __FILE__, $hash );
}
sub Define($$) {
my ( $hash, $def ) = @_;
my @a = split( '[ \t][ \t]*', $def );
return $@ unless ( FHEM::Meta::SetInternals($hash) );
use version 0.60; our $VERSION = FHEM::Meta::Get( $hash, 'version' );
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
return 'too few parameters: define
AutoShuttersControl (ASC) provides a complete automation for shutters with comprehensive
configuration options, e.g. open or close shutters depending on the sunrise or sunset,
by outdoor brightness or randomly for simulate presence.
After telling ASC which shutters should be controlled, several in-depth configuration options
are provided. With these and in combination with a resident presence state, complex scenarios are possible:
For example, shutters could be opened if a resident awakes from sleep and the sun is already rosen. Or if a
closed window with shutters down is tilted, the shutters could be half opened for ventilation.
Many more is possible.
';
$ret .= 'ASC Configuration and Information Summary
';
$ret .= ' ';
$ret .= '
';
$ret .= " ';
my $linecount = 1;
foreach my $shutter ( @{ $hash->{helper}{shuttersList} } ) {
$shutters->setShuttersDev($shutter);
if ( $linecount % 2 == 0 ) { $ret .= 'Shutters ";
$ret .= " ";
$ret .= "Next DriveUp ";
$ret .= " ";
$ret .= "Next DriveDown ";
$ret .= " ";
$ret .= "ASC Up ";
$ret .= " ";
$ret .= "ASC Down ";
$ret .= " ";
$ret .= "ASC Mode Up ";
$ret .= " ";
$ret .= "ASC Mode Down ";
$ret .= " ";
$ret .= "Partymode ";
$ret .= " ";
$ret .= "Lock-Out ";
$ret .= " ";
$ret .= "Last Drive ";
$ret .= " ";
$ret .= "Position ";
$ret .= " ";
$ret .= "Last Position ";
$ret .= " ";
$ret .= "Shading Info ";
$ret .= ''; }
else { $ret .= ' '; }
$ret .= " ';
$linecount++;
}
$ret .= '$shutter ";
$ret .= " ";
$ret .= ""
. strftime( "%e.%m.%Y - %H:%M:%S",
localtime( $shutters->getSunriseUnixTime ) )
. " ";
$ret .= " ";
$ret .= ""
. strftime( "%e.%m.%Y - %H:%M:%S",
localtime( $shutters->getSunsetUnixTime ) )
. " ";
$ret .= " ";
$ret .= "" . $shutters->getUp . " ";
$ret .= " ";
$ret .= "" . $shutters->getDown . " ";
$ret .= " ";
$ret .= "" . $shutters->getModeUp . " ";
$ret .= " ";
$ret .= "" . $shutters->getModeDown . " ";
$ret .= " ";
$ret .= "" . $shutters->getPartyMode . " ";
$ret .= " ";
$ret .= "" . $shutters->getLockOut . " ";
$ret .= " ";
$ret .= ""
. ReadingsVal( $shutter, 'ASC_ShuttersLastDrive', 'none' ) . " ";
$ret .= " ";
$ret .= "" . $shutters->getStatus . " ";
$ret .= " ";
$ret .= "" . $shutters->getLastPos . " ";
$ret .= " ";
$ret .= ""
. $shutters->getShadingStatus . ' - '
. strftime( "%H:%M:%S",
localtime( $shutters->getShadingStatusTimestamp ) )
. " ";
$ret .= '
';
return $ret;
}
sub GetMonitoredDevs($) {
my $hash = shift;
my $notifydevs = eval {
decode_json( ReadingsVal( $hash->{NAME}, '.monitoredDevs', 'none' ) );
};
my $ret = '
';
return $ret;
}
#################################
## my little helper
#################################
sub PositionValueWindowRec($$) {
my ( $shuttersDev, $posValue ) = @_;
if ( CheckIfShuttersWindowRecOpen($shuttersDev) == 1
and $shutters->getVentilateOpen eq 'on' )
{
$posValue = $shutters->getVentilatePos;
}
elsif ( CheckIfShuttersWindowRecOpen($shuttersDev) == 2
and $shutters->getSubTyp eq 'threestate'
and $ascDev->getAutoShuttersControlComfort eq 'on' )
{
$posValue = $shutters->getComfortOpenPos;
}
elsif (
CheckIfShuttersWindowRecOpen($shuttersDev) == 2
and ( $shutters->getSubTyp eq 'threestate'
or $shutters->getSubTyp eq 'twostate' )
and $shutters->getVentilateOpen eq 'on'
)
{
$posValue = $shutters->getVentilatePos;
}
if ( $shutters->getQueryShuttersPos($posValue) ) {
$posValue = $shutters->getStatus;
}
return $posValue;
}
sub AutoSearchTwilightDev($) {
my $hash = shift;
my $name = $hash->{NAME};
if ( devspec2array('TYPE=(Astro|Twilight)') > 0 ) {
CommandAttr( undef,
$name
. ' ASC_twilightDevice '
. ( devspec2array('TYPE=(Astro|Twilight)') )[0] )
if ( AttrVal( $name, 'ASC_twilightDevice', 'none' ) eq 'none' );
}
}
sub GetAttrValues($@) {
my ( $dev, $attribut, $default ) = @_;
my @values = split( ' ',
AttrVal( $dev, $attribut, ( defined($default) ? $default : 'none' ) ) );
my ( $value1, $value2 ) = split( ':', $values[0] );
my ( $value3, $value4 ) = split( ':', $values[1] )
if ( defined( $values[1] ) );
my ( $value5, $value6 ) = split( ':', $values[2] )
if ( defined( $values[2] ) );
my ( $value7, $value8 ) = split( ':', $values[2] )
if ( defined( $values[3] ) );
return (
$value1,
defined($value2) ? $value2 : 'none',
defined($value3) ? $value3 : 'none',
defined($value4) ? $value4 : 'none',
defined($value5) ? $value5 : 'none',
defined($value6) ? $value6 : 'none',
defined($value7) ? $value7 : 'none',
defined($value8) ? $value8 : 'none'
);
}
# Hilfsfunktion welche meinen ReadingString zum finden der getriggerten Devices und der Zurdnung was das Device überhaupt ist und zu welchen Rolladen es gehört aus liest und das Device extraiert
sub ExtractNotifyDevFromEvent($$$) {
my ( $hash, $shuttersDev, $shuttersAttr ) = @_;
my %notifyDevs;
while ( my $notifyDev = each %{ $hash->{monitoredDevs} } ) {
Log3( $hash->{NAME}, 4,
"AutoShuttersControl ($hash->{NAME}) - ExtractNotifyDevFromEvent - NotifyDev: "
. $notifyDev );
Log3( $hash->{NAME}, 5,
"AutoShuttersControl ($hash->{NAME}) - ExtractNotifyDevFromEvent - ShuttersDev: "
. $shuttersDev );
if ( defined( $hash->{monitoredDevs}{$notifyDev}{$shuttersDev} )
and $hash->{monitoredDevs}{$notifyDev}{$shuttersDev} eq
$shuttersAttr )
{
Log3( $hash->{NAME}, 4,
"AutoShuttersControl ($hash->{NAME}) - ExtractNotifyDevFromEvent - ShuttersDevHash: "
. $hash->{monitoredDevs}{$notifyDev}{$shuttersDev} );
Log3( $hash->{NAME}, 5,
"AutoShuttersControl ($hash->{NAME}) - ExtractNotifyDevFromEvent - return ShuttersDev: "
. $notifyDev );
$notifyDevs{$notifyDev} = $shuttersDev;
}
}
return \%notifyDevs;
}
## Ist Tag oder Nacht für den entsprechende Rolladen
sub _IsDay($) {
my ($shuttersDev) = @_;
$shutters->setShuttersDev($shuttersDev);
my $isday = ( ShuttersSunrise( $shuttersDev, 'unix' ) >
ShuttersSunset( $shuttersDev, 'unix' ) ? 1 : 0 );
my $respIsDay = $isday;
ASC_Debug( 'FnIsDay: ' . $shuttersDev . ' Allgemein: ' . $respIsDay );
if (
(
$shutters->getModeDown eq 'brightness'
or $shutters->getModeUp eq 'brightness'
)
or (
(
(
(
int( gettimeofday() / 86400 ) != int(
computeAlignTime( '24:00',
$shutters->getTimeUpEarly ) / 86400
)
and not IsWe()
)
or (
int( gettimeofday() / 86400 ) != int(
computeAlignTime( '24:00',
$shutters->getTimeUpWeHoliday ) / 86400
)
and IsWe()
and $ascDev->getSunriseTimeWeHoliday eq 'on'
)
)
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
)
)
)
)
{
my $brightnessMinVal;
if ( $shutters->getBrightnessMinVal > -1 ) {
$brightnessMinVal = $shutters->getBrightnessMinVal;
}
else {
$brightnessMinVal = $ascDev->getBrightnessMinVal;
}
my $brightnessMaxVal;
if ( $shutters->getBrightnessMaxVal > -1 ) {
$brightnessMaxVal = $shutters->getBrightnessMaxVal;
}
else {
$brightnessMaxVal = $ascDev->getBrightnessMaxVal;
}
##### Nach Sonnenuntergang / Abends
$respIsDay = (
(
(
$shutters->getBrightness > $brightnessMinVal
and $isday
and not $shutters->getSunset
)
or not $shutters->getSunset
) ? 1 : 0
) if ( $shutters->getDown eq 'brightness' );
ASC_Debug( 'FnIsDay: '
. $shuttersDev
. ' getDownBrightness: '
. $respIsDay
. ' Brightness: '
. $shutters->getBrightness
. ' BrightnessMin: '
. $brightnessMinVal
. ' Sunset: '
. $shutters->getSunset );
##### Nach Sonnenauf / Morgens
$respIsDay = (
(
(
$shutters->getBrightness > $brightnessMaxVal
and not $isday
and not $shutters->getSunrise
)
or $respIsDay
or $shutters->getSunrise
) ? 1 : 0
) if ( $shutters->getUp eq 'brightness' );
ASC_Debug( 'FnIsDay: '
. $shuttersDev
. ' getUpBrightness: '
. $respIsDay
. ' Brightness: '
. $shutters->getBrightness
. ' BrightnessMax: '
. $brightnessMaxVal
. ' Sunrise: '
. $shutters->getSunrise );
}
return $respIsDay;
}
sub ShuttersSunrise($$) {
my ( $shuttersDev, $tm ) =
@_; # Tm steht für Timemode und bedeutet Realzeit oder Unixzeit
my $autoAstroMode;
$shutters->setShuttersDev($shuttersDev);
if ( $shutters->getAutoAstroModeMorning ne 'none' ) {
$autoAstroMode = $shutters->getAutoAstroModeMorning;
$autoAstroMode =
$autoAstroMode . '=' . $shutters->getAutoAstroModeMorningHorizon
if ( $autoAstroMode eq 'HORIZON' );
}
else {
$autoAstroMode = $ascDev->getAutoAstroModeMorning;
$autoAstroMode =
$autoAstroMode . '=' . $ascDev->getAutoAstroModeMorningHorizon
if ( $autoAstroMode eq 'HORIZON' );
}
my $oldFuncHash = $shutters->getInTimerFuncHash;
my $shuttersSunriseUnixtime =
computeAlignTime( '24:00', sunrise( 'REAL', 0, '4:30', '8:30' ) );
if ( $tm eq 'unix' ) {
if ( $shutters->getUp eq 'astro' ) {
if ( ( IsWe() or IsWeTomorrow() )
and $ascDev->getSunriseTimeWeHoliday eq 'on' )
{
if ( not IsWeTomorrow() ) {
if (
IsWe()
and int( gettimeofday() / 86400 ) == int(
(
computeAlignTime(
'24:00',
sunrise_abs(
$autoAstroMode, 0,
$shutters->getTimeUpWeHoliday
)
) + 1
) / 86400
)
)
{
$shuttersSunriseUnixtime = (
computeAlignTime(
'24:00',
sunrise_abs(
$autoAstroMode, 0,
$shutters->getTimeUpWeHoliday
)
) + 1
);
}
elsif (
int( gettimeofday() / 86400 ) == int(
(
computeAlignTime(
'24:00',
sunrise_abs(
$autoAstroMode,
0,
$shutters->getTimeUpEarly,
$shutters->getTimeUpLate
)
) + 1
) / 86400
)
)
{
$shuttersSunriseUnixtime = (
computeAlignTime(
'24:00',
sunrise_abs(
$autoAstroMode, 0,
$shutters->getTimeUpWeHoliday
)
) + 1
);
}
else {
$shuttersSunriseUnixtime = (
computeAlignTime(
'24:00',
sunrise_abs(
$autoAstroMode,
0,
$shutters->getTimeUpEarly,
$shutters->getTimeUpLate
)
) + 1
);
}
}
else {
if (
IsWe()
and (
int( gettimeofday() / 86400 ) == int(
(
computeAlignTime(
'24:00',
sunrise_abs(
$autoAstroMode, 0,
$shutters->getTimeUpWeHoliday
)
) + 1
) / 86400
)
or int( gettimeofday() / 86400 ) != int(
(
computeAlignTime(
'24:00',
sunrise_abs(
$autoAstroMode, 0,
$shutters->getTimeUpWeHoliday
)
) + 1
) / 86400
)
)
)
{
$shuttersSunriseUnixtime = (
computeAlignTime(
'24:00',
sunrise_abs(
$autoAstroMode, 0,
$shutters->getTimeUpWeHoliday
)
) + 1
);
}
elsif (
int( gettimeofday() / 86400 ) == int(
(
computeAlignTime(
'24:00',
sunrise_abs(
$autoAstroMode,
0,
$shutters->getTimeUpEarly,
$shutters->getTimeUpLate
)
) + 1
) / 86400
)
)
{
$shuttersSunriseUnixtime = (
computeAlignTime(
'24:00',
sunrise_abs(
$autoAstroMode,
0,
$shutters->getTimeUpEarly,
$shutters->getTimeUpLate
)
) + 1
);
}
else {
if (
int( gettimeofday() / 86400 ) == int(
(
computeAlignTime(
'24:00',
sunrise_abs(
$autoAstroMode, 0,
$shutters->getTimeUpWeHoliday
)
) + 1
) / 86400
)
)
{
$shuttersSunriseUnixtime = (
computeAlignTime(
'24:00',
sunrise_abs(
$autoAstroMode, 0,
$shutters->getTimeUpWeHoliday
)
) + 86401
);
}
else {
$shuttersSunriseUnixtime = (
computeAlignTime(
'24:00',
sunrise_abs(
$autoAstroMode, 0,
$shutters->getTimeUpWeHoliday
)
) + 1
);
}
}
}
}
else {
$shuttersSunriseUnixtime = (
computeAlignTime(
'24:00',
sunrise_abs(
$autoAstroMode,
0,
$shutters->getTimeUpEarly,
$shutters->getTimeUpLate
)
) + 1
);
}
if ( defined($oldFuncHash)
and ref($oldFuncHash) eq 'HASH'
and ( IsWe() or IsWeTomorrow() )
and $ascDev->getSunriseTimeWeHoliday eq 'on' )
{
if ( not IsWeTomorrow() ) {
if (
int( gettimeofday() / 86400 ) == int(
(
computeAlignTime(
'24:00',
sunrise_abs(
$autoAstroMode,
0,
$shutters->getTimeUpEarly,
$shutters->getTimeUpLate
)
) + 1
) / 86400
)
)
{
$shuttersSunriseUnixtime =
( $shuttersSunriseUnixtime + 86400 )
if ( $shuttersSunriseUnixtime <
( $oldFuncHash->{sunrisetime} + 180 )
and $oldFuncHash->{sunrisetime} < gettimeofday() );
}
}
}
elsif ( defined($oldFuncHash) and ref($oldFuncHash) eq 'HASH' ) {
$shuttersSunriseUnixtime = ( $shuttersSunriseUnixtime + 86400 )
if ( $shuttersSunriseUnixtime <
( $oldFuncHash->{sunrisetime} + 180 )
and $oldFuncHash->{sunrisetime} < gettimeofday() );
}
}
elsif ( $shutters->getUp eq 'time' ) {
if ( ( IsWe() or IsWeTomorrow() )
and $ascDev->getSunriseTimeWeHoliday eq 'on' )
{
if ( not IsWeTomorrow() ) {
if (
int( gettimeofday() / 86400 ) == int(
computeAlignTime( '24:00',
$shutters->getTimeUpWeHoliday ) / 86400
)
)
{
$shuttersSunriseUnixtime =
computeAlignTime( '24:00',
$shutters->getTimeUpWeHoliday );
}
elsif (
int( gettimeofday() / 86400 ) == int(
computeAlignTime( '24:00',
$shutters->getTimeUpEarly ) / 86400
)
and $shutters->getSunrise
)
{
$shuttersSunriseUnixtime =
computeAlignTime( '24:00', $shutters->getTimeUpEarly )
+ 86400;
}
else {
$shuttersSunriseUnixtime =
computeAlignTime( '24:00',
$shutters->getTimeUpEarly );
}
}
else {
if (
IsWe()
and int( gettimeofday() / 86400 ) == int(
computeAlignTime( '24:00',
$shutters->getTimeUpWeHoliday ) / 86400
)
)
{
$shuttersSunriseUnixtime =
computeAlignTime( '24:00',
$shutters->getTimeUpWeHoliday );
}
elsif (
int( gettimeofday() / 86400 ) == int(
computeAlignTime( '24:00',
$shutters->getTimeUpEarly ) / 86400
)
)
{
$shuttersSunriseUnixtime =
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',
$shutters->getTimeUpWeHoliday ) + 86400;
}
}
}
else {
$shuttersSunriseUnixtime =
computeAlignTime( '24:00', $shutters->getTimeUpEarly );
}
}
elsif ( $shutters->getUp eq 'brightness' ) {
$shuttersSunriseUnixtime =
computeAlignTime( '24:00', $shutters->getTimeUpLate );
}
return $shuttersSunriseUnixtime;
}
elsif ( $tm eq 'real' ) {
return sunrise_abs( $autoAstroMode, 0, $shutters->getTimeUpEarly,
$shutters->getTimeUpLate )
if ( $shutters->getUp eq 'astro' );
return $shutters->getTimeUpEarly if ( $shutters->getUp eq 'time' );
}
}
sub IsAfterShuttersTimeBlocking($) {
my ($shuttersDev) = @_;
$shutters->setShuttersDev($shuttersDev);
if (
( int( gettimeofday() ) - $shutters->getLastManPosTimestamp ) <
$shutters->getBlockingTimeAfterManual
or ( not $shutters->getIsDay
and defined( $shutters->getSunriseUnixTime )
and $shutters->getSunriseUnixTime - ( int( gettimeofday() ) ) <
$shutters->getBlockingTimeBeforDayOpen )
or ( $shutters->getIsDay
and defined( $shutters->getSunriseUnixTime )
and $shutters->getSunsetUnixTime - ( int( gettimeofday() ) ) <
$shutters->getBlockingTimeBeforNightClose )
)
{
return 0;
}
else { return 1 }
}
sub IsAfterShuttersManualBlocking($) {
my $shuttersDev = shift;
$shutters->setShuttersDev($shuttersDev);
if ( $ascDev->getblockAscDrivesAfterManual
and $shutters->getStatus != $shutters->getOpenPos
and $shutters->getStatus != $shutters->getClosedPos
and $shutters->getStatus != $shutters->getWindPos
and $shutters->getStatus != $shutters->getShadingPos
and $shutters->getStatus != $shutters->getComfortOpenPos
and $shutters->getStatus != $shutters->getVentilatePos
and $shutters->getStatus != $shutters->getAntiFreezePos
and $shutters->getLastDrive eq 'manual' )
{
return 0;
}
elsif ( ( int( gettimeofday() ) - $shutters->getLastManPosTimestamp ) <
$shutters->getBlockingTimeAfterManual )
{
return 0;
}
else { return 1 }
}
sub ShuttersSunset($$) {
my ( $shuttersDev, $tm ) =
@_; # Tm steht für Timemode und bedeutet Realzeit oder Unixzeit
my $autoAstroMode;
$shutters->setShuttersDev($shuttersDev);
if ( $shutters->getAutoAstroModeEvening ne 'none' ) {
$autoAstroMode = $shutters->getAutoAstroModeEvening;
$autoAstroMode =
$autoAstroMode . '=' . $shutters->getAutoAstroModeEveningHorizon
if ( $autoAstroMode eq 'HORIZON' );
}
else {
$autoAstroMode = $ascDev->getAutoAstroModeEvening;
$autoAstroMode =
$autoAstroMode . '=' . $ascDev->getAutoAstroModeEveningHorizon
if ( $autoAstroMode eq 'HORIZON' );
}
my $oldFuncHash = $shutters->getInTimerFuncHash;
my $shuttersSunsetUnixtime =
computeAlignTime( '24:00', sunset( 'REAL', 0, '15:30', '21:30' ) );
if ( $tm eq 'unix' ) {
if ( $shutters->getDown eq 'astro' ) {
$shuttersSunsetUnixtime = (
computeAlignTime(
'24:00',
sunset_abs(
$autoAstroMode,
0,
$shutters->getTimeDownEarly,
$shutters->getTimeDownLate
)
) + 1
);
if ( defined($oldFuncHash) and ref($oldFuncHash) eq 'HASH' ) {
$shuttersSunsetUnixtime += 86400
if ( $shuttersSunsetUnixtime <
( $oldFuncHash->{sunsettime} + 180 )
and $oldFuncHash->{sunsettime} < gettimeofday() );
}
}
elsif ( $shutters->getDown eq 'time' ) {
$shuttersSunsetUnixtime =
computeAlignTime( '24:00', $shutters->getTimeDownEarly );
}
elsif ( $shutters->getDown eq 'brightness' ) {
$shuttersSunsetUnixtime =
computeAlignTime( '24:00', $shutters->getTimeDownLate );
}
return $shuttersSunsetUnixtime;
}
elsif ( $tm eq 'real' ) {
return sunset_abs(
$autoAstroMode, 0,
$shutters->getTimeDownEarly,
$shutters->getTimeDownLate
) if ( $shutters->getDown eq 'astro' );
return $shutters->getTimeDownEarly
if ( $shutters->getDown eq 'time' );
}
}
## Kontrolliert ob das Fenster von einem bestimmten Rolladen offen ist
sub CheckIfShuttersWindowRecOpen($) {
my $shuttersDev = shift;
$shutters->setShuttersDev($shuttersDev);
if ( $shutters->getWinStatus =~ /[Oo]pen|false/ ) # CK: covers: open|opened
{
return 2;
}
elsif ( $shutters->getWinStatus =~ /tilt/
and $shutters->getSubTyp eq 'threestate' ) # CK: covers: tilt|tilted
{
return 1;
}
elsif ( $shutters->getWinStatus =~ /[Cc]lose|true/ ) {
return 0;
} # CK: covers: close|closed
}
sub makeReadingName($) {
my ($rname) = @_;
my %charHash = (
chr(0xe4) => "ae", # ä
chr(0xc4) => "Ae", # Ä
chr(0xfc) => "ue", # ü
chr(0xdc) => "Ue", # Ü
chr(0xf6) => "oe", # ö
chr(0xd6) => "Oe", # Ö
chr(0xdf) => "ss" # ß
);
my $charHashkeys = join( "", keys(%charHash) );
return $rname if ( $rname =~ m/^\./ );
$rname =~ s/([$charHashkeys])/$charHash{$1}/gi;
$rname =~ s/[^a-z0-9._\-\/]/_/gi;
return $rname;
}
sub TimeMin2Sec($) {
my $min = shift;
my $sec;
$sec = $min * 60;
return $sec;
}
sub IsWe() {
my $we = main::IsWe();
return $we;
}
sub IsWeTomorrow() {
my $we = main::IsWe('tomorrow');
return $we;
}
sub _SetCmdFn($) {
my $h = shift;
my $shuttersDev = $h->{shuttersDev};
my $posValue = $h->{posValue};
$shutters->setShuttersDev($shuttersDev);
$shutters->setLastDrive( $h->{lastDrive} )
if ( defined( $h->{lastDrive} ) );
my $idleDetectionValue = $shutters->getIdleDetectionValue;
my $idleDetection = $shutters->getIdleDetection;
return
unless (
$shutters->getASCenable eq 'on'
and $ascDev->getASCenable eq 'on'
and ( $idleDetection =~ /^$idleDetectionValue$/
or $idleDetection eq 'none' )
);
if ( $shutters->getStatus != $posValue ) {
$shutters->setLastPos( $shutters->getStatus );
}
else {
$shutters->setLastDrive(
ReadingsVal( $shuttersDev, 'ASC_ShuttersLastDrive', 'none' ) );
ASC_Debug( 'FnSetCmdFn: '
. $shuttersDev
. ' - Abbruch aktuelle Position ist gleich der Zielposition '
. $shutters->getStatus . '='
. $posValue );
return;
}
ASC_Debug( 'FnSetCmdFn: '
. $shuttersDev
. ' - Rollo wird gefahren, aktuelle Position: '
. $shutters->getStatus
. ', Zielposition: '
. $posValue
. '. Grund der Fahrt: '
. $shutters->getLastDrive );
CommandSet( undef,
$shuttersDev
. ':FILTER='
. $shutters->getPosCmd . '!='
. $posValue . ' '
. $shutters->getPosSetCmd . ' '
. $posValue );
$shutters->setSelfDefenseAbsent( 0, 0 )
if ( not $shutters->getSelfDefenseAbsent
and $shutters->getSelfDefenseAbsentTimerrun );
}
sub _setShuttersLastDriveDelayed($) {
my $h = shift;
my $shuttersDevHash = $h->{devHash};
my $lastDrive = $h->{lastDrive};
readingsSingleUpdate( $shuttersDevHash, 'ASC_ShuttersLastDrive',
$lastDrive, 1 );
}
sub ASC_Debug($) {
return
unless ( AttrVal( $ascDev->getName, 'ASC_debug', 0 ) );
my $debugMsg = shift;
my $debugTimestamp = strftime( "%Y.%m.%e %T", localtime(time) );
print(
encode_utf8(
"\n" . 'ASC_DEBUG!!! ' . $debugTimestamp . ' - ' . $debugMsg . "\n"
)
);
}
sub _averageBrightness(@) {
my @input = @_;
use List::Util qw(sum);
return int( sum(@input) / @input );
}
sub _perlCodeCheck($) {
my $exec = shift;
my $val = undef;
if ( $exec =~ /^\{(.+)\}$/ ) {
$val = main::AnalyzePerlCommand( undef, $1 );
}
return $val;
}
sub PrivacyUpTime($$) {
my ( $shuttersDevHash, $shuttersSunriseUnixtime ) = @_;
my $privacyUpUnixtime;
if ( ( $shuttersSunriseUnixtime - $shutters->getPrivacyUpTime ) >
( gettimeofday() + 1 )
or $shutters->getPrivacyUpStatus == 2 )
{
$privacyUpUnixtime =
$shuttersSunriseUnixtime - $shutters->getPrivacyUpTime;
$privacyUpUnixtime += 86400
if ( $shutters->getPrivacyUpStatus == 2 );
readingsSingleUpdate( $shuttersDevHash, 'ASC_Time_PrivacyDriveUp',
strftime( "%e.%m.%Y - %H:%M", localtime($privacyUpUnixtime) ), 1 );
## Setzt den PrivacyUp Modus für die Sichtschutzfahrt auf den Status 1
## und gibt die Unixtime für die nächste Fahrt korrekt zurück
unless ( $shutters->getPrivacyUpStatus == 2 ) {
$shutters->setPrivacyUpStatus(1);
$shuttersSunriseUnixtime = $privacyUpUnixtime;
}
}
else {
readingsSingleUpdate(
$shuttersDevHash,
'ASC_Time_PrivacyDriveUp',
strftime(
"%e.%m.%Y - %H:%M",
localtime(
( $shuttersSunriseUnixtime - $shutters->getPrivacyUpTime )
+ 86400
)
),
1
);
}
return $shuttersSunriseUnixtime;
}
sub PrivacyDownTime($$) {
my ( $shuttersDevHash, $shuttersSunsetUnixtime ) = @_;
my $privacyDownUnixtime;
if ( ( $shuttersSunsetUnixtime - $shutters->getPrivacyDownTime ) >
( gettimeofday() + 1 )
or $shutters->getPrivacyDownStatus == 2 )
{
$privacyDownUnixtime =
$shuttersSunsetUnixtime - $shutters->getPrivacyDownTime;
$privacyDownUnixtime += 86400
if ( $shutters->getPrivacyDownStatus == 2 );
readingsSingleUpdate( $shuttersDevHash, 'ASC_Time_PrivacyDriveDown',
strftime( "%e.%m.%Y - %H:%M", localtime($privacyDownUnixtime) ),
1 );
## Setzt den PrivacyDown Modus für die Sichtschutzfahrt auf den Status 1
## und gibt die Unixtime für die nächste Fahrt korrekt zurück
unless ( $shutters->getPrivacyDownStatus == 2 ) {
$shutters->setPrivacyDownStatus(1);
$shuttersSunsetUnixtime = $privacyDownUnixtime;
}
}
else {
readingsSingleUpdate(
$shuttersDevHash,
'ASC_Time_PrivacyDriveDown',
strftime(
"%e.%m.%Y - %H:%M",
localtime(
( $shuttersSunsetUnixtime - $shutters->getPrivacyDownTime )
+ 86400
)
),
1
);
}
return $shuttersSunsetUnixtime;
}
sub _IsAdv {
my ( undef, undef, undef, $monthday, $month, $year, undef, undef, undef ) =
localtime( gettimeofday() );
my $adv = 0;
$year += 1900;
if ( $month < 1 ) {
if ( $monthday < 7 ) {
$adv = 1;
}
}
else {
my $time = HTTP::Date::str2time( $year . '-12-25' );
my $wday = ( localtime($time) )[6];
$wday = $wday ? $wday : 7;
$time -= ( $wday + 21 ) * 86400;
$adv = 1 if ( $time < time );
}
return $adv;
}
sub DevStateIcon($) {
my ($hash) = @_;
$hash = $defs{$hash} if ( ref($hash) ne 'HASH' );
return undef if ( !$hash );
my $name = $hash->{NAME};
if ( ReadingsVal( $name, 'state', undef ) eq 'created new drive timer' ) {
return '.*:clock';
}
elsif ( ReadingsVal( $name, 'state', undef ) eq 'selfDefense terrace' ) {
return '.*:fts_door_tilt';
}
elsif ( ReadingsVal( $name, 'state', undef ) =~ /.*asleep$/ ) {
return '.*:scene_sleeping';
}
elsif ( ReadingsVal( $name, 'state', undef ) =~
/^roommate(.come)?.(awoken|home)$/ )
{
return '.*:user_available';
}
elsif (
ReadingsVal( $name, 'state', undef ) =~ /^residents.(home|awoken)$/ )
{
return '.*:status_available';
}
elsif ( ReadingsVal( $name, 'state', undef ) eq 'manual' ) {
return '.*:fts_shutter_manual';
}
elsif ( ReadingsVal( $name, 'state', undef ) eq 'selfDefense inactive' ) {
return '.*:status_open';
}
elsif ( ReadingsVal( $name, 'state', undef ) =~ /^selfDefense.*.active$/ ) {
return '.*:status_locked';
}
elsif ( ReadingsVal( $name, 'state', undef ) eq 'day open' ) {
return '.*:scene_day';
}
elsif ( ReadingsVal( $name, 'state', undef ) eq 'night close' ) {
return '.*:scene_night';
}
elsif ( ReadingsVal( $name, 'state', undef ) eq 'shading in' ) {
return '.*:fts_shutter_shadding_run';
}
elsif ( ReadingsVal( $name, 'state', undef ) eq 'shading out' ) {
return '.*:fts_shutter_shadding_stop';
}
elsif ( ReadingsVal( $name, 'state', undef ) eq 'active' ) {
return '.*:hourglass';
}
elsif ( ReadingsVal( $name, 'state', undef ) =~ /.*privacy.*/ ) {
return '.*:fts_shutter_50';
}
elsif ( ReadingsVal( $name, 'state', undef ) eq 'adv delay close' ) {
return '.*:christmas_tree';
}
return undef;
}
######################################
######################################
########## Begin der Klassendeklarierungen für OOP (Objektorientierte Programmierung) #########################
## Klasse Rolläden (Shutters) und die Subklassen Attr und Readings ##
## desweiteren wird noch die Klasse ASC_Roommate mit eingebunden
package ASC_Shutters;
our @ISA =
qw(ASC_Shutters::Readings ASC_Shutters::Attr ASC_Roommate ASC_Window);
use strict;
use warnings;
use GPUtils qw(GP_Import);
## Import der FHEM Funktionen
BEGIN {
GP_Import(
qw(
defs
ReadingsVal
readingsSingleUpdate
gettimeofday
InternalTimer
CommandSet
Log3)
);
}
sub new {
my $class = shift;
my $self = {
shuttersDev => undef,
defaultarg => undef,
roommate => undef,
};
bless $self, $class;
return $self;
}
sub setShuttersDev {
my ( $self, $shuttersDev ) = @_;
$self->{shuttersDev} = $shuttersDev if ( defined($shuttersDev) );
return $self->{shuttersDev};
}
sub getShuttersDev {
my $self = shift;
return $self->{shuttersDev};
}
sub setAttrUpdateChanges {
my ( $self, $attr, $value ) = @_;
$self->{ $self->{shuttersDev} }{AttrUpdateChanges}{$attr} = $value;
return 0;
}
sub setHardLockOut {
my ( $self, $cmd ) = @_;
if ( $shutters->getLockOut eq 'hard'
and $shutters->getLockOutCmd ne 'none' )
{
CommandSet( undef, $self->{shuttersDev} . ' inhibit ' . $cmd )
if ( $shutters->getLockOutCmd eq 'inhibit' );
CommandSet( undef,
$self->{shuttersDev} . ' '
. ( $cmd eq 'on' ? 'blocked' : 'unblocked' ) )
if ( $shutters->getLockOutCmd eq 'blocked' );
CommandSet( undef,
$self->{shuttersDev} . ' '
. ( $cmd eq 'on' ? 'protectionOn' : 'protectionOff' ) )
if ( $shutters->getLockOutCmd eq 'protected' );
}
return 0;
}
sub setNoDelay {
my ( $self, $noDelay ) = @_;
$self->{ $self->{shuttersDev} }{noDelay} = $noDelay;
return 0;
}
sub setSelfDefenseAbsent {
my ( $self, $timerrun, $active, $timerhash ) = @_;
$self->{ $self->{shuttersDev} }{selfDefenseAbsent}{timerrun} = $timerrun;
$self->{ $self->{shuttersDev} }{selfDefenseAbsent}{active} = $active;
$self->{ $self->{shuttersDev} }{selfDefenseAbsent}{timerhash} = $timerhash
if ( defined($timerhash) );
return 0;
}
sub setDriveCmd {
my ( $self, $posValue ) = @_;
my $offSet;
my $offSetStart;
if (
( $shutters->getPartyMode eq 'on' and $ascDev->getPartyMode eq 'on' )
or ( $shutters->getAdv
and not $shutters->getQueryShuttersPos($posValue)
and not $shutters->getAdvDelay
and not $shutters->getExternalTriggerState
and not $shutters->getSelfDefenseState )
)
{
$shutters->setDelayCmd($posValue);
$ascDev->setDelayCmdReading;
$shutters->setNoDelay(0);
$shutters->setExternalTriggerState(0)
if ( $shutters->getExternalTriggerState );
FHEM::AutoShuttersControl::ASC_Debug( 'setDriveCmd: '
. $shutters->getShuttersDev
. ' - Die Fahrt wird zurückgestellt. Grund kann ein geöffnetes Fenster sein oder ein aktivierter Party Modus oder Weihnachtszeit'
);
}
else {
$shutters->setAdvDelay(0)
if ( $shutters->getAdvDelay );
$shutters->setDelayCmd('none')
if ( $shutters->getDelayCmd ne 'none' )
; # setzt den Wert auf none da der Rolladen nun gesteuert werden kann.
$shutters->setExternalTriggerState(0)
if ( $shutters->getExternalTriggerState );
### antifreeze Routine
if ( $shutters->getFreezeStatus > 0 ) {
if ( $shutters->getFreezeStatus != 1 ) {
$posValue = $shutters->getStatus;
$shutters->setLastDrive('no drive - antifreeze defense');
$shutters->setLastDriveReading;
$ascDev->setStateReading;
}
elsif ( $posValue == $shutters->getClosedPos ) {
$posValue = $shutters->getAntiFreezePos;
$shutters->setLastDrive(
$shutters->getLastDrive . ' - antifreeze mode' );
}
}
my %h = (
shuttersDev => $self->{shuttersDev},
posValue => $posValue,
);
$offSet = $shutters->getDelay if ( $shutters->getDelay > -1 );
$offSet = $ascDev->getShuttersOffset if ( $shutters->getDelay < 0 );
$offSetStart = $shutters->getDelayStart;
if ( $shutters->getSelfDefenseAbsent
and not $shutters->getSelfDefenseAbsentTimerrun
and $shutters->getSelfDefenseMode ne 'off'
and $shutters->getSelfDefenseState
and $ascDev->getSelfDefense eq 'on' )
{
InternalTimer(
gettimeofday() + $shutters->getSelfDefenseAbsentDelay,
'FHEM::AutoShuttersControl::_SetCmdFn', \%h );
$shutters->setSelfDefenseAbsent( 1, 0, \%h );
}
elsif ( $offSetStart > 0 and not $shutters->getNoDelay ) {
InternalTimer(
gettimeofday() +
int( rand($offSet) + $shutters->getDelayStart ),
'FHEM::AutoShuttersControl::_SetCmdFn', \%h
);
FHEM::AutoShuttersControl::ASC_Debug( 'FnSetDriveCmd: '
. $shutters->getShuttersDev
. ' - versetztes fahren' );
}
elsif ( $offSetStart < 1 or $shutters->getNoDelay ) {
FHEM::AutoShuttersControl::_SetCmdFn( \%h );
FHEM::AutoShuttersControl::ASC_Debug( 'FnSetDriveCmd: '
. $shutters->getShuttersDev
. ' - NICHT versetztes fahren' );
}
FHEM::AutoShuttersControl::ASC_Debug( 'FnSetDriveCmd: '
. $shutters->getShuttersDev
. ' - NoDelay: '
. ( $shutters->getNoDelay ? 'JA' : 'NEIN' ) );
$shutters->setNoDelay(0);
return 0;
}
}
sub setSunsetUnixTime {
my ( $self, $unixtime ) = @_;
$self->{ $self->{shuttersDev} }{sunsettime} = $unixtime;
return 0;
}
sub setSunset {
my ( $self, $value ) = @_;
$self->{ $self->{shuttersDev} }{sunset} = $value;
return 0;
}
sub setSunriseUnixTime {
my ( $self, $unixtime ) = @_;
$self->{ $self->{shuttersDev} }{sunrisetime} = $unixtime;
return 0;
}
sub setSunrise {
my ( $self, $value ) = @_;
$self->{ $self->{shuttersDev} }{sunrise} = $value;
return 0;
}
sub setDelayCmd {
my ( $self, $posValue ) = @_;
$self->{ $self->{shuttersDev} }{delayCmd} = $posValue;
return 0;
}
sub setLastDrive {
my ( $self, $lastDrive ) = @_;
$self->{ $self->{shuttersDev} }{lastDrive} = $lastDrive;
return 0;
}
sub setPosSetCmd {
my ( $self, $posSetCmd ) = @_;
$self->{ $self->{shuttersDev} }{posSetCmd} = $posSetCmd;
return 0;
}
sub setLastDriveReading {
my $self = shift;
my $shuttersDevHash = $defs{ $self->{shuttersDev} };
my %h = (
devHash => $shuttersDevHash,
lastDrive => $shutters->getLastDrive,
);
InternalTimer( gettimeofday() + 0.1,
'FHEM::AutoShuttersControl::_setShuttersLastDriveDelayed', \%h );
return 0;
}
sub setLastPos
{ # letzte ermittelte Position bevor die Position des Rolladen über ASC geändert wurde
my ( $self, $position ) = @_;
$self->{ $self->{shuttersDev} }{lastPos}{VAL} = $position
if ( defined($position) );
$self->{ $self->{shuttersDev} }{lastPos}{TIME} = int( gettimeofday() )
if ( defined( $self->{ $self->{shuttersDev} }{lastPos} ) );
return 0;
}
sub setLastManPos {
my ( $self, $position ) = @_;
$self->{ $self->{shuttersDev} }{lastManPos}{VAL} = $position
if ( defined($position) );
$self->{ $self->{shuttersDev} }{lastManPos}{TIME} = int( gettimeofday() )
if ( defined( $self->{ $self->{shuttersDev} }{lastManPos} )
and defined( $self->{ $self->{shuttersDev} }{lastManPos}{TIME} ) );
$self->{ $self->{shuttersDev} }{lastManPos}{TIME} =
int( gettimeofday() ) - 86400
if ( defined( $self->{ $self->{shuttersDev} }{lastManPos} )
and not defined( $self->{ $self->{shuttersDev} }{lastManPos}{TIME} ) );
return 0;
}
sub setDefault {
my ( $self, $defaultarg ) = @_;
$self->{defaultarg} = $defaultarg if ( defined($defaultarg) );
return $self->{defaultarg};
}
sub setRoommate {
my ( $self, $roommate ) = @_;
$self->{roommate} = $roommate if ( defined($roommate) );
return $self->{roommate};
}
sub setInTimerFuncHash {
my ( $self, $inTimerFuncHash ) = @_;
$self->{ $self->{shuttersDev} }{inTimerFuncHash} = $inTimerFuncHash
if ( defined($inTimerFuncHash) );
return 0;
}
sub setPrivacyDownStatus {
my ( $self, $statusValue ) = @_;
$self->{ $self->{shuttersDev} }->{privacyDownStatus} = $statusValue;
return 0;
}
sub setPrivacyUpStatus {
my ( $self, $statusValue ) = @_;
$self->{ $self->{shuttersDev} }->{privacyUpStatus} = $statusValue;
return 0;
}
sub setSelfDefenseState {
my ( $self, $value ) = @_;
$self->{ $self->{shuttersDev} }{selfDefenseState} = $value;
return 0;
}
sub setAdvDelay {
my ( $self, $advDelay ) = @_;
$self->{ $self->{shuttersDev} }->{AdvDelay} = $advDelay;
return 0;
}
sub getAdvDelay {
my $self = shift;
return (
defined( $self->{ $self->{shuttersDev} }->{AdvDelay} )
? $self->{ $self->{shuttersDev} }->{AdvDelay}
: 0
);
}
sub getPrivacyDownStatus {
my $self = shift;
return (
defined( $self->{ $self->{shuttersDev} }->{privacyDownStatus} )
? $self->{ $self->{shuttersDev} }->{privacyDownStatus}
: undef
);
}
sub getPrivacyUpStatus {
my $self = shift;
return (
defined( $self->{ $self->{shuttersDev} }->{privacyUpStatus} )
? $self->{ $self->{shuttersDev} }->{privacyUpStatus}
: undef
);
}
sub getAttrUpdateChanges {
my ( $self, $attr ) = @_;
return $self->{ $self->{shuttersDev} }{AttrUpdateChanges}{$attr}
if ( defined( $self->{ $self->{shuttersDev} }{AttrUpdateChanges} )
and
defined( $self->{ $self->{shuttersDev} }{AttrUpdateChanges}{$attr} ) );
}
sub getIsDay {
my $self = shift;
return FHEM::AutoShuttersControl::_IsDay( $self->{shuttersDev} );
}
sub getFreezeStatus {
use POSIX qw(strftime);
my $self = shift;
my $daytime = strftime( "%P", localtime() );
$daytime = (
defined($daytime) and $daytime
? $daytime
: ( strftime( "%k", localtime() ) < 12 ? 'am' : 'pm' )
);
my $outTemp = $ascDev->getOutTemp;
$outTemp = $shutters->getOutTemp if ( $shutters->getOutTemp != -100 );
if ( $shutters->getAntiFreeze ne 'off'
and $outTemp <= $ascDev->getFreezeTemp )
{
if ( $shutters->getAntiFreeze eq 'soft' ) {
return 1;
}
elsif ( $shutters->getAntiFreeze eq $daytime ) {
return 2;
}
elsif ( $shutters->getAntiFreeze eq 'hard' ) {
return 3;
}
}
else { return 0; }
}
sub getShuttersPosCmdValueNegate {
my $self = shift;
return ( $shutters->getOpenPos < $shutters->getClosedPos ? 1 : 0 );
}
sub getQueryShuttersPos
{ # Es wird geschaut ob die aktuelle Position des Rollos unterhalb der Zielposition ist
my ( $self, $posValue ) =
@_; # wenn dem so ist wird 1 zurück gegeben ansonsten 0
return (
$shutters->getShuttersPosCmdValueNegate
? $shutters->getStatus > $posValue
: $shutters->getStatus < $posValue
);
}
sub getPosSetCmd {
my $self = shift;
return (
defined( $self->{ $self->{shuttersDev} }{posSetCmd} )
? $self->{ $self->{shuttersDev} }{posSetCmd}
: $shutters->getPosCmd
);
}
sub getNoDelay {
my $self = shift;
return $self->{ $self->{shuttersDev} }{noDelay};
}
sub getSelfDefenseState {
my $self = shift;
return $self->{ $self->{shuttersDev} }{selfDefenseState}
if ( defined( $self->{ $self->{shuttersDev} }{selfDefenseState} ) );
}
sub getSelfDefenseAbsent {
my $self = shift;
return $self->{ $self->{shuttersDev} }{selfDefenseAbsent}{active};
}
sub getSelfDefenseAbsentTimerrun {
my $self = shift;
return $self->{ $self->{shuttersDev} }{selfDefenseAbsent}{timerrun};
}
sub getSelfDefenseAbsentTimerhash {
my $self = shift;
return $self->{ $self->{shuttersDev} }{selfDefenseAbsent}{timerhash}
if (
defined(
$self->{ $self->{shuttersDev} }{selfDefenseAbsent}{timerhash}
)
);
}
sub getLastDrive {
my $self = shift;
$self->{ $self->{shuttersDev} }{lastDrive} =
ReadingsVal( $self->{shuttersDev}, 'ASC_ShuttersLastDrive', 'none' )
if ( not defined( $self->{ $self->{shuttersDev} }{lastDrive} ) );
return $self->{ $self->{shuttersDev} }{lastDrive};
}
sub getLastPos
{ # letzte ermittelte Position bevor die Position des Rolladen über ASC geändert wurde
my $self = shift;
return $self->{ $self->{shuttersDev} }{lastPos}{VAL}
if ( defined( $self->{ $self->{shuttersDev} }{lastPos} )
and defined( $self->{ $self->{shuttersDev} }{lastPos}{VAL} ) );
}
sub getLastPosTimestamp {
my $self = shift;
return $self->{ $self->{shuttersDev} }{lastPos}{TIME}
if ( defined( $self->{ $self->{shuttersDev} } )
and defined( $self->{ $self->{shuttersDev} }{lastPos} )
and defined( $self->{ $self->{shuttersDev} }{lastPos}{TIME} ) );
}
sub getLastManPos
{ # letzte ermittelte Position bevor die Position des Rolladen manuell (nicht über ASC) geändert wurde
my $self = shift;
return $self->{ $self->{shuttersDev} }{lastManPos}{VAL}
if ( defined( $self->{ $self->{shuttersDev} }{lastManPos} )
and defined( $self->{ $self->{shuttersDev} }{lastManPos}{VAL} ) );
}
sub getLastManPosTimestamp {
my $self = shift;
return $self->{ $self->{shuttersDev} }{lastManPos}{TIME}
if ( defined( $self->{ $self->{shuttersDev} } )
and defined( $self->{ $self->{shuttersDev} }{lastManPos} )
and defined( $self->{ $self->{shuttersDev} }{lastManPos}{TIME} ) );
}
sub getInTimerFuncHash {
my $self = shift;
return $self->{ $self->{shuttersDev} }{inTimerFuncHash};
}
sub getSunsetUnixTime {
my $self = shift;
return $self->{ $self->{shuttersDev} }{sunsettime};
}
sub getSunset {
my $self = shift;
return (
defined( $self->{ $self->{shuttersDev} }{sunset} )
? $self->{ $self->{shuttersDev} }{sunset}
: 0
);
}
sub getSunriseUnixTime {
my $self = shift;
return $self->{ $self->{shuttersDev} }{sunrisetime};
}
sub getSunrise {
my $self = shift;
return (
defined( $self->{ $self->{shuttersDev} }{sunrise} )
? $self->{ $self->{shuttersDev} }{sunrise}
: 0
);
}
sub getRoommatesStatus {
my $self = shift;
my $loop = 0;
my @roState;
my %statePrio = (
'asleep' => 1,
'gotosleep' => 2,
'awoken' => 3,
'home' => 4,
'absent' => 5,
'gone' => 6,
'none' => 7
);
my $minPrio = 10;
foreach my $ro ( split( ",", $shutters->getRoommates ) ) {
$shutters->setRoommate($ro);
my $currentPrio = $statePrio{ $shutters->_getRoommateStatus };
$minPrio = $currentPrio if ( $minPrio > $currentPrio );
}
my %revStatePrio = reverse %statePrio;
return $revStatePrio{$minPrio};
}
sub getRoommatesLastStatus {
my $self = shift;
my $loop = 0;
my @roState;
my %statePrio = (
'asleep' => 1,
'gotosleep' => 2,
'awoken' => 3,
'home' => 6,
'absent' => 5,
'gone' => 4,
'none' => 7
);
my $minPrio = 10;
foreach my $ro ( split( ",", $shutters->getRoommates ) ) {
$shutters->setRoommate($ro);
my $currentPrio = $statePrio{ $shutters->_getRoommateLastStatus };
$minPrio = $currentPrio if ( $minPrio > $currentPrio );
}
my %revStatePrio = reverse %statePrio;
return $revStatePrio{$minPrio};
}
sub getOutTemp {
my $self = shift;
return ReadingsVal( $shutters->_getTempSensor,
$shutters->getTempSensorReading, -100 );
}
sub getIdleDetection {
my $self = shift;
return ReadingsVal( $self->{shuttersDev},
$shutters->_getIdleDetectionReading, 'none' );
}
### Begin Beschattung Objekt mit Daten befüllen
sub setShadingStatus {
my ( $self, $value ) = @_;
### Werte für value = in, out, in reserved, out reserved
$self->{ $self->{shuttersDev} }{ShadingStatus}{VAL} = $value
if ( defined($value) );
$self->{ $self->{shuttersDev} }{ShadingStatus}{TIME} = int( gettimeofday() )
if ( defined( $self->{ $self->{shuttersDev} }{ShadingStatus} ) );
return 0;
}
sub setShadingLastStatus {
my ( $self, $value ) = @_;
### Werte für value = in, out
$self->{ $self->{shuttersDev} }{ShadingLastStatus}{VAL} = $value
if ( defined($value) );
$self->{ $self->{shuttersDev} }{ShadingLastStatus}{TIME} =
int( gettimeofday() )
if ( defined( $self->{ $self->{shuttersDev} }{ShadingLastStatus} ) );
$self->{ $self->{shuttersDev} }{ShadingManualDriveStatus}{VAL} = 0
if ( $value eq 'out' );
return 0;
}
sub setShadingManualDriveStatus {
my ( $self, $value ) = @_;
### Werte für value = in, out
$self->{ $self->{shuttersDev} }{ShadingManualDriveStatus}{VAL} = $value
if ( defined($value) );
return 0;
}
sub setWindProtectionStatus { # Werte protected, unprotected
my ( $self, $value ) = @_;
$self->{ $self->{shuttersDev} }->{ASC_WindParameters}->{VAL} = $value
if ( defined($value) );
return 0;
}
sub setRainProtectionStatus { # Werte protected, unprotected
my ( $self, $value ) = @_;
$self->{ $self->{shuttersDev} }->{RainProtection}->{VAL} = $value
if ( defined($value) );
return 0;
}
sub setExternalTriggerState {
my ( $self, $value ) = @_;
$self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}->{event} = $value
if ( defined($value) );
return 0;
}
sub setPushBrightnessInArray {
my ( $self, $value ) = @_;
unshift(
@{ $self->{ $self->{shuttersDev} }->{BrightnessAverageArray}->{VAL} },
$value
);
pop( @{ $self->{ $self->{shuttersDev} }->{BrightnessAverageArray}->{VAL} } )
if (
scalar(
@{
$self->{ $self->{shuttersDev} }->{BrightnessAverageArray}->{VAL}
}
) > 3
);
}
sub getBrightnessAverage {
my $self = shift;
return &FHEM::AutoShuttersControl::_averageBrightness(
@{ $self->{ $self->{shuttersDev} }->{BrightnessAverageArray}->{VAL} } )
if (
ref( $self->{ $self->{shuttersDev} }->{BrightnessAverageArray}->{VAL} )
eq 'ARRAY'
and scalar(
@{
$self->{ $self->{shuttersDev} }->{BrightnessAverageArray}->{VAL}
}
) > 0
);
}
sub getShadingStatus { # Werte für value = in, out, in reserved, out reserved
my $self = shift;
return $self->{ $self->{shuttersDev} }{ShadingStatus}{VAL}
if ( defined( $self->{ $self->{shuttersDev} }{ShadingStatus} )
and defined( $self->{ $self->{shuttersDev} }{ShadingStatus}{VAL} ) );
}
sub getShadingLastStatus { # Werte für value = in, out
my $self = shift;
return $self->{ $self->{shuttersDev} }{ShadingLastStatus}{VAL}
if ( defined( $self->{ $self->{shuttersDev} }{ShadingLastStatus} )
and defined( $self->{ $self->{shuttersDev} }{ShadingLastStatus}{VAL} )
);
}
sub getShadingManualDriveStatus { # Werte für value = in, out
my $self = shift;
return (
defined( $self->{ $self->{shuttersDev} }{ShadingManualDriveStatus} )
and defined(
$self->{ $self->{shuttersDev} }{ShadingManualDriveStatus}{VAL}
)
? $self->{ $self->{shuttersDev} }{ShadingManualDriveStatus}{VAL}
: 0
);
}
sub getIfInShading {
my $self = shift;
return (
(
$shutters->getShadingMode ne 'off'
and $shutters->getShadingLastStatus eq 'out'
) ? 1 : 0
);
}
sub getWindProtectionStatus { # Werte protected, unprotected
my $self = shift;
return (
(
defined( $self->{ $self->{shuttersDev} }->{ASC_WindParameters} )
and defined(
$self->{ $self->{shuttersDev} }->{ASC_WindParameters}->{VAL}
)
)
? $self->{ $self->{shuttersDev} }->{ASC_WindParameters}->{VAL}
: 'unprotected'
);
}
sub getRainProtectionStatus { # Werte protected, unprotected
my $self = shift;
return (
(
defined( $self->{ $self->{shuttersDev} }->{RainProtection} )
and defined(
$self->{ $self->{shuttersDev} }->{RainProtection}->{VAL}
)
)
? $self->{ $self->{shuttersDev} }->{RainProtection}->{VAL}
: 'unprotected'
);
}
sub getShadingStatusTimestamp {
my $self = shift;
return $self->{ $self->{shuttersDev} }{ShadingStatus}{TIME}
if ( defined( $self->{ $self->{shuttersDev} } )
and defined( $self->{ $self->{shuttersDev} }{ShadingStatus} )
and defined( $self->{ $self->{shuttersDev} }{ShadingStatus}{TIME} ) );
}
sub getShadingLastStatusTimestamp {
my $self = shift;
return $self->{ $self->{shuttersDev} }{ShadingLastStatus}{TIME}
if ( defined( $self->{ $self->{shuttersDev} } )
and defined( $self->{ $self->{shuttersDev} }{ShadingLastStatus} )
and defined( $self->{ $self->{shuttersDev} }{ShadingLastStatus}{TIME} )
);
}
### Ende Beschattung
## Subklasse Attr von ASC_Shutters##
package ASC_Shutters::Attr;
use strict;
use warnings;
use GPUtils qw(GP_Import);
## Import der FHEM Funktionen
BEGIN {
GP_Import(
qw(
AttrVal
gettimeofday)
);
}
sub getAntiFreezePos {
my $self = shift;
my $val = AttrVal(
$self->{shuttersDev},
'ASC_Antifreeze_Pos',
$userAttrList{
'ASC_Antifreeze_Pos:5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100'
}[ AttrVal( $self->{shuttersDev}, 'ASC', 2 ) ]
);
if ( defined( FHEM::AutoShuttersControl::_perlCodeCheck($val) ) ) {
$val = FHEM::AutoShuttersControl::_perlCodeCheck($val);
}
return (
$val =~ /^\d+(\.\d+)?$/ ? $val : $userAttrList{
'ASC_Antifreeze_Pos:5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100'
}[ AttrVal( $self->{shuttersDev}, 'ASC', 2 ) ]
);
}
sub getShuttersPlace {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_ShuttersPlace', 'window' );
}
sub getPrivacyUpTime {
my $self = shift;
return $self->{ $self->{shuttersDev} }->{ASC_PrivacyUpValue_beforeDayOpen}
->{uptime}
if (
exists(
$self->{ $self->{shuttersDev} }->{ASC_PrivacyUpValue_beforeDayOpen}
->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }->{ASC_PrivacyUpValue_beforeDayOpen}
->{LASTGETTIME} ) < 2
);
$self->{ $self->{shuttersDev} }->{ASC_PrivacyUpValue_beforeDayOpen}
->{LASTGETTIME} = int( gettimeofday() );
my ( $upTime, $upBrightnessVal ) =
FHEM::AutoShuttersControl::GetAttrValues( $self->{shuttersDev},
'ASC_PrivacyUpValue_beforeDayOpen', '-1:-1' );
## Erwartetes Ergebnis
# upTime:upBrightnessVal
$self->{ $self->{shuttersDev} }->{ASC_PrivacyUpValue_beforeDayOpen}
->{uptime} = $upTime;
$self->{ $self->{shuttersDev} }->{ASC_PrivacyUpValue_beforeDayOpen}
->{upbrightnessval} =
( $upBrightnessVal ne 'none' ? $upBrightnessVal : -1 );
$shutters->setPrivacyUpStatus(0)
if ( defined( $shutters->getPrivacyUpStatus )
and $self->{ $self->{shuttersDev} }->{ASC_PrivacyUpValue_beforeDayOpen}
->{uptime} == -1 );
return $self->{ $self->{shuttersDev} }->{ASC_PrivacyUpValue_beforeDayOpen}
->{uptime};
}
sub getPrivacyUpBrightnessVal {
my $self = shift;
return $self->{ $self->{shuttersDev} }->{ASC_PrivacyUpValue_beforeDayOpen}
->{upbrightnessval}
if (
exists(
$self->{ $self->{shuttersDev} }->{ASC_PrivacyUpValue_beforeDayOpen}
->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }->{ASC_PrivacyUpValue_beforeDayOpen}
->{LASTGETTIME} ) < 2
);
$shutters->getPrivacyUpTime;
return (
defined(
$self->{ $self->{shuttersDev} }->{ASC_PrivacyUpValue_beforeDayOpen}
->{upbrightnessval}
)
? $self->{ $self->{shuttersDev} }->{ASC_PrivacyUpValue_beforeDayOpen}
->{upbrightnessval}
: -1
);
}
sub getPrivacyDownTime {
my $self = shift;
return $self->{ $self->{shuttersDev} }
->{ASC_PrivacyDownValue_beforeNightClose}->{downtime}
if (
exists(
$self->{ $self->{shuttersDev} }
->{ASC_PrivacyDownValue_beforeNightClose}->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }
->{ASC_PrivacyDownValue_beforeNightClose}->{LASTGETTIME} ) < 2
);
$self->{ $self->{shuttersDev} }->{ASC_PrivacyDownValue_beforeNightClose}
->{LASTGETTIME} = int( gettimeofday() );
my ( $downTime, $downBrightnessVal ) =
FHEM::AutoShuttersControl::GetAttrValues( $self->{shuttersDev},
'ASC_PrivacyDownValue_beforeNightClose', '-1:-1' );
## Erwartetes Ergebnis
# downTime:downBrightnessVal
$self->{ $self->{shuttersDev} }->{ASC_PrivacyDownValue_beforeNightClose}
->{downtime} = $downTime;
$self->{ $self->{shuttersDev} }->{ASC_PrivacyDownValue_beforeNightClose}
->{downbrightnessval} =
( $downBrightnessVal ne 'none' ? $downBrightnessVal : -1 );
$shutters->setPrivacyDownStatus(0)
if ( defined( $shutters->getPrivacyDownStatus )
and $self->{ $self->{shuttersDev} }
->{ASC_PrivacyDownValue_beforeNightClose}->{downtime} == -1 );
return $self->{ $self->{shuttersDev} }
->{ASC_PrivacyDownValue_beforeNightClose}->{downtime};
}
sub getPrivacyDownBrightnessVal {
my $self = shift;
return $self->{ $self->{shuttersDev} }
->{ASC_PrivacyDownValue_beforeNightClose}->{downbrightnessval}
if (
exists(
$self->{ $self->{shuttersDev} }
->{ASC_PrivacyDownValue_beforeNightClose}->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }
->{ASC_PrivacyDownValue_beforeNightClose}->{LASTGETTIME} ) < 2
);
$shutters->getPrivacyDownTime;
return (
defined(
$self->{ $self->{shuttersDev} }
->{ASC_PrivacyDownValue_beforeNightClose}->{downbrightnessval}
)
? $self->{ $self->{shuttersDev} }
->{ASC_PrivacyDownValue_beforeNightClose}->{downbrightnessval}
: -1
);
}
sub getPrivacyUpPos {
my $self = shift;
my $val = AttrVal( $self->{shuttersDev}, 'ASC_PrivacyUp_Pos', 50 );
if ( defined( FHEM::AutoShuttersControl::_perlCodeCheck($val) ) ) {
$val = FHEM::AutoShuttersControl::_perlCodeCheck($val);
}
return ( $val =~ /^\d+(\.\d+)?$/ ? $val : 50 );
}
sub getPrivacyDownPos {
my $self = shift;
my $val = AttrVal( $self->{shuttersDev}, 'ASC_PrivacyDown_Pos', 50 );
if ( defined( FHEM::AutoShuttersControl::_perlCodeCheck($val) ) ) {
$val = FHEM::AutoShuttersControl::_perlCodeCheck($val);
}
return ( $val =~ /^\d+(\.\d+)?$/ ? $val : 50 );
}
sub getSelfDefenseMode {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_Self_Defense_Mode', 'gone' );
}
sub getSelfDefenseAbsentDelay {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_Self_Defense_AbsentDelay', 300 );
}
sub getWiggleValue {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_WiggleValue', 5 );
}
sub getAdv {
my $self = shift;
return (
AttrVal( $self->{shuttersDev}, 'ASC_Adv', 'off' ) eq 'on'
? ( FHEM::AutoShuttersControl::_IsAdv == 1 ? 1 : 0 )
: 0
);
}
### Begin Beschattung
sub getShadingPos {
my $self = shift;
my $val = AttrVal( $self->{shuttersDev}, 'ASC_Shading_Pos',
$userAttrList{'ASC_Shading_Pos:10,20,30,40,50,60,70,80,90,100'}
[ AttrVal( $self->{shuttersDev}, 'ASC', 2 ) ] );
if ( defined( FHEM::AutoShuttersControl::_perlCodeCheck($val) ) ) {
$val = FHEM::AutoShuttersControl::_perlCodeCheck($val);
}
return (
$val =~ /^\d+(\.\d+)?$/
? $val
: $userAttrList{'ASC_Shading_Pos:10,20,30,40,50,60,70,80,90,100'}
[ AttrVal( $self->{shuttersDev}, 'ASC', 2 ) ]
);
}
sub getShadingMode {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_Shading_Mode', 'off' );
}
sub _getTempSensor {
my $self = shift;
return $self->{ $self->{shuttersDev} }->{ASC_TempSensor}->{device}
if (
exists(
$self->{ $self->{shuttersDev} }->{ASC_TempSensor}->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }->{ASC_TempSensor}->{LASTGETTIME} )
< 2
);
$self->{ $self->{shuttersDev} }->{ASC_TempSensor}->{LASTGETTIME} =
int( gettimeofday() );
my ( $device, $reading ) =
FHEM::AutoShuttersControl::GetAttrValues( $self->{shuttersDev},
'ASC_TempSensor', 'none' );
### erwartetes Ergebnis
# DEVICE:READING
$self->{ $self->{shuttersDev} }->{ASC_TempSensor}->{device} = $device;
$self->{ $self->{shuttersDev} }->{ASC_TempSensor}->{reading} =
( $reading ne 'none' ? $reading : 'temperature' );
return $self->{ $self->{shuttersDev} }->{ASC_TempSensor}->{device};
}
sub getTempSensorReading {
my $self = shift;
return $self->{ $self->{shuttersDev} }->{ASC_TempSensor}->{reading}
if (
exists(
$self->{ $self->{shuttersDev} }->{ASC_TempSensor}->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }->{ASC_TempSensor}->{LASTGETTIME} )
< 2
);
$shutters->_getTempSensor;
return (
defined( $self->{ $self->{shuttersDev} }->{ASC_TempSensor}->{reading} )
? $self->{ $self->{shuttersDev} }->{ASC_TempSensor}->{reading}
: 'temperature'
);
}
sub _getIdleDetectionReading {
my $self = shift;
return $self->{ $self->{shuttersDev} }->{ASC_Shutter_IdleDetection}
->{reading}
if (
exists(
$self->{ $self->{shuttersDev} }->{ASC_Shutter_IdleDetection}
->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }->{ASC_Shutter_IdleDetection}
->{LASTGETTIME} ) < 2
);
$self->{ $self->{shuttersDev} }->{ASC_Shutter_IdleDetection}->{LASTGETTIME}
= int( gettimeofday() );
my ( $reading, $value ) =
FHEM::AutoShuttersControl::GetAttrValues( $self->{shuttersDev},
'ASC_Shutter_IdleDetection', 'none' );
### erwartetes Ergebnis
# READING:VALUE
$self->{ $self->{shuttersDev} }->{ASC_Shutter_IdleDetection}->{reading} =
$reading;
$self->{ $self->{shuttersDev} }->{ASC_Shutter_IdleDetection}->{value} =
$value;
return $self->{ $self->{shuttersDev} }->{ASC_Shutter_IdleDetection}
->{reading};
}
sub getIdleDetectionValue {
my $self = shift;
return $self->{ $self->{shuttersDev} }->{ASC_Shutter_IdleDetection}->{value}
if (
exists(
$self->{ $self->{shuttersDev} }->{ASC_Shutter_IdleDetection}
->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }->{ASC_Shutter_IdleDetection}
->{LASTGETTIME} ) < 2
);
$shutters->_getIdleDetectionReading;
return (
defined(
$self->{ $self->{shuttersDev} }->{ASC_Shutter_IdleDetection}
->{value}
)
? $self->{ $self->{shuttersDev} }->{ASC_Shutter_IdleDetection}->{value}
: 'none'
);
}
sub _getBrightnessSensor {
my $self = shift;
return $self->{ $self->{shuttersDev} }->{ASC_BrightnessSensor}->{device}
if (
exists(
$self->{ $self->{shuttersDev} }->{ASC_BrightnessSensor}
->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }->{ASC_BrightnessSensor}
->{LASTGETTIME} ) < 2
);
$self->{ $self->{shuttersDev} }->{ASC_BrightnessSensor}->{LASTGETTIME} =
int( gettimeofday() );
my ( $device, $reading, $max, $min ) =
FHEM::AutoShuttersControl::GetAttrValues( $self->{shuttersDev},
'ASC_BrightnessSensor', 'none' );
### erwartetes Ergebnis
# DEVICE:READING MAX:MIN
$self->{ $self->{shuttersDev} }->{ASC_BrightnessSensor}->{device} = $device;
$self->{ $self->{shuttersDev} }->{ASC_BrightnessSensor}->{reading} =
( $reading ne 'none' ? $reading : 'brightness' );
$self->{ $self->{shuttersDev} }->{ASC_BrightnessSensor}->{triggermin} =
( $min ne 'none' ? $min : -1 );
$self->{ $self->{shuttersDev} }->{ASC_BrightnessSensor}->{triggermax} =
( $max ne 'none' ? $max : -1 );
return $self->{ $self->{shuttersDev} }->{ASC_BrightnessSensor}->{device};
}
sub getBrightnessReading {
my $self = shift;
return $self->{ $self->{shuttersDev} }->{ASC_BrightnessSensor}->{reading}
if (
exists(
$self->{ $self->{shuttersDev} }->{ASC_BrightnessSensor}
->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }->{ASC_BrightnessSensor}
->{LASTGETTIME} ) < 2
);
$shutters->_getBrightnessSensor;
return (
defined(
$self->{ $self->{shuttersDev} }->{ASC_BrightnessSensor}->{reading}
)
? $self->{ $self->{shuttersDev} }->{ASC_BrightnessSensor}->{reading}
: 'brightness'
);
}
sub getShadingAzimuthLeft {
my $self = shift;
return $self->{ $self->{shuttersDev} }->{ASC_Shading_InOutAzimuth}
->{leftVal}
if (
exists(
$self->{ $self->{shuttersDev} }->{ASC_Shading_InOutAzimuth}
->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }->{ASC_Shading_InOutAzimuth}
->{LASTGETTIME} ) < 2
);
$shutters->getShadingAzimuthRight;
return $self->{ $self->{shuttersDev} }->{ASC_Shading_InOutAzimuth}
->{leftVal};
}
sub getShadingAzimuthRight {
my $self = shift;
return $self->{ $self->{shuttersDev} }->{ASC_Shading_InOutAzimuth}
->{rightVal}
if (
exists(
$self->{ $self->{shuttersDev} }->{ASC_Shading_InOutAzimuth}
->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }->{ASC_Shading_InOutAzimuth}
->{LASTGETTIME} ) < 2
);
$self->{ $self->{shuttersDev} }->{ASC_Shading_InOutAzimuth}->{LASTGETTIME}
= int( gettimeofday() );
my ( $left, $right ) =
FHEM::AutoShuttersControl::GetAttrValues( $self->{shuttersDev},
'ASC_Shading_InOutAzimuth', '95:265' );
### erwartetes Ergebnis
# MIN:MAX
$self->{ $self->{shuttersDev} }->{ASC_Shading_InOutAzimuth}->{leftVal} =
$left;
$self->{ $self->{shuttersDev} }->{ASC_Shading_InOutAzimuth}->{rightVal} =
$right;
return $self->{ $self->{shuttersDev} }->{ASC_Shading_InOutAzimuth}
->{rightVal};
}
sub getShadingMinOutsideTemperature {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_Shading_Min_OutsideTemperature',
18 );
}
sub getShadingMinElevation {
my $self = shift;
return $self->{ $self->{shuttersDev} }->{ASC_Shading_MinMax_Elevation}
->{minVal}
if (
exists(
$self->{ $self->{shuttersDev} }->{ASC_Shading_MinMax_Elevation}
->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }->{ASC_Shading_MinMax_Elevation}
->{LASTGETTIME} ) < 2
);
$self->{ $self->{shuttersDev} }->{ASC_Shading_MinMax_Elevation}
->{LASTGETTIME} = int( gettimeofday() );
my ( $min, $max ) =
FHEM::AutoShuttersControl::GetAttrValues( $self->{shuttersDev},
'ASC_Shading_MinMax_Elevation', '25.0:100.0' );
### erwartetes Ergebnis
# MIN:MAX
$self->{ $self->{shuttersDev} }->{ASC_Shading_MinMax_Elevation}->{minVal} =
$min;
$self->{ $self->{shuttersDev} }->{ASC_Shading_MinMax_Elevation}->{maxVal} =
( $max ne 'none' ? $max : 100 );
return $self->{ $self->{shuttersDev} }->{ASC_Shading_MinMax_Elevation}
->{minVal};
}
sub getShadingMaxElevation {
my $self = shift;
return $self->{ $self->{shuttersDev} }->{ASC_Shading_MinMax_Elevation}
->{maxVal}
if (
exists(
$self->{ $self->{shuttersDev} }->{ASC_Shading_MinMax_Elevation}
->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }->{ASC_Shading_MinMax_Elevation}
->{LASTGETTIME} ) < 2
);
$shutters->getShadingMinElevation;
return $self->{ $self->{shuttersDev} }->{ASC_Shading_MinMax_Elevation}
->{maxVal};
}
sub getShadingStateChangeSunny {
my $self = shift;
return $self->{ $self->{shuttersDev} }
->{ASC_Shading_StateChange_SunnyCloudy}->{sunny}
if (
exists(
$self->{ $self->{shuttersDev} }
->{ASC_Shading_StateChange_SunnyCloudy}->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }
->{ASC_Shading_StateChange_SunnyCloudy}->{LASTGETTIME} ) < 2
);
$self->{ $self->{shuttersDev} }->{ASC_Shading_StateChange_SunnyCloudy}
->{LASTGETTIME} = int( gettimeofday() );
my ( $sunny, $cloudy ) =
FHEM::AutoShuttersControl::GetAttrValues( $self->{shuttersDev},
'ASC_Shading_StateChange_SunnyCloudy',
'35000:20000' );
### erwartetes Ergebnis
# SUNNY:CLOUDY
$self->{ $self->{shuttersDev} }->{ASC_Shading_StateChange_SunnyCloudy}
->{sunny} = $sunny;
$self->{ $self->{shuttersDev} }->{ASC_Shading_StateChange_SunnyCloudy}
->{cloudy} = $cloudy;
return $self->{ $self->{shuttersDev} }
->{ASC_Shading_StateChange_SunnyCloudy}->{sunny};
}
sub getShadingStateChangeCloudy {
my $self = shift;
return $self->{ $self->{shuttersDev} }
->{ASC_Shading_StateChange_SunnyCloudy}->{cloudy}
if (
exists(
$self->{ $self->{shuttersDev} }
->{ASC_Shading_StateChange_SunnyCloudy}->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }
->{ASC_Shading_StateChange_SunnyCloudy}->{LASTGETTIME} ) < 2
);
$shutters->getShadingStateChangeSunny;
return $self->{ $self->{shuttersDev} }
->{ASC_Shading_StateChange_SunnyCloudy}->{cloudy};
}
sub getShadingWaitingPeriod {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_Shading_WaitingPeriod', 1200 );
}
### Ende Beschattung
sub getExternalTriggerDevice {
my $self = shift;
return $self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}->{device}
if (
exists(
$self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}
->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}
->{LASTGETTIME} ) < 2
);
$self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}->{LASTGETTIME} =
int( gettimeofday() );
my ( $device, $reading, $valueActive, $valueInactive, $posActive,
$posInactive )
= FHEM::AutoShuttersControl::GetAttrValues( $self->{shuttersDev},
'ASC_ExternalTrigger', 'none' );
### erwartetes Ergebnis
# DEVICE:READING VALUEACTIVE:VALUEINACTIVE POSACTIVE:POSINACTIVE
$self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}->{device} =
$device;
$self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}->{reading} =
$reading;
$self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}->{valueactive} =
$valueActive;
$self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}->{valueinactive} =
$valueInactive;
$self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}->{posactive} =
$posActive;
$self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}->{posinactive} =
( $posInactive ne 'none' ? $posInactive : $shutters->getLastPos );
return $self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}->{device};
}
sub getExternalTriggerReading {
my $self = shift;
return $self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}->{reading}
if (
exists(
$self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}
->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}
->{LASTGETTIME} ) < 2
);
$shutters->getExternalTriggerDevice;
return $self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}->{reading};
}
sub getExternalTriggerValueActive {
my $self = shift;
return $self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}->{valueactive}
if (
exists(
$self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}
->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}
->{LASTGETTIME} ) < 2
);
$shutters->getExternalTriggerDevice;
return $self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}
->{valueactive};
}
sub getExternalTriggerValueInactive {
my $self = shift;
return $self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}
->{valueinactive}
if (
exists(
$self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}
->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}
->{LASTGETTIME} ) < 2
);
$shutters->getExternalTriggerDevice;
return $self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}
->{valueinactive};
}
sub getExternalTriggerPosActive {
my $self = shift;
return $self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}->{posactive}
if (
exists(
$self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}
->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}
->{LASTGETTIME} ) < 2
);
$shutters->getExternalTriggerDevice;
return $self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}->{posactive};
}
sub getExternalTriggerPosInactive {
my $self = shift;
return $self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}->{posinactive}
if (
exists(
$self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}
->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}
->{LASTGETTIME} ) < 2
);
$shutters->getExternalTriggerDevice;
return $self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}
->{posinactive};
}
sub getExternalTriggerState {
my $self = shift;
return (
(
defined(
$self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}->{event}
)
and
$self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}->{event}
) ? 1 : 0
);
}
sub getDelay {
my $self = shift;
my $val = AttrVal( $self->{shuttersDev}, 'ASC_Drive_Delay', -1 );
return ( $val =~ /^\d+$/ ? $val : -1 );
}
sub getDelayStart {
my $self = shift;
my $val = AttrVal( $self->{shuttersDev}, 'ASC_Drive_DelayStart', -1 );
return ( ( $val > 0 and $val =~ /^\d+$/ ) ? $val : -1 );
}
sub getBlockingTimeAfterManual {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_BlockingTime_afterManual',
1200 );
}
sub getBlockingTimeBeforNightClose {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_BlockingTime_beforNightClose',
3600 );
}
sub getBlockingTimeBeforDayOpen {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_BlockingTime_beforDayOpen',
3600 );
}
sub getPosCmd {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_Pos_Reading', 'pct' );
}
sub getOpenPos {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_Open_Pos',
$userAttrList{'ASC_Open_Pos:0,10,20,30,40,50,60,70,80,90,100'}
[ AttrVal( $self->{shuttersDev}, 'ASC', 2 ) ] );
}
sub getVentilatePos {
my $self = shift;
my $val = AttrVal( $self->{shuttersDev}, 'ASC_Ventilate_Pos',
$userAttrList{'ASC_Ventilate_Pos:10,20,30,40,50,60,70,80,90,100'}
[ AttrVal( $self->{shuttersDev}, 'ASC', 2 ) ] );
if ( defined( FHEM::AutoShuttersControl::_perlCodeCheck($val) ) ) {
$val = FHEM::AutoShuttersControl::_perlCodeCheck($val);
}
return (
$val =~ /^\d+(\.\d+)?$/
? $val
: $userAttrList{'ASC_Ventilate_Pos:10,20,30,40,50,60,70,80,90,100'}
[ AttrVal( $self->{shuttersDev}, 'ASC', 2 ) ]
);
}
sub getVentilatePosAfterDayClosed {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_WindowRec_PosAfterDayClosed',
'open' );
}
sub getClosedPos {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_Closed_Pos',
$userAttrList{'ASC_Closed_Pos:0,10,20,30,40,50,60,70,80,90,100'}
[ AttrVal( $self->{shuttersDev}, 'ASC', 2 ) ] );
}
sub getSleepPos {
my $self = shift;
my $val = AttrVal( $self->{shuttersDev}, 'ASC_Sleep_Pos', -1 );
if ( defined( FHEM::AutoShuttersControl::_perlCodeCheck($val) ) ) {
$val = FHEM::AutoShuttersControl::_perlCodeCheck($val);
}
return ( $val =~ /^\d+(\.\d+)?$/ ? $val : -1 );
}
sub getVentilateOpen {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_Ventilate_Window_Open', 'on' );
}
sub getComfortOpenPos {
my $self = shift;
my $val = AttrVal( $self->{shuttersDev}, 'ASC_ComfortOpen_Pos',
$userAttrList{'ASC_ComfortOpen_Pos:0,10,20,30,40,50,60,70,80,90,100'}
[ AttrVal( $self->{shuttersDev}, 'ASC', 2 ) ] );
if ( defined( FHEM::AutoShuttersControl::_perlCodeCheck($val) ) ) {
$val = FHEM::AutoShuttersControl::_perlCodeCheck($val);
}
return (
$val =~ /^\d+(\.\d+)?$/
? $val
: $userAttrList{'ASC_ComfortOpen_Pos:0,10,20,30,40,50,60,70,80,90,100'}
[ AttrVal( $self->{shuttersDev}, 'ASC', 2 ) ]
);
}
sub getPartyMode {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_Partymode', 'off' );
}
sub getRoommates {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_Roommate_Device', 'none' );
}
sub getRoommatesReading {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_Roommate_Reading', 'state' );
}
sub getWindPos {
my $self = shift;
my $name = $self->{name};
return $self->{ $self->{shuttersDev} }->{ASC_WindParameters}->{closedPos}
if (
exists(
$self->{ $self->{shuttersDev} }->{ASC_WindParameters}->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }->{ASC_WindParameters}->{LASTGETTIME}
) < 2
);
$shutters->getWindMax;
return $self->{ $self->{shuttersDev} }->{ASC_WindParameters}->{closedPos};
}
sub getWindMax {
my $self = shift;
my $name = $self->{name};
return $self->{ $self->{shuttersDev} }->{ASC_WindParameters}->{triggermax}
if (
exists(
$self->{ $self->{shuttersDev} }->{ASC_WindParameters}->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }->{ASC_WindParameters}->{LASTGETTIME}
) < 2
);
$self->{ $self->{shuttersDev} }->{ASC_WindParameters}->{LASTGETTIME} =
int( gettimeofday() );
my ( $max, $hyst, $pos ) =
FHEM::AutoShuttersControl::GetAttrValues( $self->{shuttersDev},
'ASC_WindParameters', '50:20' );
## Erwartetes Ergebnis
# max:hyst pos
$self->{ $self->{shuttersDev} }->{ASC_WindParameters}->{triggermax} = $max;
$self->{ $self->{shuttersDev} }->{ASC_WindParameters}->{triggerhyst} =
( $hyst ne 'none' ? $max - $hyst : $max - 20 );
$self->{ $self->{shuttersDev} }->{ASC_WindParameters}->{closedPos} =
( $pos ne 'none' ? $pos : $shutters->getOpenPos );
return $self->{ $self->{shuttersDev} }->{ASC_WindParameters}->{triggermax};
}
sub getWindMin {
my $self = shift;
my $name = $self->{name};
return $self->{ $self->{shuttersDev} }->{ASC_WindParameters}->{triggerhyst}
if (
exists(
$self->{ $self->{shuttersDev} }->{ASC_WindParameters}->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }->{ASC_WindParameters}->{LASTGETTIME}
) < 2
);
$shutters->getWindMax;
return $self->{ $self->{shuttersDev} }->{ASC_WindParameters}->{triggerhyst};
}
sub getWindProtection {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_WindProtection', 'on' );
}
sub getRainProtection {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_RainProtection', 'on' );
}
sub getModeUp {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_Mode_Up', 'always' );
}
sub getModeDown {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_Mode_Down', 'always' );
}
sub getLockOut {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_LockOut', 'off' );
}
sub getLockOutCmd {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_LockOut_Cmd', 'none' );
}
sub getAntiFreeze {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_Antifreeze', 'off' );
}
sub getAutoAstroModeMorning {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_AutoAstroModeMorning', 'none' );
}
sub getAutoAstroModeEvening {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_AutoAstroModeEvening', 'none' );
}
sub getAutoAstroModeMorningHorizon {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_AutoAstroModeMorningHorizon',
'none' );
}
sub getAutoAstroModeEveningHorizon {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_AutoAstroModeEveningHorizon',
'none' );
}
sub getUp {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_Up', 'astro' );
}
sub getDown {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_Down', 'astro' );
}
sub getTimeUpEarly {
my $self = shift;
my $val = AttrVal( $self->{shuttersDev}, 'ASC_Time_Up_Early', '05:00' );
if ( defined( FHEM::AutoShuttersControl::_perlCodeCheck($val) ) ) {
$val = FHEM::AutoShuttersControl::_perlCodeCheck($val);
}
return (
$val =~ /^(?:[01]?\d|2[0-3]):(?:[0-5]\d)(:(?:[0-5]\d))?$/
? $val
: '05:00'
);
}
sub getTimeUpLate {
my $self = shift;
my $val = AttrVal( $self->{shuttersDev}, 'ASC_Time_Up_Late', '08:30' );
if ( defined( FHEM::AutoShuttersControl::_perlCodeCheck($val) ) ) {
$val = FHEM::AutoShuttersControl::_perlCodeCheck($val);
}
return (
$val =~ /^(?:[01]?\d|2[0-3]):(?:[0-5]\d)(:(?:[0-5]\d))?$/
? $val
: '08:30'
);
}
sub getTimeDownEarly {
my $self = shift;
my $val = AttrVal( $self->{shuttersDev}, 'ASC_Time_Down_Early', '16:00' );
if ( defined( FHEM::AutoShuttersControl::_perlCodeCheck($val) ) ) {
$val = FHEM::AutoShuttersControl::_perlCodeCheck($val);
}
return (
$val =~ /^(?:[01]?\d|2[0-3]):(?:[0-5]\d)(:(?:[0-5]\d))?$/
? $val
: '16:00'
);
}
sub getTimeDownLate {
my $self = shift;
my $val = AttrVal( $self->{shuttersDev}, 'ASC_Time_Down_Late', '22:00' );
if ( defined( FHEM::AutoShuttersControl::_perlCodeCheck($val) ) ) {
$val = FHEM::AutoShuttersControl::_perlCodeCheck($val);
}
return (
$val =~ /^(?:[01]?\d|2[0-3]):(?:[0-5]\d)(:(?:[0-5]\d))?$/
? $val
: '22:00'
);
}
sub getTimeUpWeHoliday {
my $self = shift;
my $val =
AttrVal( $self->{shuttersDev}, 'ASC_Time_Up_WE_Holiday', '08:00' );
if ( defined( FHEM::AutoShuttersControl::_perlCodeCheck($val) ) ) {
$val = FHEM::AutoShuttersControl::_perlCodeCheck($val);
}
return (
$val =~ /^(?:[01]?\d|2[0-3]):(?:[0-5]\d)(:(?:[0-5]\d))?$/
? $val
: '08:00'
);
}
sub getBrightnessMinVal {
my $self = shift;
return $self->{ $self->{shuttersDev} }->{ASC_BrightnessSensor}->{triggermin}
if (
exists(
$self->{ $self->{shuttersDev} }->{ASC_BrightnessSensor}
->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }->{ASC_BrightnessSensor}
->{LASTGETTIME} ) < 2
);
$shutters->_getBrightnessSensor;
return $self->{ $self->{shuttersDev} }->{ASC_BrightnessSensor}
->{triggermin};
}
sub getBrightnessMaxVal {
my $self = shift;
return $self->{ $self->{shuttersDev} }->{ASC_BrightnessSensor}->{triggermax}
if (
exists(
$self->{ $self->{shuttersDev} }->{ASC_BrightnessSensor}
->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }->{ASC_BrightnessSensor}
->{LASTGETTIME} ) < 2
);
$shutters->_getBrightnessSensor;
return $self->{ $self->{shuttersDev} }->{ASC_BrightnessSensor}
->{triggermax};
}
sub getDriveUpMaxDuration {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_DriveUpMaxDuration', 60 );
}
## Subklasse Readings von ASC_Shutters ##
package ASC_Shutters::Readings;
use strict;
use warnings;
use GPUtils qw(GP_Import);
## Import der FHEM Funktionen
BEGIN {
GP_Import(
qw(
ReadingsVal
ReadingsNum)
);
}
sub getBrightness {
my $self = shift;
return ReadingsNum( $shutters->_getBrightnessSensor,
$shutters->getBrightnessReading, -1 );
}
sub getWindStatus {
my $self = shift;
return ReadingsVal( $ascDev->_getWindSensor,
$ascDev->getWindSensorReading, -1 );
}
sub getStatus {
my $self = shift;
return ReadingsNum( $self->{shuttersDev}, $shutters->getPosCmd, 0 );
}
sub getDelayCmd {
my $self = shift;
return $self->{ $self->{shuttersDev} }{delayCmd};
}
sub getASCenable {
my $self = shift;
return ReadingsVal( $self->{shuttersDev}, 'ASC_Enable', 'on' );
}
## Klasse Fenster (Window) und die Subklassen Attr und Readings ##
package ASC_Window;
our @ISA = qw(ASC_Window::Attr ASC_Window::Readings);
## Subklasse Attr von Klasse ASC_Window ##
package ASC_Window::Attr;
use strict;
use warnings;
use GPUtils qw(GP_Import);
## Import der FHEM Funktionen
BEGIN {
GP_Import(
qw(
AttrVal
gettimeofday)
);
}
sub getSubTyp {
my $self = shift;
return AttrVal( $self->{shuttersDev}, 'ASC_WindowRec_subType', 'twostate' );
}
sub _getWinDev {
my $self = shift;
return $self->{ $self->{shuttersDev} }->{ASC_WindowRec}->{device}
if (
exists(
$self->{ $self->{shuttersDev} }->{ASC_WindowRec}->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }->{ASC_WindowRec}->{LASTGETTIME} ) <
2
);
$self->{ $self->{shuttersDev} }->{ASC_WindowRec}->{LASTGETTIME} =
int( gettimeofday() );
my ( $device, $reading ) =
FHEM::AutoShuttersControl::GetAttrValues( $self->{shuttersDev},
'ASC_WindowRec', 'none' );
### erwartetes Ergebnis
# DEVICE:READING VALUEACTIVE:VALUEINACTIVE POSACTIVE:POSINACTIVE
$self->{ $self->{shuttersDev} }->{ASC_WindowRec}->{device} =
$device;
$self->{ $self->{shuttersDev} }->{ASC_WindowRec}->{reading} =
( $reading ne 'none' ? $reading : 'state' );
return $self->{ $self->{shuttersDev} }->{ASC_WindowRec}->{device};
}
sub getWinDevReading {
my $self = shift;
return $self->{ $self->{shuttersDev} }->{ASC_WindowRec}->{reading}
if (
exists(
$self->{ $self->{shuttersDev} }->{ASC_WindowRec}->{LASTGETTIME}
)
and ( gettimeofday() -
$self->{ $self->{shuttersDev} }->{ASC_WindowRec}->{LASTGETTIME} ) <
2
);
$shutters->_getWinDev;
return $self->{ $self->{shuttersDev} }->{ASC_WindowRec}->{reading};
}
## Subklasse Readings von Klasse ASC_Window ##
package ASC_Window::Readings;
use strict;
use warnings;
use GPUtils qw(GP_Import);
## Import der FHEM Funktionen
BEGIN {
GP_Import(
qw(
ReadingsVal)
);
}
sub getWinStatus {
my $self = shift;
return ReadingsVal( $shutters->_getWinDev, $shutters->getWinDevReading,
'closed' );
}
## Klasse ASC_Roommate ##
package ASC_Roommate;
use strict;
use warnings;
use GPUtils qw(GP_Import);
## Import der FHEM Funktionen
BEGIN {
GP_Import(
qw(
ReadingsVal)
);
}
sub _getRoommateStatus {
my $self = shift;
my $roommate = $self->{roommate};
return ReadingsVal( $roommate, $shutters->getRoommatesReading, 'none' );
}
sub _getRoommateLastStatus {
my $self = shift;
my $roommate = $self->{roommate};
my $default = $self->{defaultarg};
$default = 'none' if ( not defined($default) );
return ReadingsVal( $roommate, 'lastState', $default );
}
## Klasse ASC_Dev plus Subklassen ASC_Attr_Dev und ASC_Readings_Dev##
package ASC_Dev;
our @ISA = qw(ASC_Dev::Readings ASC_Dev::Attr);
use strict;
use warnings;
sub new {
my $class = shift;
my $self = { name => undef, };
bless $self, $class;
return $self;
}
sub setName {
my ( $self, $name ) = @_;
$self->{name} = $name if ( defined($name) );
return $self->{name};
}
sub setDefault {
my ( $self, $defaultarg ) = @_;
$self->{defaultarg} = $defaultarg if ( defined($defaultarg) );
return $self->{defaultarg};
}
sub getName {
my $self = shift;
return $self->{name};
}
## Subklasse Readings ##
package ASC_Dev::Readings;
use strict;
use warnings;
use GPUtils qw(GP_Import);
## Import der FHEM Funktionen
BEGIN {
GP_Import(
qw(
readingsSingleUpdate
ReadingsVal
defs)
);
}
sub setDelayCmdReading {
my $self = shift;
my $name = $self->{name};
my $hash = $defs{$name};
readingsSingleUpdate( $hash,
$shutters->getShuttersDev . '_lastDelayPosValue',
$shutters->getDelayCmd, 1 );
return 0;
}
sub setStateReading {
my $self = shift;
my $value = shift;
my $name = $self->{name};
my $hash = $defs{$name};
readingsSingleUpdate( $hash, 'state',
( defined($value) ? $value : $shutters->getLastDrive ), 1 );
return 0;
}
sub setPosReading {
my $self = shift;
my $name = $self->{name};
my $hash = $defs{$name};
readingsSingleUpdate( $hash, $shutters->getShuttersDev . '_PosValue',
$shutters->getStatus, 1 );
return 0;
}
sub setLastPosReading {
my $self = shift;
my $name = $self->{name};
my $hash = $defs{$name};
readingsSingleUpdate( $hash, $shutters->getShuttersDev . '_lastPosValue',
$shutters->getLastPos, 1 );
return 0;
}
sub getPartyMode {
my $self = shift;
my $name = $self->{name};
return ReadingsVal( $name, 'partyMode', 'off' );
}
sub getHardLockOut {
my $self = shift;
my $name = $self->{name};
return ReadingsVal( $name, 'hardLockOut', 'none' );
}
sub getSunriseTimeWeHoliday {
my $self = shift;
my $name = $self->{name};
return ReadingsVal( $name, 'sunriseTimeWeHoliday', 'none' );
}
sub getMonitoredDevs {
my $self = shift;
my $name = $self->{name};
$self->{monitoredDevs} = ReadingsVal( $name, '.monitoredDevs', 'none' );
return $self->{monitoredDevs};
}
sub getOutTemp {
my $self = shift;
return ReadingsVal( $ascDev->_getTempSensor, $ascDev->getTempSensorReading,
-100 );
}
sub getResidentsStatus {
my $self = shift;
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' );
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 {
my $self = shift;
my $name = $self->{name};
return ReadingsVal( $name, 'controlShading', 'none' );
}
sub getSelfDefense {
my $self = shift;
my $name = $self->{name};
return ReadingsVal( $name, 'selfDefense', 'none' );
}
sub getAzimuth {
my $self = shift;
my $azimuth;
$azimuth = ReadingsVal( $ascDev->_getTwilightDevice, 'azimuth', -1 )
if ( $defs{ $ascDev->_getTwilightDevice }->{TYPE} eq 'Twilight' );
$azimuth = ReadingsVal( $ascDev->_getTwilightDevice, 'SunAz', -1 )
if ( $defs{ $ascDev->_getTwilightDevice }->{TYPE} eq 'Astro' );
return $azimuth;
}
sub getElevation {
my $self = shift;
my $elevation;
$elevation = ReadingsVal( $ascDev->_getTwilightDevice, 'elevation', -1 )
if ( $defs{ $ascDev->_getTwilightDevice }->{TYPE} eq 'Twilight' );
$elevation = ReadingsVal( $ascDev->_getTwilightDevice, 'SunAlt', -1 )
if ( $defs{ $ascDev->_getTwilightDevice }->{TYPE} eq 'Astro' );
return $elevation;
}
sub getASCenable {
my $self = shift;
my $name = $self->{name};
return ReadingsVal( $name, 'ascEnable', 'none' );
}
## Subklasse Attr ##
package ASC_Dev::Attr;
use strict;
use warnings;
use GPUtils qw(GP_Import);
## Import der FHEM Funktionen
BEGIN {
GP_Import(
qw(
AttrVal
gettimeofday)
);
}
sub getShuttersOffset {
my $self = shift;
my $name = $self->{name};
return AttrVal( $name, 'ASC_shuttersDriveDelay', -1 );
}
sub getBrightnessMinVal {
my $self = shift;
my $name = $self->{name};
return $self->{ASC_brightness}->{triggermin}
if ( exists( $self->{ASC_brightness}->{LASTGETTIME} )
and ( gettimeofday() - $self->{ASC_brightness}->{LASTGETTIME} ) < 2 );
$ascDev->getBrightnessMaxVal;
return $self->{ASC_brightness}->{triggermin};
}
sub getBrightnessMaxVal {
my $self = shift;
my $name = $self->{name};
return $self->{ASC_brightness}->{triggermax}
if ( exists( $self->{ASC_brightness}->{LASTGETTIME} )
and ( gettimeofday() - $self->{ASC_brightness}->{LASTGETTIME} ) < 2 );
$self->{ASC_brightness}->{LASTGETTIME} = int( gettimeofday() );
my ( $triggermax, $triggermin ) =
FHEM::AutoShuttersControl::GetAttrValues( $name,
'ASC_brightnessDriveUpDown', '800:500' );
## erwartetes Ergebnis
# max:min
$self->{ASC_brightness}->{triggermin} = $triggermin;
$self->{ASC_brightness}->{triggermax} = $triggermax;
return $self->{ASC_brightness}->{triggermax};
}
sub _getTwilightDevice {
my $self = shift;
my $name = $self->{name};
return AttrVal( $name, 'ASC_twilightDevice', 'none' );
}
sub getAutoAstroModeEvening {
my $self = shift;
my $name = $self->{name};
return AttrVal( $name, 'ASC_autoAstroModeEvening', 'REAL' );
}
sub getAutoAstroModeEveningHorizon {
my $self = shift;
my $name = $self->{name};
return AttrVal( $name, 'ASC_autoAstroModeEveningHorizon', 0 );
}
sub getAutoAstroModeMorning {
my $self = shift;
my $name = $self->{name};
return AttrVal( $name, 'ASC_autoAstroModeMorning', 'REAL' );
}
sub getAutoAstroModeMorningHorizon {
my $self = shift;
my $name = $self->{name};
return AttrVal( $name, 'ASC_autoAstroModeMorningHorizon', 0 );
}
sub getAutoShuttersControlMorning {
my $self = shift;
my $name = $self->{name};
return AttrVal( $name, 'ASC_autoShuttersControlMorning', 'on' );
}
sub getAutoShuttersControlEvening {
my $self = shift;
my $name = $self->{name};
return AttrVal( $name, 'ASC_autoShuttersControlEvening', 'on' );
}
sub getAutoShuttersControlComfort {
my $self = shift;
my $name = $self->{name};
return AttrVal( $name, 'ASC_autoShuttersControlComfort', 'off' );
}
sub getFreezeTemp {
my $self = shift;
my $name = $self->{name};
return AttrVal( $name, 'ASC_freezeTemp', 3 );
}
sub _getTempSensor {
my $self = shift;
my $name = $self->{name};
return $self->{ASC_tempSensor}->{device}
if ( exists( $self->{ASC_tempSensor}->{LASTGETTIME} )
and ( gettimeofday() - $self->{ASC_tempSensor}->{LASTGETTIME} ) < 2 );
$self->{ASC_tempSensor}->{LASTGETTIME} = int( gettimeofday() );
my ( $device, $reading ) =
FHEM::AutoShuttersControl::GetAttrValues( $name, 'ASC_tempSensor',
'none' );
## erwartetes Ergebnis
# DEVICE:READING
return $device if ( $device eq 'none' );
$self->{ASC_tempSensor}->{device} = $device;
$self->{ASC_tempSensor}->{reading} =
( $reading ne 'none' ? $reading : 'temperature' );
return $self->{ASC_tempSensor}->{device};
}
sub getTempSensorReading {
my $self = shift;
my $name = $self->{name};
return $self->{ASC_tempSensor}->{reading}
if ( exists( $self->{ASC_tempSensor}->{LASTGETTIME} )
and ( gettimeofday() - $self->{ASC_tempSensor}->{LASTGETTIME} ) < 2 );
$ascDev->_getTempSensor;
return $self->{ASC_tempSensor}->{reading};
}
sub _getResidentsDev {
my $self = shift;
my $name = $self->{name};
return $self->{ASC_residentsDev}->{device}
if ( exists( $self->{ASC_residentsDev}->{LASTGETTIME} )
and ( gettimeofday() - $self->{ASC_residentsDev}->{LASTGETTIME} ) < 2 );
$self->{ASC_residentsDev}->{LASTGETTIME} = int( gettimeofday() );
my ( $device, $reading ) =
FHEM::AutoShuttersControl::GetAttrValues( $name, 'ASC_residentsDev',
'none' );
$self->{ASC_residentsDev}->{device} = $device;
$self->{ASC_residentsDev}->{reading} =
( $reading ne 'none' ? $reading : 'state' );
return $self->{ASC_residentsDev}->{device};
}
sub getResidentsReading {
my $self = shift;
my $name = $self->{name};
return $self->{ASC_residentsDev}->{reading}
if ( exists( $self->{ASC_residentsDev}->{LASTGETTIME} )
and ( gettimeofday() - $self->{ASC_residentsDev}->{LASTGETTIME} ) < 2 );
$ascDev->_getResidentsDev;
return $self->{ASC_residentsDev}->{reading};
}
sub _getRainSensor {
my $self = shift;
my $name = $self->{name};
return $self->{ASC_rainSensor}->{device}
if ( exists( $self->{ASC_rainSensor}->{LASTGETTIME} )
and ( gettimeofday() - $self->{ASC_rainSensor}->{LASTGETTIME} ) < 2 );
$self->{ASC_rainSensor}->{LASTGETTIME} = int( gettimeofday() );
my ( $device, $reading, $max, $hyst, $pos, $wait ) =
FHEM::AutoShuttersControl::GetAttrValues( $name, 'ASC_rainSensor',
'none' );
## erwartetes Ergebnis
# DEVICE:READING MAX:HYST
return $device if ( $device eq 'none' );
$self->{ASC_rainSensor}->{device} = $device;
$self->{ASC_rainSensor}->{reading} =
( $reading ne 'none' ? $reading : 'state' );
$self->{ASC_rainSensor}->{triggermax} = ( $max ne 'none' ? $max : 1000 );
$self->{ASC_rainSensor}->{triggerhyst} = (
$hyst ne 'none'
? $max - $hyst
: ( $self->{ASC_rainSensor}->{triggermax} * 0 )
);
$self->{ASC_rainSensor}->{shuttersClosedPos} =
( $pos ne 'none' ? $pos : $shutters->getClosedPos );
$self->{ASC_rainSensor}->{waitingTime} =
( $pos ne 'none' ? $wait : 900 );
return $self->{ASC_rainSensor}->{device};
}
sub getRainSensorReading {
my $self = shift;
my $name = $self->{name};
return $self->{ASC_rainSensor}->{reading}
if ( exists( $self->{ASC_rainSensor}->{LASTGETTIME} )
and ( gettimeofday() - $self->{ASC_rainSensor}->{LASTGETTIME} ) < 2 );
$ascDev->_getRainSensor;
return $self->{ASC_rainSensor}->{reading};
}
sub getRainTriggerMax {
my $self = shift;
my $name = $self->{name};
return $self->{ASC_rainSensor}->{triggermax}
if ( exists( $self->{ASC_rainSensor}->{LASTGETTIME} )
and ( gettimeofday() - $self->{ASC_rainSensor}->{LASTGETTIME} ) < 2 );
$ascDev->_getRainSensor;
return $self->{ASC_rainSensor}->{triggermax};
}
sub getRainTriggerMin {
my $self = shift;
my $name = $self->{name};
return $self->{ASC_rainSensor}->{triggerhyst}
if ( exists( $self->{ASC_rainSensor}->{LASTGETTIME} )
and ( gettimeofday() - $self->{ASC_rainSensor}->{LASTGETTIME} ) < 2 );
$ascDev->_getRainSensor;
return $self->{ASC_rainSensor}->{triggerhyst};
}
sub getRainSensorShuttersClosedPos {
my $self = shift;
my $name = $self->{name};
return $self->{ASC_rainSensor}->{shuttersClosedPos}
if ( exists( $self->{ASC_rainSensor}->{LASTGETTIME} )
and ( gettimeofday() - $self->{ASC_rainSensor}->{LASTGETTIME} ) < 2 );
$ascDev->_getRainSensor;
return $self->{ASC_rainSensor}->{shuttersClosedPos};
}
sub getRainWaitingTime {
my $self = shift;
my $name = $self->{name};
return $self->{ASC_rainSensor}->{waitingTime}
if ( exists( $self->{ASC_rainSensor}->{LASTGETTIME} )
and ( gettimeofday() - $self->{ASC_rainSensor}->{LASTGETTIME} ) < 2 );
$ascDev->_getRainSensor;
return $self->{ASC_rainSensor}->{waitingTime};
}
sub _getWindSensor {
my $self = shift;
my $name = $self->{name};
return $self->{ASC_windSensor}->{device}
if ( exists( $self->{ASC_windSensor}->{LASTGETTIME} )
and ( gettimeofday() - $self->{ASC_windSensor}->{LASTGETTIME} ) < 2 );
$self->{ASC_windSensor}->{LASTGETTIME} = int( gettimeofday() );
my ( $device, $reading ) =
FHEM::AutoShuttersControl::GetAttrValues( $name, 'ASC_windSensor',
'none' );
return $device if ( $device eq 'none' );
$self->{ASC_windSensor}->{device} = $device;
$self->{ASC_windSensor}->{reading} =
( $reading ne 'none' ? $reading : 'wind' );
return $self->{ASC_windSensor}->{device};
}
sub getWindSensorReading {
my $self = shift;
my $name = $self->{name};
return $self->{ASC_windSensor}->{reading}
if ( exists( $self->{ASC_windSensor}->{LASTGETTIME} )
and ( gettimeofday() - $self->{ASC_windSensor}->{LASTGETTIME} ) < 2 );
$ascDev->_getWindSensor;
return (
defined( $self->{ASC_windSensor}->{reading} )
? $self->{ASC_windSensor}->{reading}
: 'wind'
);
}
sub getblockAscDrivesAfterManual {
my $self = shift;
my $name = $self->{name};
return AttrVal( $name, 'ASC_blockAscDrivesAfterManual', 0 );
}
1;
=pod
=item device
=item summary Module for controlling shutters depending on various conditions
=item summary_DE Modul zur automatischen Rolladensteuerung auf Basis bestimmter Ereignisse
=begin html
';
$ret .= '';
$ret .= ' ';
$ret .= '
';
$ret .= " ';
if ( ref($notifydevs) eq "HASH" ) {
my $linecount = 1;
foreach my $notifydev ( sort keys( %{$notifydevs} ) ) {
if ( ref( $notifydevs->{$notifydev} ) eq "HASH" ) {
foreach
my $shutters ( sort keys( %{ $notifydevs->{$notifydev} } ) )
{
if ( $linecount % 2 == 0 ) { $ret .= 'Shutters/ASC-Device ";
$ret .= " ";
$ret .= "NOTIFYDEV ";
$ret .= " ";
$ret .= "Attribut ";
$ret .= " ";
$ret .= ''; }
else { $ret .= ' '; }
$ret .= " ';
$linecount++;
}
}
}
}
$ret .= '$shutters ";
$ret .= " ";
$ret .= "$notifydev ";
$ret .= " ";
$ret .= "$notifydevs->{$notifydev}{$shutters} ";
$ret .= " ";
$ret .= 'AutoShuttersControl
So that ASC can drive the blinds on the basis of the astronomical times, it is very important to
correctly set the location (latitude, longitude) in the device "global".
define <name> AutoShuttersControl
define myASControl AutoShuttersControl
This creates an new AutoShuttersControl device, called myASControl.
Now was the new global attribute ASC added to the FHEM installation.
Each shutter that is to be controlled by AutoShuttersControl must now have the attribute ASC set to 1 or 2.
The value 1 is to be used with devices whose state is given as position (i.e. ROLLO or Siro, shutters
openend is 0, shutters closed is 100), 2 with devices whose state is given as percent closed (i.e. HomeMatic,
shutters opened is 100, closed is 0).
After setting the attributes to all devices who should be controlled, the automatic scan at the main device
can be started for example with
set myASControl scanForShutters
Within the ASC device:
Within the shutter devices:
At the global ASC device:
At shutter devices, controlled by ASC:
HomeMaticmode. Shutter is open equals to 100, shutter is closed equals to 0, is controlled by pct values.
50:20 ASC_Closed_Pos.
Shading
Shading is only available if the following prerequests are met:
- The controlShading reading is set to on, and there is a device of type Astro or Twilight configured to ASC_twilightDevice, and ASC_tempSensor is set.
- ASC_BrightnessSensor is configured to any shutter device.
- All other attributes are optional and the default value for them is used, if they are not otherwise configured. Please review the settings carefully, especially the values for StateChange_Cloudy and StateChange_Sunny.
The following attributes are available:
- ASC_Shading_InOutAzimuth - Azimuth value from which shading is to be used when shading is exceeded and shading when undershooting is required. Defaults to 95:265.
- ASC_Shading_MinMax_Elevation - Shading starts as min point of sun elevation is reached and end as max point of sun elevation is reached, depending also on other sensor values. Defaults to 25.0:100.0.
- ASC_Shading_Min_OutsideTemperature - Shading starts at this outdoor temperature, depending also on other sensor values. Defaults to 18.0.
- ASC_Shading_Mode absent|always|off|home - see ASC_Mode_Down above, but for shading. Defaults to off.
- ASC_Shading_Pos - Shading position in percent. (Default: dependent on attributASC 85/15)
- ASC_Shading_StateChange_Cloudy - Shading ends at this outdoor brightness, depending also on other sensor values. Defaults to 20000.
- ASC_Shading_StateChange_SunnyCloudy - Shading starts/stops at this outdoor brightness, depending also on other sensor values. Defaults to 35000:20000.
- ASC_Shading_WaitingPeriod - Waiting time in seconds before additional sensor values to ASC_Shading_StateChange_Sunny or ASC_Shading_StateChange_Cloudy are used for shading. Defaults to 120.
AutoShuttersControl API description
It's possible to access internal data of the ASC module by calling the API function.
Data points of a shutter device, controlled by ASC
{ ascAPIget('Getter','SHUTTERS_DEVICENAME') }
Getter | Description |
---|---|
FreezeStatus | 1 = soft, 2 = daytime, 3 = hard |
NoDelay | Was the offset handling deactivated (e.g. by operations triggered by a window event) |
LastDrive | Reason for the last action caused by ASC |
LastPos | Last position of the shutter |
LastPosTimestamp | Timestamp of the last position |
LastManPos | Last position manually set of the shutter |
LastManPosTimestamp | Timestamp of the last position manually set |
SunsetUnixTime | Calculated sunset time in seconds since the UNIX epoche |
Sunset | 1 = operation in the evening was made, 0 = operation in the evening was not yet made |
SunriseUnixTime | Calculated sunrise time in seconds since the UNIX epoche |
Sunrise | 1 = operation in the morning was made, 0 = operation in the morning was not yet made |
RoommatesStatus | Current state of the room mate set for this shutter |
RoommatesLastStatus | Last state of the room mate set for this shutter |
ShadingStatus | Value of the current shading state. Can hold in, out, in reserved or out reserved |
ShadingStatusTimestamp | Timestamp of the last shading state |
IfInShading | Is the shutter currently in shading (depends on the shading mode) |
WindProtectionStatus | Current state of the wind protection. Can hold protection or unprotection |
RainProtectionStatus | Current state of the rain protection. Can hold protection or unprotection |
DelayCmd | Last operation order in the waiting queue. Set for example by the party mode |
Status | Position of the shutter |
ASCenable | Does ASC control the shutter? |
PrivacyDownStatus | Is the shutter currently in privacyDown mode |
outTemp | Current temperature of a configured temperature device, return -100 is no device configured |
{ ascAPIget('Getter','ROLLODEVICENAME',VALUE) }
Getter | Erläuterung |
---|---|
QueryShuttersPos | Rückgabewert 1 bedeutet das die aktuelle Position des Rollos unterhalb der Valueposition ist. 0 oder nichts bedeutet oberhalb der Valueposition. |
{ ascAPIget('Getter') }
Getter | Description |
---|---|
OutTemp | Current temperature of a configured temperature device, return -100 is no device configured |
ResidentsStatus | Current state of a configured resident device |
ResidentsLastStatus | Last state of a configured resident device |
Azimuth | Current azimuth of the sun |
Elevation | Current elevation of the sun |
ASCenable | Is ASC globally activated? |
AutoShuttersControl (ASC) ermöglicht eine vollständige Automatisierung der vorhandenen Rollläden. Das Modul bietet umfangreiche Konfigurationsmöglichkeiten, um Rollläden bspw. nach Sonnenauf- und untergangszeiten, nach Helligkeitswerten oder rein zeitgesteuert zu steuern.
Damit ASC auf Basis der astronomischen Zeiten die Rollos fahren kann, ist es ganz wichtig im Device "global" die Location (Latitude,Longitude) korrekt zu setzen.
Man kann festlegen, welche Rollläden von ASC in die Automatisierung mit aufgenommen werden sollen. Daraufhin stehen diverse Attribute zur Feinkonfiguration zur Verfügung. So sind unter anderem komplexe Lösungen wie Fahrten in Abhängigkeit des Bewohnerstatus einfach umsetzbar. Beispiel: Hochfahren von Rollläden, wenn der Bewohner erwacht ist und draußen bereits die Sonne aufgegangen ist. Weiterhin ist es möglich, dass der geschlossene Rollladen z.B. nach dem Ankippen eines Fensters in eine Lüftungsposition fährt. Und vieles mehr.
Definedefine <name> AutoShuttersControl
define myASControl AutoShuttersControl
{ ascAPIget('Getter','ROLLODEVICENAME') }
Getter | Erläuterung |
---|---|
FreezeStatus | 1=soft, 2=Daytime, 3=hard |
NoDelay | Wurde die Behandlung von Offset deaktiviert (Beispiel bei Fahrten über Fensterevents) |
LastDrive | Grund des letzten Fahrens |
LastPos | die letzte Position des Rollladens |
LastPosTimestamp | Timestamp der letzten festgestellten Position |
LastManPos | Position der letzten manuellen Fahrt |
LastManPosTimestamp | Timestamp der letzten manuellen Position |
SunsetUnixTime | berechnete Unixzeit für Abends (Sonnenuntergang) |
Sunset | 1=Abendfahrt wurde durchgeführt, 0=noch keine Abendfahrt durchgeführt |
SunriseUnixTime | berechnete Unixzeit für Morgens (Sonnenaufgang) |
Sunrise | 1=Morgenfahrt wurde durchgeführt, 0=noch keine Morgenfahrt durchgeführt |
RoommatesStatus | aktueller Status der/des Roommate/s für den Rollladen |
RoommatesLastStatus | letzter Status der/des Roommate/s für den Rollladen |
ShadingStatus | Ausgabe des aktuellen Shading Status, „in“, „out“, „in reserved“, „out reserved“ |
ShadingStatusTimestamp | Timestamp des letzten Beschattungsstatus |
IfInShading | Befindet sich der Rollladen, in Abhängigkeit des Shading Mode, in der Beschattung |
WindProtectionStatus | aktueller Status der Wind Protection „protected“ oder „unprotected“ |
RainProtectionStatus | aktueller Status der Regen Protection „unprotected“ oder „unprotected“ |
DelayCmd | letzter Fahrbefehl welcher in die Warteschlange kam. Grund z.B. Partymodus. |
Status | Position des Rollladens |
ASCenable | Abfrage ob für den Rollladen die ASC Steuerung aktiv ist. |
IsDay | Abfrage ob das Rollo im Tag oder Nachtmodus ist. Also nach Sunset oder nach Sunrise |
PrivacyDownStatus | Abfrage ob das Rollo aktuell im PrivacyDown Status steht |
OutTemp | aktuelle Außentemperatur sofern ein Sensor definiert ist, wenn nicht kommt -100 als Wert zurück |
{ ascAPIget('Getter','ROLLODEVICENAME',VALUE) }
Getter | Erläuterung |
---|---|
QueryShuttersPos | Rückgabewert 1 bedeutet das die aktuelle Position des Rollos unterhalb der Valueposition ist. 0 oder nichts bedeutet oberhalb der Valueposition. |
{ ascAPIget('Getter') }
Getter | Erläuterung |
---|---|
OutTemp | aktuelle Außentemperatur sofern ein Sensor definiert ist, wenn nicht kommt -100 als Wert zurück |
ResidentsStatus | aktueller Status des Residents Devices |
ResidentsLastStatus | letzter Status des Residents Devices |
Azimuth | Azimut Wert |
Elevation | Elevation Wert |
ASCenable | ist die ASC Steuerung global aktiv? |