From 1a8cbfc1b89c13774bcea3e968ece9c983a48ae0 Mon Sep 17 00:00:00 2001
From: LeonGaultier
Date: Tue, 11 Jun 2019 06:13:24 +0000
Subject: [PATCH] 73_AutoShuttersControl: add new attribut
ASC_Shading_MinMax_Elevation, many bugfixes
git-svn-id: https://svn.fhem.de/fhem/trunk@19594 2b470e98-0d58-463d-a4d8-8e2adae1ed80
---
fhem/CHANGED | 2 +
fhem/FHEM/73_AutoShuttersControl.pm | 238 +++++++++++++++++++++-------
2 files changed, 185 insertions(+), 55 deletions(-)
diff --git a/fhem/CHANGED b/fhem/CHANGED
index 70e403bec..d0120c7dd 100644
--- a/fhem/CHANGED
+++ b/fhem/CHANGED
@@ -1,5 +1,7 @@
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
# Do not insert empty lines here, update check depends on it.
+ - feature: 73_AutoShuttersControl: add new attribut
+ ASC_Sgading_MinMax_Elevation, many bug fixes
- bugfix: 88_HMCCU: Fixed noInitialUpdate bug
- bugfix: 70_BOTVAC: set robotSounds filter
- feature: 70_BOTVAC: add pollingMode
diff --git a/fhem/FHEM/73_AutoShuttersControl.pm b/fhem/FHEM/73_AutoShuttersControl.pm
index 70779ee3c..bd4b731aa 100644
--- a/fhem/FHEM/73_AutoShuttersControl.pm
+++ b/fhem/FHEM/73_AutoShuttersControl.pm
@@ -48,7 +48,7 @@ use strict;
use warnings;
use FHEM::Meta;
-my $version = '0.6.16';
+my $version = '0.6.17';
sub AutoShuttersControl_Initialize($) {
my ($hash) = @_;
@@ -119,8 +119,79 @@ use GPUtils qw(:all)
use Data::Dumper; #only for Debugging
use Date::Parse;
-my $missingModul = '';
-eval "use JSON qw(decode_json encode_json);1" or $missingModul .= 'JSON ';
+# my $missingModul = '';
+# eval "use JSON qw(decode_json encode_json);1" or $missingModul .= 'JSON ';
+
+# 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
BEGIN {
@@ -196,7 +267,7 @@ my %userAttrList = (
'ASC_Shading_Angle_Right' => '-',
'ASC_Shading_StateChange_Sunny' => '-',
'ASC_Shading_StateChange_Cloudy' => '-',
- 'ASC_Shading_Min_Elevation' => '-',
+ 'ASC_Shading_MinMax_Elevation' => '-',
'ASC_Shading_Min_OutsideTemperature' => '-',
'ASC_Shading_WaitingPeriod' => '-',
'ASC_Drive_Offset' => '-',
@@ -257,12 +328,13 @@ sub Define($$) {
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 ShuttersControl' if ( @a != 2 );
- return
- 'Cannot define ShuttersControl device. Perl modul '
- . ${missingModul}
- . 'is missing.'
- if ($missingModul)
- ; # Abbruch wenn benötigte Hilfsmodule nicht vorhanden sind / vorerst unwichtig
+
+# return
+# 'Cannot define ShuttersControl device. Perl modul '
+# . ${missingModul}
+# . 'is missing.'
+# if ($missingModul)
+# ; # Abbruch wenn benötigte Hilfsmodule nicht vorhanden sind / vorerst unwichtig
my $name = $a[0];
@@ -844,8 +916,6 @@ sub AddNotifyDev($@) {
%hash = map { ( $_ => 1 ) }
split( ',', "$notifyDev,$dev" );
- my $match
- ; # CK: added local variable to save matched event type (open|opened|close|closed|tilt|tilted)
$hash->{NOTIFYDEV} = join( ',', sort keys %hash );
my @devs = split( ',', $dev );
@@ -892,7 +962,7 @@ sub EventProcessingWindowRec($@) {
my ( $hash, $shuttersDev, $events ) = @_;
my $name = $hash->{NAME};
- if ( $events =~ m#.*state:.*(open(?>ed)?|closed?|tilt(?>ed)?)#
+ if ( $events =~ m#.*state:.*?([Oo]pen(?>ed)?|[Cc]losed?|tilt(?>ed)?)#
and IsAfterShuttersManualBlocking($shuttersDev) )
{
my $match = $1;
@@ -912,9 +982,10 @@ sub EventProcessingWindowRec($@) {
#### Hardware Lock der Rollläden
$shutters->setHardLockOut('off')
- if ( $match =~ /close/ and $shutters->getShuttersPlace eq 'terrace' );
+ if ( $match =~ /[Cc]lose/
+ and $shutters->getShuttersPlace eq 'terrace' );
$shutters->setHardLockOut('on')
- if ( $match =~ /open/
+ if ( $match =~ /[Oo]pen/
and $shutters->getShuttersPlace eq 'terrace' );
# my $queryShuttersPosWinRecTilted = (
@@ -939,7 +1010,7 @@ sub EventProcessingWindowRec($@) {
);
if (
- $match =~ /close/
+ $match =~ /[Cc]lose/
and IsAfterShuttersTimeBlocking($shuttersDev)
and ( $shutters->getStatus == $shutters->getVentilatePos
or $shutters->getStatus == $shutters->getComfortOpenPos
@@ -991,7 +1062,7 @@ sub EventProcessingWindowRec($@) {
elsif (
(
$match =~ /tilt/
- or ( $match =~ /open/
+ or ( $match =~ /[Oo]pen/
and $shutters->getSubTyp eq 'twostate' )
)
and $shutters->getVentilateOpen eq 'on'
@@ -1002,7 +1073,7 @@ sub EventProcessingWindowRec($@) {
$shutters->setNoOffset(1);
$shutters->setDriveCmd( $shutters->getVentilatePos );
}
- elsif ( $match =~ /open/
+ elsif ( $match =~ /[Oo]pen/
and $shutters->getSubTyp eq 'threestate' )
{
my $posValue;
@@ -1951,6 +2022,7 @@ sub ShadingProcessing($@) {
if ( $azimuth < $winPosMin
or $azimuth > $winPosMax
or $elevation < $shutters->getShadingMinElevation
+ or $elevation > $shutters->getShadingMaxElevation
or $brightness < $shutters->getShadingStateChangeCloudy
or $outTemp < $shutters->getShadingMinOutsideTemperature )
{
@@ -1986,6 +2058,7 @@ sub ShadingProcessing($@) {
elsif ( $azimuth > $winPosMin
and $azimuth < $winPosMax
and $elevation > $shutters->getShadingMinElevation
+ and $elevation < $shutters->getShadingMaxElevation
and $brightness > $shutters->getShadingStateChangeSunny
and $outTemp > $shutters->getShadingMinOutsideTemperature )
{
@@ -2036,14 +2109,14 @@ sub ShadingProcessingDriveCommand($$) {
if ( $shutters->getShadingStatus eq 'in'
and $getShadingPos != $getStatus )
{
- my $queryShuttersShadingPos = (
- $shutters->getShuttersPosCmdValueNegate
- ? $getStatus > $getShadingPos
- : $getStatus < $getShadingPos
- );
+ # my $queryShuttersShadingPos = (
+ # $shutters->getShuttersPosCmdValueNegate
+ # ? $getStatus > $getShadingPos
+ # : $getStatus < $getShadingPos
+ # );
if (
- not $queryShuttersShadingPos
+ not $shutters->getQueryShuttersPos( $shutters->getShadingPos )
and not( CheckIfShuttersWindowRecOpen($shuttersDev) == 2
and $shutters->getShuttersPlace eq 'terrace' )
)
@@ -2233,7 +2306,7 @@ sub ShuttersCommandSet($$$) {
)
or ( CheckIfShuttersWindowRecOpen($shuttersDev) == 2
and $shutters->getShuttersPlace eq 'terrace'
- and not $shutters->getQueryShuttersPos($posValue) )
+ and $shutters->getQueryShuttersPos($posValue) )
)
)
{
@@ -2356,11 +2429,9 @@ sub CreateSunRiseSetShuttersTimer($$) {
}
InternalTimer( $shuttersSunsetUnixtime,
- 'FHEM::AutoShuttersControl::SunSetShuttersAfterTimerFn', \%funcHash )
- if ( $ascDev->getAutoShuttersControlEvening eq 'on' );
+ 'FHEM::AutoShuttersControl::SunSetShuttersAfterTimerFn', \%funcHash );
InternalTimer( $shuttersSunriseUnixtime,
- 'FHEM::AutoShuttersControl::SunRiseShuttersAfterTimerFn', \%funcHash )
- if ( $ascDev->getAutoShuttersControlMorning eq 'on' );
+ 'FHEM::AutoShuttersControl::SunRiseShuttersAfterTimerFn', \%funcHash );
$ascDev->setStateReading('created new drive timer');
}
@@ -2394,7 +2465,12 @@ sub RenewSunRiseSetShuttersTimer($) {
# ; # temporär muss später gelöscht werden ab Version 0.4.11beta9
# delFromDevAttrList( $_, 'ASC_BrightnessMaxVal' )
# ; # temporär muss später gelöscht werden ab Version 0.4.11beta9
+ $attr{$_}{'ASC_Shading_MinMax_Elevation'} =
+ AttrVal( $_, 'ASC_Shading_Min_Elevation', 'none' )
+ if ( AttrVal( $_, 'ASC_Shading_Min_Elevation', 'none' ) ne 'none' );
+ delFromDevAttrList( $_, 'ASC_Shading_Min_Elevation' )
+ ; # temporär muss später gelöscht werden ab Version 0.6.17
}
}
@@ -2480,13 +2556,14 @@ sub SunSetShuttersAfterTimerFn($) {
$homemode = $ascDev->getResidentsStatus if ( $homemode eq 'none' );
if (
- (
+ $ascDev->getAutoShuttersControlEvening eq 'on'
+ and IsAfterShuttersManualBlocking($shuttersDev)
+ and (
$shutters->getModeDown eq $homemode
or ( $shutters->getModeDown eq 'absent'
and $homemode eq 'gone' )
or $shutters->getModeDown eq 'always'
)
- and IsAfterShuttersManualBlocking($shuttersDev)
)
{
# my $queryShuttersPosPrivacyDown = (
@@ -2526,12 +2603,16 @@ sub SunRiseShuttersAfterTimerFn($) {
$homemode = $ascDev->getResidentsStatus if ( $homemode eq 'none' );
if (
- $shutters->getModeUp eq $homemode
- or ( $shutters->getModeUp eq 'absent'
- and $homemode eq 'gone' )
- or $shutters->getModeUp eq 'always'
+ $ascDev->getAutoShuttersControlMorning eq 'on'
+ and (
+ $shutters->getModeUp eq $homemode
+ or ( $shutters->getModeUp eq 'absent'
+ and $homemode eq 'gone' )
+ or $shutters->getModeUp eq 'always'
+ )
)
{
+
if (
(
$shutters->getRoommatesStatus eq 'home'
@@ -2552,6 +2633,7 @@ sub SunRiseShuttersAfterTimerFn($) {
ShuttersCommandSet( $hash, $shuttersDev, $shutters->getOpenPos );
}
}
+
CreateSunRiseSetShuttersTimer( $hash, $shuttersDev );
}
@@ -3365,7 +3447,7 @@ sub CheckIfShuttersWindowRecOpen($) {
my $shuttersDev = shift;
$shutters->setShuttersDev($shuttersDev);
- if ( $shutters->getWinStatus =~ /open/ ) # CK: covers: open|opened
+ if ( $shutters->getWinStatus =~ /[Oo]pen/ ) # CK: covers: open|opened
{
return 2;
}
@@ -3374,7 +3456,7 @@ sub CheckIfShuttersWindowRecOpen($) {
{
return 1;
}
- elsif ( $shutters->getWinStatus =~ /close/ ) {
+ elsif ( $shutters->getWinStatus =~ /[Cc]lose/ ) {
return 0;
} # CK: covers: close|closed
}
@@ -4089,15 +4171,13 @@ sub _getBrightnessSensor {
### erwartetes Ergebnis
# DEVICE:READING MAX:MIN
-
- return $device if ( $device eq 'none' );
$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' );
+ ( $min ne 'none' ? $min : -1 );
$self->{ $self->{shuttersDev} }->{ASC_BrightnessSensor}->{triggermax} =
- ( $max ne 'none' ? $max : '-1' );
+ ( $max ne 'none' ? $max : -1 );
return $self->{ $self->{shuttersDev} }->{ASC_BrightnessSensor}->{device};
}
@@ -4154,7 +4234,53 @@ sub getShadingMinOutsideTemperature {
sub getShadingMinElevation {
my $self = shift;
- return AttrVal( $self->{shuttersDev}, 'ASC_Shading_Min_Elevation', 25.0 );
+ 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 {
@@ -5157,7 +5283,8 @@ sub getblockAscDrivesAfterManual {
=pod
=item device
=item summary Module for controlling shutters depending on various conditions
-=item summary_DE Modul zur Automatischen Rolladensteuerung auf Basis bestimmter Ereignisse
+=item summary_DE Modul zur automatischen Rolladensteuerung auf Basis bestimmter Ereignisse
+
=begin html
@@ -5315,21 +5442,21 @@ sub getblockAscDrivesAfterManual {
if the ASC_autoAstroModeMorning attribute is set to HORIZON. Defaults to 0.
- ASC_autoShuttersControlComfort - on/off -
+ ASC_autoShuttersControlComfort - on|off -
Controls the comfort functions: If a three state sensor, like the HmIP-SRH window handle
sensor, is installed, ASC will open the window if the sensor signals open position. The
ASC_ComfortOpen_Pos attribute has to be set for the shutter to on, defaults to off.
- ASC_autoShuttersControlEvening - on/off - Enables the automatic control by ASC
+ ASC_autoShuttersControlEvening - on|off - Enables the automatic control by ASC
at the evenings.
- ASC_autoShuttersControlMorning - on/off - Enables the automatic control by ASC
+ ASC_autoShuttersControlMorning - on|off - Enables the automatic control by ASC
at the mornings.
- ASC_blockAscDrivesAfterManual - 0,1 - If set to 1, ASC will not
+ ASC_blockAscDrivesAfterManual 0|1 - If set to 1, ASC will not
automatically control a shutter if there was an manual control to the shutter. To be considered, the
ASC_ShuttersLastDrive reading has to contain the value manual and the shutter is in
an unknown (i.e. not otherwise configured in ASC) position.
@@ -5411,7 +5538,7 @@ sub getblockAscDrivesAfterManual {
At shutter devices, controlled by ASC:
- - ASC - 0/1/2
+
- ASC - 0|1|2
- 0 - don't create attributes for ASC at the first scan and don't be controlled
by ASC
@@ -5421,7 +5548,7 @@ sub getblockAscDrivesAfterManual {
controlled by pct values.
- ASC_Antifreeze - soft/am/pm/hard/off - Freeze protection.
+ ASC_Antifreeze - soft|am|pm|hard|off - Freeze protection.
- soft - see ASC_Antifreeze_Pos.
- hard / am / pm - freeze protection will be active (everytime,
@@ -5643,8 +5770,8 @@ sub getblockAscDrivesAfterManual {
points. East is 90 °, South 180 °, West is 270 ° and North is 0 °.
Defaults to South (180).
- - ASC_Shading_Min_Elevation - Shading starts as this point of sun elevation is
- reached, depending also on other sensor values. Defaults to 25.0.
+
- 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.
@@ -5978,10 +6105,10 @@ sub getblockAscDrivesAfterManual {
- ASC_Pos_Reading - Name des Readings, welches die Position des Rollladen in Prozent an gibt; wird bei unbekannten Device Typen auch als set Befehl zum fahren verwendet
- ASC_PrivacyDownTime_beforNightClose - wie viele Sekunden vor dem abendlichen schließen soll der Rollladen in die Sichtschutzposition fahren, -1 bedeutet das diese Funktion unbeachtet bleiben soll (default: -1)
- ASC_PrivacyDown_Pos - Position den Rollladens für den Sichtschutz (default: 50)
- - ASC_WindProtection - on/off - soll der Rollladen beim Regenschutz beachtet werden. On=JA, off=NEIN.
+ - ASC_WindProtection - on/off - soll der Rollladen beim Regenschutz beachtet werden. on=JA, off=NEIN.
- ASC_Roommate_Device - mit Komma getrennte Namen des/der Roommate Device/s, welche den/die Bewohner des Raumes vom Rollladen wiedergibt. Es macht nur Sinn in Schlaf- oder Kinderzimmern (default: none)
- ASC_Roommate_Reading - das Reading zum Roommate Device, welches den Status wieder gibt (default: state)
- - SC_Self_Defense_Exclude - on/off - bei on Wert wird dieser Rollladen bei aktiven Self Defense und offenen Fenster nicht runter gefahren, wenn Residents absent ist. (default: off)
+ ASC_Self_Defense_Exclude - on/off - bei on Wert wird dieser Rollladen bei aktiven Self Defense und offenen Fenster nicht runter gefahren, wenn Residents absent ist. (default: off)
Beschreibung der Beschattungsfunktion
Damit die Beschattung Funktion hat, müssen folgende Anforderungen erfüllt sein.
@@ -5991,7 +6118,7 @@ sub getblockAscDrivesAfterManual {
- ASC_Shading_Angle_Left - Vorlaufwinkel im Bezug zum Fenster, ab wann abgeschattet wird. Beispiel: Fenster 180° - 85° ==> ab Sonnenpos. 95° wird abgeschattet (default: 75)
- ASC_Shading_Angle_Right - Nachlaufwinkel im Bezug zum Fenster, bis wann abgeschattet wird. Beispiel: Fenster 180° + 85° ==> bis Sonnenpos. 265° wird abgeschattet (default: 75)
- ASC_Shading_Direction - Position in Grad, auf der das Fenster liegt - genau Osten wäre 90, Süden 180 und Westen 270 (default: 180)
- - ASC_Shading_Min_Elevation - ab welcher Höhe des Sonnenstandes soll beschattet werden, immer in Abhängigkeit der anderen einbezogenen Sensorwerte (default: 25.0)
+ - ASC_Shading_MinMax_Elevation - ab welcher min Höhe des Sonnenstandes soll beschattet und ab welcher max Höhe wieder beendet werden, immer in Abhängigkeit der anderen einbezogenen Sensorwerte (default: 25.0:100.0)
- ASC_Shading_Min_OutsideTemperature - ab welcher Temperatur soll Beschattet werden, immer in Abhängigkeit der anderen einbezogenen Sensorwerte (default: 18)
- ASC_Shading_Mode - absent,always,off,home / wann soll die Beschattung nur stattfinden. (default: off)
- ASC_Shading_Pos - Position des Rollladens für die Beschattung
@@ -6099,7 +6226,8 @@ sub getblockAscDrivesAfterManual {
"FHEM": 5.00918799,
"perl": 5.016,
"Meta": 0,
- "JSON": 0
+ "JSON": 0,
+ "Date::Parse": 0
},
"recommends": {
},