#! /usr/bin/perl
#
#check_watchptHumid_linux.pl
#2009 - 2010 Julius Schlosburg
#Gets humidity from a Watchport Digi sensor
# Mandatory switches:
# -wu	Upper humidity warning
# -cu		Upper humidity critical
# -cl		Lower humidity warning
# -wl		Lower humidity critical
#
# optional:
#
# --port		port
# -h, --help	show help
#
#    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, either version 3 of the License, or
#    (at your option) any 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, see <http://www.gnu.org/licenses/>.

use strict;
use Device::SerialPort;
use Getopt::Long;
use Array::Compare;

my $argwu;
my $argcu;
my $argwl;
my $argcl;
my $argPort = '';
my $argHelp;
 
#get limited options set
GetOptions(
	"wu=i" => \$argwu,
	"cu=i" => \$argcu,
	"wl=i" => \$argwl,
	"cl=i" => \$argcl,
	"port:s" => \$argPort,
	"h|help" => \$argHelp
);

my $exitcode = 3;
my $warningL = $argwl;
my $criticalL = $argcl;
my $warningU = $argwu;
my $criticalU = $argcu;
my $port = $argPort;
my $showHelp = $argHelp;

#validate options
if($port eq ""){
	$port = "/dev/ttyUSB0";
}

if($warningL == "" || $criticalL == "" || $warningU == "" || $criticalU == "" || $showHelp){
	print "Usage: \n perl check_watchptHumid_linux.pl -wu <upper warning level> -cu <upper critical level> -wl <lower warning level> -cl <lower critical level> [--port <port to use, default /dev/ttyUSB0>]\n\n";
	exit;
}

# $options is in the correct order
my @options = ($criticalL,$warningL,$warningU,$criticalU);
# If $options is different after it's sorted then the arguments don't make sense, i.e. the lower warning % can't be lower than the lower critical %
my @sOptions = sort{$a <=> $b} @options;
my $comparator = Array::Compare->new;
if(!$comparator->compare(\@options, \@sOptions)){
	print "Your warn and crit levels don\'t make sense. The values must have the following relationship: \'cl < wl < wu < cu\'. \n Remember these are humidity percents!\n";
	exit;
}

my $state = 4;

#get temp
my $humidity = getHumidity($port);
	
if ($humidity > $warningU){
	$state++;
}
elsif ($humidity < $warningU){
		$state--;
}
if ($humidity > $criticalU){
	$state++;
}
elsif ($humidity < $criticalU){
		$state--;
}
if ($humidity < $warningL){
	$state++;
}
elsif ($humidity > $warningL){
		$state--;
}
if ($humidity < $criticalL){
	$state++;
}
elsif ($humidity > $criticalL){
		$state--;
}
if ($state eq 0){
	print "OK: Humidity is good at $humidity%";
	$exitcode = '0';
}
elsif ($state  < 3){
		print "WARNING: Humidity is at $humidity%";
		$exitcode = '1';
}
elsif ($state eq 4){
		print "CRITICAL: Humidity is at $humidity%";
		$exitcode = '2';
}
#Performance data:
print "|humidity=$humidity;$warningU;$criticalU;$warningL;$criticalL;0;100\n";
exit $exitcode;
	
#######################SUBS################################################

sub getHumidity{
	
	my $usbPort = $_[0];
	#Create Serial port object
	my $ob = Device::SerialPort->new ($port) or die "CRITICAL, can't open serial port $port! $!";
	$ob->baudrate(9600);
	$ob->parity('none');
	$ob->databits(8);
	$ob->stopbits(1);
	$ob->handshake('none');
	$ob->stty_inlcr;
	$ob->write_settings || undef $ob;
	# Send TF command to watchport... tells device to return temp in F
	$ob->write("H\r");
	$ob->read_char_time(5);
	my ($count, $humidityRead) = $ob->read(255);
	if ($humidityRead =~ /(\d{1,3})%/){
		$humidityRead = $1;
	}
	undef $ob;
	return $humidityRead;
}
