#!/bin/sh

# check temperature and humidity using the temper command
version="1.1"

# temper generates output like
#   /dev/hidraw3    TEMPer2HumiV1.x 34.26   20.5
#   /dev/hidraw1    TEMPerV1.2      27.62   XX

# check_tempers looks at the minimum/maximum over all devices,
# or at a single device

# Use -h for usage and help

# https://www.syonex.com/resources/software/
# John Sellens jsellens@syonex.com
# Use as you wish, provided "AS IS", no warranties


PATH=/usr/local/sbin:/sbin:/usr/sbin:/usr/local/bin:/bin:/usr/bin
# PATH=/usr/lib/nagios/plugins:$PATH
export PATH
umask 022

myname=`basename "$0"`
tmp="/tmp/$myname.$$"
trap "rm -f '$tmp'" EXIT

OK=0
WARNING=1
CRITICAL=2
UNKNOWN=3


errorout() {
    if [ -z "$mrtg" ]; then
	# on stdout, because nagios likes it that way
	echo "$@"
    else
	# on stderr, with name, because we are not nagios style
	echo 1>&2 "$myname:" "$@"
    fi
}
error() {
    if [ -z "$mrtg" ]; then
	# on stdout, because nagios likes it that way
	echo "$myname:" "$@"
    else
	# on stderr, because we are not nagios style
	echo 1>&2 "$myname:" "$@"
    fi
}
fatal() {
    error "$@"
    exit $UNKNOWN
}
usagestr='[-t type] [-d device] [-m]
    [-H hostname] [-u url]
    [-cT temp] [-ct temp] [-wT temp] [-wt temp]
    [-cH hum] [-ch hum] [-wH hum] [-wh hum]
    [-F] [-C]'
usage() {
    fatal "usage: $myname $usagestr"
}
help() {
    cat <<EOF
$myname version $version John Sellens jsellens@syonex.com

Check temperature and humidity using the temper command.
Limits are applied to the minimum/maxmimum values reported
across all devices selected.

Usage:
$myname $usagestr

Option and argument parsing is rather rudimentary.

Options (none are required):
 -h, --help
    Print (this) detailed help screen
-d device
    Consider only the results from this device e.g. /dev/hidraw1
-H hostname
    Probe URL on hostname, rather than running temper locally
-mh
    MRTG style output, not Nagios plugin style -- min, max humidity)
    Reported in hundredths of a percent of relative humidity.
-mt
    MRTG style output, not Nagios plugin style -- min, max temperature
    Reported in hundredths of a degree of temperature.
-np
    No proxy -- if checking a URL, tell curl to not use any defined proxy
-t type
    Consider only the results from this type e.g. TEMPerV1.2
-u url
    Probe URL, rather than running temper locally.
    Default url is http://hostname/quick/temperc
    If url is provided, hostname (if any) is ignored.
-C
    Temperature values are in degreses Celsius (default)
-F
    Temperature values are in degreses Fahrenheit
-cH hum
    Critical if maximum humidity is greater than the value 'hum'
-ch hum
    Critical if minimum humidity is less than the value 'hum'
-cT temp
    Critical if maximum temperature is greater than the value 'temp'
-ct temp
    Critical if minimum temperature is less than the value 'temp'
-wH hum
    Warning if maximum humidity is greater than the value 'hum'
-wh hum
    Warning if minimum humidity is less than the value 'hum'
-wT temp
    Warning if maximum temperature is greater than the value 'temp'
-wt temp
    Warning if minimum temperature is less than the value 'temp'
EOF
    exit 0
}

ok() {
    echo OK: "$@"
    exit $OK
}
warning() {
    errorout WARNING: "$@"
    exit $WARNING
}
critical() {
    errorout CRITICAL: "$@"
    exit $CRITICAL
}
unknown() {
    errorout UNKNOWN: "$@"
    exit $UNKNOWN
}


degrees="C"
host=""
mrtg=""
noproxy=""
temperarg=""
temperurl="temperc"
url=""
while [ $# -gt 0 ]; do
    case "$1" in
	-h|--help|-\?)
	    help
	    ;;

	-cT)
	    shift
	    cmaxt="$1"
	    ;;
	-ct)
	    shift
	    cmint="$1"
	    ;;
	-wT)
	    shift
	    wmaxt="$1"
	    ;;
	-wt)
	    shift
	    wmint="$1"
	    ;;

	-cH)
	    shift
	    cmaxh="$1"
	    ;;
	-ch)
	    shift
	    cminh="$1"
	    ;;
	-wH)
	    shift
	    wmaxh="$1"
	    ;;
	-wh)
	    shift
	    wminh="$1"
	    ;;

	-C)
	    degrees="C"
	    temperarg=""
	    temperurl="temperc"
	    ;;
	-d)
	    shift
	    device="$1"
	    ;;
	-F)
	    degrees="F"
	    temperarg="-f"
	    temperurl="temperf"
	    ;;
	-H)
	    shift
	    host="$1"
	    ;;
	-mh)
	    mrtg="hum"
	    ;;
	-mt)
	    mrtg="temp"
	    ;;
	-np)
	    noproxy="*"
	    ;;
	-t)
	    shift
	    type="$1"
	    ;;
	-u)
	    shift
	    url="$1"
	    ;;

	*)
	    usage
	    ;;
    esac
    shift
done


if [ -z "$host" -a -z "$url" ]; then
    # look locally, since they gave no host or url to use
    cmdname="temper"
    temper > "$tmp" 2>&1
    ret=$?
    # cp /tmp/ttest $tmp
else
    # go over the net
    cmdname="curl"
    if [ -z "$url" ]; then
	url="http://$host/quick/$temperurl"
    fi
    curl --noproxy "$noproxy" --silent --show-error "$url" > "$tmp" 2>&1
    ret=$?
fi
if [ $ret -ne 0 ]; then
    unknown "$cmdname" command failed: `tr '\n' ' ' < "$tmp"`
fi
if [ -z "$tmp" ]; then
    unknown "$cmdname" command returned no output
fi

# OK - we have our data - what shall we do with it?

if [ ! -z "$mrtg" ]; then
    # Assume we get at least one of the reading we care about.
    # If we don't get humidity, we return max 0, min 100, which will
    # look weird (on purpose).
    exec awk <"$tmp" \
	-v target="$host" \
	-v type="$mrtg" \
	'
	BEGIN { minh=100; maxh=0; }
	{ tmp=""; }
	$1=="temper" && NF==5 { tmp = $4; hum = $5; }
	$1!="temper" && NF==4 { tmp = $3; hum = $4; }
	tmp == "" { next; }	# did not find a row we care about
	mint=="" { mint=tmp; maxt=tmp; }
	tmp < mint { mint = tmp; }
	tmp > maxt { maxt = tmp; }
	hum!="XX" && minh=="" { minh=hum; maxh=hum; }
	hum!="XX" && hum < minh { minh=hum; }
	hum!="XX" && hum > maxh { maxh=hum; }
	END  {
	    if ( type == "hum" ) {
		print minh*100; print maxh*100;
	    } else {
		print mint*100; print maxt*100;
	    }
	    print "uptime unknown";
	    if ( target == "" ) { target = "localhost"; }
	    print target;
	}
	'
fi



# We assume that we have at least one temperature value

awk <"$tmp" \
    -v ok="$OK" -v unkn="$UNKNOWN" -v warn="$WARNING" -v crit="$CRITICAL" \
    -v "t=$type" -v "d=$device" -v "deg=$degrees" \
    -v "cmaxh=$cmaxh" \
    -v "cmaxt=$cmaxt" \
    -v "cminh=$cminh" \
    -v "cmint=$cmint" \
    -v "wmaxh=$wmaxh" \
    -v "wmaxt=$wmaxt" \
    -v "wminh=$wminh" \
    -v "wmint=$wmint" \
    '
    { tmp=""; }
    $1=="temper" && NF==5 { dev = $2; type = $3; tmp = $4; hum = $5; }
    $1!="temper" && NF==4 { dev = $1; type = $2; tmp = $3; hum = $4; }
    tmp == "" { next; }	# did not find a row we care about
    d!="" && dev!=d { next; }
    t!="" && type!=t { next; }
    mint=="" { mint=tmp; maxt=tmp; }
    tmp < mint { mint = tmp; }
    tmp > maxt { maxt = tmp; }
    hum!="XX" && minh=="" { minh=hum; maxh=hum; }
    hum!="XX" && hum < minh { minh=hum; }
    hum!="XX" && hum > maxh { maxh=hum; }
    {
	pdata = pdata sprintf( "dev%d=%s type%d=%s temp%d=%s ",
	    NR, dev, NR, type, NR, tmp );
    }
    hum!="XX" {
	pdata = pdata sprintf( "hum%d=%s ",
	    NR, hum );
    }
    END  {
# printf "mint=\"%s\" maxt=\"%s\" minh=\"%s\" maxh=\"%s\"\n",
# mint, maxt, minh, maxh;
	if ( cmaxt!="" && maxt>cmaxt ) {
	    critmsg = critmsg "Temperature too high: " maxt ">" cmaxt "; ";
	} else if ( wmaxt!="" && maxt>wmaxt ) {
	    warnmsg = warnmsg "Temperature too high: " maxt ">" wmaxt "; ";
	}
	if ( cmint!="" && mint<cmint ) {
	    critmsg = critmsg "Temperature too low: " mint "<" cmint "; ";
	} else if ( wmint!="" && mint<wmint ) {
	    warnmsg = warnmsg "Temperature too low: " mint "<" wmint "; ";
	}
	if ( mint != maxt ) {
	    okmsg = okmsg "Max/Min Temperature (" deg "): " maxt "/" mint "; ";
	} else {
	    okmsg = okmsg "Temperature (" deg "): " maxt "; ";
	}

	if ( minh != "" ) {
	    if ( cmaxh!="" && maxh>cmaxh ) {
		critmsg = critmsg "Humidity too high: " maxh ">" cmaxh "; ";
	    } else if ( wmaxh!="" && maxh>wmaxh ) {
		warnmsg = warnmsg "Humidity too high: " maxh ">" wmaxh "; ";
	    }
	    if ( cmint!="" && minh<cminh ) {
		critmsg = critmsg "Humidity too low: " minh "<" cminh "; ";
	    } else if ( wminh!="" && minh<wminh ) {
		warnmsg = warnmsg "Humidity too low: " minh "<" wminh "; ";
	    }
	    if ( minh != maxh ) {
		okmsg = okmsg "Max/Min Humidity: " maxh "%/" minh "%; ";
	    } else {
		okmsg = okmsg "Humidity: " maxh "%; ";
	    }
	}

	if ( critmsg != "" ) {
	    printf "CRITICAL: ";
	    code = crit;
	} else if ( warnmsg != "" ) {
	    printf "WARNING: ";
	    code = warn;
	} else if ( unknmsg != "" ) {
	    printf "UNKNOWN: ";
	    code = unkn;
	} else {
	    printf "OK: ";
	    code = ok;
	}
	msg = critmsg warnmsg unknmsg okmsg varmsg;
	gsub( /  */, " ", msg );
	sub( /[ ,]*$/, "", msg );
	print msg " | " pdata;
	exit code;
    }
    '

exit $?
