#!/usr/bin/perl -w

# ---

=head1 NAME

check_voltage.pl - Nagios plugin for checking voltage of eib/knx nodes

=head1 SYNOPSIS

=over 4

=item check_voltage.pl -E EIB/KNX-address -U url [-v] [-w warning_threshold] [-c critical_threshold]

=item check_voltage.pl [-h|-V]

=back

=head1 OPTIONS

=over 4

=item -E|--eibaddr=expression

Physical EIB/KNX address e.g. 1.1.1 

=item -U|--url=expression

BCU-Connection to EIB/KNX-Bus e.g. ip:127.0.0.1

=item -w|--warning=threshold

threshold can be max (warn if < 0 or > max), min:max (warn if < min or >
max), min: (warn if < min), or @min:max (warn if >= min and <= max). All
values must be integer.

=item -c|--critical=threshold

see --warning for explanation of threshold format

=item -t|--timeout=seconds

timeout after check_voltage.pl exits.

=item -v|--verbose

increases verbosity, specify twice to see the original output.

=item -V|--version

print version and exit

=item -h|--help

print help message and exit

=back

=cut

use strict;				# strict syntax usage, predeclared Vars
use warnings; 				# for perl versions lesser than 5.6
use FindBin;				# find path from this plugin
use lib "$FindBin::Bin/../perl/lib";		
use Nagios::Plugin; 			# with const, vars and functions
use Getopt::Long qw(:config no_ignore_case bundling); 	# Get options 
							# case-sensitive
                                                        # bundled options
use Pod::Usage;				# Perl Online Dokumentation (POD)
#use Test::More tests => 6;		# Testing Module for development

### Variables ################################################################
my $np = Nagios::Plugin->new(shortname => "VOLTAGE");  # create Nagios Object
#ok(defined $np,'new is giving something back');
#ok($np->isa('Nagios::Plugin'),'is from the right type');
my $warn_threshold = '0:';
my $crit_threshold = '0:';
my $what = '';
my $result = UNKNOWN;
my $version = 'V1.1/2010-07-01';
my $printversion = 0;
my $verbose = 0;
my $help = 0;
my $timeout = 10;  # 10s by default
my $debug = 0;
my $voltage = 0;
my $url = '';
##############################################################################

GetOptions(
   "E|eibaddr=s"	=> \$what,		# =s string type
   "w|warnings=s"	=> \$warn_threshold,
   "c|critical=s"	=> \$crit_threshold,
   "t|timeout=s"	=> \$timeout,
   "h|help"		=> \$help,
   "V|version"		=> \$printversion,
   "v|verbose+"		=> \$verbose,		# Option can set multiple
   "d|debug:+"		=> \$debug,
   "U|url=s"		=> \$url		#  e.g ip:127.0.0.1
) or pod2usage({ -exitval => UNKNOWN,
                 -verbose => 0,
                 -msg     => "*** unknown argument found ***" });

pod2usage(-verbose => 2,
          -exitval => UNKNOWN,
	  -output  => \*STDOUT,
         ) if ( $help );

pod2usage(-msg     => "\n$0 -- version: $version\n",
          -verbose => 0,
          -exitval => UNKNOWN,
         ) if ( $printversion );

pod2usage(-msg     => "*** no eibaddr and/or url specified ***",
          -verbose => 0,
          -exitval => UNKNOWN,
	) unless ($what && $url) ;

# Test of the options
#ok($crit_threshold =~ /^\d\d$/,'Crit-Value has two numbers');
#ok($warn_threshold =~ /^\d\d$/,'Warn-Value has two numbers');
#ok($what =~ /^(\d|\d\d)\.\d\.(\d|\d\d|\d\d\d)$/,'Eibaddr has right format');
#ok($timeout =~ /\d/, 'Timeoutvalue is a number');

if ( $debug >= 2 ) {                               # Debug Information
	print "Plugin options:\n";
	printf "    %-23s %d\n", "verbose:", $verbose;
	printf "    %-23s %s\n", "warning:", $warn_threshold || '';
	printf "    %-23s %s\n", "critical:", $crit_threshold || '';
	printf "    %-23s %s\n", "timeout:", $timeout || '';
	printf "    %-23s %s\n", "eibaddr:", $what || '';
	printf "    %-23s %s\n", "debug:", $debug || '';
	printf "    %-23s %s\n", "url:", $url || '';
	printf "    %-23s %s\n", "version:", $version || '';
}

# set timeout alarm
$SIG{ALRM} = sub { $np->nagios_die("Timeout reached"); }; # Return: UNKNOWN
alarm($timeout);

# allocate thresholds
$np->set_thresholds(
   warning  => $warn_threshold,		# Option -w to warn_threshold
   critical => $crit_threshold		# Option -c to crit_threshold
);

# Debug-Information about threshold values
print "DEBUG: warn= $warn_threshold, crit= $crit_threshold\n" if ($debug);

# The core programm call
open ( OUT, "LANG=C /usr/bin/madcread $url $what 1 1 2>&1 |" ) # open Output
   or $np->nagios_die( "can't start /usr/bin/madcread" );      # LANG=C for Engl

while (<OUT>) {					# While OUTPUT is there
   print "$_" if ($verbose);			# if verbose, print current line
   chomp $_;					# Cut current textline $_

   if ($_ =~ /^Value: /) 			# If "Value: " is the first word
   {
      ($voltage = $_) =~ s/Value: //i;    	# Delete string "Value: "
      $voltage *= 0.15;				# Convert to Volt-Value
      last;      				# Exit Loop
   }
   else 
   {
      $np->nagios_exit( CRITICAL, "unreadable voltage");
      last;
   }
}
close (OUT);

# Debug-Messages
if ($debug >= 2)
{
	printf "    %-23s %d\n", "voltage:", $voltage;
}

# Performance-Data
$np->add_perfdata( label => "voltage", value => $voltage, 
                   uom => "V", threshold => $np->threshold() # Unit Of Mes. 
);

# Compare the actual value with the threshold
$result = $np->check_threshold(  $voltage );

# Reset alarm
alarm(0);

# Return exit-code
$np->nagios_exit( $result, "Voltage: $voltage Volt"); 

=head1 EXAMPLES

=head2 Command line example

Check the voltage of the EIB/KNX-Bus at an EIB/KNX-Device over IP-Gateway:

$ check_voltage.pl -E 1.1.1 -U ip:127.0.0.1 

VOLTAGE OK - Voltage: 27 Volt

=head2 Nagios configuration example

 define command {
   command_name    check_voltage
   command_line    $USER1$/check_voltage.pl --eibaddr $HOSTADDRESS$ --url 
                   $ARG1$ -w $ARG2$ -c $ARG3$
 }

 define service {
   host_name            1.1.1:_Switch
   service_description  Voltage
   check_command        check_voltage!ip:127.0.0.1!22:29!21:30
   use                  generic-service
}

The Values for Warning and Critical are recommanded by the EIB/KNX-Specs, that limit the voltage from minimum 21 Volts to 30 Volts. One Volt before these Values you will get a warning message from Nagios by using this values. 

 define host {
   use                   generic-node            ; Name of host template
   host_name             1.1.1:_Switch
   alias                 Switch 1.1.1
   address               1.1.1
 }

The pysical Address of the EIB/KNX-Device is defined as regular address.

=head1 NAGIOS PLUGIN NOTES

Nagios plugin reference: http://nagiosplug.sourceforge.net/developer-guidelines.html

This plugin does NOT use Nagios DEFAULT_SOCKET_TIMEOUT (provided by utils.pm as $TIMEOUT) because the path to utils.pm must be specified completely in this program and forces users to edit the source code if their install location is different (if they realize this is the problem). The utils.pm will be deprecated soon and using the Nagios::Plugin from CPAN is recommanded. You can view the default timeout for this module by using the -vv option. 

Other than that, it attempts to follow published guidelines for Nagios plugins.

=head1 AUTHOR

Sebastian Renker, <sebastian.renker@stud.fh-erfurt.de>

=head1 KNOWN ISSUES

none

=head1 BUGS

none

=head1 LICENSE

This program 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; version 2 of the License (and no
later version).

This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

=head1 HISTORY

V1.1/2010-07-01 following nagios plugin development guidelines
V1.0/2010-05-06 inital version for bachelor thesis

=cut
