#!/usr/local/bin/perl
#
# Check a liebert crac
#
# $Header: /opt/home/doke/work/nagios/RCS/check_liebert_crac,v 1.18 2015/03/16 20:15:37 doke Exp $



use strict;
use warnings;
#no warnings 'uninitialized';
no warnings 'redefine';
use Getopt::Long;
use Net::SNMP;


use vars qw( $crit_temp_range $warn_temp_range $crit_humidity_range
    $warn_humidity_range $community $use_snmpv2c $timeout $host $verbose $help $mib2
    $enterprises $liebert $prefered_maxmsgsize $maxrepetitions $dbname $dbuser
    $dbpasswd_file $maxrepetitions @crits @warns @unknowns @oks @ignores
    $rc $sep %ports_to_expect_up $port %conditionDescrs );

$warn_temp_range = '60:78';   
$crit_temp_range = '55:83';   
$warn_humidity_range = '35:65';   
$crit_humidity_range = '30:75';   

$host = '';
$community = 'LiebertEM';
$timeout = 10;
$verbose = 0;
$help = 0;


$use_snmpv2c = 1;   
$prefered_maxmsgsize = 1472;   # default
$maxrepetitions = 1;   # leiberts seem to be faster if they don't have to bundle



$mib2 = '1.3.6.1.2.1';
$enterprises = '1.3.6.1.4.1';
$liebert = "$enterprises.476";

# extracted from leibert mib with snmp2perl
%conditionDescrs = ( 
    '1.3.6.1.4.1.476.1.42.3.2.1' => 'lgpConditionsWellKnown',
    '1.3.6.1.4.1.476.1.42.3.2.1.1' => 'HighTemperature',
    '1.3.6.1.4.1.476.1.42.3.2.1.2' => 'LowTemperature',
    '1.3.6.1.4.1.476.1.42.3.2.1.3' => 'HighHumidity',
    '1.3.6.1.4.1.476.1.42.3.2.1.4' => 'LowHumidity',
    '1.3.6.1.4.1.476.1.42.3.2.1.5' => 'LossOfAirflow',
    '1.3.6.1.4.1.476.1.42.3.2.1.5.1' => 'LossOfAirflow1',
    '1.3.6.1.4.1.476.1.42.3.2.1.5.2' => 'LossOfAirflow2',
    '1.3.6.1.4.1.476.1.42.3.2.1.5.3' => 'LossOfAirflowBlower1',
    '1.3.6.1.4.1.476.1.42.3.2.1.6' => 'ChangeFilter',
    '1.3.6.1.4.1.476.1.42.3.2.1.7' => 'CompressorHighHeadPressure',
    '1.3.6.1.4.1.476.1.42.3.2.1.7.1' => 'Compressor1HighHeadPressure',
    '1.3.6.1.4.1.476.1.42.3.2.1.7.2' => 'Compressor2HighHeadPressure',
    '1.3.6.1.4.1.476.1.42.3.2.1.7.3' => 'Compressor3HighHeadPressure',
    '1.3.6.1.4.1.476.1.42.3.2.1.7.4' => 'Compressor4HighHeadPressure',
    '1.3.6.1.4.1.476.1.42.3.2.1.8' => 'CompressorOverload',
    '1.3.6.1.4.1.476.1.42.3.2.1.8.1' => 'Compressor1Overload',
    '1.3.6.1.4.1.476.1.42.3.2.1.8.2' => 'Compressor2Overload',
    '1.3.6.1.4.1.476.1.42.3.2.1.9' => 'CompressorShortCycle',
    '1.3.6.1.4.1.476.1.42.3.2.1.9.1' => 'Compressor1ShortCycle',
    '1.3.6.1.4.1.476.1.42.3.2.1.9.2' => 'Compressor2ShortCycle',
    '1.3.6.1.4.1.476.1.42.3.2.1.10' => 'CompressorLowSuctionPressure',
    '1.3.6.1.4.1.476.1.42.3.2.1.11' => 'MainFanOverLoad',
    '1.3.6.1.4.1.476.1.42.3.2.1.12' => 'ManualOverride',
    '1.3.6.1.4.1.476.1.42.3.2.1.13' => 'StandbyGlycoolPumpOn',
    '1.3.6.1.4.1.476.1.42.3.2.1.14' => 'WaterUnderFloor',
    '1.3.6.1.4.1.476.1.42.3.2.1.15' => 'HumidifierProblem',
    '1.3.6.1.4.1.476.1.42.3.2.1.16' => 'LowWaterInHumidifier',
    '1.3.6.1.4.1.476.1.42.3.2.1.17' => 'SmokeDetected',
    '1.3.6.1.4.1.476.1.42.3.2.1.18' => 'LowWaterFlow',
    '1.3.6.1.4.1.476.1.42.3.2.1.19' => 'LostPower',
    '1.3.6.1.4.1.476.1.42.3.2.1.20' => 'lgpGeneralFault',
    '1.3.6.1.4.1.476.1.42.3.2.1.21' => 'LocalAlarm',
    '1.3.6.1.4.1.476.1.42.3.2.1.21.1' => 'LocalAlarm1',
    '1.3.6.1.4.1.476.1.42.3.2.1.21.2' => 'LocalAlarm2',
    '1.3.6.1.4.1.476.1.42.3.2.1.21.3' => 'LocalAlarm3',
    '1.3.6.1.4.1.476.1.42.3.2.1.21.4' => 'LocalAlarm4',
    '1.3.6.1.4.1.476.1.42.3.2.1.21.5' => 'LocalAlarm5',
    '1.3.6.1.4.1.476.1.42.3.2.1.21.6' => 'LocalAlarm6',
    '1.3.6.1.4.1.476.1.42.3.2.1.21.7' => 'LocalAlarm7',
    '1.3.6.1.4.1.476.1.42.3.2.1.21.8' => 'LocalAlarm8',
    '1.3.6.1.4.1.476.1.42.3.2.1.22' => 'StandbyUnitOn',
    '1.3.6.1.4.1.476.1.42.3.2.1.23' => 'CompressorLowPressure',
    '1.3.6.1.4.1.476.1.42.3.2.1.23.1' => 'Compressor1LowPressure',
    '1.3.6.1.4.1.476.1.42.3.2.1.23.2' => 'Compressor2LowPressure',
    '1.3.6.1.4.1.476.1.42.3.2.1.23.3' => 'Compressor3LowPressure',
    '1.3.6.1.4.1.476.1.42.3.2.1.23.4' => 'Compressor4LowPressure',
    '1.3.6.1.4.1.476.1.42.3.2.1.24' => 'HighWaterInPan',
    '1.3.6.1.4.1.476.1.42.3.2.1.25' => 'FaultySensor',
    '1.3.6.1.4.1.476.1.42.3.2.1.26' => 'ServiceCooling',
    '1.3.6.1.4.1.476.1.42.3.2.1.27' => 'ServiceHumidifier',
    '1.3.6.1.4.1.476.1.42.3.2.1.28' => 'SystemControlBatteryLow',
    '1.3.6.1.4.1.476.1.42.3.2.1.29' => 'GroundSystemFault',
    '1.3.6.1.4.1.476.1.42.3.2.1.30' => 'GroundFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.31' => 'SecurityBreach',
    '1.3.6.1.4.1.476.1.42.3.2.1.32' => 'EmergencyShutdown',
    '1.3.6.1.4.1.476.1.42.3.2.1.33' => 'OnBypass',
    '1.3.6.1.4.1.476.1.42.3.2.1.33.1' => 'LoadOnBypass',
    '1.3.6.1.4.1.476.1.42.3.2.1.33.2' => 'LoadOnMaintenceBypass',
    '1.3.6.1.4.1.476.1.42.3.2.1.33.3' => 'ParallelSysLoadOnBypass',
    '1.3.6.1.4.1.476.1.42.3.2.1.33.4' => 'LoadOnBypassByImpact',
    '1.3.6.1.4.1.476.1.42.3.2.1.33.5' => 'LoadTransferedToBypass',
    '1.3.6.1.4.1.476.1.42.3.2.1.33.6' => 'EmergencyTransferToBypass',
    '1.3.6.1.4.1.476.1.42.3.2.1.34' => 'OutputToLoadVoltTHD',
    '1.3.6.1.4.1.476.1.42.3.2.1.35' => 'LogicFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.36' => 'PowerSupplyFault',
    '1.3.6.1.4.1.476.1.42.3.2.1.36.1' => 'PowerSupply1Fault',
    '1.3.6.1.4.1.476.1.42.3.2.1.36.2' => 'PowerSupply2Fault',
    '1.3.6.1.4.1.476.1.42.3.2.1.37' => 'PowerSupplyFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.37.1' => 'PowerSupply1Failure',
    '1.3.6.1.4.1.476.1.42.3.2.1.37.2' => 'PowerSupply2Failure',
    '1.3.6.1.4.1.476.1.42.3.2.1.37.3' => 'Source1PowerSupplyInputFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.37.4' => 'Source2PowerSupplyInputFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.37.5' => 'PowerSupplyLogicFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.37.6' => 'CompressorPowerSupplyFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.38' => 'OverVoltage',
    '1.3.6.1.4.1.476.1.42.3.2.1.38.1' => 'Source1OverVoltage',
    '1.3.6.1.4.1.476.1.42.3.2.1.38.2' => 'Source2OverVoltage',
    '1.3.6.1.4.1.476.1.42.3.2.1.38.3' => 'OutputToLoadOverVoltage',
    '1.3.6.1.4.1.476.1.42.3.2.1.38.4' => 'InputOverVoltage',
    '1.3.6.1.4.1.476.1.42.3.2.1.38.5' => 'BypassOverVoltage',
    '1.3.6.1.4.1.476.1.42.3.2.1.38.6' => 'BypassOverVoltageFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.38.7' => 'BatteryOverVoltage',
    '1.3.6.1.4.1.476.1.42.3.2.1.38.8' => 'DcBusOverVoltage',
    '1.3.6.1.4.1.476.1.42.3.2.1.38.8.1' => 'DcBus1OverVoltage',
    '1.3.6.1.4.1.476.1.42.3.2.1.38.8.2' => 'DcBus2OverVoltage',
    '1.3.6.1.4.1.476.1.42.3.2.1.38.8.3' => 'DcBus1OverVoltageFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.38.8.4' => 'DcBus2OverVoltageFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.39' => 'UnderVoltage',
    '1.3.6.1.4.1.476.1.42.3.2.1.39.1' => 'Source1UnderVoltage',
    '1.3.6.1.4.1.476.1.42.3.2.1.39.2' => 'Source2UnderVoltage',
    '1.3.6.1.4.1.476.1.42.3.2.1.39.3' => 'OutputToLoadUnderVoltage',
    '1.3.6.1.4.1.476.1.42.3.2.1.39.4' => 'Source1UnderVoltageRMS',
    '1.3.6.1.4.1.476.1.42.3.2.1.39.5' => 'Source2UnderVoltageRMS',
    '1.3.6.1.4.1.476.1.42.3.2.1.39.6' => 'InputUnderVoltage',
    '1.3.6.1.4.1.476.1.42.3.2.1.39.7' => 'BypassUnderVoltage',
    '1.3.6.1.4.1.476.1.42.3.2.1.39.8' => 'BypassUnderVoltageFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.39.9' => 'BatteryUnderVoltage',
    '1.3.6.1.4.1.476.1.42.3.2.1.39.10' => 'DcBusUnderVoltage',
    '1.3.6.1.4.1.476.1.42.3.2.1.39.10.1' => 'DcBus1UnderVoltage',
    '1.3.6.1.4.1.476.1.42.3.2.1.39.10.2' => 'DcBus2UnderVoltage',
    '1.3.6.1.4.1.476.1.42.3.2.1.39.10.3' => 'DcBus1UnderVoltageFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.39.10.4' => 'DcBus2UnderVoltageFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.40' => 'Overload',
    '1.3.6.1.4.1.476.1.42.3.2.1.40.1' => 'Source1Overload',
    '1.3.6.1.4.1.476.1.42.3.2.1.40.2' => 'SystemOverload',
    '1.3.6.1.4.1.476.1.42.3.2.1.40.3' => 'Source1PeakCurrentOverLoad',
    '1.3.6.1.4.1.476.1.42.3.2.1.40.4' => 'Source2PeakCurrentOverLoad',
    '1.3.6.1.4.1.476.1.42.3.2.1.40.5' => 'OutputToLoadOverLimit',
    '1.3.6.1.4.1.476.1.42.3.2.1.40.6' => 'OutputToLoadOverload',
    '1.3.6.1.4.1.476.1.42.3.2.1.40.7' => 'ParallelSysOverload',
    '1.3.6.1.4.1.476.1.42.3.2.1.41' => 'ScrShort',
    '1.3.6.1.4.1.476.1.42.3.2.1.41.1' => 'Source1ScrShort',
    '1.3.6.1.4.1.476.1.42.3.2.1.41.2' => 'Source2ScrShort',
    '1.3.6.1.4.1.476.1.42.3.2.1.41.3' => 'BypassScrShort',
    '1.3.6.1.4.1.476.1.42.3.2.1.42' => 'ScrOpen',
    '1.3.6.1.4.1.476.1.42.3.2.1.42.1' => 'Source1ScrOpen',
    '1.3.6.1.4.1.476.1.42.3.2.1.42.2' => 'Source2ScrOpen',
    '1.3.6.1.4.1.476.1.42.3.2.1.42.3' => 'BypassScrOpen',
    '1.3.6.1.4.1.476.1.42.3.2.1.43' => 'FanFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.43.1' => 'Fan1Failure',
    '1.3.6.1.4.1.476.1.42.3.2.1.44' => 'TransferInhibited',
    '1.3.6.1.4.1.476.1.42.3.2.1.45' => 'AutoReTransferPrimed',
    '1.3.6.1.4.1.476.1.42.3.2.1.46' => 'SourcesOutOfSync',
    '1.3.6.1.4.1.476.1.42.3.2.1.47' => 'SourceFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.47.1' => 'Source1Failure',
    '1.3.6.1.4.1.476.1.42.3.2.1.47.2' => 'Source2Failure',
    '1.3.6.1.4.1.476.1.42.3.2.1.48' => 'AutoReTransferInhibited',
    '1.3.6.1.4.1.476.1.42.3.2.1.49' => 'AutoReTransferFailed',
    '1.3.6.1.4.1.476.1.42.3.2.1.50' => 'FuseOpen',
    '1.3.6.1.4.1.476.1.42.3.2.1.50.1' => 'ControlFuse1Open',
    '1.3.6.1.4.1.476.1.42.3.2.1.50.2' => 'ControlFuse2Open',
    '1.3.6.1.4.1.476.1.42.3.2.1.50.3' => 'RectifierFuseOpen',
    '1.3.6.1.4.1.476.1.42.3.2.1.50.4' => 'InverterFuseOpen',
    '1.3.6.1.4.1.476.1.42.3.2.1.50.5' => 'OutputToLoadFuseOpen',
    '1.3.6.1.4.1.476.1.42.3.2.1.50.6' => 'DcCapacitorFuseOpen',
    '1.3.6.1.4.1.476.1.42.3.2.1.51' => 'Disconnect',
    '1.3.6.1.4.1.476.1.42.3.2.1.51.1' => 'Source1DisconnectOpen',
    '1.3.6.1.4.1.476.1.42.3.2.1.51.2' => 'Source2DisconnectOpen',
    '1.3.6.1.4.1.476.1.42.3.2.1.51.3' => 'Source1PduDisconnectOpen',
    '1.3.6.1.4.1.476.1.42.3.2.1.51.4' => 'Source2PduDisconnectOpen',
    '1.3.6.1.4.1.476.1.42.3.2.1.51.5' => 'OutputToLoadDisconnect1Open',
    '1.3.6.1.4.1.476.1.42.3.2.1.51.6' => 'OutputToLoadDisconnect2Open',
    '1.3.6.1.4.1.476.1.42.3.2.1.51.7' => 'Source1BypassDisconnectClosed',
    '1.3.6.1.4.1.476.1.42.3.2.1.51.8' => 'Source2BypassDisconnectClosed',
    '1.3.6.1.4.1.476.1.42.3.2.1.51.9' => 'OutputToLoadNeutralDisconnectOpen',
    '1.3.6.1.4.1.476.1.42.3.2.1.51.10' => 'BatteryDisconnectOpen',
    '1.3.6.1.4.1.476.1.42.3.2.1.51.11' => 'InputDisconnectOpen',
    '1.3.6.1.4.1.476.1.42.3.2.1.51.12' => 'OutputToLoadDisconnectOpen',
    '1.3.6.1.4.1.476.1.42.3.2.1.51.13' => 'BypassDisconnectOpen',
    '1.3.6.1.4.1.476.1.42.3.2.1.51.14' => 'StaticSwitchDisconnectOpen',
    '1.3.6.1.4.1.476.1.42.3.2.1.52' => 'FrequencyDeviation',
    '1.3.6.1.4.1.476.1.42.3.2.1.52.1' => 'Source1FrequencyDeviation',
    '1.3.6.1.4.1.476.1.42.3.2.1.52.2' => 'Source2FrequencyDeviation',
    '1.3.6.1.4.1.476.1.42.3.2.1.52.3' => 'InputFrequencyDeviation',
    '1.3.6.1.4.1.476.1.42.3.2.1.52.4' => 'OutputToLoadFrequencyDeviation',
    '1.3.6.1.4.1.476.1.42.3.2.1.53' => 'OverCurrent',
    '1.3.6.1.4.1.476.1.42.3.2.1.53.1' => 'Source1OverCurrent',
    '1.3.6.1.4.1.476.1.42.3.2.1.53.2' => 'Source2OverCurrent',
    '1.3.6.1.4.1.476.1.42.3.2.1.53.3' => 'OutputToLoadOverCurrent',
    '1.3.6.1.4.1.476.1.42.3.2.1.53.4' => 'GroundOverCurrent',
    '1.3.6.1.4.1.476.1.42.3.2.1.53.5' => 'RectifierOverCurrent',
    '1.3.6.1.4.1.476.1.42.3.2.1.53.6' => 'InverterOverCurrent',
    '1.3.6.1.4.1.476.1.42.3.2.1.53.7' => 'BatteryConverterOverCurrent',
    '1.3.6.1.4.1.476.1.42.3.2.1.53.8' => 'BatteryBalancerOverCurrent',
    '1.3.6.1.4.1.476.1.42.3.2.1.53.9' => 'HumidifierOverCurrent',
    '1.3.6.1.4.1.476.1.42.3.2.1.54' => 'SensorFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.54.1' => 'OutputToLoadVoltageSensorFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.54.2' => 'Source1VoltageSensorFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.54.3' => 'Source2VoltageSensorFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.54.4' => 'Source1ScrSensorFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.54.5' => 'Source2ScrSensorFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.54.6' => 'Source1CurrentSensorFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.54.7' => 'Source2CurrentSensorFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.54.8' => 'RoomTempHumiditySensorFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.54.9' => 'GlycolTempSensorFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.54.10' => 'Local1SensorFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.54.11' => 'Compressor1SensorFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.54.12' => 'Compressor2SensorFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.54.13' => 'SupplySensorFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.55' => 'InternalCommunicationFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.56' => 'ExternalCommunicationFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.57' => 'SourceGateDriveFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.57.1' => 'Source1GateDriveFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.57.2' => 'Source2GateDriveFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.58' => 'DisconnectFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.58.1' => 'OutputToLoadNeutralDisconnectFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.58.2' => 'Source1DisconnectShuntTripFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.58.3' => 'Source2DisconnectShuntTripFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.58.4' => 'InverterDisconnectFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.58.5' => 'BatteryDisconnectFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.59' => 'OverTemperature',
    '1.3.6.1.4.1.476.1.42.3.2.1.59.1' => 'HeatSink1OverTemperature',
    '1.3.6.1.4.1.476.1.42.3.2.1.59.2' => 'Ambient1OverTemperature',
    '1.3.6.1.4.1.476.1.42.3.2.1.59.3' => 'SystemOverTemperature',
    '1.3.6.1.4.1.476.1.42.3.2.1.59.4' => 'TransformerOverTemperature',
    '1.3.6.1.4.1.476.1.42.3.2.1.59.5' => 'BatteryOverTemperature',
    '1.3.6.1.4.1.476.1.42.3.2.1.59.6' => 'RectifierOverTemperature',
    '1.3.6.1.4.1.476.1.42.3.2.1.59.7' => 'InverterOverTemperature',
    '1.3.6.1.4.1.476.1.42.3.2.1.59.8' => 'RectifierInductorOverTemperature',
    '1.3.6.1.4.1.476.1.42.3.2.1.59.9' => 'InverterInductorOverTemperature',
    '1.3.6.1.4.1.476.1.42.3.2.1.59.10' => 'BatteryConverterOverTemperature',
    '1.3.6.1.4.1.476.1.42.3.2.1.59.11' => 'BatteryBalancerInductorOverTemperature',
    '1.3.6.1.4.1.476.1.42.3.2.1.59.12' => 'ChilledWaterOverTemperature',
    '1.3.6.1.4.1.476.1.42.3.2.1.59.13' => 'ElectricHeatersOverTemperature',
    '1.3.6.1.4.1.476.1.42.3.2.1.60' => 'LoadOnAlternateSource',
    '1.3.6.1.4.1.476.1.42.3.2.1.61' => 'PhaseRotationError',
    '1.3.6.1.4.1.476.1.42.3.2.1.61.1' => 'Source1PhaseRotationError',
    '1.3.6.1.4.1.476.1.42.3.2.1.61.2' => 'Source2PhaseRotationError',
    '1.3.6.1.4.1.476.1.42.3.2.1.61.3' => 'BypassPhaseRotationError',
    '1.3.6.1.4.1.476.1.42.3.2.1.61.4' => 'InputPhaseRotationError',
    '1.3.6.1.4.1.476.1.42.3.2.1.62' => 'ControlModuleFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.62.1' => 'ControlModule1Failure',
    '1.3.6.1.4.1.476.1.42.3.2.1.63' => 'HistoryLogFull',
    '1.3.6.1.4.1.476.1.42.3.2.1.64' => 'ConfigurationModified',
    '1.3.6.1.4.1.476.1.42.3.2.1.65' => 'PasswordModified',
    '1.3.6.1.4.1.476.1.42.3.2.1.66' => 'TimeModified',
    '1.3.6.1.4.1.476.1.42.3.2.1.67' => 'DateModified',
    '1.3.6.1.4.1.476.1.42.3.2.1.68' => 'EventLogCleared',
    '1.3.6.1.4.1.476.1.42.3.2.1.69' => 'HistoryLogCleared',
    '1.3.6.1.4.1.476.1.42.3.2.1.70' => 'UtilityFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.71' => 'BatteryTestInProgress',
    '1.3.6.1.4.1.476.1.42.3.2.1.72' => 'LoadOnBattery',
    '1.3.6.1.4.1.476.1.42.3.2.1.74' => 'ReplaceBattery',
    '1.3.6.1.4.1.476.1.42.3.2.1.75' => 'UpsShutdownPending',
    '1.3.6.1.4.1.476.1.42.3.2.1.76' => 'BatteryChargerFailed',
    '1.3.6.1.4.1.476.1.42.3.2.1.77' => 'BypassVoltageUnqualified',
    '1.3.6.1.4.1.476.1.42.3.2.1.78' => 'CheckAirFilter',
    '1.3.6.1.4.1.476.1.42.3.2.1.79' => 'BrownOut',
    '1.3.6.1.4.1.476.1.42.3.2.1.80' => 'MultipleTransferLockout',
    '1.3.6.1.4.1.476.1.42.3.2.1.81' => 'BypassPhaseLost',
    '1.3.6.1.4.1.476.1.42.3.2.1.82' => 'MaintenceBypassInhibited',
    '1.3.6.1.4.1.476.1.42.3.2.1.83' => 'LoadLockedOnBypass',
    '1.3.6.1.4.1.476.1.42.3.2.1.84' => 'OutputToLoadShort',
    '1.3.6.1.4.1.476.1.42.3.2.1.85' => 'EmergencyTransferToInverter',
    '1.3.6.1.4.1.476.1.42.3.2.1.86' => 'lgpConditonEmergencyPowerOff',
    '1.3.6.1.4.1.476.1.42.3.2.1.87' => 'InverterBackFeed',
    '1.3.6.1.4.1.476.1.42.3.2.1.88' => 'DcGroundFault',
    '1.3.6.1.4.1.476.1.42.3.2.1.89' => 'StaticTransferSwitchInhibited',
    '1.3.6.1.4.1.476.1.42.3.2.1.90' => 'BatteryLogFullWarning',
    '1.3.6.1.4.1.476.1.42.3.2.1.91' => 'InputCurrentUnbalanced',
    '1.3.6.1.4.1.476.1.42.3.2.1.92' => 'SelfTestFailed',
    '1.3.6.1.4.1.476.1.42.3.2.1.93' => 'InverterOutOfSynchronization',
    '1.3.6.1.4.1.476.1.42.3.2.1.94' => 'ModuleAlarm',
    '1.3.6.1.4.1.476.1.42.3.2.1.94.1' => 'iModuleUnit1Alarm',
    '1.3.6.1.4.1.476.1.42.3.2.1.94.2' => 'iModuleUnit2Alarm',
    '1.3.6.1.4.1.476.1.42.3.2.1.94.3' => 'iModuleUnit3Alarm',
    '1.3.6.1.4.1.476.1.42.3.2.1.94.4' => 'iModuleUnit4Alarm',
    '1.3.6.1.4.1.476.1.42.3.2.1.94.5' => 'iModuleUnit5Alarm',
    '1.3.6.1.4.1.476.1.42.3.2.1.94.6' => 'iModuleUnit6Alarm',
    '1.3.6.1.4.1.476.1.42.3.2.1.94.7' => 'iModuleUnit7Alarm',
    '1.3.6.1.4.1.476.1.42.3.2.1.94.8' => 'iModuleUnit8Alarm',
    '1.3.6.1.4.1.476.1.42.3.2.1.95' => 'ActiveModuleAlarm',
    '1.3.6.1.4.1.476.1.42.3.2.1.96' => 'ControlFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.96.1' => 'MainControlFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.96.2' => 'RedundantControlFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.96.3' => 'ParallelSysControlFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.97' => 'ControlWarning',
    '1.3.6.1.4.1.476.1.42.3.2.1.97.1' => 'MainControlWarning',
    '1.3.6.1.4.1.476.1.42.3.2.1.97.2' => 'RedundantControlWarning',
    '1.3.6.1.4.1.476.1.42.3.2.1.98' => 'UserInterfaceFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.99' => 'LostPowerRedundancy',
    '1.3.6.1.4.1.476.1.42.3.2.1.100' => 'PowerModuleFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.101' => 'BatteryModuleFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.102' => 'OutputToLoadOff',
    '1.3.6.1.4.1.476.1.42.3.2.1.103' => 'SystemOff',
    '1.3.6.1.4.1.476.1.42.3.2.1.104' => 'RectifierStartupFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.105' => 'RectifierFault',
    '1.3.6.1.4.1.476.1.42.3.2.1.106' => 'InverterShutdownLowDc',
    '1.3.6.1.4.1.476.1.42.3.2.1.107' => 'InverterFault',
    '1.3.6.1.4.1.476.1.42.3.2.1.108' => 'InverterDcOffsetOverrun',
    '1.3.6.1.4.1.476.1.42.3.2.1.109' => 'ParallelSysLowBatteryWarning',
    '1.3.6.1.4.1.476.1.42.3.2.1.110' => 'ParallelSysLoadShareFault',
    '1.3.6.1.4.1.476.1.42.3.2.1.111' => 'BatteryFault',
    '1.3.6.1.4.1.476.1.42.3.2.1.112' => 'BatteryConverterFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.113' => 'BatteryBalancerFault',
    '1.3.6.1.4.1.476.1.42.3.2.1.114' => 'psUpsOperationFault',
    '1.3.6.1.4.1.476.1.42.3.2.1.115' => 'OutputToLoadOnJointMode',
    '1.3.6.1.4.1.476.1.42.3.2.1.116' => 'InputNeutralLost',
    '1.3.6.1.4.1.476.1.42.3.2.1.117' => 'LowBatteryWarning',
    '1.3.6.1.4.1.476.1.42.3.2.1.118' => 'InternalFault',
    '1.3.6.1.4.1.476.1.42.3.2.1.119' => 'BatteryTestFailed',
    '1.3.6.1.4.1.476.1.42.3.2.1.120' => 'PowerModuleWarning',
    '1.3.6.1.4.1.476.1.42.3.2.1.121' => 'BatteryModuleWarning',
    '1.3.6.1.4.1.476.1.42.3.2.1.122' => 'ControlModuleWarning',
    '1.3.6.1.4.1.476.1.42.3.2.1.123' => 'UpsOperationFault',
    '1.3.6.1.4.1.476.1.42.3.2.1.124' => 'ActiveAlarm',
    '1.3.6.1.4.1.476.1.42.3.2.1.125' => 'RectifierCommunicationFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.126' => 'InverterCommunicationFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.127' => 'ParallelSysConnectionFault',
    '1.3.6.1.4.1.476.1.42.3.2.1.128' => 'ParallelSysCommunicationFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.129' => 'LostBatteryRedundancy',
    '1.3.6.1.4.1.476.1.42.3.2.1.130' => 'CompPumpDownFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.130.1' => 'Comp1PumpDownFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.130.2' => 'Comp2PumpDownFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.131' => 'ChilledWaterLowWaterFlow',
    '1.3.6.1.4.1.476.1.42.3.2.1.132' => 'AirFilterClogged',
    '1.3.6.1.4.1.476.1.42.3.2.1.133' => 'HumidifierFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.134' => 'RunHoursExceeded',
    '1.3.6.1.4.1.476.1.42.3.2.1.134.1' => 'UnitRunHrsExceeded',
    '1.3.6.1.4.1.476.1.42.3.2.1.134.2' => 'Comp1RunHrsExceeded',
    '1.3.6.1.4.1.476.1.42.3.2.1.134.3' => 'Comp2RunHrsExceeded',
    '1.3.6.1.4.1.476.1.42.3.2.1.134.4' => 'FreeCoolRunHrsExceeded',
    '1.3.6.1.4.1.476.1.42.3.2.1.134.5' => 'ElectricalHeater1RunHrsExceeded',
    '1.3.6.1.4.1.476.1.42.3.2.1.134.6' => 'ElectricalHeater2RunHrsExceeded',
    '1.3.6.1.4.1.476.1.42.3.2.1.134.7' => 'ElectricalHeater3RunHrsExceeded',
    '1.3.6.1.4.1.476.1.42.3.2.1.134.8' => 'HotWaterRunHrsExceeded',
    '1.3.6.1.4.1.476.1.42.3.2.1.134.9' => 'HotGasRunHrsExceeded',
    '1.3.6.1.4.1.476.1.42.3.2.1.134.10' => 'HumidifierRunHrsExceeded',
    '1.3.6.1.4.1.476.1.42.3.2.1.134.11' => 'DehumidiferRunHrsExceeded',
    '1.3.6.1.4.1.476.1.42.3.2.1.135' => 'CommWarning',
    '1.3.6.1.4.1.476.1.42.3.2.1.135.1' => 'CommWarningUnit1',
    '1.3.6.1.4.1.476.1.42.3.2.1.135.2' => 'CommWarningUnit2',
    '1.3.6.1.4.1.476.1.42.3.2.1.135.3' => 'CommWarningUnit3',
    '1.3.6.1.4.1.476.1.42.3.2.1.135.4' => 'CommWarningUnit4',
    '1.3.6.1.4.1.476.1.42.3.2.1.135.5' => 'CommWarningUnit5',
    '1.3.6.1.4.1.476.1.42.3.2.1.135.6' => 'CommWarningUnit6',
    '1.3.6.1.4.1.476.1.42.3.2.1.135.7' => 'CommWarningUnit7',
    '1.3.6.1.4.1.476.1.42.3.2.1.135.8' => 'CommWarningUnit8',
    '1.3.6.1.4.1.476.1.42.3.2.1.135.9' => 'CommWarningUnit9',
    '1.3.6.1.4.1.476.1.42.3.2.1.135.10' => 'CommWarningUnit10',
    '1.3.6.1.4.1.476.1.42.3.2.1.135.11' => 'CommWarningUnit11',
    '1.3.6.1.4.1.476.1.42.3.2.1.135.12' => 'CommWarningUnit12',
    '1.3.6.1.4.1.476.1.42.3.2.1.135.13' => 'CommWarningUnit13',
    '1.3.6.1.4.1.476.1.42.3.2.1.135.14' => 'CommWarningUnit14',
    '1.3.6.1.4.1.476.1.42.3.2.1.135.15' => 'CommWarningUnit15',
    '1.3.6.1.4.1.476.1.42.3.2.1.135.16' => 'CommWarningUnit16',
    '1.3.6.1.4.1.476.1.42.3.2.1.136' => 'UnitOn',
    '1.3.6.1.4.1.476.1.42.3.2.1.137' => 'UnitOff',
    '1.3.6.1.4.1.476.1.42.3.2.1.138' => 'SleepModeOff',
    '1.3.6.1.4.1.476.1.42.3.2.1.139' => 'PowerOn',
    '1.3.6.1.4.1.476.1.42.3.2.1.140' => 'SystemOnStanby',
    '1.3.6.1.4.1.476.1.42.3.2.1.141' => 'PowerOff',
    '1.3.6.1.4.1.476.1.42.3.2.1.142' => 'HighTemperatureGroup',
    '1.3.6.1.4.1.476.1.42.3.2.1.142.1' => 'HighTemperatureSensor1',
    '1.3.6.1.4.1.476.1.42.3.2.1.142.2' => 'HighTemperatureDigitalScroll1',
    '1.3.6.1.4.1.476.1.42.3.2.1.142.3' => 'HighTemperatureDigitalScroll2',
    '1.3.6.1.4.1.476.1.42.3.2.1.142.4' => 'HighTemperatureUser1',
    '1.3.6.1.4.1.476.1.42.3.2.1.142.5' => 'HighTemperatureInternal',
    '1.3.6.1.4.1.476.1.42.3.2.1.143' => 'LowTemperatureGroup',
    '1.3.6.1.4.1.476.1.42.3.2.1.143.1' => 'LowTemperatureSensor1',
    '1.3.6.1.4.1.476.1.42.3.2.1.143.2' => 'LowTemperatureInternal',
    '1.3.6.1.4.1.476.1.42.3.2.1.144' => 'HighHumidityGroup',
    '1.3.6.1.4.1.476.1.42.3.2.1.144.1' => 'HighHumiditySensor1',
    '1.3.6.1.4.1.476.1.42.3.2.1.145' => 'LowHumidityGroup',
    '1.3.6.1.4.1.476.1.42.3.2.1.145.1' => 'LowHumiditySensor1',
    '1.3.6.1.4.1.476.1.42.3.2.1.146' => 'PeerNetworkNoMaster',
    '1.3.6.1.4.1.476.1.42.3.2.1.147' => 'NoOnOffPermissions',
    '1.3.6.1.4.1.476.1.42.3.2.1.148' => 'PeerNetworkFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.149' => 'UnitDisabled',
    '1.3.6.1.4.1.476.1.42.3.2.1.150' => 'UnitShutdown',
    '1.3.6.1.4.1.476.1.42.3.2.1.151' => 'PeerNetworkDiscovered',
    '1.3.6.1.4.1.476.1.42.3.2.1.152' => 'LossOfWaterFlow',
    '1.3.6.1.4.1.476.1.42.3.2.1.153' => 'CondensatePumpHighWater',
    '1.3.6.1.4.1.476.1.42.3.2.1.154' => 'GeneralAlarm',
    '1.3.6.1.4.1.476.1.42.3.2.1.155' => 'ProductSpecific',
    '1.3.6.1.4.1.476.1.42.3.2.1.156' => 'ReheatLockout',
    '1.3.6.1.4.1.476.1.42.3.2.1.157' => 'HumidifierLockout',
    '1.3.6.1.4.1.476.1.42.3.2.1.158' => 'CompressorsLockout',
    '1.3.6.1.4.1.476.1.42.3.2.1.159' => 'CallService',
    '1.3.6.1.4.1.476.1.42.3.2.1.160' => 'LowMemoryGroup',
    '1.3.6.1.4.1.476.1.42.3.2.1.160.1' => 'LowMemory1',
    '1.3.6.1.4.1.476.1.42.3.2.1.161' => 'MemoryFailureGroup',
    '1.3.6.1.4.1.476.1.42.3.2.1.161.1' => 'Memory1Failure',
    '1.3.6.1.4.1.476.1.42.3.2.1.161.2' => 'Memory2Failure',
    '1.3.6.1.4.1.476.1.42.3.2.1.162' => 'UnitCodeErrorGroup',
    '1.3.6.1.4.1.476.1.42.3.2.1.162.1' => 'UnitCodeNotConfigured',
    '1.3.6.1.4.1.476.1.42.3.2.1.162.2' => 'UnitCode01OutOfRange',
    '1.3.6.1.4.1.476.1.42.3.2.1.162.3' => 'UnitCode02OutOfRange',
    '1.3.6.1.4.1.476.1.42.3.2.1.162.4' => 'UnitCode03OutOfRange',
    '1.3.6.1.4.1.476.1.42.3.2.1.162.5' => 'UnitCode04OutOfRange',
    '1.3.6.1.4.1.476.1.42.3.2.1.162.6' => 'UnitCode05OutOfRange',
    '1.3.6.1.4.1.476.1.42.3.2.1.162.7' => 'UnitCode06OutOfRange',
    '1.3.6.1.4.1.476.1.42.3.2.1.162.8' => 'UnitCode07OutOfRange',
    '1.3.6.1.4.1.476.1.42.3.2.1.162.9' => 'UnitCode08OutOfRange',
    '1.3.6.1.4.1.476.1.42.3.2.1.162.10' => 'UnitCode09OutOfRange',
    '1.3.6.1.4.1.476.1.42.3.2.1.162.11' => 'UnitCode10OutOfRange',
    '1.3.6.1.4.1.476.1.42.3.2.1.162.12' => 'UnitCode11OutOfRange',
    '1.3.6.1.4.1.476.1.42.3.2.1.162.13' => 'UnitCode12OutOfRange',
    '1.3.6.1.4.1.476.1.42.3.2.1.162.14' => 'UnitCode13OutOfRange',
    '1.3.6.1.4.1.476.1.42.3.2.1.162.15' => 'UnitCode14OutOfRange',
    '1.3.6.1.4.1.476.1.42.3.2.1.162.16' => 'UnitCode15OutOfRange',
    '1.3.6.1.4.1.476.1.42.3.2.1.162.17' => 'UnitCode16OutOfRange',
    '1.3.6.1.4.1.476.1.42.3.2.1.162.18' => 'UnitCode17OutOfRange',
    '1.3.6.1.4.1.476.1.42.3.2.1.162.19' => 'UnitCode18OutOfRange',
    '1.3.6.1.4.1.476.1.42.3.2.1.163' => 'HighExternalDewPoint',
    '1.3.6.1.4.1.476.1.42.3.2.1.164' => 'HcbDisconnected',
    '1.3.6.1.4.1.476.1.42.3.2.1.175' => 'SystemAccessGroup',
    '1.3.6.1.4.1.476.1.42.3.2.1.175.1' => 'FrontAccessOpen',
    '1.3.6.1.4.1.476.1.42.3.2.1.175.2' => 'RearAccessOpen',
    '1.3.6.1.4.1.476.1.42.3.2.1.176' => 'DamperFailure',
    '1.3.6.1.4.1.476.1.42.3.2.1.176.1' => 'EmergencyDamperFailure',
    '1.3.6.1.4.1.476.1.42.3.4.2.2.3.1.6' => 'lgpEnvHumiditySetPoint', 

    );


sub usage {
    my( $rc ) = @_;
    print "Usage: $0 [options] -H <host> [-C <community>]
    -H s  hostname
    -C s  snmp community [$community]
    -w r  warning temperature range [$warn_temp_range]
    -c r  critical temperature range [$crit_temp_range]
    -r r  warning relative humidity range [$warn_humidity_range]
    -R r  critical relative humidity range [$crit_humidity_range]
    -t n  snmp timeout in seconds [$timeout]
    -v    verbose
    -h    help
";
    exit $rc;
    }

Getopt::Long::Configure ("bundling");
GetOptions(
    'H=s' => \$host,
    'C=s' => \$community,
    'w=s' => \$warn_temp_range,
    'c=s' => \$crit_temp_range,
    'r=s' => \$warn_humidity_range,
    'R=s' => \$crit_humidity_range,
    't=i' => \$timeout,
    'v+' => \$verbose,
    'h' => \$help,
    );
&usage( 0 ) if ( $help );

&usage( 1 ) if ( ! $host );

# test the ranges
out_of_range( $crit_temp_range, 1 );
out_of_range( $warn_temp_range, 1 );
out_of_range( $crit_humidity_range, 1 );
out_of_range( $warn_humidity_range, 1 );


check_liebert_crac();

$rc = 0;
$sep = '';
if ( $#crits >= 0 ) {
    $rc = 2;
    print "CRITICAL ", join( ", ", @crits );
    $sep = '; ';
    }
if ( $#warns >= 0 ) {
    $rc = 1 if ( $rc == 0 );
    print $sep, "Warning ", join( ", ", @warns );
    $sep = '; ';
    }
if ( $#unknowns >= 0 ) {
    $rc = 3 if ( $rc == 0 );
    print $sep, "Unknown ", join( ", ", @unknowns );
    }
if ( $rc == 0 || $verbose ) {
    print $sep, "Ok ", join( ", ", @oks );
    $sep = '; ';
    }
if ( $#ignores >= 0 ) {
    print $sep, "Ignoring ", join( ", ", @ignores );
    }
print "\n";
exit $rc;



##################



sub check_liebert_crac {
    my( $session, $error, $sysDescr, $sysName, $val, $system_on, $table,
	$row, $temp, $humidity, $msg, $result, $oid, $descr_oid, $descr,
	$rows, $setpoint_row );

    # open the snmp session
    $verbose && print "opening snmp session to $host\n";
    ( $session, $error ) = Net::SNMP->session(
        -version => 'snmpv2c',    
        -hostname => $host,
        -community => $community,
        -timeout => $timeout,
        #-maxmsgsize => 2000,
        #-debug => 0x02
        );
    if ( ! defined( $session ) ) {
	$verbose && print "snmp setup error: $error\n";
        push @crits, "snmp setup error: $error";
        return;
        }
    $session->translate( [ '-octetstring' => 0, '-timeticks' => 0 ] );
    #$session->translate( '-all' => 0 );
    #$session->translate( '-unsigned' => 1 );

    $verbose > 1 && print "snmp session default maxmsgsize = ", 
	$session->max_msg_size(), "\n";

    $sysDescr = snmp_get_one( $session, 'sysDescr', "$mib2.1.1.0" );
    if ( ! defined $sysDescr ) { 
	push @crits, "cannot get sysDescr: " . $session->error();
	return;
	}

    $sysName = snmp_get_one( $session, 'sysName', "$mib2.1.5.0" );
    if ( defined $sysName && $sysName ne 'Uninitialized' )  { 
	push @oks, $sysName;
	}
    if ( $sysDescr ne 'Uninitialized' )  { 
	push @oks, $sysDescr;
	}

    $val = snmp_get_one( $session, 'lgpEnvStateSystem', "$liebert.1.42.3.4.3.1.0" );
    if ( ! defined $val ) { 
	push @crits, "no system state, web card may need to be reseated";
	}
    elsif ( $val == 1 ) { 
	$system_on = 1;
	}
    else { 
	push @oks, "system off";
	}

    # not all models/versions have this
    $val = snmp_get_one( $session, 'lgpEnvStateGeneralAlarmOutput', "$liebert.1.42.3.4.3.8.0" );
    if ( defined $val && $val != 2 ) { 
	push @crits, "general alarm";
	}

    # every model and version I know of has this
    $val = snmp_get_one( $session, 'lgpConditionsPresent', "$liebert.1.42.3.2.2.0" );
    if ( ! defined $val ) { 
	push @crits, "unable to get number of alarms present";
	}
    elsif ( $val > 0 ) { 
	my( @alarms, $state, $acked, $nalarms );
	#push @crits, "$val alarms";

	# lgpConditionTable
	# col 2 lgpConditionDescr   as a well known oid
	# col 3 lgpConditionTime   in timeticks 
	# col 12 lgpConditionCurrentState   active(1) inactive(2)
	# col 14 lgpConditionSeverity   not-applicable(0)
	# col 18 lgpConditionAcknowledged   notAcknowledged(1)  acknowledged(2)
	$table = snmp_table( $session, 'lgpConditionTable', "$liebert.1.42.3.2.3",
	    [ 2, 12, 18 ] );
	if ( $table ) { 
	    $rows = scalar @$table ;
	    foreach $row ( 1 .. $rows ) {
		$state = $table->[$row][12];
		next if ( ! defined $state );
		$acked = $table->[$row][18];
		$descr_oid = $table->[$row][2];
		$descr = $conditionDescrs{ $descr_oid }; 
		if ( ! defined $descr ) {
		    $descr = 'unknown'; 
		    }
		$verbose && print "alarm $state $acked $descr_oid $descr\n";
		next if ( $state != 1 || $acked != 1 ); 
		push @alarms, $descr;
		}
	    }
	else { 
	    push @warns, "can't get alarm table";
	    }
	$nalarms = scalar @alarms;
	if ( $nalarms == 0 )  { 
	    push @oks, "no active unacked alarms";
	    }
	else { 
	    push @crits, "$val alarm: " . join( ' ', @alarms );
	    }
	}
    else { 
	push @oks, "no alarms";
	}

    # temps
    $table = snmp_table( $session, 'lgpEnvTemperatureTableDegF', 
	"$liebert.1.42.3.4.1.2.3", [ 2, 3 ] );
    if ( $table ) {
	$rows = scalar @$table;
	foreach $row ( 1 .. $rows ) {
	    # col 2 lgpEnvTemperatureDescrDegF
	    # col 3 lgpEnvTemperatureMeasurementDegF
	    if ( defined $table->[$row][2] ) { 
		$verbose && print "    temp $table->[$row][2] $table->[$row][3]\n";
		if ( $table->[$row][2] eq '1.3.6.1.4.1.476.1.42.3.4.1.1.2' 
			|| $rows == 2 )  {
		    # lgpEnvReturnAirTemperature, or there's only one entry
		    $temp = $table->[$row][3];
		    if ( out_of_range( $crit_temp_range, $temp ) ) { 
			$msg = "${temp}F out of range $crit_temp_range";
			if ( $system_on ) { 
			    push @crits, $msg;
			    }
			else { 
			    push @ignores, $msg;
			    }
			}
		    elsif ( out_of_range( $warn_temp_range, $temp ) ) { 
			$msg = "${temp}F out of range $warn_temp_range";
			if ( $system_on ) { 
			    push @warns, $msg;
			    }
			else { 
			    push @ignores, $msg;
			    }
			}
		    else { 
			$msg = "${temp}F";
			push @oks, $msg;
			}
		    last;
		    }
		}
	    }
	}



    # humidity
    $table = snmp_table( $session, 'lgpEnvHumidityTableRel', 
	"$liebert.1.42.3.4.2.2.3", [ 2, 3 ] );
    if ( $table ) {
	$rows = scalar @$table;
	foreach $row ( 1 .. $rows ) {
	    # col 2 lgpEnvHumidityDescrRel
	    # col 3 lgpEnvHumidityMeasurementRel
	    if ( defined $table->[$row][2] ) { 
		$verbose && print "    rh $table->[$row][2] $table->[$row][3]\n";
		if ( $table->[$row][2] eq '1.3.6.1.4.1.476.1.42.3.4.2.1.2' 
			|| $rows == 2 )  {
		    # lgpEnvReturnAirHumidity, or there's only one entry
		    $humidity = $table->[$row][3];
		    if ( out_of_range( $crit_humidity_range, $humidity ) ) { 
			$msg = "${humidity}% rh out of range $crit_humidity_range";
			if ( $system_on ) { 
			    push @crits, $msg;
			    }
			else { 
			    push @ignores, $msg;
			    }
			}
		    elsif ( out_of_range( $warn_humidity_range, $humidity ) ) { 
			$msg = "${humidity}% rh out of range $warn_humidity_range";
			if ( $system_on ) { 
			    push @warns, $msg;
			    }
			else { 
			    push @ignores, $msg;
			    }
			}
		    else { 
			$msg = "${humidity}% rh";
			push @oks, $msg;
			}
		    last;
		    }
		}
	    }
	}


    # humidity setpoints
    # make sure no-one's screwed witht them again
    # 
    # first find out which row is the control humidity, and which is return
    $setpoint_row = -1;
    $result = snmp_walk( $session, 'lgpEnvHumidityDescrRel', 
	"$liebert.1.42.3.4.2.2.3.1.2" );
    foreach $oid ( sort keys %$result ) {
	$val = $result->{ $oid };
	# lgpEnvControlHumidity
	if ( $val eq '1.3.6.1.4.1.476.1.42.3.4.2.1.1' )  { 
	    $oid =~ m/\.(\d+)$/; 
	    $setpoint_row = $1;
	    }
	}

    if ( $setpoint_row > 0 ) { 
	$result = snmp_walk( $session, 'lgpEnvHumiditySetPoint', 
	    "$liebert.1.42.3.4.2.2.3.1.6" );
	foreach $oid ( sort keys %$result ) {
	    $oid =~ m/\.(\d+)$/; 
	    $row = $1;
	    if ( $row == $setpoint_row ) { 
		$val = $result->{ $oid };
		$verbose && print "    rh setpoint $row $val\n";
		if ( $val < 40 ) { 
		    push @warns, "humidity setpoint $row $val% too low";
		    }
		elsif ( $val > 60 ) { 
		    push @warns, "humidity setpoint $row $val% too high";
		    }
		}
	    }
	}
    }








sub snmp_get {
    my( $session, $name, $oids ) = @_;
    my( $result, $oid, $val );

    $verbose && print "snmp_get $name\n";
    $result = $session->get_request( -varbindlist => $oids );
    if ( ! defined( $result ) ) {
        #warn "snmpget error: ", $session->error(), "\n";
        return undef;
        }

    foreach $oid ( @$oids ) {
	if ( ! exists $result->{ $oid } ) {
	    #warn "snmpget error: requested oid not in response\n";
	    $verbose && print "    $oid: no response\n";
	    $result->{ $oid } = undef;
	    }
	elsif ( $result->{ $oid } eq 'noSuchInstance' )  {
	    $verbose && print "    $oid: noSuchInstance\n";
	    $result->{ $oid } = undef;
	    }
	elsif ( $result->{ $oid } eq 'noSuchObject' )  {
	    $verbose && print "    $oid: noSuchObject\n";
	    $result->{ $oid } = undef;
	    }
	elsif ( $verbose ) {
	    $val = $result->{ $oid };
	    $val =~ tr/\040-\176//cd;
	    print "    $oid: $val\n";
	    }
	}

    return $result;
    }





sub snmp_get_one {
    my( $session, $name, $oid ) = @_;
    my( @oids, $result, $oid2, $val );

    $verbose && print "snmp_get $name\n";
    @oids = ( $oid );
    $result = $session->get_request( -varbindlist => \@oids );
    if ( ! defined( $result ) ) {
        #warn "snmpget error: ", $session->error(), "\n";
        return undef;
        }

    if ( ! exists $result->{ $oid } ) {
        #warn "snmpget error: requested oid not in response\n";
	$verbose && print "    $oid: no response\n";
        return undef;
        }
    elsif ( $result->{ $oid } eq 'noSuchInstance' )  {
	$verbose && print "    $oid: noSuchInstance\n";
        return undef;
        }
    elsif ( $result->{ $oid } eq 'noSuchObject' )  {
	$verbose && print "    $oid: noSuchObject\n";
        return undef;
        }

    if ( $verbose ) {
	$val = $result->{ $oid };
	$val =~ tr/\040-\176//cd;
	print "    $oid: $val\n";
	}
    return $result->{ $oid };
    }




sub snmp_walk {
    my( $session, $name, $baseoid ) = @_;
    my( $result );

    $verbose && print "walking $name\n";
    $result = $session->get_table( -baseoid => $baseoid, 
	-maxrepetitions => $maxrepetitions );
    #print "session error ", $session->error(), "\n";
    if ( ! defined( $result )
            && $session->error() !~ m/Requested table is empty/ ) {
        push @unknowns, sprintf( "error walking $name table on %s: %s",
            $session->hostname, $session->error() );
        return undef;
        }

    if ( $verbose > 1 ) {
	my( $oid, $val );
	foreach $oid ( sort keys %$result ) {
	    $val = $result->{ $oid };
	    print "$oid = $val\n";
	    }
	}

    return $result;
    }







# walk a table 
# With the optional columns parameter, just walk those selected columns out of it.  
# Return a pointer to a 2d array.  
sub snmp_table {
    my( $session, $name, $baseoid, $columns ) = @_;
    my( $result, $rows, $oid, $val, $col, $row, $data, @oids, $maxmsgsize );

    $verbose && print "walking $name table $baseoid @$columns\n";
    if ( defined $columns ) { 
	foreach $col ( @$columns ) { 
	    $verbose && print "<$baseoid.1.$col\n";
	    push @oids, "$baseoid.1.$col";
	    }
	}
    else { 
	push @oids, $baseoid;
	}

    $data = [];

    foreach $oid ( @oids ) { 
	foreach $maxmsgsize ( 1472, 1600, 1800, 2048, 4096, 9000 ) { 
	    $session->max_msg_size( $maxmsgsize );
	    $verbose > 1 && print "snmp get_entries tring maxmsgsize $maxmsgsize\n";

	    # get_entries has a bug where index 0 stops the result
	    # It thinks it's a duplicate?
	    # It has another bug where it stops on gaps.
	    #$result = $session->get_entries( -columns => \@oids );

	    # get_table doesn't do this stupidity
	    $result = $session->get_table( -baseoid => $oid, 
		-maxrepetitions => $maxrepetitions );

	    if ( defined( $result ) ) {
		last;
		}
	    elsif ( $session->error() =~ m/Requested table is empty/ ) {
		# ok
		#return $data;
		last;
		}
	    elsif ( $session->error() =~ m/Message size exceeded buffer maxMsgSize/ ) {
		# retry with different size
		$verbose && print "snmp get_entries failed with maxmsgsize $maxmsgsize\n";
		next;
		}
	    else { 
		$verbose && print "snmp get_entries failed with error ", $session->error(), "\n";
		last;
		}
	    # else try a bigger maxmessage size
	    }

	if ( ! defined( $result ) ) {
	    #push @crits, sprintf "error walking $name table on %s: %s",
		#$session->hostname, $session->error();
	    next;
	    }

	foreach $oid ( sort keys %$result ) {
	    $val = $result->{ $oid };
	    $verbose > 1 && print "> $oid = $val\n";
	    next if ( $val eq 'endOfMibView' );
	    if ( $oid =~ m/.*\.(\d+)\.(\d+)$/ ) {
		$col = $1; $row = $2;
		$data->[$row][$col] = $val;
		}
	    }
	}

    if ( scalar( @$data ) < 1 ) {
        push @unknowns, sprintf "no rows in $name table on %s: %s",
            $session->hostname, $session->error();
	return undef;
        }

    return $data;
    }









# walk a table where the "row" index is actually multiple levels in the oid 
# ie a 3 part index
sub snmp_table_multi_index {
    my( $session, $name, $baseoid, $columns, $nindexes ) = @_;
    my( $result, $rows, $oid, $val, $col, $row, $data, @oids, $maxmsgsize );

    $verbose && print "walking $name table $baseoid @$columns\n";

    if ( defined $columns ) { 
	foreach $col ( @$columns ) { 
	    push @oids, "$baseoid.1.$col";
	    }
	}
    else { 
	push @oids, $baseoid;
	}

    $data = {};
    foreach $maxmsgsize ( $prefered_maxmsgsize, 1472, 1600, 1800, 2048, 4096, 9000 ) { 
	$session->max_msg_size( $maxmsgsize );
	$verbose > 1 && print "snmp get_entries tring maxmsgsize $maxmsgsize\n";

	$result = $session->get_entries( -columns => \@oids, 
	    -maxrepetitions => $maxrepetitions );
	if ( defined( $result ) ) {
	    last;
	    }
	elsif ( $session->error() =~ m/Requested table is empty/ ) {
	    # ok
	    return $data;
	    }
	elsif ( $session->error() !~ m/Message size exceeded buffer maxMsgSize/ ) {
	    last;
	    }
	}
    if ( ! defined( $result ) ) {
	push @crits, sprintf "error walking $name table on %s: %s",
	    $session->hostname, $session->error();
	return undef;
	}

    foreach $oid ( sort keys %$result ) {
	$val = $result->{ $oid };
	$verbose > 1 && print "$oid = $val\n";
	next if ( $val eq 'endOfMibView' );
	if ( ( $nindexes == 3 && $oid =~ m/.*\.(\d+)\.(\d+\.\d+\.\d+)$/ ) 
		|| ( $nindexes == 2 && $oid =~ m/.*\.(\d+)\.(\d+\.\d+)$/ )
		|| ( $nindexes == 4 && $oid =~ m/.*\.(\d+)\.(\d+\.\d+\.\d+\.\d+)$/ ) ) {
	    $col = $1; $row = $2;
	    $data->{$row}[$col] = $val;
	    }
	}

    if ( scalar( keys %$data ) < 1 ) {
        push @unknowns, sprintf "no rows in $name table on %s: %s",
            $session->hostname, $session->error();
	return undef;
        }

    return $data;
    }




sub out_of_range {
    my( $range, $n ) = @_;
    my( $low, $high );

    if ( $range =~ m/^(\d+):(\d+)$/ ) {
	$low = $1; $high = $2;
	if ( $low > $high ) {
	    print "ERROR: invalid range: '$range'\n";
	    exit 3;   # nagios unknown exit code
	    }
	elsif ( $n < $low || $high < $n ) {
	    return 1;
	    }
	}
    elsif ( $range =~ m/^:?(\d+)$/ ) {
	$high = $1;
	if ( $high < $n ) {
	    return 1;
	    }
	}
    elsif ( $range =~ m/^(\d+):$/ ) {
	$low = $1;
	if ( $n < $low ) {
	    return 1;
	    }
	}
    else {
	print "ERROR: can't parse range: '$range'\n";
	exit 3;   # nagios unknown exit code
	}
    }


