#!/bin/bash
###########
#
# check_snmp_apciem
# Checks APC Integrated Environment Monitor
# for temperature and humidity
#
# Author: Ian Perry
# Created: 2021-01-05
#
###########
temperatureOID="1.3.6.1.4.1.318.1.1.10.2.3.2.1.4"
temperature=0
tempBash=0
temperatureUnitOID="1.3.6.1.4.1.318.1.1.10.2.3.2.1.5"
temperatureUnit=0
humidityOID="1.3.6.1.4.1.318.1.1.10.2.3.2.1.6"
humidity=0
check="all"
checkList="all temperature humidity" # List of valid checks
checkListLower=$(echo $checkList | awk '{print tolower($0)}') # Convert to lowercase for input validation
outString=""
textVal=""
dataVal=""
returnStat=0
crit=""
warn=""
critLow=0
critHigh=0
warnLow=0
warnHigh=0
multiplier=1
offset=0
verbose=0

set -e
while getopts ":H:t:c:w:m:o:v" opt; do
    case $opt in
    H ) # Specify hostname
        HSTNAME="$OPTARG" # Hostname reserved keyword
        ;;
    t ) # Specify test, default all
        check="$OPTARG"
        ;;
    c ) # Specify crit value for amperage and wattage
        crit="$OPTARG"
        ;;
    w ) # Specify warn value for amperage and wattage
        warn="$OPTARG"
        ;;
    m )
        # Specify humidity multiplier
        multiplier="$OPTARG"
        ;;
    o )
        # Specify offset in +-#
        offset="$OPTARG"
        ;;
    v )
        # Enable verbosity
        verbose=1
        ;;
    ? )
        echo "script usage: $(basename $0) [-H hostname] [-t test] [-c crit] [-w warn] [-m humidityMultiplier] [-o +-humidityOffset] [-v verbose]" >&2
        exit 3
        ;;
    esac
done

round () {
    echo $(printf %.0f $(echo "scale=0;(((10^0)*$1)+0.5)/(10^0)" | bc))
}
vout () {
    if (($verbose == 1)) ; then echo "$1"; fi
}

# Convert input check to lowercase for validation
check=$(echo $check | awk '{print tolower($0)}')

if [[ ${offset:0:1} == '+' ]] ; then
    offset=${offset:1}
fi

vout "Passed arguments: Hostname $HSTNAME test: $check crit: $crit warn: $warn multiplier: $multiplier offset: $offset"

# If check is not valid, quit.
if ! $(echo $checkListLower | grep -q $check); then
    echo "Invalid check specified. Valid selection: $checkList"
    exit 3
fi

# Temperature check
if [[ $check == "all" ]] || [[ $check == "temperature" ]] ; then
    if ! [[ $crit ]] ; then
        crit="35:95"
    fi
    if ! [[ $warn ]] ; then
        warn="40:85"
    fi
    critLow=$(echo $crit | awk -F: '{print $1}')
    critHigh=$(echo $crit | awk -F: '{print $2}')
    warnLow=$(echo $warn | awk -F: '{print $1}')
    warnHigh=$(echo $warn | awk -F: '{print $2}')

    temperature=$(snmpwalk -c public -v1 -Ovq $HSTNAME $temperatureOID)
    temperatureUnit=$(snmpwalk -c public -v1 -Ovq $HSTNAME $temperatureUnitOID)
    vout "Temperature unit: $temperatureUnit temperature: $temperature"
    

    if [[ $temperature ]] ; then
        if (($temperatureUnit == 1)) ; then
            tempBash=$(echo "scale=0; (($temperature*(9/5))+32)" | bc -l) # Convert from C to F as int
            temperature=$(echo "scale=1; (($temperature*(9/5))+32)" | bc -l) # 1 decimal for data processing
        else
            tempBash=$temperature
            temperature=$(echo "scale=1; $temperature/1" | bc -l)
        fi

        dataVal+="temp_f=$temperature;$warn;$crit "
        if (($tempBash > $warnLow && $tempBash < $warnHigh)) ; then
            textVal+="OK - Temperature within normal bounds. Temperature ${temperature}F. "
        elif (($tempBash <= $critLow || $tempBash >= $critHigh)) ; then
            textVal+="CRITICAL - Temperature outside critical range. Temperature ${temperature}F. "
            returnStat=3
        elif (($tempBash <= $warnLow || $tempBash >= $warnHigh)) ; then
            textVal+="WARNING - Temperature outside normal range. Temperature ${temperature}F. "
            returnStat=$(($returnStat>1 ? $returnStat : 1))
        else
            textVal+="UNKNOWN - Invalid temperature returned. Temperature ${temperature}F. "
            returnStat=$(($returnStat>2 ? $returnStat : 2))
        fi
    else
        textVal+="UNKNOWN - No temperature was returned on check. "
        returnStat=$(($returnStat>2 ? $returnStat : 2))
    fi

fi

# Humidity check
if [[ $check == "all" ]] || [[ $check == "humidity" ]] ; then
    if ! [[ $crit ]] ; then
        crit="30:70"
    fi
    if ! [[ $warn ]] ; then
        warn="40:60"
    fi
    critLow=$(echo $crit | awk -F: '{print $1}')
    critHigh=$(echo $crit | awk -F: '{print $2}')
    warnLow=$(echo $warn | awk -F: '{print $1}')
    warnHigh=$(echo $warn | awk -F: '{print $2}')

    # Grab humidity via SNMP
    humidity=$(snmpwalk -c public -v1 -Ovq $HSTNAME $humidityOID)
    vout "Humidity pulled from device: $humidity"
    # Apply multiplier
    humidity=$(echo "scale=2; $humidity * $multiplier" | bc -l)
    # Round to nearest integer
    humidity=$(round $humidity)
    vout "Humidity after multiplier: $humidity"
    # Add offset
    humidity=$(echo "scale=0;$humidity + $offset" | bc -l)
    vout "Humidity after offset: $humidity"

    if [[ $humidity ]] ; then
        dataVal+="humidity=$humidity;$warn;$crit "
        if (($humidity > $warnLow && $humidity < $warnHigh)) ; then
            textVal+="OK - Humidity within normal bounds. Humidity ${humidity}%. "
        elif (($humidity <= $critLow || $humidity >= $critHigh)) ; then
            textVal+="CRITICAL - Humidity outside critical range. Humidity ${humidity}%. "
            returnStat=3
        elif (($humidity <= $warnLow || $humidity >= $warnHigh)) ; then
            textVal+="WARNING - Humidity outside normal range. Humidity ${humidity}%. "
            returnStat=$(($returnStat>1 ? $returnStat : 1))
        else
            textVal+="UNKNOWN - Invalid Humidity returned. Humidity ${humidity}%. "
            returnStat=$(($returnStat>2 ? $returnStat : 2))
        fi
    else
        textVal+="UNKNOWN - No humidity value was returned on check. "
        returnStat=$(($returnStat>2 ? $returnStat : 2))
    fi
fi

outString+=$textVal
outString+="|"
outString+=$dataVal

case $returnStat in
    0)
        echo $outString
        exit 0
        ;;
    1)
        echo $outString
        exit 1
        ;;
    2)
        echo $outString
        exit 3
        ;;
    3)
        echo $outString
        exit 2
        ;;
    *)
        echo "UNKNOWN -- Script returned a faulty return status. Return status $returnStat. Output $outString"
        exit 3
        ;;
esac


