mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-02-25 16:05:19 +00:00
1663 lines
60 KiB
Perl
1663 lines
60 KiB
Perl
##########################################################################
|
|
# $Id$
|
|
#
|
|
# copyright ###################################################################
|
|
#
|
|
# 98_monitoring.pm
|
|
#
|
|
# Originally initiated by igami
|
|
#
|
|
# This file is part of FHEM.
|
|
#
|
|
# FHEM 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 (at your option) any later
|
|
# version.
|
|
#
|
|
# FHEM 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.
|
|
#
|
|
# You should have received a copy of the GNU General Public License along with
|
|
# FHEM. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
# packages ####################################################################
|
|
package FHEM::Automation::monitoring; ##no critic qw(Package)
|
|
use strict;
|
|
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
|
|
ReadingsAge
|
|
devspec2array
|
|
AnalyzeCommandChain
|
|
AnalyzeCommand
|
|
EvalSpecials
|
|
AnalyzePerlCommand
|
|
perlSyntaxCheck
|
|
FmtDateTime time_str2num
|
|
notifyRegexpChanged
|
|
deviceEvents
|
|
) )
|
|
};
|
|
|
|
# initialize ##################################################################
|
|
sub Initialize {
|
|
my $hash = shift // return;
|
|
|
|
$hash->{DefFn} = \&Define;
|
|
$hash->{UndefFn} = \&Undefine;
|
|
$hash->{SetFn} = \&Set;
|
|
$hash->{GetFn} = \&Get;
|
|
$hash->{AttrFn} = \&Attr;
|
|
$hash->{NotifyFn} = \&Notify;
|
|
|
|
|
|
$hash->{AttrList} =
|
|
"addStateEvent:1,0 ".
|
|
"blacklist:textField-long ".
|
|
"disable:1,0 ".
|
|
"disabledForIntervals ".
|
|
"errorFuncAdd:textField-long ".
|
|
"errorFuncAdded:textField-long ".
|
|
"errorFuncRemove:textField-long ".
|
|
"errorWait ".
|
|
"errorReturn:textField-long ".
|
|
"getDefault:all,error,warning ".
|
|
"setActiveFunc:textField-long ".
|
|
"setInactiveFunc:textField-long ".
|
|
"warningFuncAdd:textField-long ".
|
|
"warningFuncAdded:textField-long ".
|
|
"warningFuncRemove:textField-long ".
|
|
"warningWait ".
|
|
"warningReturn:textField-long ".
|
|
"whitelist:textField-long ".
|
|
$readingFnAttributes;
|
|
return;
|
|
}
|
|
|
|
# regular Fn ##################################################################
|
|
sub Define {
|
|
my $hash = shift // return;
|
|
my $def = shift // return;
|
|
my ($SELF, $TYPE, @re) = split m{\s+}xms, $def, 5;
|
|
|
|
return("Usage: define <name> $TYPE <add-event> [<remove-event>]")
|
|
if( !@re || @re > 2);
|
|
|
|
monitoring_NOTIFYDEV($hash) if !$init_done;
|
|
setActive($hash) if $init_done;
|
|
|
|
return;
|
|
}
|
|
|
|
sub Undefine {
|
|
my $hash = shift // return;
|
|
|
|
setInactive($hash);
|
|
monitoring_RemoveInternalTimer($hash);
|
|
|
|
return;
|
|
}
|
|
|
|
sub Set {
|
|
my ($hash, @arr) = @_;
|
|
my $TYPE = $hash->{TYPE};
|
|
|
|
return '"set <monitoring>" needs at least one argument' if @arr < 2;
|
|
|
|
my $SELF = shift @arr;
|
|
my $argument = shift @arr;
|
|
my $value = @arr ? join ' ', @arr : '';
|
|
my %monitoring_sets = (
|
|
active => 'active:noArg',
|
|
clear => 'clear:all,error,warning',
|
|
errorAdd => 'errorAdd:textField',
|
|
errorRemove => 'errorRemove:'.
|
|
join( q{,}, ReadingsVal($SELF, 'error', '')),
|
|
inactive => 'inactive:noArg',
|
|
warningAdd => 'warningAdd:textField',
|
|
warningRemove => 'warningRemove:'.
|
|
join q{,}, ReadingsVal($SELF, 'warning', '')
|
|
);
|
|
|
|
return "Unknown argument $argument, choose one of ".
|
|
join " ", sort values %monitoring_sets
|
|
if !exists $monitoring_sets{$argument};
|
|
|
|
if ( $argument eq 'active' ) {
|
|
return setActive($hash);
|
|
}
|
|
if ( $argument eq 'inactive' ) {
|
|
setInactive($hash);
|
|
readingsSingleUpdate($hash, 'state', $argument, 0);
|
|
|
|
Log3($SELF, 3, "$SELF ($TYPE) set $SELF inactive");
|
|
|
|
return monitoring_RemoveInternalTimer($hash);
|
|
}
|
|
if ( $argument eq 'clear' ) {
|
|
readingsBeginUpdate($hash);
|
|
|
|
if ( $value =~ m{\A(warning|all)\z}xms ) {
|
|
readingsBulkUpdate($hash, 'warning', '', 0);
|
|
readingsBulkUpdate($hash, 'warningCount', 0, 0);
|
|
|
|
for my $r (keys %{$hash->{READINGS}}){
|
|
if($r =~ m{(warning)Add_(.+)}xms){
|
|
RemoveInternalTimer("$SELF|$1|add|$2");
|
|
|
|
delete $hash->{READINGS}{$r};
|
|
}
|
|
}
|
|
}
|
|
if ( $value =~ m{\A(error|all)\z}xms ) {
|
|
readingsBulkUpdate($hash, 'error', '', 0);
|
|
readingsBulkUpdate($hash, 'errorCount', 0, 0);
|
|
|
|
for my $r ( keys %{$hash->{READINGS}} ) {
|
|
if ( $r =~ m{(error)Add_(.+)}xms ) {
|
|
RemoveInternalTimer("$SELF|$1|add|$2");
|
|
|
|
delete $hash->{READINGS}{$r};
|
|
}
|
|
}
|
|
}
|
|
|
|
readingsBulkUpdate($hash, 'state', "$argument $value", 0)
|
|
if !IsDisabled($SELF);
|
|
readingsEndUpdate($hash, 0);
|
|
|
|
Log3($SELF, 2, "$TYPE ($SELF) set $SELF $argument $value");
|
|
}
|
|
elsif($argument =~ m{\A(error|warning)(Add|Remove)\z}xms){
|
|
monitoring_modify("$SELF|$1|".lc($2)."|$value");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
sub Get {
|
|
my ($hash, @arr) = @_;
|
|
my $TYPE = $hash->{TYPE};
|
|
my $SELF = shift @arr;
|
|
|
|
return if IsDisabled($SELF);
|
|
return("\"get $TYPE\" needs at least one argument") if !@arr;
|
|
|
|
my $argument = shift @arr;
|
|
my $value = @arr ? join ' ', @arr : '';
|
|
my $default = AttrVal($SELF, 'getDefault', 'all');
|
|
my %monitoring_gets = (
|
|
all => 'all:noArg',
|
|
default => 'default:noArg',
|
|
error => 'error:noArg',
|
|
warning => 'warning:noArg'
|
|
);
|
|
my @ret;
|
|
|
|
return
|
|
"Unknown argument $argument, choose one of ".
|
|
join ' ', sort values %monitoring_gets if !exists $monitoring_gets{$argument};
|
|
|
|
if ( $argument eq 'all' || $argument eq 'default' && $default eq 'all' ) {
|
|
push @ret, monitoring_return($hash, 'error');
|
|
push @ret, monitoring_return($hash, 'warning');
|
|
}
|
|
elsif ( $argument eq 'default' ) {
|
|
push @ret, monitoring_return($hash, $default);
|
|
}
|
|
elsif($argument eq 'error' || $argument eq 'warning') {
|
|
push @ret, monitoring_return($hash, $argument);
|
|
}
|
|
@ret = grep { defined } @ret; #prevent uninitialized warnings
|
|
return join ("\n\n", @ret)."\n" if @ret;
|
|
return;
|
|
}
|
|
|
|
sub Attr {
|
|
my ($cmd, $SELF, $attribute, $value) = @_;
|
|
my $hash = $defs{$SELF} // return;
|
|
|
|
if($attribute =~ "blacklist" && $value){
|
|
my @blacklist;
|
|
|
|
push @blacklist, devspec2array($_) for (split m{[\s]+}x, $value);
|
|
|
|
my %blacklist = map{ $_ => 1 } @blacklist;
|
|
|
|
for my $name (sort keys %blacklist){
|
|
monitoring_modify("$SELF|warning|remove|$name");
|
|
monitoring_modify("$SELF|error|remove|$name");
|
|
}
|
|
}
|
|
elsif($attribute eq 'whitelist'){
|
|
monitoring_NOTIFYDEV($hash);
|
|
|
|
return if !$value;
|
|
my @whitelist;
|
|
|
|
push @whitelist, devspec2array($_) for (split m{[\s]+}x, $value);
|
|
|
|
for my $list ( qw(warning error) ){
|
|
for my $name ( split m{,}x, ReadingsVal($SELF, $list, '') ) {
|
|
monitoring_modify("$SELF|$list|remove|$name")
|
|
if !grep {m{$name}x} @whitelist;
|
|
}
|
|
}
|
|
}
|
|
elsif($attribute eq 'disable'){
|
|
if($cmd eq 'set' and $value == 1){
|
|
return setActive($hash);
|
|
}
|
|
setInactive($hash);
|
|
readingsSingleUpdate($hash, 'state', 'disabled', 0);
|
|
Log3($SELF, 3, "$hash->{TYPE} ($SELF) attr $SELF disabled");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
sub Notify {
|
|
my $hash = shift // return;
|
|
my $dev_hash = shift // return;
|
|
my $SELF = $hash->{NAME};
|
|
my $name = $dev_hash->{NAME};
|
|
my $TYPE = $hash->{TYPE};
|
|
|
|
return if(
|
|
!$init_done ||
|
|
IsDisabled($SELF) ||
|
|
IsDisabled($name) ||
|
|
$SELF eq $name # do not process own events
|
|
);
|
|
|
|
my $events = deviceEvents($dev_hash, AttrVal($SELF, 'addStateEvent', 0));
|
|
|
|
return if !$events;
|
|
|
|
if($name eq 'global' && 'INITIALIZED|REREADCFG' =~ m{\Q@{$events}\E}x){
|
|
setActive($hash);
|
|
|
|
return;
|
|
}
|
|
|
|
my ($addRegex, $removeRegex) = split m{[\s]+}x, InternalVal($SELF, 'DEF', '');
|
|
|
|
=pod this seems to be useless?
|
|
return unless(
|
|
$addRegex =~ m/^$name:/ ||
|
|
$removeRegex && $removeRegex =~ m/^$name:/ ||
|
|
$events
|
|
);
|
|
=cut
|
|
|
|
my @blacklist;
|
|
|
|
push @blacklist, devspec2array($_)
|
|
for (split m{[\s]+}x, AttrVal($SELF, 'blacklist', ''));
|
|
|
|
return if @blacklist && grep { m{\A${name}\z}x } @blacklist;
|
|
|
|
my @whitelist;
|
|
|
|
push @whitelist, devspec2array($_)
|
|
for (split m{[\s]+}x, AttrVal($SELF, 'whitelist', ''));
|
|
|
|
return if @whitelist && !grep { m{\A$name\z}x } @whitelist;
|
|
|
|
for my $event (@{$events}){
|
|
next if !$event;
|
|
|
|
my $addMatch = "$name:$event" =~ m{\A$addRegex\z}xms;
|
|
my $removeMatch = $removeRegex ? "$name:$event" =~ m{\A$removeRegex\z}xms : 0;
|
|
#Log3($hash, 3, "notify called with add $addMatch and remove $removeMatch");
|
|
|
|
next if !$addMatch && !$removeMatch;
|
|
|
|
Log3($SELF, 4 , "$TYPE ($SELF) triggered by \"$name $event\"");
|
|
|
|
for my $list ( qw (error warning) ){
|
|
my $listFuncAdd = AttrVal($SELF, $list.'FuncAdd', 'preset');
|
|
my $listFuncRemove = AttrVal($SELF, $list.'FuncRemove', 'preset');
|
|
#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
|
|
'$event' => $event,
|
|
'$addMatch' => $addMatch,
|
|
'$removeMatch' => $removeMatch
|
|
);
|
|
|
|
$cmd = EvalSpecials($cmd, %specials);
|
|
|
|
# CMD ausführen
|
|
my $listWait = AnalyzePerlCommand( $hash, $cmd );
|
|
$listWait = 0 if !looks_like_number($listWait);
|
|
|
|
if ( $listFuncAdd eq 'preset' && $listFuncRemove eq 'preset' ) {
|
|
Log3(
|
|
$SELF, 5, "$TYPE ($SELF) ".
|
|
$list."FuncAdd and $list"."FuncRemove are preset"
|
|
);
|
|
if ( !$removeRegex ) {
|
|
if ( $listWait == 0 ) {
|
|
Log3(
|
|
$SELF, 2, "$TYPE ($SELF) ".
|
|
"set \"$list"."Wait\" while \"$list".
|
|
"FuncAdd\" and \"$list"."FuncRemove\" are same"
|
|
) if $list eq 'error';
|
|
|
|
next;
|
|
}
|
|
|
|
Log3($SELF, 5, "$TYPE ($SELF) only addRegex is defined");
|
|
|
|
monitoring_modify("$SELF|$list|remove|$name");
|
|
monitoring_modify("$SELF|$list|add|$name|$listWait");
|
|
|
|
next;
|
|
}
|
|
else{
|
|
#next unless($list eq 'error' || AttrVal($SELF, 'errorWait', undef));
|
|
next if $list ne 'error' && !AttrVal($SELF, 'errorWait', undef);
|
|
|
|
Log3(
|
|
$SELF, 5, "$TYPE ($SELF) ".
|
|
"addRegex ($addRegex) and removeRegex ($removeRegex) are defined"
|
|
);
|
|
|
|
monitoring_modify("$SELF|$list|remove|$name") if $removeMatch;
|
|
monitoring_modify("$SELF|$list|add|$name|$listWait") if $addMatch;
|
|
|
|
next;
|
|
}
|
|
}
|
|
|
|
$listFuncAdd = 1 if $listFuncAdd eq 'preset' && $addMatch;
|
|
|
|
if(!$removeRegex){
|
|
Log3($SELF, 5, "$TYPE ($SELF) only addRegex is defined");
|
|
|
|
if ( $listFuncRemove eq 'preset' ) {
|
|
if ( $listWait == 0 ) {
|
|
Log3(
|
|
$SELF, 2, "$TYPE ($SELF) ".
|
|
"set \"$list"."Wait\" while \"$list".
|
|
"FuncAdd\" and \"$list"."FuncRemove\" are same"
|
|
) if $list eq 'error';
|
|
|
|
next;
|
|
}
|
|
|
|
$listFuncRemove = $listFuncAdd;
|
|
}
|
|
}
|
|
else{
|
|
Log3(
|
|
$SELF, 5, "$TYPE ($SELF) ".
|
|
"addRegex ($addRegex) and removeRegex ($removeRegex) are defined"
|
|
);
|
|
|
|
$listFuncRemove = 1 if $listFuncRemove eq 'preset' && $removeMatch;
|
|
}
|
|
|
|
#$listFuncAdd = eval($listFuncAdd) if $listFuncAdd =~ /^\{.*\}$/s;
|
|
if ( $listFuncAdd =~ m{\A\{.*\}\z}xs ) {
|
|
$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")
|
|
if $listFuncRemove && $listFuncRemove eq '1';
|
|
monitoring_modify("$SELF|$list|add|$name|$listWait")
|
|
if $listFuncAdd && $listFuncAdd eq '1';
|
|
|
|
next;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
# module Fn ###################################################################
|
|
sub monitoring_modify {
|
|
my ($SELF, $list, $operation, $value, $wait) = split m{[|]}x, shift;
|
|
my $hash = $defs{$SELF} // return;
|
|
|
|
return if IsDisabled($SELF);
|
|
|
|
my $at;
|
|
#$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 (@change, %readings);
|
|
%readings = map{ $_ => 1 } split m{,}xms, ReadingsVal($SELF, $list, '');
|
|
my $arg = "$SELF|$list|$operation|$value";
|
|
my $reading = $list."Add_".$value;
|
|
|
|
Log3(
|
|
$SELF, 5 , "$TYPE ($SELF)".
|
|
"\n entering monitoring_modify".
|
|
"\n reading: $list".
|
|
"\n operation: $operation".
|
|
"\n value: $value".
|
|
"\n at: ".($at ? FmtDateTime($at) : "now")
|
|
);
|
|
|
|
if ( $operation eq 'add' ) {
|
|
return if
|
|
$readings{$value} ||
|
|
ReadingsVal($SELF, 'error', '') =~ m{(?:^|,)$value(?:,|$)}x
|
|
;
|
|
|
|
if ( $at ){
|
|
return if $hash->{READINGS}{$reading};
|
|
|
|
readingsSingleUpdate($hash, $reading, FmtDateTime($at), 0);
|
|
InternalTimer($at, \&monitoring_modify, $arg);
|
|
|
|
return;
|
|
}
|
|
monitoring_modify("$SELF|warning|remove|$value|quiet")
|
|
if $list eq 'error';
|
|
$readings{$value} = 1;
|
|
delete $hash->{READINGS}{$reading};
|
|
}
|
|
elsif ( $operation eq 'remove' ) {
|
|
push(@change, 1) if delete $readings{$value};
|
|
delete $hash->{READINGS}{$reading};
|
|
}
|
|
|
|
RemoveInternalTimer("$SELF|$list|add|$value");
|
|
|
|
#return unless(@change || $operation eq 'add');
|
|
return if !@change && $operation ne 'add';
|
|
|
|
my $allCount =
|
|
int(keys %readings) +
|
|
ReadingsNum($SELF, ($list eq 'warning' ? 'error' : 'warning').'Count', 0)
|
|
;
|
|
|
|
if ($operation eq 'add') {
|
|
my $name = $value;
|
|
my $listFuncAdded = AttrVal($SELF, $list.'FuncAdded', '');
|
|
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);
|
|
readingsBulkUpdate($hash, 'state', "$list $operation: $value");
|
|
readingsBulkUpdate($hash, $list, join ",", sort keys %readings);
|
|
readingsBulkUpdate($hash, $list.'Count', int(keys %readings));
|
|
readingsBulkUpdate($hash, 'allCount', $allCount)
|
|
if !$wait || $wait ne 'quiet';
|
|
readingsEndUpdate($hash, 1);
|
|
|
|
return;
|
|
}
|
|
|
|
sub monitoring_NOTIFYDEV {
|
|
my $hash = shift // return;
|
|
my $SELF = $hash->{NAME} // return;
|
|
my $NOTIFYDEV = $init_done ? AttrVal($SELF, 'whitelist', undef) : 'global'; #|| join(",", (InternalVal($SELF, "DEF", undef) =~ m/(?:^|\s)([^:\s]+):/g))
|
|
|
|
if ($NOTIFYDEV) {
|
|
$NOTIFYDEV =~ s{[\s]+}{,}gx;
|
|
return notifyRegexpChanged($hash, "$NOTIFYDEV,global");
|
|
}
|
|
$NOTIFYDEV = join q{|}, split m{[\s]+}x, InternalVal($SELF, 'DEF', undef);
|
|
return notifyRegexpChanged($hash, "$NOTIFYDEV|global");
|
|
}
|
|
|
|
sub monitoring_RemoveInternalTimer {
|
|
my $hash = shift // return;
|
|
my $SELF = $hash->{NAME} // return;
|
|
|
|
for my $reading (sort keys %{$hash->{READINGS}}){
|
|
RemoveInternalTimer("$SELF|$1|add|$2")
|
|
if $reading =~ m{(error|warning)Add_(.+)}xms;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
sub monitoring_return {
|
|
my $hash = shift // return;
|
|
my $list = shift // return;
|
|
|
|
my $SELF = $hash->{NAME} // return;
|
|
my @errors = split m{,}xms, ReadingsVal($SELF, 'error', '');
|
|
my @warnings = split m{,}xms, ReadingsVal($SELF, 'warning', '');
|
|
my $value = ReadingsVal($SELF, $list, undef);
|
|
my $ret = AttrVal($SELF, $list.'Return', undef);
|
|
$ret = '"$list: $value"' if !$ret && $value;
|
|
|
|
return if !$ret;
|
|
#return ;
|
|
|
|
if ( !eval{ $ret = eval($ret) ; 1 } ) { ##no critic qw(StringyEval)
|
|
return Log3($hash->{NAME}, 1, "Evaluation error: $@");
|
|
}
|
|
return $ret;
|
|
}
|
|
|
|
sub setActive {
|
|
my $hash = shift // return;
|
|
my $SELF = $hash->{NAME} // return;
|
|
my $TYPE = $hash->{TYPE};
|
|
|
|
monitoring_NOTIFYDEV($hash);
|
|
readingsSingleUpdate($hash, 'state', 'active', 0);
|
|
Log3($SELF, 3, "$TYPE ($SELF) set $SELF active");
|
|
|
|
for my $reading (reverse sort keys %{$hash->{READINGS}}){
|
|
if ( $reading =~ m{(error|warning)Add_(.+)}xms ) {
|
|
my $wait = time_str2num(ReadingsVal($SELF, $reading, ''));
|
|
|
|
next if !looks_like_number($wait);
|
|
|
|
$wait -= gettimeofday();
|
|
|
|
if($wait > 0){
|
|
Log3($SELF, 4 , "$TYPE ($SELF) restore Timer \"$SELF|$1|add|$2\"");
|
|
|
|
monitoring_modify("$SELF|$1|add|$2|$wait");
|
|
}
|
|
else{
|
|
monitoring_modify("$SELF|$1|add|$2");
|
|
}
|
|
}
|
|
}
|
|
|
|
AnalyzeCommandChain(undef, AttrVal($SELF, 'setActiveFunc', 'preset'));
|
|
|
|
return;
|
|
}
|
|
|
|
sub setInactive {
|
|
my $hash = shift // return;
|
|
my $SELF = $hash->{NAME} // return;
|
|
my $TYPE = $hash->{TYPE};
|
|
|
|
notifyRegexpChanged($hash,'',1);
|
|
AnalyzeCommandChain(undef, AttrVal($SELF, 'setInactiveFunc', 'preset'));
|
|
|
|
return;
|
|
}
|
|
|
|
1;
|
|
|
|
__END__
|
|
|
|
# commandref ##################################################################
|
|
=pod
|
|
=item helper
|
|
=encoding utf8
|
|
=item summary monitors devices towards events and stores them in two lists
|
|
=item summary_DE überwacht Geräte auf Events und speichert diese in zwei Listen
|
|
|
|
=begin html
|
|
|
|
<a id="monitoring"></a>
|
|
<h3>monitoring</h3>
|
|
<div>
|
|
<ul>
|
|
Each <i>monitoring</i> has a <i>warning</i>- and an <i>error</i> list, which are stored
|
|
as readings. <br>
|
|
When a defined add-event occurs, the device is set to the warning
|
|
list after a predefined time.<br>
|
|
After a further predefined time, the device is deleted from the
|
|
warning list and set to the error list.<br>
|
|
If a defined remove-event occurs, the device is deleted from both
|
|
lists and still running timers are canceled.<br>
|
|
This makes it easy to create group messages and send them
|
|
formatted by two attributes.<br>
|
|
<br>
|
|
The following applications are possible and are described
|
|
<a href="#monitoring-examples"><u>below</u></a>:<br>
|
|
<ul>
|
|
<li>opened windows</li>
|
|
<li>battery warnings</li>
|
|
<li>activity monitor</li>
|
|
<li>
|
|
regular maintenance (for example changing the table water
|
|
filter or cleaning rooms)
|
|
</li>
|
|
<li>
|
|
operating hours dependent maintenance (for example clean the
|
|
Beamer filter)
|
|
</li>
|
|
</ul>
|
|
<br>
|
|
The monitor does not send a message by itself, a <a href="#notify"><u>notify</u></a>
|
|
or <a href="#DOIF"><u>DOIF</u></a> is
|
|
necessary, which responds to the event "<monitoring-name> error
|
|
add: <name>" and then sends the return value of "get
|
|
<monitoring-name> default".
|
|
<br>
|
|
<a id="monitoring-define"></a>
|
|
<h4>Define</h4>
|
|
<ul>
|
|
<code>
|
|
define <name> monitoring <add-event> [<remove-event>]
|
|
</code>
|
|
<br>
|
|
The syntax for <add-event> and <remove-event> is the
|
|
same as the pattern for <a href="#notify">notify</a>
|
|
(device-name or device-name:event).<br>
|
|
If only an <add-event> is defined, the device is deleted from
|
|
both lists as it occurs and the timers for warning and error are
|
|
started.<br>
|
|
</ul>
|
|
<a id="monitoring-set"></a>
|
|
<h4>Set</h4>
|
|
<ul>
|
|
<a id="monitoring-set-active"></a><li>
|
|
<code>active</code><br>
|
|
Two things will happen:<br>
|
|
1. Restores pending timers, or sets the devices immediately to the
|
|
corresponding list if the time is in the past.<br>
|
|
2. Executes the commands specified under the "setActiveFunc" attribute.
|
|
</li>
|
|
<a id="monitoring-set-clear"></a><li>
|
|
<code>clear (warning|error|all)</code><br>
|
|
Removes all devices from the specified list and aborts timers for this
|
|
list. With "all", all devices are removed from both lists and all
|
|
running timers are aborted.
|
|
</li>
|
|
<a id="monitoring-set-errorAdd"></a><li>
|
|
<code>errorAdd <name></code><br>
|
|
Add <name> to the error list.
|
|
</li>
|
|
<a id="monitoring-set-errorRemove"></a><li>
|
|
<code>errorRemove <name></code><br>
|
|
Removes <name> from the error list.
|
|
</li>
|
|
<a id="monitoring-set-inactive"></a><li>
|
|
<code>inactive</code><br>
|
|
Two things will happen:<br>
|
|
1. Executes the commands specified under the "setInactiveFunc" attribute.<br>
|
|
2. Inactivates the current device. Note the slight difference to the
|
|
disable attribute: using set inactive the state is automatically saved
|
|
to the statefile on shutdown, there is no explicit save necesary.
|
|
</li>
|
|
<a id="monitoring-set-warningAdd"></a><li>
|
|
<code>warningAdd <name></code><br>
|
|
Add <name> to the warning list.
|
|
</li>
|
|
<a id="monitoring-set-warningRemove"></a><li>
|
|
<code>warningRemove <name></code><br>
|
|
Removes <name> from the warning list.
|
|
</li>
|
|
</ul>
|
|
<a id="monitoring-get"></a>
|
|
<h4>Get</h4>
|
|
<ul>
|
|
<a id="monitoring-get-all"></a><li>
|
|
<code>all</code><br>
|
|
Returns the error and warning list, separated by a blank line.<br>
|
|
The formatting can be set with the attributes "errorReturn" and
|
|
"warningReturn".
|
|
</li>
|
|
<a id="monitoring-get-default"></a><li>
|
|
<code>default</code><br>
|
|
The "default" value can be set in the attribute "getDefault" and is
|
|
intended to leave the configuration for the return value in the
|
|
monitoring device. If nothing is specified "all" is used.
|
|
</li>
|
|
<a id="monitoring-get-error"></a><li>
|
|
<code>error</code><br>
|
|
Returns the error list.<br>
|
|
The formatting can be set with the attribute "errorReturn".
|
|
</li>
|
|
<a id="monitoring-get-warning"></a><li>
|
|
<code>warning</code><br>
|
|
Returns the warning list.<br>
|
|
The formatting can be set with the attribute "warningReturn".
|
|
</li>
|
|
</ul>
|
|
<a id="monitoring-readings"></a>
|
|
<h4>Readings</h4><br>
|
|
<ul>
|
|
<li>
|
|
<code>allCount</code><br>
|
|
Displays the amount of devices on the warning and error list..
|
|
</li>
|
|
<li>
|
|
<code>error</code><br>
|
|
Comma-separated list of devices.
|
|
</li>
|
|
<li>
|
|
<code>errorAdd_<name></code><br>
|
|
Displays the time when the device will be set to the error list.
|
|
</li>
|
|
<li>
|
|
<code>errorCount</code><br>
|
|
Displays the amount of devices on the error list.
|
|
</li>
|
|
<li>
|
|
<code>state</code><br>
|
|
Displays the status (active, inactive, or disabled). In "active" it
|
|
displays which device added to which list or was removed from which
|
|
list.
|
|
</li>
|
|
<li>
|
|
<code>warning</code><br>
|
|
Comma-separated list of devices.
|
|
</li>
|
|
<li>
|
|
<code>warningAdd_<name></code><br>
|
|
Displays the time when the device will be set to the warning list.
|
|
</li>
|
|
<li>
|
|
<code>warningCount</code><br>
|
|
Displays the amount of devices on the warning list.
|
|
</li>
|
|
</ul>
|
|
<a id="monitoring-attr"></a>
|
|
<h4>Attributes</h4>
|
|
<ul>
|
|
<li>
|
|
<a href="#addStateEvent">
|
|
<u><code>addStateEvent</code></u>
|
|
</a>
|
|
</li>
|
|
<a id="monitoring-attr-blacklist"></a><li>
|
|
<code>blacklist <devspec list></code><br>
|
|
Space-separated list of devspecs which will be ignored.<br>
|
|
If the attribute is set all devices which are specified by the devspecs
|
|
are removed from both lists.
|
|
</li>
|
|
<a id="monitoring-attr-disable"></a><li>
|
|
<code>disable (1|0)</code><br>
|
|
1: Executes the commands specified under the "setInactiveFunc" attribute
|
|
and disables the monitoring.<br>
|
|
0: see "set active"
|
|
</li>
|
|
<li>
|
|
<a href="#disabledForIntervals">
|
|
<u><code>disabledForIntervals HH:MM-HH:MM HH:MM-HH-MM ...</code></u>
|
|
</a>
|
|
</li>
|
|
<a id="monitoring-attr-errorFuncAdd"></a><li>
|
|
<code>errorFuncAdd {<perl code>}</code><br>
|
|
The following variables are available in this function:
|
|
<br>
|
|
<ul>
|
|
<li>
|
|
<code>$name</code><br>
|
|
Name of the event triggering device
|
|
</li>
|
|
<li>
|
|
<code>$event</code><br>
|
|
Includes the complete event, e.g.
|
|
<code>measured-temp: 21.7 (Celsius)</code>
|
|
</li>
|
|
<li>
|
|
<code>$addMatch</code><br>
|
|
Has the value 1 if the add-event is true
|
|
</li>
|
|
<li>
|
|
<code>$removeMatch</code><br>
|
|
Has the value 1 if the remove-event is true
|
|
</li>
|
|
<li>
|
|
<code>$SELF</code><br>
|
|
Name of the monitoring
|
|
</li>
|
|
</ul>
|
|
If the function returns a 1, the device is set to the error list after
|
|
the wait time.<br>
|
|
If the attribute is not set, it will be checked for
|
|
<code>$addMatch</code>.
|
|
</li>
|
|
<a id="monitoring-attr-errorFuncAdded"></a><li>
|
|
<code>errorFuncAdded {<perl code>}</code><br>
|
|
The following variables are available in this function:
|
|
<br>
|
|
<ul>
|
|
<li>
|
|
<code>$name</code><br>
|
|
Name of the event triggering device
|
|
</li>
|
|
<li>
|
|
<code>$SELF</code><br>
|
|
Name of the monitoring
|
|
</li>
|
|
</ul>
|
|
This function will be executed when a device is added to the error list.
|
|
</li>
|
|
<a id="monitoring-attr-errorFuncRemove"></a><li>
|
|
<code>errorFuncRemove {<perl code>}</code><br>
|
|
This function provides the same variables as for "errorFuncAdd".<br>
|
|
If the function returns a 1, the device is removed from the error list
|
|
and still running timers are canceled.<br>
|
|
If the attribute is not set, it will be checked for
|
|
<code>$removeMatch</code> if there is a
|
|
<code><remove-event></code> in the DEF, otherwise it will be
|
|
checked for <code>errorFuncAdd</code>.
|
|
</li>
|
|
<a id="monitoring-attr-errorWait"></a><li>
|
|
<code>errorWait <perl code></code><br>
|
|
Code returning waiting time (in seconds) until the device is set to the error list.
|
|
</li>
|
|
<a id="monitoring-attr-errorReturn"></a><li>
|
|
<code>errorReturn {<perl code>}</code><br>
|
|
The following variables are available in this attribute:
|
|
<ul>
|
|
<li>
|
|
<code>@errors</code><br>
|
|
Array with all devices on the error list.
|
|
</li>
|
|
<li>
|
|
<code>@warnings</code><br>
|
|
Array with all devices on the warning list.
|
|
</li>
|
|
<li>
|
|
<code>$SELF</code><br>
|
|
Name of the monitoring
|
|
</li>
|
|
</ul>
|
|
With this attribute the output created with "get <name> error"
|
|
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>
|
|
<a id="monitoring-attr-getDefault"></a><li>
|
|
<code>getDefault (all|error|warning)</code><br>
|
|
This attribute can be used to specify which list(s) are / are returned
|
|
by "get <name> default". If the attribute is not set, "all" will
|
|
be used.
|
|
</li>
|
|
<a id="monitoring-attr-setActiveFunc"></a><li>
|
|
<code>setActiveFunc <statement></code><br>
|
|
The statement is one of the FHEM command types and is executed when you
|
|
define the monitoring or "set active".<br>
|
|
For a battery message <code>"trigger battery=low battery: low"</code>
|
|
can be useful.
|
|
</li>
|
|
<a id="monitoring-attr-setInactiveFunc"></a><li>
|
|
<code>setInactiveFunc <statement></code><br>
|
|
The statement is one of the FHEM command types and is executed when you
|
|
define the monitoring or "set inactive".
|
|
</li>
|
|
<a id="monitoring-attr-warningFuncAdd"></a><li>
|
|
<code>warningFuncAdd {<perl code>}</code><br>
|
|
Like errorFuncAdd, just for the warning list.
|
|
</li>
|
|
<a id="monitoring-attr-warningFuncAdded"></a><li>
|
|
<code>warningFuncAdded {<perl code>}</code><br>
|
|
Like errorFuncAdded, just for the warning list.
|
|
</li>
|
|
<a id="monitoring-attr-warningFuncRemove"></a><li>
|
|
<code>warningFuncRemove {<perl code>}</code><br>
|
|
Like errorFuncRemove, just for the warning list.
|
|
</li>
|
|
<a id="monitoring-attr-warningWait"></a><li>
|
|
<code>warningWait <perl code></code><br>
|
|
Like errorWait, just for the warning list.
|
|
</li>
|
|
<a id="monitoring-attr-warningReturn"></a><li>
|
|
<code>warningReturn {<perl code>}</code><br>
|
|
Like errorReturn, just for the warning list.
|
|
</li>
|
|
<a id="monitoring-attr-whitelist"></a><li>
|
|
<code>whitelist <devspec list></code><br>
|
|
Space-separated list of devspecs which are allowed.<br>
|
|
If the attribute is set all devices which are not specified by the
|
|
devspecs are removed from both lists.
|
|
</li>
|
|
<li>
|
|
<a href="#readingFnAttributes">
|
|
<u><code>readingFnAttributes</code></u>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
<a id="monitoring-examples"></a>
|
|
<h4>Examples</h4>
|
|
<ul>
|
|
<a href="https://wiki.fhem.de/wiki/Import_von_Code_Snippets">
|
|
<u>The following sample codes can be imported via "Raw definition".</u>
|
|
</a>
|
|
<br><br>
|
|
<li>
|
|
<b>
|
|
Global, flexible opened windows/doors message
|
|
<a href="https://forum.fhem.de/index.php/topic,36504">
|
|
<u>(similar to those described in the forum)</u>
|
|
</a>
|
|
</b>
|
|
<br>
|
|
<pre>defmod Fenster_monitoring monitoring .*:(open|tilted) .*:closed
|
|
attr Fenster_monitoring errorReturn {return if !@errors;;\
|
|
$_ = AttrVal($_, 'alias', $_) for @errors;;\
|
|
return("Das Fenster \"$errors[0]\" ist schon länger geöffnet.") if(int(@errors) == 1);;\
|
|
@errors = sort {lc($a) cmp lc($b)} @errors;;\
|
|
return(join("\n - ", "Die folgenden ".@errors." Fenster sind schon länger geöffnet:", @errors))\
|
|
}
|
|
attr Fenster_monitoring errorWait {AttrVal($name, "winOpenTimer", 60*10)}
|
|
attr Fenster_monitoring warningReturn {return if !@warnings;;\
|
|
$_ = AttrVal($_, 'alias', $_) for @warnings;;\
|
|
return("Das Fenster \"$warnings[0]\" ist seit kurzem geöffnet.") if(int(@warnings) == 1);;\
|
|
@warnings = sort {lc($a) cmp lc($b)} @warnings;;\
|
|
return(join("\n - ", "Die folgenden ".@warnings." Fenster sind seit kurzem geöffnet:", @warnings))\
|
|
}</pre>
|
|
As soon as a device triggers an "open" or "tilded" event, the device is
|
|
set to the warning list and a timer is started after which the device
|
|
is moved from the warning to the error list. The waiting time can be
|
|
set for each device via userattr "winOpenTimer". The default value is
|
|
10 minutes.<br>
|
|
As soon as a device triggers a "closed" event, the device is deleted
|
|
from both lists and still running timers are stopped.
|
|
</li>
|
|
<br>
|
|
<li>
|
|
<b>Battery monitoring</b><br>
|
|
<pre>defmod Batterie_monitoring monitoring .*:battery:.low .*:battery:.ok
|
|
attr Batterie_monitoring errorReturn {return if !@errors;;\
|
|
$_ = AttrVal($_, 'alias', $_) for @errors;;\
|
|
return("Bei dem Gerät \"$errors[0]\" muss die Batterie gewechselt werden.") if(int(@errors) == 1);;\
|
|
@errors = sort {lc($a) cmp lc($b)} @errors;;\
|
|
return(join("\n - ", "Die folgenden ".@errors." Geräten muss die Batterie gewechselt werden:", @errors))\
|
|
}
|
|
attr Batterie_monitoring errorWait 60*60*24*14
|
|
attr Batterie_monitoring warningReturn {return if !@warnings;;\
|
|
$_ = AttrVal($_, 'alias', $_) for @warnings;;\
|
|
return("Bei dem Gerät \"$warnings[0]\" muss die Batterie demnächst gewechselt werden.") if(int(@warnings) == 1);;\
|
|
@warnings = sort {lc($a) cmp lc($b)} @warnings;;\
|
|
return(join("\n - ", "Die folgenden ".@warnings." Geräten muss die Batterie demnächst gewechselt werden:", @warnings))\
|
|
}</pre>
|
|
As soon as a device triggers a "battery: low" event, the device is set
|
|
to the warning list and a timer is started after which the device is
|
|
moved from the warning to the error list. The waiting time is set to 14
|
|
days.<br>
|
|
As soon as a device triggers a "battery: ok" event, the device is
|
|
deleted from both lists and still running timers are stopped.
|
|
</li>
|
|
<br>
|
|
<li>
|
|
<b>Activity Monitor</b><br>
|
|
<pre>defmod Activity_monitoring monitoring .*:.*
|
|
attr Activity_monitoring errorReturn {return if !@errors;;\
|
|
$_ = AttrVal($_, 'alias', $_) for @errors;;\
|
|
return("Das Gerät \"$errors[0]\" hat sich seit mehr als 24 Stunden nicht mehr gemeldet.") if(int(@errors) == 1);;\
|
|
@errors = sort {lc($a) cmp lc($b)} @errors;;\
|
|
return(join("\n - ", "Die folgenden ".@errors." Geräten haben sich seit mehr als 24 Stunden nicht mehr gemeldet:", @errors))\
|
|
}
|
|
attr Activity_monitoring errorWait 60*60*24
|
|
attr Activity_monitoring warningReturn {return if !@warnings;;\
|
|
$_ = AttrVal($_, 'alias', $_) for @warnings;;\
|
|
return("Das Gerät \"$warnings[0]\" hat sich seit mehr als 12 Stunden nicht mehr gemeldet.") if(int(@warnings) == 1);;\
|
|
@warnings = sort {lc($a) cmp lc($b)} @warnings;;\
|
|
return(join("\n - ", "Die folgenden ".@warnings." Geräten haben sich seit mehr als 12 Stunden nicht mehr gemeldet:", @warnings))\
|
|
}
|
|
attr Activity_monitoring warningWait 60*60*12</pre>
|
|
Devices are not monitored until they have triggered at least one event.
|
|
If the device does not trigger another event in 12 hours, it will be
|
|
set to the warning list. If the device does not trigger another event
|
|
within 24 hours, it will be moved from the warning list to the error
|
|
list.<br>
|
|
<br>
|
|
Note: It is recommended to use the whitelist attribute.
|
|
</li>
|
|
<br>
|
|
<li>
|
|
<b>Regular maintenance (for example changing the table water filter)</b>
|
|
<br>
|
|
<pre>defmod Wasserfilter_monitoring monitoring Wasserfilter_DashButton:.*:.short
|
|
attr Wasserfilter_monitoring errorReturn {return if !@errors;;\
|
|
return "Der Wasserfilter muss gewechselt werden.";;\
|
|
}
|
|
attr Wasserfilter_monitoring errorWait 60*60*24*30
|
|
attr Wasserfilter_monitoring warningReturn {return if !@warnings;;\
|
|
return "Der Wasserfilter muss demnächst gewechselt werden.";;\
|
|
}
|
|
attr Wasserfilter_monitoring warningWait 60*60*24*25</pre>
|
|
A <a href="#dash_dhcp"><u>DashButton</u></a> is used to tell FHEM that
|
|
the water filter has been changed.<br>
|
|
After 30 days, the DashButton is set to the error list.
|
|
</li>
|
|
<br>
|
|
<li>
|
|
<b>Regular maintenance (for example cleaning rooms)</b>
|
|
<br>
|
|
<pre>defmod putzen_DashButton dash_dhcp
|
|
attr putzen_DashButton allowed AC:63:BE:2E:19:AF,AC:63:BE:49:23:48,AC:63:BE:49:5E:FD,50:F5:DA:93:2B:EE,AC:63:BE:B2:07:78
|
|
attr putzen_DashButton devAlias ac-63-be-2e-19-af:Badezimmer\
|
|
ac-63-be-49-23-48:Küche\
|
|
ac-63-be-49-5e-fd:Schlafzimmer\
|
|
50-f5-da-93-2b-ee:Arbeitszimmer\
|
|
ac-63-be-b2-07-78:Wohnzimmer
|
|
attr putzen_DashButton event-min-interval .*:5
|
|
attr putzen_DashButton port 6767
|
|
attr putzen_DashButton userReadings state {return (split(":", @{$hash->{CHANGED}}[0]))[0];;}
|
|
attr putzen_DashButton widgetOverride allowed:textField-long devAlias:textField-long
|
|
|
|
defmod putzen_monitoring monitoring putzen_DashButton:.*:.short
|
|
attr putzen_monitoring errorFuncAdd {$event =~ m/^(.+):/;;\
|
|
$name = $1;;\
|
|
return 1;;\
|
|
}
|
|
attr putzen_monitoring errorReturn {return if !@errors;;\
|
|
return("Der Raum \"$errors[0]\" muss wieder geputzt werden.") if(int(@errors) == 1);;\
|
|
return(join("\n - ", "Die folgenden Räume müssen wieder geputzt werden:", @errors))\
|
|
}
|
|
attr putzen_monitoring errorWait 60*60*24*7</pre>
|
|
Several <a href="#dash_dhcp"><u>DashButton</u></a> are used to inform
|
|
FHEM that the rooms have been cleaned.<br>
|
|
After 7 days, the room is set to the error list.<br>
|
|
However, the room name is not the device name but the readings name and
|
|
is changed in the <code>errorFuncAdd</code> attribute.
|
|
</li>
|
|
<br>
|
|
<li>
|
|
<b>
|
|
Operating hours dependent maintenance
|
|
(for example, clean the Beamer filter)
|
|
</b>
|
|
<br>
|
|
<pre>defmod BeamerFilter_monitoring monitoring Beamer_HourCounter:pulseTimeOverall BeamerFilter_DashButton:.*:.short
|
|
attr BeamerFilter_monitoring userattr errorInterval
|
|
attr BeamerFilter_monitoring errorFuncAdd {return 1\
|
|
if(ReadingsVal($name, "pulseTimeOverall", 0) >= \
|
|
ReadingsVal($name, "pulseTimeService", 0)\
|
|
+ (AttrVal($SELF, "errorInterval", 0))\
|
|
&& $addMatch\
|
|
);;\
|
|
return;;\
|
|
}
|
|
attr BeamerFilter_monitoring errorFuncRemove {return if !$removeMatch;;\
|
|
$name = "Beamer_HourCounter";;\
|
|
fhem(\
|
|
"setreading $name pulseTimeService "\
|
|
.ReadingsVal($name, "pulseTimeOverall", 0)\
|
|
);;\
|
|
return 1;;\
|
|
}
|
|
attr BeamerFilter_monitoring errorInterval 60*60*200
|
|
attr BeamerFilter_monitoring errorReturn {return if !@errors;;\
|
|
return "Der Filter vom Beamer muss gereinigt werden.";;\
|
|
}
|
|
attr BeamerFilter_monitoring warningFuncAdd {return}
|
|
attr BeamerFilter_monitoring warningFuncRemove {return}</pre>
|
|
An <a href="#HourCounter"><u>HourCounter</u></a> is used to record the
|
|
operating hours of a beamer and a
|
|
<a href="#dash_dhcp"><u>DashButton</u></a> to tell FHEM that the filter
|
|
has been cleaned.<br>
|
|
If the filter has not been cleaned for more than 200 hours, the device
|
|
is set to the error list.<br>
|
|
If cleaning is acknowledged with the DashButton, the device is removed
|
|
from the error list and the current operating hours are stored in the
|
|
HourCounter device.
|
|
</li>
|
|
</ul>
|
|
</ul>
|
|
</div>
|
|
|
|
=end html
|
|
|
|
=begin html_DE
|
|
|
|
<a id="monitoring"></a>
|
|
<h3>monitoring</h3>
|
|
<div>
|
|
<ul>
|
|
Jedes <i>monitoring</i> verfügt über eine <i>warning</i>- und eine <i>error</i>-Liste,
|
|
welche als Readings gespeichert werden.<br>
|
|
Beim Auftreten eines definierten add-events wird das Gerät nach einer
|
|
vorgegeben Zeit auf die warning-Liste gesetzt.<br>
|
|
Nach einer weiteren vorgegeben Zeit wird das Gerät von der
|
|
warning-Liste gelöscht und auf die error-Liste gesetzt.<br>
|
|
Beim Auftreten eines definierten remove-events wird das Gerät von
|
|
beiden Listen gelöscht und noch laufende Timer abgebrochen.<br>
|
|
Hiermit lassen sich auf einfache Weise Sammelmeldungen erstellen und durch
|
|
zwei Attribute formatiert ausgeben.<br>
|
|
<br>
|
|
Folgende Anwendungen sind möglich und werden
|
|
<a href="#monitoring-examples"><u>unten</u></a> beschrieben:<br>
|
|
<ul>
|
|
<li>geöffnete Fenster</li>
|
|
<li>Batterie Warnungen</li>
|
|
<li>Activity Monitor</li>
|
|
<li>
|
|
regelmäßige Wartungsarbeiten
|
|
(z.B. Tischwasserfilter wechseln oder Räume putzen)
|
|
</li>
|
|
<li>
|
|
Betriebsstunden abhängige Wartungsarbeiten
|
|
(z.B. Beamer Filter reinigen)
|
|
</li>
|
|
</ul>
|
|
<br>
|
|
Das monitor sendet selbst keine Benachrichtung, hierfür ist ein <a href="#notify"><u>notify</u></a>
|
|
oder <a href="#DOIF"><u>DOIF</u></a> notwendig, welches auf das Event "<monitoring-name> error
|
|
add: <name>" reagiert und dann den Rückgabewert von
|
|
"get <monitoring-name> default" versendet.
|
|
<br>
|
|
<a id="monitoring-define"></a>
|
|
<h4>Define</h4>
|
|
<ul>
|
|
<code>
|
|
define <name> monitoring <add-event> [<remove-event>]
|
|
</code>
|
|
<br>
|
|
Die Syntax für <add-event> und <remove-event> ist die
|
|
gleiche wie für das Suchmuster von
|
|
<a href="#notify"><u>notify</u></a> (Gerätename
|
|
oder Gerätename:Event).<br>
|
|
Ist nur ein <add-event> definiert wird beim auftreten das
|
|
Gerät von beiden Listen gelöscht und die Timer für warning
|
|
und error werden gestartet.<br>
|
|
</ul>
|
|
<a id="monitoring-set"></a>
|
|
<h4>Set</h4>
|
|
<ul>
|
|
<a id="monitoring-set-active"></a><li>
|
|
<code>active</code><br>
|
|
Es passieren zwei Dinge:<br>
|
|
1. Stellt noch ausstehende Timer wieder her, bzw. setzt die Geräte
|
|
sofort auf die entsprechende Liste, falls der Zeitpunkt in der
|
|
Vergangenheit liegt.<br>
|
|
2. Führt die unter dem Attribut "setActiveFunc" angegeben Befehle
|
|
aus.
|
|
</li>
|
|
<a id="monitoring-set-clear"></a><li>
|
|
<code>clear (warning|error|all)</code><br>
|
|
Entfernt alle Geräte von der angegeben Liste und bricht für
|
|
diese Liste laufende Timer ab. Bei "all" werden alle Geräte von
|
|
beiden Listen entfernt und alle laufenden Timer abgebrochen.
|
|
</li>
|
|
<a id="monitoring-set-errorAdd"></a><li>
|
|
<code>errorAdd <name></code><br>
|
|
Fügt <name> zu der error-Liste hinzu.
|
|
</li>
|
|
<a id="monitoring-set-errorRemove"></a><li>
|
|
<code>errorRemove <name></code><br>
|
|
Entfernt <name> von der error-Liste.
|
|
</li>
|
|
<a id="monitoring-set-inactive"></a><li>
|
|
<code>inactive</code><br>
|
|
Deaktiviert das monitoring. Beachte den leichten semantischen
|
|
Unterschied zum disable Attribut: "set inactive" wird bei einem
|
|
shutdown automatisch in fhem.state gespeichert, es ist kein save
|
|
notwendig.
|
|
</li>
|
|
<a id="monitoring-set-warningAdd"></a><li>
|
|
<code>warningAdd <name></code><br>
|
|
Fügt <name> zu der warning-Liste hinzu.
|
|
</li>
|
|
<a id="monitoring-set-warningRemove"></a><li>
|
|
<code>warningRemove <name></code><br>
|
|
Entfernt <name> von der warning-Liste.
|
|
</li>
|
|
</ul>
|
|
<a id="monitoring-get"></a>
|
|
<h4>Get</h4>
|
|
<ul>
|
|
<a id="monitoring-get-all"></a><li>
|
|
<code>all</code><br>
|
|
Gibt, durch eine Leerzeile getrennt, die error- und warning-Liste
|
|
zurück.<br>
|
|
Die Formatierung kann dabei mit den Attributen "errorReturn" und
|
|
"warningReturn" eingestellt werden.
|
|
</li>
|
|
<a id="monitoring-get-default"></a><li>
|
|
<code>default</code><br>
|
|
Der "default" Wert kann in dem Attribut "getDefault" festgelegt werden
|
|
und ist dazu gedacht um die Konfiguration für den
|
|
Rückgabewert im monitoring Gerät zu belassen. Wird nichts
|
|
angegeben wird "all" verwendent.
|
|
</li>
|
|
<a id="monitoring-get-error"></a><li>
|
|
<code>error</code><br>
|
|
Gibt die error-Liste zurück.<br>
|
|
Die Formatierung kann dabei mit dem Attribut "errorReturn" eingestellt
|
|
werden.
|
|
</li>
|
|
<a id="monitoring-get-warning"></a><li>
|
|
<code>warning</code><br>
|
|
Gibt die warning-Liste zurück.<br>
|
|
Die Formatierung kann dabei mit dem Attribut "warningReturn"
|
|
eingestellt werden.
|
|
</li>
|
|
</ul>
|
|
<a id="monitoring-readings"></a>
|
|
<h4>Readings</h4>
|
|
<ul>
|
|
<li>
|
|
<code>allCount</code><br>
|
|
Zeigt die Anzahl der Geräte in der warning- und error-Liste an.
|
|
</li>
|
|
<li>
|
|
<code>error</code><br>
|
|
Durch Komma getrennte Liste von Geräten.
|
|
</li>
|
|
<li>
|
|
<code>errorAdd_<name></code><br>
|
|
Zeigt den Zeitpunkt an wann das Gerät auf die error-Liste gesetzt
|
|
wird.
|
|
</li>
|
|
<li>
|
|
<code>errorCount</code><br>
|
|
Zeigt die Anzahl der Geräte in der error-Liste an.
|
|
</li>
|
|
<li>
|
|
<code>state</code><br>
|
|
Zeigt den Status (active, inactive oder disabled) an. Bei "active" wird
|
|
angezeigt welches Gerät zu welcher Liste hinzugefügt bzw. von welcher
|
|
Liste entfernt wurde.
|
|
</li>
|
|
<li>
|
|
<code>warning</code><br>
|
|
Durch Komma getrennte Liste von Geräten.
|
|
</li>
|
|
<li>
|
|
<code>warningAdd_<name></code><br>
|
|
Zeigt den Zeitpunkt an wann das Gerät auf die warning-Liste
|
|
gesetzt wird.
|
|
</li>
|
|
<li>
|
|
<code>warningCount</code><br>
|
|
Zeigt die Anzahl der Geräte in der warning-Liste an.
|
|
</li>
|
|
</ul>
|
|
<a id="monitoring-attr"></a>
|
|
<h4>Attribute</h4>
|
|
<ul>
|
|
<li>
|
|
<a href="#addStateEvent">
|
|
<u><code>addStateEvent</code></u>
|
|
</a>
|
|
</li>
|
|
<a id="monitoring-attr-blacklist"></a><li>
|
|
<code>blacklist <devspec list></code><br>
|
|
Durch Leerzeichen getrennte Liste von devspecs, die ignoriert werden.<br>
|
|
Wenn das Attribut gesetzt wird, werden alle Geräte von beiden Listen gelöscht,
|
|
die durch die devspecs definiert sind .
|
|
</li>
|
|
<a id="monitoring-attr-disable"></a><li>
|
|
<code>disable (1|0)</code><br>
|
|
1: Deaktiviert das monitoring.<br>
|
|
0: siehe "set active"
|
|
</li>
|
|
<li>
|
|
<a href="#disabledForIntervals">
|
|
<u><code>disabledForIntervals HH:MM-HH:MM HH:MM-HH-MM ...</code></u>
|
|
</a>
|
|
</li>
|
|
<a id="monitoring-attr-errorFuncAdd"></a><li>
|
|
<code>errorFuncAdd {<perl code>}</code><br>
|
|
In dieser Funktion stehen die folgende Variablen zur Verfügung:
|
|
<br>
|
|
<ul>
|
|
<li>
|
|
<code>$name</code><br>
|
|
Name des Event auslösenden Gerätes
|
|
</li>
|
|
<li>
|
|
<code>$event</code><br>
|
|
Beinhaltet das komplette Event, z.B.
|
|
<code>measured-temp: 21.7 (Celsius)</code>
|
|
</li>
|
|
<li>
|
|
<code>$addMatch</code><br>
|
|
Hat den Wert 1, falls das add-event zutrifft
|
|
</li>
|
|
<li>
|
|
<code>$removeMatch</code><br>
|
|
Hat den Wert 1, falls das remove-event zutrifft
|
|
</li>
|
|
<li>
|
|
<code>$SELF</code><br>
|
|
Eigenname des monitoring
|
|
</li>
|
|
</ul>
|
|
Gibt die Funktion eine 1 zurück, wird das Gerät, nach der
|
|
Wartezeit, auf die error-Liste gesetzt.<br>
|
|
Wenn das Attribut nicht gesetzt ist wird auf <code>$addMatch</code>
|
|
geprüft.
|
|
</li>
|
|
<a id="monitoring-attr-errorFuncAdded"></a><li>
|
|
<code>errorFuncAdded {<perl code>}</code><br>
|
|
In dieser Funktion stehen die folgende Variablen zur Verfügung:
|
|
<br>
|
|
<ul>
|
|
<li>
|
|
<code>$name</code><br>
|
|
Name des Event auslösenden Gerätes
|
|
</li>
|
|
<li>
|
|
<code>$SELF</code><br>
|
|
Eigenname des monitoring
|
|
</li>
|
|
</ul>
|
|
Diese Funktion wird ausgeführt, wenn ein Gerät in die Fehlerliste aufgenommen wird.
|
|
</li>
|
|
<a id="monitoring-attr-errorFuncRemove"></a><li>
|
|
<code>errorFuncRemove {<perl code>}</code><br>
|
|
In dieser Funktion stehen die selben Variablen wie bei "errorFuncAdd"
|
|
zur Verfügung.<br>
|
|
Gibt die Funktion eine 1 zurück, wird das Gerät von der
|
|
error-Liste entfernt und noch laufende Timer werden abgebrochen.<br>
|
|
Wenn das Attribut nicht gesetzt ist wird bei einer DEF mit
|
|
<code><remove-event></code> auf <code>$removeMatch</code>
|
|
geprüft und bei einer DEF ohne <code><remove-event></code>
|
|
auf <code>errorFuncAdd</code>.
|
|
</li>
|
|
<a id="monitoring-attr-errorWait"></a><li>
|
|
<code>errorWait <perl code></code><br>
|
|
Wartezeit (Rückgabe in Sekunden) bis das Gerät auf die error-Liste gesetzt wird.
|
|
</li>
|
|
<a id="monitoring-attr-errorReturn"></a><li>
|
|
<code>errorReturn {<perl code>}</code><br>
|
|
In diesem Attribut stehen folgende Variablen zur Verfügung:
|
|
<ul>
|
|
<li>
|
|
<code>@errors</code><br>
|
|
Array mit allen Geräten auf der error-Liste.
|
|
</li>
|
|
<li>
|
|
<code>@warnings</code><br>
|
|
Array mit allen Geräten auf der warning-Liste.
|
|
</li>
|
|
<li>
|
|
<code>$SELF</code><br>
|
|
Eigenname des monitoring
|
|
</li>
|
|
</ul>
|
|
Mit diesem Attribut kann die Ausgabe die mit "get <name> error"
|
|
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>
|
|
<a id="monitoring-attr-getDefault"></a><li>
|
|
<code>getDefault (all|error|warning)</code><br>
|
|
Mit diesem Attribut kann festgelegt werden welche Liste/n mit "get
|
|
<name> default" zurück gegeben wird/werden. Wenn das
|
|
Attribut nicht gesetzt ist wird "all" verwendet.
|
|
</li>
|
|
<a id="monitoring-attr-setActiveFunc"></a><li>
|
|
<code>setActiveFunc <Anweisung></code><br>
|
|
Die Anweisung ist einer der FHEM
|
|
<a href="#command"><u>Befehlstypen</u></a> und wird beim Definieren des
|
|
monitoring oder bei "set active" ausgeführt.<br>
|
|
Für eine Batterie Meldung kann <code>"trigger battery=low
|
|
battery:low"</code> sinnvoll sein.
|
|
</li>
|
|
<a id="monitoring-attr-setInactiveFunc"></a><li>
|
|
<code>setInactiveFunc <Anweisung></code><br>
|
|
Die Anweisung ist einer der FHEM
|
|
<a href="#command"><u>Befehlstypen</u></a> und wird beim Definieren des
|
|
monitoring oder bei "set inactive" ausgeführt.
|
|
</li>
|
|
|
|
<a id="monitoring-attr-warningFuncAdd"></a><li>
|
|
<code>warningFuncAdd {<perl code>}</code><br>
|
|
Wie errorFuncAdd, nur für die warning-Liste.
|
|
</li>
|
|
<a id="monitoring-attr-warningFuncAdded"></a><li>
|
|
<code>warningFuncAdded {<perl code>}</code><br>
|
|
Wie errorFuncAdded, nur für die warning-Liste.
|
|
</li>
|
|
<a id="monitoring-attr-warningFuncRemove"></a><li>
|
|
<code>warningFuncRemove {<perl code>}</code><br>
|
|
Wie errorFuncRemove, nur für die warning-Liste.
|
|
</li>
|
|
<a id="monitoring-attr-warningWait"></a><li>
|
|
<code>warningWait <perl code></code><br>
|
|
Wie errorWait, nur für die warning-Liste.
|
|
</li>
|
|
<a id="monitoring-attr-warningReturn"></a><li>
|
|
<code>warningReturn {<perl code>}</code><br>
|
|
Wie errorReturn, nur für die warning-Liste.
|
|
</li>
|
|
<a id="monitoring-attr-whitelist"></a><li>
|
|
<code>whitelist <devspec list></code><br>
|
|
Durch Leerzeichen getrennte Liste von devspecs die erlaubt sind.<br>
|
|
Wenn das Attribut gesetzt wird, werden alle Geräte von beiden Listen
|
|
gelöscht, die nicht durch die devspecs definiert sind .
|
|
</li>
|
|
<li>
|
|
<a href="#readingFnAttributes">
|
|
<u><code>readingFnAttributes</code></u>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
<a id="monitoring-examples"></a>
|
|
<h4>Beispiele</h4>
|
|
<ul>
|
|
<a href="https://wiki.fhem.de/wiki/Import_von_Code_Snippets">
|
|
<u>
|
|
Die folgenden beispiel Codes können per "Raw defnition"
|
|
importiert werden.
|
|
</u>
|
|
</a>
|
|
<br><br>
|
|
<li>
|
|
<b>
|
|
Globale, flexible Fenster-/Tür-Offen-Meldungen
|
|
<a href="https://forum.fhem.de/index.php/topic,36504">
|
|
<u>(ähnlich wie im Forum beschrieben)</u>
|
|
</a>
|
|
</b>
|
|
<br>
|
|
<pre>defmod Fenster_monitoring monitoring .*:(open|tilted) .*:closed
|
|
attr Fenster_monitoring errorReturn {return if !@errors;;\
|
|
$_ = AttrVal($_, 'alias', $_) for @errors;;\
|
|
return("Das Fenster \"$errors[0]\" ist schon länger geöffnet.") if(int(@errors) == 1);;\
|
|
@errors = sort {lc($a) cmp lc($b)} @errors;;\
|
|
return(join("\n - ", "Die folgenden ".@errors." Fenster sind schon länger geöffnet:", @errors))\
|
|
}
|
|
attr Fenster_monitoring errorWait {AttrVal($name, 'winOpenTimer', 60*10)}
|
|
attr Fenster_monitoring warningReturn {return if !@warnings;;\
|
|
$_ = AttrVal($_, 'alias', $_) for @warnings;;\
|
|
return("Das Fenster \"$warnings[0]\" ist seit kurzem geöffnet.") if(int(@warnings) == 1);;\
|
|
@warnings = sort {lc($a) cmp lc($b)} @warnings;;\
|
|
return(join("\n - ", "Die folgenden ".@warnings." Fenster sind seit kurzem geöffnet:", @warnings))\
|
|
}</pre>
|
|
Sobald ein Gerät ein "open" oder "tilded" Event auslöst wird
|
|
das Gerät auf die warning-Liste gesetzt und es wird ein Timer
|
|
gestartet nach dessen Ablauf das Gerät von der warning- auf die
|
|
error-Liste verschoben wird. Die Wartezeit kann für jedes
|
|
Gerät per userattr "winOpenTimer" festgelegt werden. Der
|
|
Vorgabewert sind 10 Minuten.<br>
|
|
Sobald ein Gerät ein "closed" Event auslöst wird das
|
|
Gerät von beiden Listen gelöscht und noch laufende Timer
|
|
werden gestoppt.
|
|
</li>
|
|
<br>
|
|
<li>
|
|
<b>Batterieüberwachung</b><br>
|
|
<pre>defmod Batterie_monitoring monitoring .*:battery:.low .*:battery:.ok
|
|
attr Batterie_monitoring errorReturn {return if !@errors;;\
|
|
$_ = AttrVal($_, 'alias', $_) for @errors;;\
|
|
return("Bei dem Gerät \"$errors[0]\" muss die Batterie gewechselt werden.") if(int(@errors) == 1);;\
|
|
@errors = sort {lc($a) cmp lc($b)} @errors;;\
|
|
return(join("\n - ", "Die folgenden ".@errors." Geräten muss die Batterie gewechselt werden:", @errors))\
|
|
}
|
|
attr Batterie_monitoring errorWait 60*60*24*14
|
|
attr Batterie_monitoring warningReturn {return if !@warnings;;\
|
|
$_ = AttrVal($_, 'alias', $_) for @warnings;;\
|
|
return("Bei dem Gerät \"$warnings[0]\" muss die Batterie demnächst gewechselt werden.") if int @warnings == 1;;\
|
|
@warnings = sort {lc($a) cmp lc($b)} @warnings;;\
|
|
return(join("\n - ", "Die folgenden ".@warnings." Geräten muss die Batterie demnächst gewechselt werden:", @warnings))\
|
|
}</pre>
|
|
Sobald ein Gerät ein "battery: low" Event auslöst wird das
|
|
Gerät auf die warning-Liste gesetzt und es wird ein Timer
|
|
gestartet nach dessen Ablauf das Gerät von der warning- auf die
|
|
error-Liste verschoben wird. Die Wartezeit ist auf 14 Tage
|
|
eingestellt.<br>
|
|
Sobald ein Gerät ein "battery: ok" Event auslöst wird das
|
|
Gerät von beiden Listen gelöscht und noch laufende Timer
|
|
werden gestoppt.
|
|
</li>
|
|
<br>
|
|
<li>
|
|
<b>Activity Monitor</b><br>
|
|
<pre>defmod Activity_monitoring monitoring .*:.*
|
|
attr Activity_monitoring errorReturn {return if !@errors;;\
|
|
$_ = AttrVal($_, 'alias', $_) for @errors;;\
|
|
return("Das Gerät \"$errors[0]\" hat sich seit mehr als 24 Stunden nicht mehr gemeldet.") if(int(@errors) == 1);;\
|
|
@errors = sort {lc($a) cmp lc($b)} @errors;;\
|
|
return(join("\n - ", "Die folgenden ".@errors." Geräten haben sich seit mehr als 24 Stunden nicht mehr gemeldet:", @errors))\
|
|
}
|
|
attr Activity_monitoring errorWait 60*60*24
|
|
attr Activity_monitoring warningReturn {return if !@warnings;;\
|
|
$_ = AttrVal($_, 'alias', $_) for @warnings;;\
|
|
return("Das Gerät \"$warnings[0]\" hat sich seit mehr als 12 Stunden nicht mehr gemeldet.") if(int(@warnings) == 1);;\
|
|
@warnings = sort {lc($a) cmp lc($b)} @warnings;;\
|
|
return(join("\n - ", "Die folgenden ".@warnings." Geräten haben sich seit mehr als 12 Stunden nicht mehr gemeldet:", @warnings))\
|
|
}
|
|
attr Activity_monitoring warningWait 60*60*12</pre>
|
|
Geräte werden erst überwacht, wenn sie mindestens ein Event
|
|
ausgelöst haben. Sollte das Gerät in 12 Stunden kein weiterer
|
|
Event auslösen, wird es auf die warning-Liste gesetzt. Sollte das
|
|
Gerät in 24 Stunden kein weiteres Event auslösen, wird es von
|
|
der warning- auf die error-Liste verschoben.<br>
|
|
<br>
|
|
Hinweis: Es ist empfehlenswert das whitelist Attribut zu verwenden.
|
|
</li>
|
|
<br>
|
|
<li>
|
|
<b>
|
|
regelmäßige Wartungsarbeiten
|
|
(z.B. Tischwasserfilter wechseln)
|
|
</b>
|
|
<br>
|
|
<pre>defmod Wasserfilter_monitoring monitoring Wasserfilter_DashButton:.*:.short
|
|
attr Wasserfilter_monitoring errorReturn {return if !@errors;;\
|
|
return "Der Wasserfilter muss gewechselt werden.";;\
|
|
}
|
|
attr Wasserfilter_monitoring errorWait 60*60*24*30
|
|
attr Wasserfilter_monitoring warningReturn {return if !@warnings;;\
|
|
return "Der Wasserfilter muss demnächst gewechselt werden.";;\
|
|
}
|
|
attr Wasserfilter_monitoring warningWait 60*60*24*25</pre>
|
|
Hierbei wird ein <a href="#dash_dhcp"><u>DashButton</u></a> genutzt um
|
|
FHEM mitzuteilen, dass der Wasserfilter gewechselt wurde.<br>
|
|
Nach 30 Tagen wird der DashButton auf die error-Liste gesetzt.
|
|
</li>
|
|
<br>
|
|
<li>
|
|
<b>
|
|
regelmäßige Wartungsarbeiten
|
|
(z.B. Räume putzen)
|
|
</b>
|
|
<br>
|
|
<pre>defmod putzen_DashButton dash_dhcp
|
|
attr putzen_DashButton allowed AC:63:BE:2E:19:AF,AC:63:BE:49:23:48,AC:63:BE:49:5E:FD,50:F5:DA:93:2B:EE,AC:63:BE:B2:07:78
|
|
attr putzen_DashButton devAlias ac-63-be-2e-19-af:Badezimmer\
|
|
ac-63-be-49-23-48:Küche\
|
|
ac-63-be-49-5e-fd:Schlafzimmer\
|
|
50-f5-da-93-2b-ee:Arbeitszimmer\
|
|
ac-63-be-b2-07-78:Wohnzimmer
|
|
attr putzen_DashButton event-min-interval .*:5
|
|
attr putzen_DashButton port 6767
|
|
attr putzen_DashButton userReadings state {return (split(":", @{$hash->{CHANGED}}[0]))[0];;}
|
|
attr putzen_DashButton widgetOverride allowed:textField-long devAlias:textField-long
|
|
|
|
defmod putzen_monitoring monitoring putzen_DashButton:.*:.short
|
|
attr putzen_monitoring errorFuncAdd {$event =~ m/^(.+):/;;\
|
|
$name = $1;;\
|
|
return 1;;\
|
|
}
|
|
attr putzen_monitoring errorReturn {return if !@errors;;\
|
|
return("Der Raum \"$errors[0]\" muss wieder geputzt werden.") if(int(@errors) == 1);;\
|
|
return(join("\n - ", "Die folgenden Räume müssen wieder geputzt werden:", @errors))\
|
|
}
|
|
attr putzen_monitoring errorWait 60*60*24*7</pre>
|
|
Hierbei werden mehrere <a href="#dash_dhcp"><u>DashButton</u></a>
|
|
genutzt um FHEM mitzuteilen, dass die Räume geputzt wurden.<br>
|
|
Nach 7 Tagen wird der Raum auf die error-Liste gesetzt.<br>
|
|
Der Raum Name ist hierbei jedoch nicht der Geräte-Name, sondern der
|
|
Readings-Name und wird in dem <code>errorFuncAdd</code>-Attribut
|
|
geändert.
|
|
</li>
|
|
<br>
|
|
<li>
|
|
<b>
|
|
Betriebsstunden abhängige Wartungsarbeiten
|
|
(z.B. Beamer Filter reinigen)
|
|
</b>
|
|
<br>
|
|
<pre>defmod BeamerFilter_monitoring monitoring Beamer_HourCounter:pulseTimeOverall BeamerFilter_DashButton:.*:.short
|
|
attr BeamerFilter_monitoring userattr errorInterval
|
|
attr BeamerFilter_monitoring errorFuncAdd {return 1\
|
|
if(ReadingsVal($name, "pulseTimeOverall", 0) >= \
|
|
ReadingsVal($name, "pulseTimeService", 0)\
|
|
+ (AttrVal($SELF, "errorInterval", 0))\
|
|
&& $addMatch\
|
|
);;\
|
|
return;;\
|
|
}
|
|
attr BeamerFilter_monitoring errorFuncRemove {return if !$removeMatch;;\
|
|
$name = "Beamer_HourCounter";;\
|
|
fhem(\
|
|
"setreading $name pulseTimeService "\
|
|
.ReadingsVal($name, "pulseTimeOverall", 0)\
|
|
);;\
|
|
return 1;;\
|
|
}
|
|
attr BeamerFilter_monitoring errorInterval 60*60*200
|
|
attr BeamerFilter_monitoring errorReturn {return if !@errors;;\
|
|
return "Der Filter vom Beamer muss gereinigt werden.";;\
|
|
}
|
|
attr BeamerFilter_monitoring warningFuncAdd {return}
|
|
attr BeamerFilter_monitoring warningFuncRemove {return}</pre>
|
|
Hierbei wird ein <a href="#HourCounter"><u>HourCounter</u></a> genutzt
|
|
um die Betriebsstunden eine Beamer zu erfassen und ein
|
|
<a href="#dash_dhcp"><u>DashButton</u></a> um FHEM mitzuteilen, dass der
|
|
Filter gereinigt wurde.<br>
|
|
Wurde der Filter länger als 200 Betriebsstunden nicht gereinigt
|
|
wird das Gerät auf die error-Liste gesetzt.<br>
|
|
Wurde die Reinigung mit dem DashButton quittiert wird das Gerät
|
|
von der error-Liste entfernt und der aktuelle Betriebsstunden-Stand in
|
|
dem HourCounter Gerät gespeichert.
|
|
</li>
|
|
</ul>
|
|
</ul>
|
|
</div>
|
|
|
|
=end html_DE
|
|
=cut
|