mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-02-26 10:34:52 +00:00
73_AutoShuttersControl: fix commandref and bug in shading function, change code
git-svn-id: https://svn.fhem.de/fhem/trunk@22328 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
b89d209cbc
commit
d567d45247
@ -1,5 +1,7 @@
|
|||||||
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
|
# 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.
|
# Do not insert empty lines here, update check depends on it.
|
||||||
|
- bugfix: 73_AutoShuttersControl: fix commandref and bug in shading function
|
||||||
|
change code
|
||||||
- feature: 76_SMAPortal: statistics data provider of Month, Year and Total
|
- feature: 76_SMAPortal: statistics data provider of Month, Year and Total
|
||||||
- change: 89_FULLY: Accepts port number in device definition
|
- change: 89_FULLY: Accepts port number in device definition
|
||||||
- change: 93_DbRep: improve get <> versionNotes 2
|
- change: 93_DbRep: improve get <> versionNotes 2
|
||||||
|
@ -97,7 +97,6 @@ sub Initialize {
|
|||||||
. 'ASC_expert:1 '
|
. 'ASC_expert:1 '
|
||||||
. 'ASC_blockAscDrivesAfterManual:0,1 '
|
. 'ASC_blockAscDrivesAfterManual:0,1 '
|
||||||
. 'ASC_debug:1 '
|
. 'ASC_debug:1 '
|
||||||
. 'ASC_slatDriveCmdInverse:0,1 '
|
|
||||||
. $readingFnAttributes;
|
. $readingFnAttributes;
|
||||||
$hash->{NotifyOrderPrefix} = '51-'; # Order Nummer für NotifyFn
|
$hash->{NotifyOrderPrefix} = '51-'; # Order Nummer für NotifyFn
|
||||||
$hash->{FW_detailFn} =
|
$hash->{FW_detailFn} =
|
||||||
@ -895,7 +894,6 @@ sub Initialize {
|
|||||||
<li><strong>ASC_twilightDevice</strong> - das Device, welches die Informationen zum Sonnenstand liefert. Wird unter anderem für die Beschattung verwendet.</li>
|
<li><strong>ASC_twilightDevice</strong> - das Device, welches die Informationen zum Sonnenstand liefert. Wird unter anderem für die Beschattung verwendet.</li>
|
||||||
<a name="ASC_windSensor"></a>
|
<a name="ASC_windSensor"></a>
|
||||||
<li><strong>ASC_windSensor - DEVICE[:READING]</strong> - Sensor für die Windgeschwindigkeit. Kombination aus Device und Reading.</li>
|
<li><strong>ASC_windSensor - DEVICE[:READING]</strong> - Sensor für die Windgeschwindigkeit. Kombination aus Device und Reading.</li>
|
||||||
<li><strong>ASC_slatDriveCmdInverse</strong> - Vertauscht wie Reihnfolge der Fahrbefehle für Slat und Drive</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
@ -1030,7 +1028,7 @@ sub Initialize {
|
|||||||
<tr><td>ExternalTriggerPosActive</td><td>Rolloposition welche angefahren werden soll wenn der erste externe Trigger aktiv wird.</td></tr>
|
<tr><td>ExternalTriggerPosActive</td><td>Rolloposition welche angefahren werden soll wenn der erste externe Trigger aktiv wird.</td></tr>
|
||||||
<tr><td>ExternalTriggerPosActive2</td><td>Rolloposition welche angefahren werden soll wenn der zweite externe Trigger aktiv wird.</td></tr>
|
<tr><td>ExternalTriggerPosActive2</td><td>Rolloposition welche angefahren werden soll wenn der zweite externe Trigger aktiv wird.</td></tr>
|
||||||
<tr><td>ExternalTriggerPosInactive</td><td>Rolloposition welche angefahren werden soll wenn der externe Trigger inaktiv wird.</td></tr>
|
<tr><td>ExternalTriggerPosInactive</td><td>Rolloposition welche angefahren werden soll wenn der externe Trigger inaktiv wird.</td></tr>
|
||||||
<tr><td>ExternalTriggerState</td><td>aktueller Status des externen Triggers, 0 oder 1</td></tr>
|
<tr><td>ExternalTriggerStatus</td><td>aktueller Status des externen Triggers, 0 oder 1</td></tr>
|
||||||
<tr><td>Delay</td><td>konfigurierte Verzögerungswert welcher für die Zufallsberechnung werwendet werden soll</td></tr>
|
<tr><td>Delay</td><td>konfigurierte Verzögerungswert welcher für die Zufallsberechnung werwendet werden soll</td></tr>
|
||||||
<tr><td>DelayStart</td><td>konfigurierter fester Verzögerungswert</td></tr>
|
<tr><td>DelayStart</td><td>konfigurierter fester Verzögerungswert</td></tr>
|
||||||
<tr><td>BlockingTimeAfterManual</td><td>konfigurierte Blockzeit nach einer manuellen Fahrt</td></tr>
|
<tr><td>BlockingTimeAfterManual</td><td>konfigurierte Blockzeit nach einer manuellen Fahrt</td></tr>
|
||||||
@ -1140,7 +1138,7 @@ sub Initialize {
|
|||||||
</p>
|
</p>
|
||||||
<u>Übersicht für das Rollladen-Device Setter</u>
|
<u>Übersicht für das Rollladen-Device Setter</u>
|
||||||
<ul>
|
<ul>
|
||||||
<code>{ ascAPIset('SETTER','ROLLODEVICENAME') }</code><br>
|
<code>{ ascAPIset('SETTER','ROLLODEVICENAME','VALUE') }</code><br>
|
||||||
</ul>
|
</ul>
|
||||||
<table>
|
<table>
|
||||||
<tr><th>Setter</th><th>Erläuterung</th></tr>
|
<tr><th>Setter</th><th>Erläuterung</th></tr>
|
||||||
@ -1232,23 +1230,6 @@ sub Initialize {
|
|||||||
<tr><td>RainWaitingTime</td><td> </td></tr>
|
<tr><td>RainWaitingTime</td><td> </td></tr>
|
||||||
<tr><td>BlockAscDrivesAfterManual</td><td> </td></tr>
|
<tr><td>BlockAscDrivesAfterManual</td><td> </td></tr>
|
||||||
</table>
|
</table>
|
||||||
</p>
|
|
||||||
<u>Übersicht für das ASC Device Setter</u>
|
|
||||||
<ul>
|
|
||||||
<code>{ ascAPIget('SETTER') }</code><br>
|
|
||||||
</ul>
|
|
||||||
<table>
|
|
||||||
<tr><th>Setter</th><th>Erläuterung</th></tr>
|
|
||||||
<tr><td>AutoAstroModeEvening</td><td> </td></tr>
|
|
||||||
<tr><td>AutoAstroModeEveningHorizon</td><td> </td></tr>
|
|
||||||
<tr><td>AutoAstroModeMorning</td><td> </td></tr>
|
|
||||||
<tr><td>AutoAstroModeMorningHorizon</td><td> </td></tr>
|
|
||||||
<tr><td>AutoShuttersControlMorning</td><td> </td></tr>
|
|
||||||
<tr><td>AutoShuttersControlEvening</td><td> </td></tr>
|
|
||||||
<tr><td>AutoShuttersControlComfort</td><td> </td></tr>
|
|
||||||
<tr><td>FreezeTemp</td><td> </td></tr>
|
|
||||||
<tr><td>BlockAscDrivesAfterManual</td><td> 0,1</td></tr>
|
|
||||||
</table>
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
=end html_DE
|
=end html_DE
|
||||||
@ -1272,7 +1253,7 @@ sub Initialize {
|
|||||||
],
|
],
|
||||||
"release_status": "testing",
|
"release_status": "testing",
|
||||||
"license": "GPL_2",
|
"license": "GPL_2",
|
||||||
"version": "v0.10.1",
|
"version": "v0.10.2",
|
||||||
"author": [
|
"author": [
|
||||||
"Marko Oldenburg <leongaultier@gmail.com>"
|
"Marko Oldenburg <leongaultier@gmail.com>"
|
||||||
],
|
],
|
||||||
|
@ -98,7 +98,7 @@ if ($@) {
|
|||||||
# JSON preference order
|
# JSON preference order
|
||||||
local $ENV{PERL_JSON_BACKEND} =
|
local $ENV{PERL_JSON_BACKEND} =
|
||||||
'Cpanel::JSON::XS,JSON::XS,JSON::PP,JSON::backportPP'
|
'Cpanel::JSON::XS,JSON::XS,JSON::PP,JSON::backportPP'
|
||||||
unless ( defined( $ENV{PERL_JSON_BACKEND} ) );
|
if ( !defined( $ENV{PERL_JSON_BACKEND} ) );
|
||||||
|
|
||||||
require JSON;
|
require JSON;
|
||||||
import JSON qw( decode_json encode_json );
|
import JSON qw( decode_json encode_json );
|
||||||
@ -317,8 +317,7 @@ sub ascAPIset {
|
|||||||
|
|
||||||
if ( defined($shutterDev)
|
if ( defined($shutterDev)
|
||||||
&& $shutterDev
|
&& $shutterDev
|
||||||
&& defined($value)
|
&& defined($value) )
|
||||||
&& $value )
|
|
||||||
{
|
{
|
||||||
$shutters->setShuttersDev($shutterDev);
|
$shutters->setShuttersDev($shutterDev);
|
||||||
$shutters->$setter($value);
|
$shutters->$setter($value);
|
||||||
@ -331,7 +330,7 @@ sub Define {
|
|||||||
my $hash = shift // return;
|
my $hash = shift // return;
|
||||||
my $aArg = shift // return;
|
my $aArg = shift // return;
|
||||||
|
|
||||||
return $@ unless ( FHEM::Meta::SetInternals($hash) );
|
return $@ if ( !FHEM::Meta::SetInternals($hash) );
|
||||||
use version 0.60; our $VERSION = FHEM::Meta::Get( $hash, 'version' );
|
use version 0.60; our $VERSION = FHEM::Meta::Get( $hash, 'version' );
|
||||||
|
|
||||||
return 'only one AutoShuttersControl instance allowed'
|
return 'only one AutoShuttersControl instance allowed'
|
||||||
@ -434,32 +433,30 @@ sub Notify {
|
|||||||
if ( $ascDev->getASCenable eq 'none' );
|
if ( $ascDev->getASCenable eq 'none' );
|
||||||
CommandAttr( undef,
|
CommandAttr( undef,
|
||||||
$name . ' devStateIcon { ShuttersControl_DevStateIcon($name) }' )
|
$name . ' devStateIcon { ShuttersControl_DevStateIcon($name) }' )
|
||||||
unless (
|
if (
|
||||||
AttrVal(
|
AttrVal(
|
||||||
$name, 'devStateIcon',
|
$name, 'devStateIcon',
|
||||||
'{ ShuttersControl_DevStateIcon($name) }'
|
'{ ShuttersControl_DevStateIcon($name) }'
|
||||||
) eq '{ ShuttersControl_DevStateIcon($name) }'
|
) ne '{ ShuttersControl_DevStateIcon($name) }'
|
||||||
);
|
);
|
||||||
CommandDeleteAttr( undef, $name . ' event-on-change-reading' )
|
CommandDeleteAttr( undef, $name . ' event-on-change-reading' )
|
||||||
unless (
|
if ( AttrVal( $name, 'event-on-change-reading', 'none' ) ne 'none' );
|
||||||
AttrVal( $name, 'event-on-change-reading', 'none' ) eq 'none' );
|
|
||||||
CommandDeleteAttr( undef, $name . ' event-on-update-reading' )
|
CommandDeleteAttr( undef, $name . ' event-on-update-reading' )
|
||||||
unless (
|
if ( AttrVal( $name, 'event-on-update-reading', 'none' ) ne 'none' );
|
||||||
AttrVal( $name, 'event-on-update-reading', 'none' ) eq 'none' );
|
|
||||||
|
|
||||||
# Ist der Event ein globaler und passt zum Rest der Abfrage oben wird nach neuen Rolläden Devices gescannt und eine Liste im Rolladenmodul sortiert nach Raum generiert
|
# Ist der Event ein globaler und passt zum Rest der Abfrage oben wird nach neuen Rolläden Devices gescannt und eine Liste im Rolladenmodul sortiert nach Raum generiert
|
||||||
ShuttersDeviceScan($hash)
|
ShuttersDeviceScan($hash)
|
||||||
unless ( ReadingsVal( $name, 'userAttrList', 'none' ) eq 'none' );
|
if ( ReadingsVal( $name, 'userAttrList', 'none' ) ne 'none' );
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
unless ( ref( $hash->{helper}{shuttersList} ) eq 'ARRAY'
|
if ( ref( $hash->{helper}{shuttersList} ) ne 'ARRAY'
|
||||||
&& scalar( @{ $hash->{helper}{shuttersList} } ) > 0 );
|
|| scalar( @{ $hash->{helper}{shuttersList} } ) == 0 );
|
||||||
|
|
||||||
my $posReading = $shutters->getPosCmd;
|
my $posReading = $shutters->getPosCmd;
|
||||||
|
|
||||||
if ( $devname eq $name ) {
|
if ( $devname eq $name ) {
|
||||||
if ( grep m{^userAttrList:.rolled.out$}xms, @{$events} ) {
|
if ( grep m{^userAttrList:.rolled.out$}xms, @{$events} ) {
|
||||||
unless ( scalar( @{ $hash->{helper}{shuttersList} } ) == 0 ) {
|
if ( scalar( @{ $hash->{helper}{shuttersList} } ) > 0 ) {
|
||||||
WriteReadingsShuttersList($hash);
|
WriteReadingsShuttersList($hash);
|
||||||
UserAttributs_Readings_ForShutters( $hash, 'add' );
|
UserAttributs_Readings_ForShutters( $hash, 'add' );
|
||||||
InternalTimer(
|
InternalTimer(
|
||||||
@ -771,7 +768,7 @@ sub ShuttersDeviceScan {
|
|||||||
|
|
||||||
CommandDeleteReading( undef, $name . ' .*_nextAstroTimeEvent' );
|
CommandDeleteReading( undef, $name . ' .*_nextAstroTimeEvent' );
|
||||||
|
|
||||||
unless ( scalar(@list) > 0 ) {
|
if ( scalar(@list) == 0 ) {
|
||||||
readingsBeginUpdate($hash);
|
readingsBeginUpdate($hash);
|
||||||
readingsBulkUpdate( $hash, 'userAttrList', 'none' );
|
readingsBulkUpdate( $hash, 'userAttrList', 'none' );
|
||||||
readingsBulkUpdate( $hash, 'state', 'no shutters found' );
|
readingsBulkUpdate( $hash, 'state', 'no shutters found' );
|
||||||
@ -1229,7 +1226,7 @@ sub EventProcessingWindowRec {
|
|||||||
elsif ($match =~ m{[Oo]pen|false}xms
|
elsif ($match =~ m{[Oo]pen|false}xms
|
||||||
&& $shutters->getSubTyp eq 'threestate' )
|
&& $shutters->getSubTyp eq 'threestate' )
|
||||||
{
|
{
|
||||||
my $posValue = $shutters->getStatus;
|
my $posValue = $shutters->getStatus;
|
||||||
my $setLastDrive;
|
my $setLastDrive;
|
||||||
if ( $ascDev->getAutoShuttersControlComfort eq 'on'
|
if ( $ascDev->getAutoShuttersControlComfort eq 'on'
|
||||||
and
|
and
|
||||||
@ -1273,12 +1270,12 @@ sub EventProcessingRoommate {
|
|||||||
"AutoShuttersControl ($name) - EventProcessingRoommate: $shuttersDev und Events $events"
|
"AutoShuttersControl ($name) - EventProcessingRoommate: $shuttersDev und Events $events"
|
||||||
);
|
);
|
||||||
|
|
||||||
my $getModeUp = $shutters->getModeUp;
|
my $getModeUp = $shutters->getModeUp;
|
||||||
my $getModeDown = $shutters->getModeDown;
|
my $getModeDown = $shutters->getModeDown;
|
||||||
my $getRoommatesStatus = $shutters->getRoommatesStatus;
|
my $getRoommatesStatus = $shutters->getRoommatesStatus;
|
||||||
my $getRoommatesLastStatus = $shutters->getRoommatesLastStatus;
|
my $getRoommatesLastStatus = $shutters->getRoommatesLastStatus;
|
||||||
my $event = $1;
|
my $event = $1;
|
||||||
my $posValue = $shutters->getStatus;
|
my $posValue = $shutters->getStatus;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
( $event eq 'home' || $event eq 'awoken' )
|
( $event eq 'home' || $event eq 'awoken' )
|
||||||
@ -1902,49 +1899,108 @@ sub EventProcessingBrightness {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return EventProcessingShadingBrightness( $hash, $shuttersDev, $events )
|
return EventProcessingShadingBrightness( $hash, $shuttersDev, $events )
|
||||||
unless (
|
if (
|
||||||
(
|
(
|
||||||
$shutters->getDown eq 'brightness'
|
$shutters->getDown ne 'brightness'
|
||||||
|| $shutters->getUp eq 'brightness'
|
&& $shutters->getUp ne 'brightness'
|
||||||
)
|
)
|
||||||
|| (
|
|| (
|
||||||
(
|
(
|
||||||
|
$shutters->getDown eq 'brightness'
|
||||||
|
|| $shutters->getUp eq 'brightness'
|
||||||
|
)
|
||||||
|
&& (
|
||||||
(
|
(
|
||||||
(
|
(
|
||||||
int( gettimeofday() / 86400 ) != int(
|
(
|
||||||
computeAlignTime( '24:00',
|
int( gettimeofday() / 86400 ) == int(
|
||||||
$shutters->getTimeUpEarly ) / 86400
|
computeAlignTime( '24:00',
|
||||||
|
$shutters->getTimeUpEarly ) / 86400
|
||||||
|
)
|
||||||
|
&& (
|
||||||
|
!IsWe()
|
||||||
|
|| (
|
||||||
|
IsWe()
|
||||||
|
&& $ascDev->getSunriseTimeWeHoliday eq 'off'
|
||||||
|
|| (
|
||||||
|
$ascDev->getSunriseTimeWeHoliday eq 'on'
|
||||||
|
&& $shutters->getTimeUpWeHoliday eq
|
||||||
|
'01:25' )
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
&& (
|
|| (
|
||||||
!IsWe()
|
int( gettimeofday() / 86400 ) == int(
|
||||||
|| ( IsWe()
|
computeAlignTime( '24:00',
|
||||||
&& $ascDev->getSunriseTimeWeHoliday eq 'off' )
|
$shutters->getTimeUpWeHoliday ) / 86400
|
||||||
|
)
|
||||||
|
&& IsWe()
|
||||||
|
&& $ascDev->getSunriseTimeWeHoliday eq 'on'
|
||||||
|
&& $shutters->getTimeUpWeHoliday ne '01:25'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
&& int( gettimeofday() / 86400 ) == int(
|
||||||
|
computeAlignTime( '24:00', $shutters->getTimeUpLate ) /
|
||||||
|
86400
|
||||||
|
)
|
||||||
|
|
||||||
|| (
|
|| (
|
||||||
int( gettimeofday() / 86400 ) != int(
|
(
|
||||||
computeAlignTime( '24:00',
|
int( gettimeofday() / 86400 ) != int(
|
||||||
$shutters->getTimeUpWeHoliday ) / 86400
|
computeAlignTime( '24:00',
|
||||||
|
$shutters->getTimeUpEarly ) / 86400
|
||||||
|
)
|
||||||
|
&& (
|
||||||
|
!IsWe()
|
||||||
|
|| (
|
||||||
|
IsWe()
|
||||||
|
&& $ascDev->getSunriseTimeWeHoliday eq 'off'
|
||||||
|
|| (
|
||||||
|
$ascDev->getSunriseTimeWeHoliday eq 'on'
|
||||||
|
&& $shutters->getTimeUpWeHoliday eq
|
||||||
|
'01:25' )
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
&& IsWe()
|
|| (
|
||||||
&& $ascDev->getSunriseTimeWeHoliday eq 'on'
|
int( gettimeofday() / 86400 ) != int(
|
||||||
&& $shutters->getTimeUpWeHoliday eq '01:25'
|
computeAlignTime( '24:00',
|
||||||
|
$shutters->getTimeUpWeHoliday ) / 86400
|
||||||
|
)
|
||||||
|
&& IsWe()
|
||||||
|
&& $ascDev->getSunriseTimeWeHoliday eq 'on'
|
||||||
|
&& $shutters->getTimeUpWeHoliday ne '01:25'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
&& int( gettimeofday() / 86400 ) != int(
|
||||||
|
computeAlignTime( '24:00', $shutters->getTimeUpLate ) /
|
||||||
|
86400
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
&& int( gettimeofday() / 86400 ) == int(
|
&& (
|
||||||
computeAlignTime( '24:00', $shutters->getTimeUpLate ) /
|
(
|
||||||
86400
|
int( gettimeofday() / 86400 ) == int(
|
||||||
|
computeAlignTime(
|
||||||
|
'24:00', $shutters->getTimeDownEarly
|
||||||
|
) / 86400
|
||||||
|
)
|
||||||
|
&& int( gettimeofday() / 86400 ) == int(
|
||||||
|
computeAlignTime( '24:00', $shutters->getTimeDownLate
|
||||||
|
) / 86400
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|| (
|
||||||
|| (
|
int( gettimeofday() / 86400 ) != int(
|
||||||
int( gettimeofday() / 86400 ) != int(
|
computeAlignTime(
|
||||||
computeAlignTime( '24:00', $shutters->getTimeDownEarly ) /
|
'24:00', $shutters->getTimeDownEarly
|
||||||
86400
|
) / 86400
|
||||||
)
|
)
|
||||||
&& int( gettimeofday() / 86400 ) == int(
|
&& int( gettimeofday() / 86400 ) != int(
|
||||||
computeAlignTime( '24:00', $shutters->getTimeDownLate ) /
|
computeAlignTime( '24:00', $shutters->getTimeDownLate
|
||||||
86400
|
) / 86400
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -2089,8 +2145,8 @@ sub EventProcessingBrightness {
|
|||||||
$shutters->setLastDrive('brightness privacy day open');
|
$shutters->setLastDrive('brightness privacy day open');
|
||||||
ShuttersCommandSet( $hash, $shuttersDev,
|
ShuttersCommandSet( $hash, $shuttersDev,
|
||||||
$shutters->getPrivacyUpPos )
|
$shutters->getPrivacyUpPos )
|
||||||
unless (
|
if (
|
||||||
!$shutters->getQueryShuttersPos(
|
$shutters->getQueryShuttersPos(
|
||||||
$shutters->getPrivacyUpPos
|
$shutters->getPrivacyUpPos
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -2166,7 +2222,7 @@ sub EventProcessingBrightness {
|
|||||||
|| $shutters->getModeDown eq 'always'
|
|| $shutters->getModeDown eq 'always'
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
my $posValue = $shutters->getStatus;
|
my $posValue = $shutters->getStatus;
|
||||||
my $lastDrive;
|
my $lastDrive;
|
||||||
|
|
||||||
## Setzt den PrivacyDown Modus für die Sichtschutzfahrt auf den Status 0
|
## Setzt den PrivacyDown Modus für die Sichtschutzfahrt auf den Status 0
|
||||||
@ -2224,8 +2280,8 @@ sub EventProcessingBrightness {
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
$shutters->getPrivacyDownStatus != 2
|
$shutters->getPrivacyDownStatus != 2
|
||||||
&& ( $posValue != $shutters->getStatus
|
# && ( $posValue != $shutters->getStatus
|
||||||
|| $shutters->getSelfDefenseState )
|
# || $shutters->getSelfDefenseState )
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
$shutters->setSunrise(0);
|
$shutters->setSunrise(0);
|
||||||
@ -2243,7 +2299,7 @@ sub EventProcessingBrightness {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
EventProcessingShadingBrightness( $hash, $shuttersDev, $events )
|
EventProcessingShadingBrightness( $hash, $shuttersDev, $events )
|
||||||
unless ( $shutters->getPrivacyDownStatus == 2 );
|
if ( $shutters->getPrivacyDownStatus != 2 );
|
||||||
|
|
||||||
ASC_Debug( 'EventProcessingBrightness: '
|
ASC_Debug( 'EventProcessingBrightness: '
|
||||||
. $shutters->getShuttersDev
|
. $shutters->getShuttersDev
|
||||||
@ -2253,7 +2309,7 @@ sub EventProcessingBrightness {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
EventProcessingShadingBrightness( $hash, $shuttersDev, $events )
|
EventProcessingShadingBrightness( $hash, $shuttersDev, $events )
|
||||||
unless ( $shutters->getPrivacyDownStatus == 2 );
|
if ( $shutters->getPrivacyDownStatus != 2 );
|
||||||
|
|
||||||
ASC_Debug( 'EventProcessingBrightness: '
|
ASC_Debug( 'EventProcessingBrightness: '
|
||||||
. $shutters->getShuttersDev
|
. $shutters->getShuttersDev
|
||||||
@ -2909,13 +2965,13 @@ sub EventProcessingExternalTriggerDevice {
|
|||||||
if ( $1 eq $triggerValActive2 ) {
|
if ( $1 eq $triggerValActive2 ) {
|
||||||
$shutters->setLastDrive('external trigger2 device active');
|
$shutters->setLastDrive('external trigger2 device active');
|
||||||
$shutters->setNoDelay(1);
|
$shutters->setNoDelay(1);
|
||||||
$shutters->setExternalTriggerState(1);
|
$shutters->setExternalTriggerStatus(1);
|
||||||
ShuttersCommandSet( $hash, $shuttersDev, $triggerPosActive2 );
|
ShuttersCommandSet( $hash, $shuttersDev, $triggerPosActive2 );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$shutters->setLastDrive('external trigger device active');
|
$shutters->setLastDrive('external trigger device active');
|
||||||
$shutters->setNoDelay(1);
|
$shutters->setNoDelay(1);
|
||||||
$shutters->setExternalTriggerState(1);
|
$shutters->setExternalTriggerStatus(1);
|
||||||
ShuttersCommandSet( $hash, $shuttersDev, $triggerPosActive );
|
ShuttersCommandSet( $hash, $shuttersDev, $triggerPosActive );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2933,7 +2989,7 @@ sub EventProcessingExternalTriggerDevice {
|
|||||||
|
|
||||||
$shutters->setLastDrive('external trigger device inactive');
|
$shutters->setLastDrive('external trigger device inactive');
|
||||||
$shutters->setNoDelay(1);
|
$shutters->setNoDelay(1);
|
||||||
$shutters->setExternalTriggerState(1);
|
$shutters->setExternalTriggerStatus(1);
|
||||||
ShuttersCommandSet(
|
ShuttersCommandSet(
|
||||||
$hash,
|
$hash,
|
||||||
$shuttersDev,
|
$shuttersDev,
|
||||||
@ -2960,7 +3016,6 @@ sub ShuttersCommandSet {
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
(
|
(
|
||||||
# $posValue == $shutters->getShadingPos &&
|
|
||||||
CheckIfShuttersWindowRecOpen($shuttersDev) == 2
|
CheckIfShuttersWindowRecOpen($shuttersDev) == 2
|
||||||
&& $shutters->getShuttersPlace eq 'terrace'
|
&& $shutters->getShuttersPlace eq 'terrace'
|
||||||
&& ( $shutters->getLockOut eq 'soft'
|
&& ( $shutters->getLockOut eq 'soft'
|
||||||
@ -2968,8 +3023,6 @@ sub ShuttersCommandSet {
|
|||||||
&& !$shutters->getQueryShuttersPos($posValue)
|
&& !$shutters->getQueryShuttersPos($posValue)
|
||||||
)
|
)
|
||||||
|| (
|
|| (
|
||||||
# $posValue != $shutters->getShadingPos
|
|
||||||
# && (
|
|
||||||
(
|
(
|
||||||
$shutters->getPartyMode eq 'on'
|
$shutters->getPartyMode eq 'on'
|
||||||
&& $ascDev->getPartyMode eq 'on'
|
&& $ascDev->getPartyMode eq 'on'
|
||||||
@ -2999,9 +3052,7 @@ sub ShuttersCommandSet {
|
|||||||
&& $shutters->getShuttersPlace eq 'terrace'
|
&& $shutters->getShuttersPlace eq 'terrace'
|
||||||
&& !$shutters->getQueryShuttersPos($posValue) )
|
&& !$shutters->getQueryShuttersPos($posValue) )
|
||||||
|| ( $shutters->getRainProtectionStatus eq 'protected'
|
|| ( $shutters->getRainProtectionStatus eq 'protected'
|
||||||
&& $shutters->getWindProtectionStatus eq 'protected' )
|
|| $shutters->getWindProtectionStatus eq 'protected' )
|
||||||
|
|
||||||
# )
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -3034,9 +3085,10 @@ sub ShuttersCommandSet {
|
|||||||
|
|
||||||
## Sub welche die InternalTimer nach entsprechenden Sunset oder Sunrise zusammen stellt
|
## Sub welche die InternalTimer nach entsprechenden Sunset oder Sunrise zusammen stellt
|
||||||
sub CreateSunRiseSetShuttersTimer {
|
sub CreateSunRiseSetShuttersTimer {
|
||||||
my $hash = shift;
|
my $hash = shift;
|
||||||
my $shuttersDev = shift // return Log3( $hash->{NAME}, 1,
|
my $shuttersDev = shift // return Log3( $hash->{NAME}, 1,
|
||||||
"AutoShuttersControl ($hash->{NAME}) - Error in function CreateSunRiseSetShuttersTimer. No shuttersDev given");
|
"AutoShuttersControl ($hash->{NAME}) - Error in function CreateSunRiseSetShuttersTimer. No shuttersDev given"
|
||||||
|
);
|
||||||
|
|
||||||
my $name = $hash->{NAME};
|
my $name = $hash->{NAME};
|
||||||
my $shuttersDevHash = $defs{$shuttersDev};
|
my $shuttersDevHash = $defs{$shuttersDev};
|
||||||
@ -3102,7 +3154,7 @@ sub CreateSunRiseSetShuttersTimer {
|
|||||||
if ( defined( $shutters->getInTimerFuncHash ) );
|
if ( defined( $shutters->getInTimerFuncHash ) );
|
||||||
|
|
||||||
## Setzt den Privacy Modus für die Sichtschutzfahrt auf den Status 0
|
## Setzt den Privacy Modus für die Sichtschutzfahrt auf den Status 0
|
||||||
## 1 bedeutet das PrivacyDown Timer aktiviert wurde, 2 beudet das er im privacyDown ist
|
## 1 bedeutet das Privacy Timer aktiviert wurde, 2 beudet das er im privacy ist
|
||||||
## also das Rollo in privacy Position steht und VOR der endgültigen Nacht oder Tagfahrt
|
## also das Rollo in privacy Position steht und VOR der endgültigen Nacht oder Tagfahrt
|
||||||
$shutters->setPrivacyUpStatus(0)
|
$shutters->setPrivacyUpStatus(0)
|
||||||
if ( !defined( $shutters->getPrivacyUpStatus ) );
|
if ( !defined( $shutters->getPrivacyUpStatus ) );
|
||||||
@ -3355,8 +3407,8 @@ sub SunSetShuttersAfterTimerFn {
|
|||||||
$shutters->setLastDrive('timer privacy night close');
|
$shutters->setLastDrive('timer privacy night close');
|
||||||
ShuttersCommandSet( $hash, $shuttersDev,
|
ShuttersCommandSet( $hash, $shuttersDev,
|
||||||
$shutters->getPrivacyDownPos )
|
$shutters->getPrivacyDownPos )
|
||||||
unless (
|
if (
|
||||||
$shutters->getQueryShuttersPos( $shutters->getPrivacyDownPos )
|
!$shutters->getQueryShuttersPos( $shutters->getPrivacyDownPos )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -3378,7 +3430,7 @@ sub SunSetShuttersAfterTimerFn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unless ( $shutters->getPrivacyDownStatus == 2 ) {
|
if ( $shutters->getPrivacyDownStatus != 2 ) {
|
||||||
$shutters->setSunrise(0);
|
$shutters->setSunrise(0);
|
||||||
$shutters->setSunset(1);
|
$shutters->setSunset(1);
|
||||||
}
|
}
|
||||||
@ -3456,8 +3508,8 @@ sub SunRiseShuttersAfterTimerFn {
|
|||||||
$shutters->setLastDrive('timer privacy day open');
|
$shutters->setLastDrive('timer privacy day open');
|
||||||
ShuttersCommandSet( $hash, $shuttersDev,
|
ShuttersCommandSet( $hash, $shuttersDev,
|
||||||
$shutters->getPrivacyUpPos )
|
$shutters->getPrivacyUpPos )
|
||||||
unless (
|
if (
|
||||||
!$shutters->getQueryShuttersPos(
|
$shutters->getQueryShuttersPos(
|
||||||
$shutters->getPrivacyUpPos
|
$shutters->getPrivacyUpPos
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -3482,7 +3534,7 @@ sub SunRiseShuttersAfterTimerFn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unless ( $shutters->getPrivacyUpStatus == 2 ) {
|
if ( $shutters->getPrivacyUpStatus != 2 ) {
|
||||||
$shutters->setSunrise(1);
|
$shutters->setSunrise(1);
|
||||||
$shutters->setSunset(0);
|
$shutters->setSunset(0);
|
||||||
}
|
}
|
||||||
@ -4559,11 +4611,11 @@ sub _SetCmdFn {
|
|||||||
my $idleDetection = $shutters->getIdleDetection;
|
my $idleDetection = $shutters->getIdleDetection;
|
||||||
|
|
||||||
return
|
return
|
||||||
unless (
|
if (
|
||||||
$shutters->getASCenable eq 'on'
|
$shutters->getASCenable eq 'off'
|
||||||
&& $ascDev->getASCenable eq 'on'
|
&& $ascDev->getASCenable eq 'off'
|
||||||
&& ( $idleDetection =~ m{^$idleDetectionValue$}xms
|
&& ( $idleDetection !~ m{^$idleDetectionValue$}xms
|
||||||
|| $idleDetection eq 'none' )
|
|| $idleDetection ne 'none' )
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( $shutters->getStatus != $posValue ) {
|
if ( $shutters->getStatus != $posValue ) {
|
||||||
@ -4642,63 +4694,32 @@ sub _SetCmdFn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $ascDev->getSlatDriveCmdInverse
|
CommandSet( undef,
|
||||||
&& $slatPos > -1
|
|
||||||
&& $shutters->getSlatPosCmd ne 'none' )
|
|
||||||
{
|
|
||||||
CommandSet(
|
|
||||||
undef,
|
|
||||||
(
|
|
||||||
$shutters->getSlatDevice ne 'none'
|
|
||||||
? $shutters->getSlatDevice
|
|
||||||
: $shuttersDev
|
|
||||||
)
|
|
||||||
. ' '
|
|
||||||
. $shutters->getSlatPosCmd . ' '
|
|
||||||
. $slatPos
|
|
||||||
);
|
|
||||||
|
|
||||||
InternalTimer(
|
|
||||||
gettimeofday() + 3,
|
|
||||||
sub() {
|
|
||||||
CommandSet( undef,
|
|
||||||
$shuttersDev
|
|
||||||
. ':FILTER='
|
|
||||||
. $shutters->getPosCmd . '!='
|
|
||||||
. $posValue . ' '
|
|
||||||
. $driveCommand );
|
|
||||||
},
|
|
||||||
$shuttersDev
|
$shuttersDev
|
||||||
);
|
. ':FILTER='
|
||||||
}
|
. $shutters->getPosCmd . '!='
|
||||||
else {
|
. $posValue . ' '
|
||||||
CommandSet( undef,
|
. $driveCommand );
|
||||||
$shuttersDev
|
|
||||||
. ':FILTER='
|
|
||||||
. $shutters->getPosCmd . '!='
|
|
||||||
. $posValue . ' '
|
|
||||||
. $driveCommand );
|
|
||||||
|
|
||||||
InternalTimer(
|
InternalTimer(
|
||||||
gettimeofday() + 3,
|
gettimeofday() + 3,
|
||||||
sub() {
|
sub() {
|
||||||
CommandSet(
|
CommandSet(
|
||||||
undef,
|
undef,
|
||||||
(
|
(
|
||||||
$shutters->getSlatDevice ne 'none'
|
$shutters->getSlatDevice ne 'none'
|
||||||
? $shutters->getSlatDevice
|
? $shutters->getSlatDevice
|
||||||
: $shuttersDev
|
: $shuttersDev
|
||||||
)
|
)
|
||||||
. ' '
|
. ' '
|
||||||
. $shutters->getSlatPosCmd . ' '
|
. $shutters->getSlatPosCmd . ' '
|
||||||
. $slatPos
|
. $slatPos
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
$shuttersDev
|
$shuttersDev
|
||||||
)
|
)
|
||||||
if ( $slatPos > -1
|
if ( $slatPos > -1
|
||||||
&& $shutters->getSlatPosCmd ne 'none' );
|
&& $shutters->getSlatPosCmd ne 'none' );
|
||||||
}
|
|
||||||
|
|
||||||
$shutters->setSelfDefenseAbsent( 0, 0 )
|
$shutters->setSelfDefenseAbsent( 0, 0 )
|
||||||
if (!$shutters->getSelfDefenseAbsent
|
if (!$shutters->getSelfDefenseAbsent
|
||||||
@ -4721,7 +4742,7 @@ sub _setShuttersLastDriveDelayed {
|
|||||||
|
|
||||||
sub ASC_Debug {
|
sub ASC_Debug {
|
||||||
return
|
return
|
||||||
unless ( AttrVal( $ascDev->getName, 'ASC_debug', 0 ) );
|
if ( !AttrVal( $ascDev->getName, 'ASC_debug', 0 ) );
|
||||||
|
|
||||||
my $debugMsg = shift;
|
my $debugMsg = shift;
|
||||||
my $debugTimestamp = strftime( "%Y.%m.%e %T", localtime(time) );
|
my $debugTimestamp = strftime( "%Y.%m.%e %T", localtime(time) );
|
||||||
@ -4773,7 +4794,7 @@ sub PrivacyUpTime {
|
|||||||
strftime( "%e.%m.%Y - %H:%M", localtime($privacyUpUnixtime) ), 1 );
|
strftime( "%e.%m.%Y - %H:%M", localtime($privacyUpUnixtime) ), 1 );
|
||||||
## Setzt den PrivacyUp Modus für die Sichtschutzfahrt auf den Status 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
|
## und gibt die Unixtime für die nächste Fahrt korrekt zurück
|
||||||
unless ( $shutters->getPrivacyUpStatus == 2 ) {
|
if ( $shutters->getPrivacyUpStatus != 2 ) {
|
||||||
$shutters->setPrivacyUpStatus(1);
|
$shutters->setPrivacyUpStatus(1);
|
||||||
$shuttersSunriseUnixtime = $privacyUpUnixtime;
|
$shuttersSunriseUnixtime = $privacyUpUnixtime;
|
||||||
}
|
}
|
||||||
@ -4817,7 +4838,7 @@ sub PrivacyDownTime {
|
|||||||
1 );
|
1 );
|
||||||
## Setzt den PrivacyDown Modus für die Sichtschutzfahrt auf den Status 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
|
## und gibt die Unixtime für die nächste Fahrt korrekt zurück
|
||||||
unless ( $shutters->getPrivacyDownStatus == 2 ) {
|
if ( $shutters->getPrivacyDownStatus != 2 ) {
|
||||||
$shutters->setPrivacyDownStatus(1);
|
$shutters->setPrivacyDownStatus(1);
|
||||||
$shuttersSunsetUnixtime = $privacyDownUnixtime;
|
$shuttersSunsetUnixtime = $privacyDownUnixtime;
|
||||||
}
|
}
|
||||||
@ -4964,7 +4985,6 @@ sub _CheckShuttersConditionsForShadingFn {
|
|||||||
my $warnMessage;
|
my $warnMessage;
|
||||||
my $infoMessage;
|
my $infoMessage;
|
||||||
|
|
||||||
|
|
||||||
$infoMessage .= (
|
$infoMessage .= (
|
||||||
$shutters->getShadingMode ne 'off'
|
$shutters->getShadingMode ne 'off'
|
||||||
&& $ascDev->getAutoShuttersControlShading eq 'on'
|
&& $ascDev->getAutoShuttersControlShading eq 'on'
|
||||||
|
@ -168,7 +168,7 @@ sub setDriveCmd {
|
|||||||
$posValue)
|
$posValue)
|
||||||
&& !$FHEM::Automation::ShuttersControl::shutters->getAdvDelay
|
&& !$FHEM::Automation::ShuttersControl::shutters->getAdvDelay
|
||||||
&& !$FHEM::Automation::ShuttersControl::shutters
|
&& !$FHEM::Automation::ShuttersControl::shutters
|
||||||
->getExternalTriggerState
|
->getExternalTriggerStatus
|
||||||
&& !$FHEM::Automation::ShuttersControl::shutters
|
&& !$FHEM::Automation::ShuttersControl::shutters
|
||||||
->getSelfDefenseState
|
->getSelfDefenseState
|
||||||
)
|
)
|
||||||
@ -177,9 +177,9 @@ sub setDriveCmd {
|
|||||||
$FHEM::Automation::ShuttersControl::shutters->setDelayCmd($posValue);
|
$FHEM::Automation::ShuttersControl::shutters->setDelayCmd($posValue);
|
||||||
$FHEM::Automation::ShuttersControl::ascDev->setDelayCmdReading;
|
$FHEM::Automation::ShuttersControl::ascDev->setDelayCmdReading;
|
||||||
$FHEM::Automation::ShuttersControl::shutters->setNoDelay(0);
|
$FHEM::Automation::ShuttersControl::shutters->setNoDelay(0);
|
||||||
$FHEM::Automation::ShuttersControl::shutters->setExternalTriggerState(0)
|
$FHEM::Automation::ShuttersControl::shutters->setExternalTriggerStatus(0)
|
||||||
if ( $FHEM::Automation::ShuttersControl::shutters
|
if ( $FHEM::Automation::ShuttersControl::shutters
|
||||||
->getExternalTriggerState );
|
->getExternalTriggerStatus );
|
||||||
|
|
||||||
FHEM::Automation::ShuttersControl::ASC_Debug( 'setDriveCmd: '
|
FHEM::Automation::ShuttersControl::ASC_Debug( 'setDriveCmd: '
|
||||||
. $FHEM::Automation::ShuttersControl::shutters->getShuttersDev
|
. $FHEM::Automation::ShuttersControl::shutters->getShuttersDev
|
||||||
@ -193,9 +193,9 @@ sub setDriveCmd {
|
|||||||
if ( $FHEM::Automation::ShuttersControl::shutters->getDelayCmd ne
|
if ( $FHEM::Automation::ShuttersControl::shutters->getDelayCmd ne
|
||||||
'none' )
|
'none' )
|
||||||
; # setzt den Wert auf none da der Rolladen nun gesteuert werden kann.
|
; # setzt den Wert auf none da der Rolladen nun gesteuert werden kann.
|
||||||
$FHEM::Automation::ShuttersControl::shutters->setExternalTriggerState(0)
|
$FHEM::Automation::ShuttersControl::shutters->setExternalTriggerStatus(0)
|
||||||
if ( $FHEM::Automation::ShuttersControl::shutters
|
if ( $FHEM::Automation::ShuttersControl::shutters
|
||||||
->getExternalTriggerState );
|
->getExternalTriggerStatus );
|
||||||
|
|
||||||
### antifreeze Routine
|
### antifreeze Routine
|
||||||
if ( $FHEM::Automation::ShuttersControl::shutters->getAntiFreezeStatus >
|
if ( $FHEM::Automation::ShuttersControl::shutters->getAntiFreezeStatus >
|
||||||
@ -453,6 +453,20 @@ sub setAdvDelay {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub getExternalTriggerStatus {
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
return (
|
||||||
|
(
|
||||||
|
defined(
|
||||||
|
$self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}->{event}
|
||||||
|
)
|
||||||
|
and
|
||||||
|
$self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}->{event}
|
||||||
|
) ? 1 : 0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
sub getHomemode {
|
sub getHomemode {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
@ -872,7 +886,7 @@ sub setRainProtectionStatus { # Werte protected, unprotected
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub setExternalTriggerState {
|
sub setExternalTriggerStatus {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $value = shift;
|
my $value = shift;
|
||||||
|
|
||||||
|
@ -110,9 +110,10 @@ sub _getPosition {
|
|||||||
);
|
);
|
||||||
|
|
||||||
$posAssignment = (
|
$posAssignment = (
|
||||||
$posAssignment =~ m{\A\d+(\.\d+)?\z}xms
|
defined($posAssignment)
|
||||||
? $posAssignment
|
&& $posAssignment =~ m{\A\d+(\.\d+)?\z}xms
|
||||||
: 'none'
|
? $posAssignment
|
||||||
|
: 'none'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -1198,20 +1199,6 @@ sub getExternalTriggerPosInactive {
|
|||||||
->{posinactive};
|
->{posinactive};
|
||||||
}
|
}
|
||||||
|
|
||||||
sub getExternalTriggerState {
|
|
||||||
my $self = shift;
|
|
||||||
|
|
||||||
return (
|
|
||||||
(
|
|
||||||
defined(
|
|
||||||
$self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}->{event}
|
|
||||||
)
|
|
||||||
and
|
|
||||||
$self->{ $self->{shuttersDev} }->{ASC_ExternalTrigger}->{event}
|
|
||||||
) ? 1 : 0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub setDelay {
|
sub setDelay {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $attrVal = shift;
|
my $attrVal = shift;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user