diff --git a/contrib/DeviceMonitor/98_DeviceMonitor.pm b/contrib/DeviceMonitor/98_DeviceMonitor.pm index 83f4ed321..2f671affd 100644 --- a/contrib/DeviceMonitor/98_DeviceMonitor.pm +++ b/contrib/DeviceMonitor/98_DeviceMonitor.pm @@ -1,124 +1,266 @@ -# $Id: 98_DeviceMonitor.pm $ -# -# Copyright (C) 2012 Dennis Gnoyke -# -# This script is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# -# This library is free software; you can redistribute it and/or modify -# it under the same terms as Perl itself, either Perl version 5.8.7 or, -# at your option, any later version of Perl 5 you may have available. -# -package main; -use strict; -use warnings; - -sub DeviceMonitor_Initialize($) -{ - my ($hash) = @_; - $hash->{DefFn} = "DeviceMonitor_Define"; - $hash->{NotifyFn} = "DeviceMonitor_Notify"; - $hash->{AttrList} = "disable:0,1"; - addToAttrList("device_timeout"); -} - -sub DeviceMonitor_Define($$) -{ - my ($hash, $def) = @_; - my @a = split("[ \t][ \t]*", $def); - my $u = "wrong syntax: define DeviceMonitor "; - return $u if(int(@a) < 2); - $hash->{CHANGED}[0] = "DEFINED"; - $hash->{STATE} = "DEFINED"; - return undef; -} - -sub DeviceMonitor_Notify($$) -{ -#******************************************************************************* -# Purpose: Checks for timeout - Notify reacts on triggers fired from the Device -# Author : Dennis Gnoyke -# Date : 21.10.2012 -# Changes: 27.10.2012 GN Code optimized, Events reduced -# Remarks: EXPERIMENTAL VERSION !!!!!!! -# -#**************************** Begin of Code ************************************* - my ($ownhash, $devhash) = @_; - my $devName = $devhash->{NAME} ; #Name of the Device which has triggered this event - my $ownName = $ownhash->{NAME} ; #Name of DeviceMonitor - my $enabled = $ownhash->{ENABLED}; #DeviceMonitor enabled ? - my $timeoutinterval = 0; - my $devState = "unknown"; - - $timeoutinterval = AttrVal($devName, "device_timeout", "undef"); #Timeout configured ? - return "" if ($timeoutinterval eq "undef"); - - $devhash->{HEALTH_MONITORED_BY} = $ownName; - - if(AttrVal($devName, "disable", 0) > 0){$timeoutinterval = 0}; #Device Enabled ? - if(AttrVal($ownName, "disable", 0) > 0) #DeviceMonitor Enabled ? - { - $timeoutinterval = 0; - $ownhash->{STATE} = "DISABLED"; - } - else - { - $ownhash->{STATE} = "ENABLED"; - } - - # Get current HealthState - if (!defined($devhash->{HEALTH_STATE})) - { - $devState = "unknown"; - } - else - { - $devState = $devhash->{HEALTH_STATE}; - } - - if ($timeoutinterval < 1) #device_timeout set to 0 - { - if ($devState ne "unknown"){DoTrigger($devName,"health_state: unknown")}; - $devhash->{HEALTH_STATE} = "unknown"; - $devhash->{HEALTH_TIME} = TimeNow(); - $ownhash->{READINGS}{$devName}{VAL} = "unknown"; - $ownhash->{READINGS}{$devName}{TIME} = TimeNow(); - } - else - { - if ($devState ne "alive"){DoTrigger($devName,"health_state: alive")}; - RemoveInternalTimer($devhash); - $devhash->{HEALTH_STATE} = "alive"; - $devhash->{HEALTH_TIME} = TimeNow(); - $ownhash->{READINGS}{$devName}{VAL} = "alive"; - $ownhash->{READINGS}{$devName}{TIME} = TimeNow(); - InternalTimer(gettimeofday()+($timeoutinterval*60), "DeviceMonitor_Timer", $devhash, 0); - } - return undef; -#**************************** End of Code ************************************* - } - -sub DeviceMonitor_Timer($) -{ -#******************************************************************************* -# Purpose: Checks for timeout - Will be called if timeout occured -# Author : Dennis Gnoyke -# Date : 21.10.2012 -# Changes: 22.10.2012 GN Typo Death -> Dead -# Remarks: EXPERIMENTAL VERSION !!!!!!! -# -#**************************** Begin of Code ************************************* - #set the HEALTH_STATE to "dead" if not already set - my ($devhash) = @_; - my $ownName = $devhash->{HEALTH_MONITORED_BY}; - my $devName = $devhash->{NAME}; - - DoTrigger($devName,"health_state: dead"); - $devhash->{HEALTH_STATE} = "dead"; - $devhash->{HEALTH_TIME} = TimeNow(); - $defs{$ownName}{READINGS}{$devName}{TIME} = TimeNow(); - $defs{$ownName}{READINGS}{$devName}{VAL} = "dead"; -#**************************** End of Code ***************************************** -} +# $Id: 98_DeviceMonitor.pm $ +# +# Copyright (C) 2012 Dennis Gnoyke +# +# This script is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# +# This library is free software; you can redistribute it and/or modify +# it under the same terms as Perl itself, either Perl version 5.8.7 or, +# at your option, any later version of Perl 5 you may have available. +# +package main; +use strict; +use warnings; + +sub DeviceMonitor_Initialize($) +{ + my ($hash) = @_; + $hash->{DefFn} = "DeviceMonitor_Define"; + $hash->{UndefFn} = "DeviceMonitor_Undef"; + $hash->{NotifyFn} = "DeviceMonitor_Notify"; + $hash->{GetFn} = "DeviceMonitor_Get"; + $hash->{AttrList} = "disable:0,1"; + addToAttrList("device_timeout"); +} + +sub DeviceMonitor_Define($$) +{ + my ($hash, $def) = @_; + my @a = split("[ \t][ \t]*", $def); + my $u = "wrong syntax: define DeviceMonitor "; + return $u if(int(@a) < 2); + $hash->{CHANGED}[0] = "DEFINED"; + $hash->{STATE} = "DEFINED"; + return undef; +} + +sub +DeviceMonitor_Undef($$) +{ + my ($hash, $arg) = @_; + + return DeviceMonitor_Remove($hash,"all"); + return undef; +} + + +sub DeviceMonitor_Get($@) +{ +#******************************************************************************* +# Purpose: Get some results +# Author : Dennis Gnoyke +# Date : 27.10.2012 +# Changes: +# Remarks: +#**************************** Begin of Code ************************************* + my ($hash, @a) = @_; + return "argument is missing" if(int(@a) != 2); + + my ($criteria, $output) = split ("_",lc($a[1])); + return DeviceMonitor_GetResult($a[0],$criteria,$output); +#**************************** End of Code ***************************************** +} + +sub DeviceMonitor_Notify($$) +{ +#******************************************************************************* +# Purpose: Checks for timeout - Notify reacts on triggers fired from the Device +# Author : Dennis Gnoyke +# Date : 21.10.2012 +# Changes: 27.10.2012 GN Code optimized, Events reduced +# Remarks: EXPERIMENTAL VERSION !!!!!!! +# +#**************************** Begin of Code ************************************* + my ($ownhash, $devhash) = @_; + my $devName = $devhash->{NAME} ; #Name of the Device which has triggered this event + my $ownName = $ownhash->{NAME} ; #Name of DeviceMonitor + my $enabled = $ownhash->{ENABLED}; #DeviceMonitor enabled ? + my $timeoutinterval = 0; + my $devState = "unknown"; + + $timeoutinterval = AttrVal($devName, "device_timeout", 0); #Timeout configured ? + return "" if ($timeoutinterval < 1 && !defined($defs{$devName}{HEALTH_MONITORED_BY})); #Leave NTFY if device is not configured for DeviceMonitor + + if(AttrVal($devName, "disable", 0) > 0){$timeoutinterval = 0}; #Device Enabled ? + if(AttrVal($ownName, "disable", 0) > 0) #DeviceMonitor Enabled ? + { + $timeoutinterval = 0; + $ownhash->{STATE} = "DISABLED"; + } + else + { + $ownhash->{STATE} = "ENABLED"; + } + + Log 4, "'$devName' is now monitored by '$ownName'" if(!defined($defs{$devName}{HEALTH_MONITORED_BY})); + $devhash->{HEALTH_MONITORED_BY} = $ownName; + # Get current HealthState + if (!defined($devhash->{HEALTH_STATE})){$devState = "unknown"}else{$devState = $devhash->{HEALTH_STATE}} + + if ($timeoutinterval < 1) #device_timeout set to 0, remove it from monitor + { + DeviceMonitor_Remove($ownName,$devName); + RemoveInternalTimer($devhash); + } + else + { + if ($devState ne "alive"){DoTrigger($devName,"health_state: alive")}; + RemoveInternalTimer($devhash); + $devhash->{HEALTH_STATE} = "alive"; + $devhash->{HEALTH_TIME} = TimeNow(); + $ownhash->{READINGS}{$devName}{VAL} = "alive"; + $ownhash->{READINGS}{$devName}{TIME} = TimeNow(); + InternalTimer(gettimeofday()+($timeoutinterval*60), "DeviceMonitor_Timer", $devhash, 0); + } + return undef; +#**************************** End of Code ************************************* + } + +sub DeviceMonitor_Timer($) +{ +#******************************************************************************* +# Purpose: Checks for timeout - Will be called if timeout occured +# Author : Dennis Gnoyke +# Date : 21.10.2012 +# Changes: 22.10.2012 GN Typo Death -> Dead +# Remarks: +# +#**************************** Begin of Code ************************************* + #set the HEALTH_STATE to "dead" if not already set + my ($devhash) = @_; + my $ownName = $devhash->{HEALTH_MONITORED_BY}; + my $devName = $devhash->{NAME}; + + if(AttrVal($devName, "device_timeout", 0) < 1) #device_timeout set to 0, remove it from monitor + { + DeviceMonitor_Remove($ownName,$devName); + } + else + { + DoTrigger($devName,"health_state: dead"); + $devhash->{HEALTH_STATE} = "dead"; + $devhash->{HEALTH_TIME} = TimeNow(); + $defs{$ownName}{READINGS}{$devName}{TIME} = TimeNow(); + $defs{$ownName}{READINGS}{$devName}{VAL} = "dead"; + } + RemoveInternalTimer($devhash); +#**************************** End of Code ***************************************** +} + +sub DeviceMonitor_GetResult($$$) +{ +#******************************************************************************* +# Purpose: Get results from DeviceMonitor readings +# Author : Dennis Gnoyke +# Date : 27.10.2012 +# Changes: +# Remarks: $_[0] = DeviceMonitor +# $_[1] = Criteria dead|alive|total +# $_[2] = Output as count|text|html +#**************************** Begin of Code ************************************* + my $hash = $defs{$_[0]}{READINGS}; + my $cnt = 0; #counter + my @result ; #result array + $result[0] ="null"; #default + my $tmp = ""; #temp var + + foreach my $readings_name (sort keys %{$hash}) #Loop through Readings + { + my $val = $hash->{$readings_name}; + if(ref($val)) + { + my $readings_value = $val->{VAL}; + my $readings_time = $val->{TIME}; + if ($readings_value eq $_[1]) #value like dead or alive + { + $result["$cnt"] = $readings_name.','."has health_state '$readings_value' reported at $readings_time"; + $cnt = $cnt + 1 + } + elsif($_[1] eq "total") + { + $result["$cnt"] = $readings_name.','."has health_state '$readings_value' reported at $readings_time"; + $cnt = $cnt + 1 + } + } + } + if ($result[0] eq "null") + { + return 0 if($_[2] eq "count"); + return "$_[0]: There was no match for your criteria '$_[1]'" if($_[2] eq "text"); + return "$_[0]: There was no match for your criteria '$_[1]'" if($_[2] eq "html"); + return "$_[0]: Unknown argument $_[2] , syntax is _ criteria=dead,alive,total output=count,text,html"; + } + else + { + if($_[2] eq "count"){return $cnt} + elsif($_[2] eq "text") + { + foreach (@result) + { + my ($device, $value) = split (",",$_); + $tmp .= "Device $device $value\n"; + } + return $tmp; + } + elsif($_[2] eq "html") + { + $tmp = "\n"; + foreach (@result) + { + my ($device, $value) = split (",",$_); + $tmp .= "\n"; + }; + $tmp .= "
Device $device $value
"; + return $tmp; + } + else{return "$_[0]: Unknown argument $_[2] , syntax is _ criteria=dead,alive,total output=count,text,html"} + } +#**************************** End of Code ***************************************** +} + + +sub DeviceMonitor_Remove($$) +{ +#******************************************************************************* +# Purpose: Resets DeviceMonitor readings +# Author : Dennis Gnoyke +# Date : 28.10.2012 +# Changes: +# Remarks: $_[0] = DeviceMonitor +# $_[1] = Criteria devicename|all +# +#**************************** Begin of Code ************************************* + my $hash = $defs{$_[0]}{READINGS}; + + if(defined($hash->{$_[1]})) #remove single device from monitor + { + delete $hash->{$_[1]}; + if(defined($defs{$_[1]}{HEALTH_MONITORED_BY})){delete $defs{$_[1]}{HEALTH_MONITORED_BY}}; + if(defined($defs{$_[1]}{HEALTH_STATE})){delete $defs{$_[1]}{HEALTH_STATE}}; + if(defined($defs{$_[1]}{HEALTH_TIME})){delete $defs{$_[1]}{HEALTH_TIME}}; + RemoveInternalTimer($defs{$_[1]}); + Log 4, "'$_[1]' is no longer monitored by '$_[0]'"; + } + elsif(uc($_[1]) eq "ALL") #remove all devices from monitor + { + foreach my $readings_name (sort keys %{$hash}) #Loop through Readings + { + delete $hash->{$readings_name}; + if(defined($defs{$readings_name}{HEALTH_MONITORED_BY})){delete $defs{$readings_name}{HEALTH_MONITORED_BY}}; + if(defined($defs{$readings_name}{HEALTH_STATE})){delete $defs{$readings_name}{HEALTH_STATE}}; + if(defined($defs{$readings_name}{HEALTH_TIME})){delete $defs{$readings_name}{HEALTH_TIME}}; + RemoveInternalTimer($defs{$readings_name}); + } + Log 4, "all devices removed from '$_[0]', please note that devices will appear again if their device_timeout attr is still set and '$_[0]' is defined and enabled!"; + } + else + { + return "$_[0]: Can`t remove $_[1] check spelling and upper/lower cases"; + } + +#**************************** End of Code ***************************************** +} + 1; \ No newline at end of file