2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-01-31 06:39:11 +00:00

98_monitoring: packeged version

git-svn-id: https://svn.fhem.de/fhem/trunk@26025 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
Beta-User 2022-05-06 05:46:06 +00:00
parent 6dffd61ce4
commit 705981ce71
3 changed files with 145 additions and 68 deletions

View File

@ -1,5 +1,6 @@
# 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.
- change: 98_monitoring: now packaged
- change: 50_Signalbot: send message box, 0.10.5 group functions - change: 50_Signalbot: send message box, 0.10.5 group functions
- bugfix: 32_withings: fixed sessionkey retrieval - bugfix: 32_withings: fixed sessionkey retrieval
- bugfix: 70_SVDRP: handle timers with german Umlaute - bugfix: 70_SVDRP: handle timers with german Umlaute

View File

@ -1,6 +1,6 @@
# Id ########################################################################## ##########################################################################
# $Id$ # $Id$
#
# copyright ################################################################### # copyright ###################################################################
# #
# 98_monitoring.pm # 98_monitoring.pm
@ -22,48 +22,88 @@
# FHEM. If not, see <http://www.gnu.org/licenses/>. # FHEM. If not, see <http://www.gnu.org/licenses/>.
# packages #################################################################### # packages ####################################################################
package main; package FHEM::Automation::monitoring; ##no critic qw(Package)
use strict; use strict;
use warnings; use warnings;
use Carp qw(carp);
use Scalar::Util qw(looks_like_number);
use Time::HiRes qw(gettimeofday);
use GPUtils qw(GP_Import);
sub ::monitoring_Initialize { goto &Initialize }
BEGIN {
GP_Import( qw(
readingsSingleUpdate
readingsBeginUpdate
readingsBulkUpdate
readingsEndUpdate
Log3 fhem
defs attr
DAYSECONDS HOURSECONDS MINUTESECONDS
init_done
InternalTimer
RemoveInternalTimer
readingFnAttributes
IsDisabled
AttrVal
InternalVal
ReadingsVal
ReadingsNum
devspec2array
AnalyzeCommandChain
AnalyzeCommand
EvalSpecials
AnalyzePerlCommand
perlSyntaxCheck
FmtDateTime time_str2num
notifyRegexpChanged
deviceEvents
) )
};
# initialize ################################################################## # initialize ##################################################################
sub monitoring_Initialize { sub Initialize {
my $hash = shift // return; my $hash = shift // return;
my $TYPE = "monitoring";
$hash->{DefFn} = $TYPE."_Define"; $hash->{DefFn} = \&Define;
$hash->{UndefFn} = $TYPE."_Undefine"; $hash->{UndefFn} = \&Undefine;
$hash->{SetFn} = $TYPE."_Set"; $hash->{DeleteFn} = \&Delete;
$hash->{GetFn} = $TYPE."_Get"; #$hash->{RenameFn} = \&Rename;
$hash->{AttrFn} = $TYPE."_Attr"; $hash->{SetFn} = \&Set;
$hash->{NotifyFn} = $TYPE."_Notify"; $hash->{GetFn} = \&Get;
$hash->{AttrFn} = \&Attr;
$hash->{NotifyFn} = \&Notify;
$hash->{AttrList} =
"addStateEvent:1,0 ". $hash->{AttrList} =
"blacklist:textField-long ". "addStateEvent:1,0 ".
"disable:1,0 ". "blacklist:textField-long ".
"disabledForIntervals ". "disable:1,0 ".
"errorFuncAdd:textField-long ". "disabledForIntervals ".
"errorFuncAdded:textField-long ". "errorFuncAdd:textField-long ".
"errorFuncRemove:textField-long ". "errorFuncAdded:textField-long ".
"errorWait ". "errorFuncRemove:textField-long ".
"errorReturn:textField-long ". "errorWait ".
"getDefault:all,error,warning ". "errorReturn:textField-long ".
"setActiveFunc:textField-long ". "getDefault:all,error,warning ".
"setInactiveFunc:textField-long ". "setActiveFunc:textField-long ".
"warningFuncAdd:textField-long ". "setInactiveFunc:textField-long ".
"warningFuncAdded:textField-long ". "warningFuncAdd:textField-long ".
"warningFuncRemove:textField-long ". "warningFuncAdded:textField-long ".
"warningWait ". "warningFuncRemove:textField-long ".
"warningReturn:textField-long ". "warningWait ".
"whitelist:textField-long ". "warningReturn:textField-long ".
$readingFnAttributes "whitelist:textField-long ".
; $readingFnAttributes;
return; return;
} }
# regular Fn ################################################################## # regular Fn ##################################################################
sub monitoring_Define { sub Define {
my $hash = shift // return; my $hash = shift // return;
my $def = shift // return; my $def = shift // return;
my ($SELF, $TYPE, @re) = split m{\s+}xms, $def, 5; my ($SELF, $TYPE, @re) = split m{\s+}xms, $def, 5;
@ -72,21 +112,21 @@ sub monitoring_Define {
if( !@re || @re > 2); if( !@re || @re > 2);
monitoring_NOTIFYDEV($hash) if !$init_done; monitoring_NOTIFYDEV($hash) if !$init_done;
monitoring_setActive($hash) if $init_done; setActive($hash) if $init_done;
return; return;
} }
sub monitoring_Undefine { sub Undefine {
my $hash = shift // return; my $hash = shift // return;
monitoring_setInactive($hash); setInactive($hash);
monitoring_RemoveInternalTimer($hash); monitoring_RemoveInternalTimer($hash);
return; return;
} }
sub monitoring_Set { sub Set {
my ($hash, @arr) = @_; my ($hash, @arr) = @_;
my $TYPE = $hash->{TYPE}; my $TYPE = $hash->{TYPE};
@ -112,10 +152,10 @@ sub monitoring_Set {
if !exists $monitoring_sets{$argument}; if !exists $monitoring_sets{$argument};
if ( $argument eq 'active' ) { if ( $argument eq 'active' ) {
return monitoring_setActive($hash); return setActive($hash);
} }
if ( $argument eq 'inactive' ) { if ( $argument eq 'inactive' ) {
monitoring_setInactive($hash); setInactive($hash);
readingsSingleUpdate($hash, 'state', $argument, 0); readingsSingleUpdate($hash, 'state', $argument, 0);
Log3($SELF, 3, "$SELF ($TYPE) set $SELF inactive"); Log3($SELF, 3, "$SELF ($TYPE) set $SELF inactive");
@ -163,7 +203,7 @@ sub monitoring_Set {
return; return;
} }
sub monitoring_Get { sub Get {
my ($hash, @arr) = @_; my ($hash, @arr) = @_;
my $TYPE = $hash->{TYPE}; my $TYPE = $hash->{TYPE};
my $SELF = shift @arr; my $SELF = shift @arr;
@ -196,12 +236,12 @@ sub monitoring_Get {
elsif($argument eq 'error' || $argument eq 'warning') { elsif($argument eq 'error' || $argument eq 'warning') {
push @ret, monitoring_return($hash, $argument); push @ret, monitoring_return($hash, $argument);
} }
@ret = grep { defined } @ret; #prevent uninitialized warnings
return join("\n\n", @ret)."\n" if @ret; return join ("\n\n", @ret)."\n" if @ret;
return; return;
} }
sub monitoring_Attr { sub Attr {
my ($cmd, $SELF, $attribute, $value) = @_; my ($cmd, $SELF, $attribute, $value) = @_;
my $hash = $defs{$SELF} // return; my $hash = $defs{$SELF} // return;
@ -228,15 +268,15 @@ sub monitoring_Attr {
for my $list ( qw(warning error) ){ for my $list ( qw(warning error) ){
for my $name ( split m{,}x, ReadingsVal($SELF, $list, '') ) { for my $name ( split m{,}x, ReadingsVal($SELF, $list, '') ) {
monitoring_modify("$SELF|$list|remove|$name") monitoring_modify("$SELF|$list|remove|$name")
if !grep {m/$name/} @whitelist; if !grep {m{$name}x} @whitelist;
} }
} }
} }
elsif($attribute eq 'disable'){ elsif($attribute eq 'disable'){
if($cmd eq 'set' and $value == 1){ if($cmd eq 'set' and $value == 1){
return monitoring_setActive($hash); return setActive($hash);
} }
monitoring_setInactive($hash); setInactive($hash);
readingsSingleUpdate($hash, 'state', 'disabled', 0); readingsSingleUpdate($hash, 'state', 'disabled', 0);
Log3($SELF, 3, "$hash->{TYPE} ($SELF) attr $SELF disabled"); Log3($SELF, 3, "$hash->{TYPE} ($SELF) attr $SELF disabled");
} }
@ -244,7 +284,7 @@ sub monitoring_Attr {
return; return;
} }
sub monitoring_Notify { sub Notify {
my $hash = shift // return; my $hash = shift // return;
my $dev_hash = shift // return; my $dev_hash = shift // return;
my $SELF = $hash->{NAME}; my $SELF = $hash->{NAME};
@ -262,8 +302,8 @@ sub monitoring_Notify {
return if !$events; return if !$events;
if($name eq 'global' && 'INITIALIZED|REREADCFG' =~ m/\Q@{$events}\E/){ if($name eq 'global' && 'INITIALIZED|REREADCFG' =~ m{\Q@{$events}\E}x){
monitoring_setActive($hash); setActive($hash);
return; return;
} }
@ -283,32 +323,43 @@ sub monitoring_Notify {
push @blacklist, devspec2array($_) push @blacklist, devspec2array($_)
for (split m{[\s]+}x, AttrVal($SELF, 'blacklist', '')); for (split m{[\s]+}x, AttrVal($SELF, 'blacklist', ''));
return if @blacklist && grep {/$name/} @blacklist; return if @blacklist && grep { m{$name}x } @blacklist;
my @whitelist; my @whitelist;
push @whitelist, devspec2array($_) push @whitelist, devspec2array($_)
for (split m{[\s]+}x, AttrVal($SELF, 'whitelist', '')); for (split m{[\s]+}x, AttrVal($SELF, 'whitelist', ''));
return if @whitelist && !grep {/$name/} @whitelist; return if @whitelist && !grep { m{$name}x } @whitelist;
for my $event (@{$events}){ for my $event (@{$events}){
next if !$event; next if !$event;
my $addMatch = "$name:$event" =~ m{\A$addRegex\z}xms; my $addMatch = "$name:$event" =~ m{\A$addRegex\z}xms;
my $removeMatch = $removeRegex ? "$name:$event" =~ m{\A$removeRegex\z}xms : 0; my $removeMatch = $removeRegex ? "$name:$event" =~ m{\A$removeRegex\z}xms : 0;
#Log3($hash, 3, "monitoring_notify called with add $addMatch and remove $removeMatch"); #Log3($hash, 3, "notify called with add $addMatch and remove $removeMatch");
#next unless(defined($event) && ($addMatch || $removeMatch)); #next unless(defined($event) && ($addMatch || $removeMatch));
next if !$addMatch && !$removeMatch; next if !$addMatch && !$removeMatch;
#Log3($hash, 3, "monitoring_notify unless 1 replacement passed w. $addMatch and remove $removeMatch"); #Log3($hash, 3, "notify unless 1 replacement passed w. $addMatch and remove $removeMatch");
Log3($SELF, 4 , "$TYPE ($SELF) triggered by \"$name $event\""); Log3($SELF, 4 , "$TYPE ($SELF) triggered by \"$name $event\"");
for my $list ( qw (error warning) ){ for my $list ( qw (error warning) ){
my $listFuncAdd = AttrVal($SELF, $list.'FuncAdd', 'preset'); my $listFuncAdd = AttrVal($SELF, $list.'FuncAdd', 'preset');
my $listFuncRemove = AttrVal($SELF, $list.'FuncRemove', 'preset'); my $listFuncRemove = AttrVal($SELF, $list.'FuncRemove', 'preset');
my $listWait = eval(AttrVal($SELF, $list.'Wait', 0)); #my $listWait = eval(AttrVal($SELF, $list.'Wait', 0));
my $cmd = AttrVal($SELF, $list.'Wait', 0);
my %specials = (
'$name' => $name, #Name des Event auslösenden Gerätes
'$SELF' => $SELF, #Eigenname des monitoring
);
$cmd = EvalSpecials($cmd, %specials);
# CMD ausführen
my $listWait = AnalyzePerlCommand( $hash, $cmd );
$listWait = 0 if !looks_like_number($listWait); $listWait = 0 if !looks_like_number($listWait);
if ( $listFuncAdd eq 'preset' && $listFuncRemove eq 'preset' ) { if ( $listFuncAdd eq 'preset' && $listFuncRemove eq 'preset' ) {
@ -378,9 +429,17 @@ sub monitoring_Notify {
$listFuncRemove = 1 if $listFuncRemove eq 'preset' && $removeMatch; $listFuncRemove = 1 if $listFuncRemove eq 'preset' && $removeMatch;
} }
$listFuncAdd = eval($listFuncAdd) if $listFuncAdd =~ /^\{.*\}$/s; #$listFuncAdd = eval($listFuncAdd) if $listFuncAdd =~ /^\{.*\}$/s;
$listFuncRemove = eval($listFuncRemove) if ( $listFuncAdd =~ m{\A\{.*\}\z}xs ) {
if($listFuncRemove =~ /^\{.*\}$/s); $listFuncAdd = EvalSpecials($listFuncAdd, %specials);
# CMD ausführen
$listFuncAdd = AnalyzePerlCommand( $hash, $listFuncAdd)
};
if($listFuncRemove =~ m{\A\{.*\}\z}xs ) {
$listFuncRemove = EvalSpecials($listFuncRemove, %specials);
$listFuncRemove = AnalyzePerlCommand($hash, $listFuncRemove)
}
monitoring_modify("$SELF|$list|remove|$name") monitoring_modify("$SELF|$list|remove|$name")
if $listFuncRemove && $listFuncRemove eq '1'; if $listFuncRemove && $listFuncRemove eq '1';
@ -402,7 +461,11 @@ sub monitoring_modify {
return if IsDisabled($SELF); return if IsDisabled($SELF);
my $at; my $at;
$at = eval($wait + gettimeofday()) if $wait && $wait ne 'quiet'; #$at = eval($wait + gettimeofday()) if $wait && $wait ne 'quiet';
if ( $wait && $wait ne 'quiet' ) {
$at = looks_like_number($wait) ? $wait : AnalyzeCommandChain($hash, $wait);
$at +=gettimeofday();
}
my $TYPE = $hash->{TYPE}; my $TYPE = $hash->{TYPE};
my (@change, %readings); my (@change, %readings);
%readings = map{ $_ => 1 } split m{,}xms, ReadingsVal($SELF, $list, ''); %readings = map{ $_ => 1 } split m{,}xms, ReadingsVal($SELF, $list, '');
@ -421,14 +484,14 @@ sub monitoring_modify {
if ( $operation eq 'add' ) { if ( $operation eq 'add' ) {
return if return if
$readings{$value} || $readings{$value} ||
ReadingsVal($SELF, 'error', '') =~ m/(?:^|,)$value(?:,|$)/ ReadingsVal($SELF, 'error', '') =~ m{(?:^|,)$value(?:,|$)}x
; ;
if ( $at ){ if ( $at ){
return if $hash->{READINGS}{$reading}; return if $hash->{READINGS}{$reading};
readingsSingleUpdate($hash, $reading, FmtDateTime($at), 0); readingsSingleUpdate($hash, $reading, FmtDateTime($at), 0);
InternalTimer($at, 'monitoring_modify', $arg); InternalTimer($at, \&monitoring_modify, $arg);
return; return;
} }
@ -455,7 +518,13 @@ sub monitoring_modify {
if ($operation eq 'add') { if ($operation eq 'add') {
my $name = $value; my $name = $value;
my $listFuncAdded = AttrVal($SELF, $list.'FuncAdded', ''); my $listFuncAdded = AttrVal($SELF, $list.'FuncAdded', '');
$listFuncAdded = $listFuncAdded =~ /^\{.*\}$/s ? eval($listFuncAdded) : fhem($listFuncAdded); my %specials = (
'$name' => $name, #Name des Event auslösenden Gerätes
'$SELF' => $SELF, #Eigenname des monitoring
);
$listFuncAdded = EvalSpecials($listFuncAdded, %specials);
$listFuncAdded = AnalyzeCommandChain($hash, $listFuncAdded);
#$listFuncAdded = $listFuncAdded =~ /^\{.*\}$/s ? eval($listFuncAdded) : fhem($listFuncAdded);
} }
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
@ -506,10 +575,15 @@ sub monitoring_return {
$ret = '"$list: $value"' if !$ret && $value; $ret = '"$list: $value"' if !$ret && $value;
return if !$ret; return if !$ret;
return eval($ret); #return ;
if ( !eval{ $ret = eval($ret) ; 1 } ) { ##no critic qw(StringyEval)
return Log3($hash->{NAME}, 1, "Evaluation error: $@");
}
return $ret;
} }
sub monitoring_setActive { sub setActive {
my $hash = shift // return; my $hash = shift // return;
my $SELF = $hash->{NAME} // return; my $SELF = $hash->{NAME} // return;
my $TYPE = $hash->{TYPE}; my $TYPE = $hash->{TYPE};
@ -542,7 +616,7 @@ sub monitoring_setActive {
return; return;
} }
sub monitoring_setInactive { sub setInactive {
my $hash = shift // return; my $hash = shift // return;
my $SELF = $hash->{NAME} // return; my $SELF = $hash->{NAME} // return;
my $TYPE = $hash->{TYPE}; my $TYPE = $hash->{TYPE};
@ -827,7 +901,8 @@ __END__
</li> </li>
</ul> </ul>
With this attribute the output created with "get &lt;name&gt; error" With this attribute the output created with "get &lt;name&gt; error"
can be formatted. can be formatted.<br>
Note: As evaluation is done in package context, using functions from main may require redirection in lexical main context (e.g. use double colons "::myFunction($SELF)").
</li> </li>
<a id="monitoring-attr-getDefault"></a><li> <a id="monitoring-attr-getDefault"></a><li>
<code>getDefault (all|error|warning)</code><br> <code>getDefault (all|error|warning)</code><br>
@ -1332,7 +1407,8 @@ attr BeamerFilter_monitoring warningFuncRemove {return}</pre>
</li> </li>
</ul> </ul>
Mit diesem Attribut kann die Ausgabe die mit "get &lt;name&gt; error" Mit diesem Attribut kann die Ausgabe die mit "get &lt;name&gt; error"
erzeugt wird angepasst werden. erzeugt wird angepasst werden.<br>
Hinweis: Da der Code im package-Kontext evaluiert wird, muss ggf. bei Funktionen aus dem main Kontext explizit ein Verweis auf diesen Kontext ergänzt werden(z.B. mit vorangestelltem doppeltem Doppelpunt "::myFunction($SELF)").
</li> </li>
<a id="monitoring-attr-getDefault"></a><li> <a id="monitoring-attr-getDefault"></a><li>
<code>getDefault (all|error|warning)</code><br> <code>getDefault (all|error|warning)</code><br>

View File

@ -536,7 +536,7 @@ FHEM/98_ModbusAttr.pm StefanStrobel Sonstiges
FHEM/98_ModbusElsnerWS.pm klaus.schauer Sonstiges FHEM/98_ModbusElsnerWS.pm klaus.schauer Sonstiges
FHEM/98_ModbusSET.pm StefanStrobel Sonstiges FHEM/98_ModbusSET.pm StefanStrobel Sonstiges
FHEM/98_ModbusTrovis5576.pm Reinerlein Heizungssteuerung/Raumklima FHEM/98_ModbusTrovis5576.pm Reinerlein Heizungssteuerung/Raumklima
FHEM/98_monitoring.pm Beta-User Automatisierung FHEM/98_monitoring.pm Beta-User Automatisierung https://forum.fhem.de/index.php/topic,126515.0.html
FHEM/98_notice.pm mfr69bs Sonstiges FHEM/98_notice.pm mfr69bs Sonstiges
FHEM/98_PHC.pm StefanStrobel Sonstiges FHEM/98_PHC.pm StefanStrobel Sonstiges
FHEM/98_PID20.pm John Automatisierung FHEM/98_PID20.pm John Automatisierung