#!/usr/bin/perl -w
#
#=============================== SUMMARY =======================================
#
# Program : check_dell_ups.pl
# Version : 2012-04-23
# Date    : April 23 2012
# Author  : Troy Lea - plugins@box293.com
# Summary : This is a Nagios plugin that checks the status of a Dell UPS 
#           via a network mananagement card. Specifically this is for the UPS
#			devices manufactured by Eaton for Dell.
# Copyright: Troy Lea 2012
#
#============================ PROGRAM 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, 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/>.
#	
#
#                    GNU GENERAL PUBLIC LICENSE
#                       Version 3, 29 June 2007
#
# Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
# Everyone is permitted to copy and distribute verbatim copies
# of this license document, but changing it is not allowed.
#
#                            Preamble
#
#  The GNU General Public License is a free, copyleft license for
# software and other kinds of works.
#
#  The licenses for most software and other practical works are designed
# to take away your freedom to share and change the works.  By contrast,
# the GNU General Public License is intended to guarantee your freedom to
# share and change all versions of a program--to make sure it remains free
# software for all its users.  We, the Free Software Foundation, use the
# GNU General Public License for most of our software; it applies also to
# any other work released this way by its authors.  You can apply it to
# your programs, too.
#
#  When we speak of free software, we are referring to freedom, not
# price.  Our General Public Licenses are designed to make sure that you
# have the freedom to distribute copies of free software (and charge for
# them if you wish), that you receive source code or can get it if you
# want it, that you can change the software or use pieces of it in new
# free programs, and that you know you can do these things.
#
#  To protect your rights, we need to prevent others from denying you
# these rights or asking you to surrender the rights.  Therefore, you have
# certain responsibilities if you distribute copies of the software, or if
# you modify it: responsibilities to respect the freedom of others.
#
#   For example, if you distribute copies of such a program, whether
# gratis or for a fee, you must pass on to the recipients the same
# freedoms that you received.  You must make sure that they, too, receive
# or can get the source code.  And you must show them these terms so they
# know their rights.
#
#   Developers that use the GNU GPL protect your rights with two steps:
# (1) assert copyright on the software, and (2) offer you this License
# giving you legal permission to copy, distribute and/or modify it.
#
#   For the developers' and authors' protection, the GPL clearly explains
# that there is no warranty for this free software.  For both users' and
# authors' sake, the GPL requires that modified versions be marked as
# changed, so that their problems will not be attributed erroneously to
# authors of previous versions.
#
#   Some devices are designed to deny users access to install or run
# modified versions of the software inside them, although the manufacturer
# can do so.  This is fundamentally incompatible with the aim of
# protecting users' freedom to change the software.  The systematic
# pattern of such abuse occurs in the area of products for individuals to
# use, which is precisely where it is most unacceptable.  Therefore, we
# have designed this version of the GPL to prohibit the practice for those
# products.  If such problems arise substantially in other domains, we
# stand ready to extend this provision to those domains in future versions
# of the GPL, as needed to protect the freedom of users.
#
#   Finally, every program is threatened constantly by software patents.
# States should not allow patents to restrict development and use of
# software on general-purpose computers, but in those that do, we wish to
# avoid the special danger that patents applied to a free program could
# make it effectively proprietary.  To prevent this, the GPL assures that
# patents cannot be used to render the program non-free.
#
#   The precise terms and conditions for copying, distribution and
# modification follow.
#
#                        TERMS AND CONDITIONS
# 
#   0. Definitions.
# 
#   "This License" refers to version 3 of the GNU General Public License.
# 
#   "Copyright" also means copyright-like laws that apply to other kinds of
# works, such as semiconductor masks.
# 
#   "The Program" refers to any copyrightable work licensed under this
# License.  Each licensee is addressed as "you".  "Licensees" and
# "recipients" may be individuals or organizations.
#
#   To "modify" a work means to copy from or adapt all or part of the work
# in a fashion requiring copyright permission, other than the making of an
# exact copy.  The resulting work is called a "modified version" of the
# earlier work or a work "based on" the earlier work.
#
#   A "covered work" means either the unmodified Program or a work based
# on the Program.
#
#   To "propagate" a work means to do anything with it that, without
# permission, would make you directly or secondarily liable for
# infringement under applicable copyright law, except executing it on a
# computer or modifying a private copy.  Propagation includes copying,
# distribution (with or without modification), making available to the
# public, and in some countries other activities as well.
#
#   To "convey" a work means any kind of propagation that enables other
# parties to make or receive copies.  Mere interaction with a user through
# a computer network, with no transfer of a copy, is not conveying.
#
#   An interactive user interface displays "Appropriate Legal Notices"
# to the extent that it includes a convenient and prominently visible
# feature that (1) displays an appropriate copyright notice, and (2)
# tells the user that there is no warranty for the work (except to the
# extent that warranties are provided), that licensees may convey the
# work under this License, and how to view a copy of this License.  If
# the interface presents a list of user commands or options, such as a
# menu, a prominent item in the list meets this criterion.
#
#   1. Source Code.
# 
#   The "source code" for a work means the preferred form of the work
# for making modifications to it.  "Object code" means any non-source
# form of a work.
# 
#   A "Standard Interface" means an interface that either is an official
# standard defined by a recognized standards body, or, in the case of
# interfaces specified for a particular programming language, one that
# is widely used among developers working in that language.
# 
#   The "System Libraries" of an executable work include anything, other
# than the work as a whole, that (a) is included in the normal form of
# packaging a Major Component, but which is not part of that Major
# Component, and (b) serves only to enable use of the work with that
# Major Component, or to implement a Standard Interface for which an
# implementation is available to the public in source code form.  A
# "Major Component", in this context, means a major essential component
# (kernel, window system, and so on) of the specific operating system
# (if any) on which the executable work runs, or a compiler used to
# produce the work, or an object code interpreter used to run it.
# 
#   The "Corresponding Source" for a work in object code form means all
# the source code needed to generate, install, and (for an executable
# work) run the object code and to modify the work, including scripts to
# control those activities.  However, it does not include the work's
# System Libraries, or general-purpose tools or generally available free
# programs which are used unmodified in performing those activities but
# which are not part of the work.  For example, Corresponding Source
# includes interface definition files associated with source files for
# the work, and the source code for shared libraries and dynamically
# linked subprograms that the work is specifically designed to require,
# such as by intimate data communication or control flow between those
# subprograms and other parts of the work.
# 
#   The Corresponding Source need not include anything that users
# can regenerate automatically from other parts of the Corresponding
# Source.
# 
#   The Corresponding Source for a work in source code form is that
# same work.
# 
#   2. Basic Permissions.
# 
#   All rights granted under this License are granted for the term of
# copyright on the Program, and are irrevocable provided the stated
# conditions are met.  This License explicitly affirms your unlimited
# permission to run the unmodified Program.  The output from running a
# covered work is covered by this License only if the output, given its
# content, constitutes a covered work.  This License acknowledges your
# rights of fair use or other equivalent, as provided by copyright law.
# 
#   You may make, run and propagate covered works that you do not
# convey, without conditions so long as your license otherwise remains
# in force.  You may convey covered works to others for the sole purpose
# of having them make modifications exclusively for you, or provide you
# with facilities for running those works, provided that you comply with
# the terms of this License in conveying all material for which you do
# not control copyright.  Those thus making or running the covered works
# for you must do so exclusively on your behalf, under your direction
# and control, on terms that prohibit them from making any copies of
# your copyrighted material outside their relationship with you.
# 
#   Conveying under any other circumstances is permitted solely under
# the conditions stated below.  Sublicensing is not allowed; section 10
# makes it unnecessary.
# 
#   3. Protecting Users' Legal Rights From Anti-Circumvention Law.
# 
#   No covered work shall be deemed part of an effective technological
# measure under any applicable law fulfilling obligations under article
# 11 of the WIPO copyright treaty adopted on 20 December 1996, or
# similar laws prohibiting or restricting circumvention of such
# measures.
# 
#   When you convey a covered work, you waive any legal power to forbid
# circumvention of technological measures to the extent such circumvention
# is effected by exercising rights under this License with respect to
# the covered work, and you disclaim any intention to limit operation or
# modification of the work as a means of enforcing, against the work's
# users, your or third parties' legal rights to forbid circumvention of
# technological measures.
# 
#   4. Conveying Verbatim Copies.
# 
#   You may convey verbatim copies of the Program's source code as you
# receive it, in any medium, provided that you conspicuously and
# appropriately publish on each copy an appropriate copyright notice;
# keep intact all notices stating that this License and any
# non-permissive terms added in accord with section 7 apply to the code;
# keep intact all notices of the absence of any warranty; and give all
# recipients a copy of this License along with the Program.
# 
#   You may charge any price or no price for each copy that you convey,
# and you may offer support or warranty protection for a fee.
# 
#   5. Conveying Modified Source Versions.
# 
#   You may convey a work based on the Program, or the modifications to
# produce it from the Program, in the form of source code under the
# terms of section 4, provided that you also meet all of these conditions:
# 
#     a) The work must carry prominent notices stating that you modified
#     it, and giving a relevant date.
# 
#     b) The work must carry prominent notices stating that it is
#     released under this License and any conditions added under section
#     7.  This requirement modifies the requirement in section 4 to
#     "keep intact all notices".
# 
#     c) You must license the entire work, as a whole, under this
#     License to anyone who comes into possession of a copy.  This
#     License will therefore apply, along with any applicable section 7
#     additional terms, to the whole of the work, and all its parts,
#     regardless of how they are packaged.  This License gives no
#     permission to license the work in any other way, but it does not
#     invalidate such permission if you have separately received it.
# 
#     d) If the work has interactive user interfaces, each must display
#     Appropriate Legal Notices; however, if the Program has interactive
#     interfaces that do not display Appropriate Legal Notices, your
#     work need not make them do so.
# 
#   A compilation of a covered work with other separate and independent
# works, which are not by their nature extensions of the covered work,
# and which are not combined with it such as to form a larger program,
# in or on a volume of a storage or distribution medium, is called an
# "aggregate" if the compilation and its resulting copyright are not
# used to limit the access or legal rights of the compilation's users
# beyond what the individual works permit.  Inclusion of a covered work
# in an aggregate does not cause this License to apply to the other
# parts of the aggregate.
# 
#   6. Conveying Non-Source Forms.
# 
#   You may convey a covered work in object code form under the terms
# of sections 4 and 5, provided that you also convey the
# machine-readable Corresponding Source under the terms of this License,
# in one of these ways:
# 
#     a) Convey the object code in, or embodied in, a physical product
#     (including a physical distribution medium), accompanied by the
#     Corresponding Source fixed on a durable physical medium
#     customarily used for software interchange.
# 
#     b) Convey the object code in, or embodied in, a physical product
#     (including a physical distribution medium), accompanied by a
#     written offer, valid for at least three years and valid for as
#     long as you offer spare parts or customer support for that product
#     model, to give anyone who possesses the object code either (1) a
#     copy of the Corresponding Source for all the software in the
#     product that is covered by this License, on a durable physical
#     medium customarily used for software interchange, for a price no
#     more than your reasonable cost of physically performing this
#     conveying of source, or (2) access to copy the
#     Corresponding Source from a network server at no charge.
# 
#     c) Convey individual copies of the object code with a copy of the
#     written offer to provide the Corresponding Source.  This
#     alternative is allowed only occasionally and noncommercially, and
#     only if you received the object code with such an offer, in accord
#     with subsection 6b.
# 
#     d) Convey the object code by offering access from a designated
#     place (gratis or for a charge), and offer equivalent access to the
#     Corresponding Source in the same way through the same place at no
#     further charge.  You need not require recipients to copy the
#     Corresponding Source along with the object code.  If the place to
#     copy the object code is a network server, the Corresponding Source
#     may be on a different server (operated by you or a third party)
#     that supports equivalent copying facilities, provided you maintain
#     clear directions next to the object code saying where to find the
#     Corresponding Source.  Regardless of what server hosts the
#     Corresponding Source, you remain obligated to ensure that it is
#     available for as long as needed to satisfy these requirements.
# 
#     e) Convey the object code using peer-to-peer transmission, provided
#     you inform other peers where the object code and Corresponding
#     Source of the work are being offered to the general public at no
#     charge under subsection 6d.
# 
#   A separable portion of the object code, whose source code is excluded
# from the Corresponding Source as a System Library, need not be
# included in conveying the object code work.
# 
#   A "User Product" is either (1) a "consumer product", which means any
# tangible personal property which is normally used for personal, family,
# or household purposes, or (2) anything designed or sold for incorporation
# into a dwelling.  In determining whether a product is a consumer product,
# doubtful cases shall be resolved in favor of coverage.  For a particular
# product received by a particular user, "normally used" refers to a
# typical or common use of that class of product, regardless of the status
# of the particular user or of the way in which the particular user
# actually uses, or expects or is expected to use, the product.  A product
# is a consumer product regardless of whether the product has substantial
# commercial, industrial or non-consumer uses, unless such uses represent
# the only significant mode of use of the product.
# 
#   "Installation Information" for a User Product means any methods,
# procedures, authorization keys, or other information required to install
# and execute modified versions of a covered work in that User Product from
# a modified version of its Corresponding Source.  The information must
# suffice to ensure that the continued functioning of the modified object
# code is in no case prevented or interfered with solely because
# modification has been made.
# 
#   If you convey an object code work under this section in, or with, or
# specifically for use in, a User Product, and the conveying occurs as
# part of a transaction in which the right of possession and use of the
# User Product is transferred to the recipient in perpetuity or for a
# fixed term (regardless of how the transaction is characterized), the
# Corresponding Source conveyed under this section must be accompanied
# by the Installation Information.  But this requirement does not apply
# if neither you nor any third party retains the ability to install
# modified object code on the User Product (for example, the work has
# been installed in ROM).
# 
#   The requirement to provide Installation Information does not include a
# requirement to continue to provide support service, warranty, or updates
# for a work that has been modified or installed by the recipient, or for
# the User Product in which it has been modified or installed.  Access to a
# network may be denied when the modification itself materially and
# adversely affects the operation of the network or violates the rules and
# protocols for communication across the network.
# 
#   Corresponding Source conveyed, and Installation Information provided,
# in accord with this section must be in a format that is publicly
# documented (and with an implementation available to the public in
# source code form), and must require no special password or key for
# unpacking, reading or copying.
# 
#   7. Additional Terms.
# 
#   "Additional permissions" are terms that supplement the terms of this
# License by making exceptions from one or more of its conditions.
# Additional permissions that are applicable to the entire Program shall
# be treated as though they were included in this License, to the extent
# that they are valid under applicable law.  If additional permissions
# apply only to part of the Program, that part may be used separately
# under those permissions, but the entire Program remains governed by
# this License without regard to the additional permissions.
# 
#   When you convey a copy of a covered work, you may at your option
# remove any additional permissions from that copy, or from any part of
# it.  (Additional permissions may be written to require their own
# removal in certain cases when you modify the work.)  You may place
# additional permissions on material, added by you to a covered work,
# for which you have or can give appropriate copyright permission.
# 
#   Notwithstanding any other provision of this License, for material you
# add to a covered work, you may (if authorized by the copyright holders of
# that material) supplement the terms of this License with terms:
# 
#     a) Disclaiming warranty or limiting liability differently from the
#     terms of sections 15 and 16 of this License; or
# 
#     b) Requiring preservation of specified reasonable legal notices or
#     author attributions in that material or in the Appropriate Legal
#     Notices displayed by works containing it; or
# 
#     c) Prohibiting misrepresentation of the origin of that material, or
#     requiring that modified versions of such material be marked in
#     reasonable ways as different from the original version; or
# 
#     d) Limiting the use for publicity purposes of names of licensors or
#     authors of the material; or
# 
#     e) Declining to grant rights under trademark law for use of some
#     trade names, trademarks, or service marks; or
# 
#     f) Requiring indemnification of licensors and authors of that
#     material by anyone who conveys the material (or modified versions of
#     it) with contractual assumptions of liability to the recipient, for
#     any liability that these contractual assumptions directly impose on
#     those licensors and authors.
# 
#   All other non-permissive additional terms are considered "further
# restrictions" within the meaning of section 10.  If the Program as you
# received it, or any part of it, contains a notice stating that it is
# governed by this License along with a term that is a further
# restriction, you may remove that term.  If a license document contains
# a further restriction but permits relicensing or conveying under this
# License, you may add to a covered work material governed by the terms
# of that license document, provided that the further restriction does
# not survive such relicensing or conveying.
# 
#   If you add terms to a covered work in accord with this section, you
# must place, in the relevant source files, a statement of the
# additional terms that apply to those files, or a notice indicating
# where to find the applicable terms.
# 
#   Additional terms, permissive or non-permissive, may be stated in the
# form of a separately written license, or stated as exceptions;
# the above requirements apply either way.
# 
#   8. Termination.
# 
#   You may not propagate or modify a covered work except as expressly
# provided under this License.  Any attempt otherwise to propagate or
# modify it is void, and will automatically terminate your rights under
# this License (including any patent licenses granted under the third
# paragraph of section 11).
# 
#   However, if you cease all violation of this License, then your
# license from a particular copyright holder is reinstated (a)
# provisionally, unless and until the copyright holder explicitly and
# finally terminates your license, and (b) permanently, if the copyright
# holder fails to notify you of the violation by some reasonable means
# prior to 60 days after the cessation.
# 
#   Moreover, your license from a particular copyright holder is
# reinstated permanently if the copyright holder notifies you of the
# violation by some reasonable means, this is the first time you have
# received notice of violation of this License (for any work) from that
# copyright holder, and you cure the violation prior to 30 days after
# your receipt of the notice.
# 
#   Termination of your rights under this section does not terminate the
# licenses of parties who have received copies or rights from you under
# this License.  If your rights have been terminated and not permanently
# reinstated, you do not qualify to receive new licenses for the same
# material under section 10.
# 
#   9. Acceptance Not Required for Having Copies.
# 
#   You are not required to accept this License in order to receive or
# run a copy of the Program.  Ancillary propagation of a covered work
# occurring solely as a consequence of using peer-to-peer transmission
# to receive a copy likewise does not require acceptance.  However,
# nothing other than this License grants you permission to propagate or
# modify any covered work.  These actions infringe copyright if you do
# not accept this License.  Therefore, by modifying or propagating a
# covered work, you indicate your acceptance of this License to do so.
# 
#   10. Automatic Licensing of Downstream Recipients.
# 
#   Each time you convey a covered work, the recipient automatically
# receives a license from the original licensors, to run, modify and
# propagate that work, subject to this License.  You are not responsible
# for enforcing compliance by third parties with this License.
# 
#   An "entity transaction" is a transaction transferring control of an
# organization, or substantially all assets of one, or subdividing an
# organization, or merging organizations.  If propagation of a covered
# work results from an entity transaction, each party to that
# transaction who receives a copy of the work also receives whatever
# licenses to the work the party's predecessor in interest had or could
# give under the previous paragraph, plus a right to possession of the
# Corresponding Source of the work from the predecessor in interest, if
# the predecessor has it or can get it with reasonable efforts.
# 
#   You may not impose any further restrictions on the exercise of the
# rights granted or affirmed under this License.  For example, you may
# not impose a license fee, royalty, or other charge for exercise of
# rights granted under this License, and you may not initiate litigation
# (including a cross-claim or counterclaim in a lawsuit) alleging that
# any patent claim is infringed by making, using, selling, offering for
# sale, or importing the Program or any portion of it.
# 
#   11. Patents.
# 
#   A "contributor" is a copyright holder who authorizes use under this
# License of the Program or a work on which the Program is based.  The
# work thus licensed is called the contributor's "contributor version".
# 
#   A contributor's "essential patent claims" are all patent claims
# owned or controlled by the contributor, whether already acquired or
# hereafter acquired, that would be infringed by some manner, permitted
# by this License, of making, using, or selling its contributor version,
# but do not include claims that would be infringed only as a
# consequence of further modification of the contributor version.  For
# purposes of this definition, "control" includes the right to grant
# patent sublicenses in a manner consistent with the requirements of
# this License.
# 
#   Each contributor grants you a non-exclusive, worldwide, royalty-free
# patent license under the contributor's essential patent claims, to
# make, use, sell, offer for sale, import and otherwise run, modify and
# propagate the contents of its contributor version.
# 
#   In the following three paragraphs, a "patent license" is any express
# agreement or commitment, however denominated, not to enforce a patent
# (such as an express permission to practice a patent or covenant not to
# sue for patent infringement).  To "grant" such a patent license to a
# party means to make such an agreement or commitment not to enforce a
# patent against the party.
# 
#   If you convey a covered work, knowingly relying on a patent license,
# and the Corresponding Source of the work is not available for anyone
# to copy, free of charge and under the terms of this License, through a
# publicly available network server or other readily accessible means,
# then you must either (1) cause the Corresponding Source to be so
# available, or (2) arrange to deprive yourself of the benefit of the
# patent license for this particular work, or (3) arrange, in a manner
# consistent with the requirements of this License, to extend the patent
# license to downstream recipients.  "Knowingly relying" means you have
# actual knowledge that, but for the patent license, your conveying the
# covered work in a country, or your recipient's use of the covered work
# in a country, would infringe one or more identifiable patents in that
# country that you have reason to believe are valid.
# 
#   If, pursuant to or in connection with a single transaction or
# arrangement, you convey, or propagate by procuring conveyance of, a
# covered work, and grant a patent license to some of the parties
# receiving the covered work authorizing them to use, propagate, modify
# or convey a specific copy of the covered work, then the patent license
# you grant is automatically extended to all recipients of the covered
# work and works based on it.
# 
#   A patent license is "discriminatory" if it does not include within
# the scope of its coverage, prohibits the exercise of, or is
# conditioned on the non-exercise of one or more of the rights that are
# specifically granted under this License.  You may not convey a covered
# work if you are a party to an arrangement with a third party that is
# in the business of distributing software, under which you make payment
# to the third party based on the extent of your activity of conveying
# the work, and under which the third party grants, to any of the
# parties who would receive the covered work from you, a discriminatory
# patent license (a) in connection with copies of the covered work
# conveyed by you (or copies made from those copies), or (b) primarily
# for and in connection with specific products or compilations that
# contain the covered work, unless you entered into that arrangement,
# or that patent license was granted, prior to 28 March 2007.
# 
#   Nothing in this License shall be construed as excluding or limiting
# any implied license or other defenses to infringement that may
# otherwise be available to you under applicable patent law.
# 
#   12. No Surrender of Others' Freedom.
# 
#   If conditions are imposed on you (whether by court order, agreement or
# otherwise) that contradict the conditions of this License, they do not
# excuse you from the conditions of this License.  If you cannot convey a
# covered work so as to satisfy simultaneously your obligations under this
# License and any other pertinent obligations, then as a consequence you may
# not convey it at all.  For example, if you agree to terms that obligate you
# to collect a royalty for further conveying from those to whom you convey
# the Program, the only way you could satisfy both those terms and this
# License would be to refrain entirely from conveying the Program.
# 
#   13. Use with the GNU Affero General Public License.
# 
#   Notwithstanding any other provision of this License, you have
# permission to link or combine any covered work with a work licensed
# under version 3 of the GNU Affero General Public License into a single
# combined work, and to convey the resulting work.  The terms of this
# License will continue to apply to the part which is the covered work,
# but the special requirements of the GNU Affero General Public License,
# section 13, concerning interaction through a network will apply to the
# combination as such.
# 
#   14. Revised Versions of this License.
# 
#   The Free Software Foundation may publish revised and/or new versions of
# the GNU General Public License from time to time.  Such new versions will
# be similar in spirit to the present version, but may differ in detail to
# address new problems or concerns.
# 
#   Each version is given a distinguishing version number.  If the
# Program specifies that a certain numbered version of the GNU General
# Public License "or any later version" applies to it, you have the
# option of following the terms and conditions either of that numbered
# version or of any later version published by the Free Software
# Foundation.  If the Program does not specify a version number of the
# GNU General Public License, you may choose any version ever published
# by the Free Software Foundation.
# 
#   If the Program specifies that a proxy can decide which future
# versions of the GNU General Public License can be used, that proxy's
# public statement of acceptance of a version permanently authorizes you
# to choose that version for the Program.
# 
#   Later license versions may give you additional or different
# permissions.  However, no additional obligations are imposed on any
# author or copyright holder as a result of your choosing to follow a
# later version.
# 
#   15. Disclaimer of Warranty.
# 
#   THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
# APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
# HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
# OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
# IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
# ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
# 
#   16. Limitation of Liability.
# 
#   IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
# WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
# THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
# GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
# USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
# DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
# PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
# EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGES.
# 
#   17. Interpretation of Sections 15 and 16.
# 
#   If the disclaimer of warranty and limitation of liability provided
# above cannot be given local legal effect according to their terms,
# reviewing courts shall apply local law that most closely approximates
# an absolute waiver of all civil liability in connection with the
# Program, unless a warranty or assumption of liability accompanies a
# copy of the Program in return for a fee.
# 
#====================== END OF TERMS AND CONDITIONS ============================
#
#====================== INFORMATION ABOUT THIS PLUGIN ==========================
#
# This is a nagios plugin that checks the status of a Dell UPS via a network 
# mananagement card. Specifically this is for the UPS devices manufactured 
# by Eaton for Dell.
#
# This program is written and maintained by:
#   Troy Lea - plugins@box293.com
#
# It is based on check_dell_openmanage.pl plugin by:
#   Jason Ellison - infotek@gmail.com
#
# Which in turn is based on check_snmp_temperature.pl plugin by:
#   William Leibzon - william@leibzon.org
#
# Using information from MibUpsDell.mib which is supplied part of the firmware
# download file DELL_NMC-UPS-FW--H910P-_A02_R286786.exe. This download is for
# the network management card H910P.
#
# Tested with the following:
#
# 	UPS:
# 		Dell UPS Short Depth Rack 2700W High Efficiency Online HV-230V
#			Firmware 01.04.0008
#
# 	Network Management Card:
#		H910P
#			Firmware 01.10.0005
#
#============================== SETUP NOTES ====================================
#
# Copy this file to your Nagios installation folder in "libexec/". 
#
# You must have enabled SNMP on the UPS and define the community. 
# On the server that will be running the plugin you must have the perl
# "Net::SNMP" module installed.
#
# perl -MCPAN -e shell
# cpan> install Net::SNMP
#
# For SNMPv3 support make sure you have the following modules installed:
#   Crypt::DES, Digest::MD5, Digest::SHA1, and Digest::HMAC
#
#========================== SETUP EXAMPLES =====================================
#
# define command{
#       command_name    check_dell_ups
#       command_line    $USER1$/check_dell_ups.pl -H $HOSTADDRESS$ -C $ARG1$ -T $ARG2$ $ARG3$ $ARG4$ $ARG5$ $ARG6$ $ARG7$ $ARG8$
#       }
#
# define service{
#       use                     generic-service
#       host_name               UPS01
#       service_description     Global Status
#       check_command           check_dell_ups!public!global_status
#       normal_check_interval   3
#       retry_check_interval    1
#       }
#
# define service{
#       use                     generic-service
#       host_name               UPS01
#       service_description     Battery Remaining
#       check_command           check_dell_ups!public!battery_remaining!-U m!-w 15!-c 8
#       normal_check_interval   3
#       retry_check_interval    1
#       }
#
#================================= REVISION ====================================
#
# Version 2011-03-13
# The first version released. Includes the following checks: battery_monitoring_status, 
# battery_remaining, battery_test_status, firmware_version, global_status, 
# model, output_va_consumption, output_watt_consumption, output_watt_remaining,
# serial_number, ups_mode
#
#
# Version 2011-03-26
# * Updated command example to include $ARG3$ to $ARG8$
# * Updated battery_monitoring_status check to report a CRITICAL status if traps
# 11, 13, 15 or 57 are present (alerting that the UPS is either over/under AC Voltage
# OR Input Frequency is out of range OR UPS is on battery) (if 57 is present it will NOT
# report a CRITICAL status if 61 is ALSO present)
# * Checking for the Net::SNMP Library occurs first and will report an error
# when not in verbose mode
# * Added alarm_status check
# * Added more information in the help text
#
#
# Version 2012-04-23
# * Added firmware_version_nic check that will report the Network Management Card 
# Firmware Version
#
#=========================== START OF PROGRAM CODE =============================
use Getopt::Long;

use strict;
my $Version='2012-04-23';

my @unit_dependant_checks = ('battery_remaining');
my @unit_types = ('h','m','s');
my $unit_type_check;
my $unit_type_defined;
my $perf_data;


my %check_types = (
	"alarm_status" => [
		'physicalUPSAlarmsStatus'
	],
	"battery_monitoring_status" => [
		'physicalBatteryABMStatus',
		'physicalUPSAlarmsStatus'
	],
	"battery_remaining" => [
		'physicalBatterySecondsRemaining'
	],
	"battery_test_status" => [
		'physicalBatteryTestStatus'
	],
	"firmware_version" => [
		'productIDVersion',
		'productIDBuildNumber'
	],
	"firmware_version_nic" => [
		'NICBuildNumber'
	],
	"global_status" => [
		'productStatusGlobalStatus'
	],
	"model" => [
		'productIDDisplayName'
	],
	"output_va_consumption" => [
		'physicalOutputVA'
	],
	"output_watt_consumption" => [
		'physicalOutputPresentConsumption'
	],
	"output_watt_remaining" => [
		'physicalOutputInstantHeadroom'
	],
	"serial_number" => [
		'physicalIdentSerialNumber'
	],
	"ups_mode" => [
		'physicalIdentConverterType'
	]	
);

my %ups_oids = (
	'NICBuildNumber'=>'.1.3.6.1.2.1.33.1.1.4.0',
	'productIDDisplayName'=>'.1.3.6.1.4.1.674.10902.2.100.1.0',
	'productIDDescription'=>'.1.3.6.1.4.1.674.10902.2.100.2.0',
	'productIDVendor'=>'.1.3.6.1.4.1.674.10902.2.100.3.0',
	'productIDVersion'=>'.1.3.6.1.4.1.674.10902.2.100.4.0',
	'productIDBuildNumber'=>'.1.3.6.1.4.1.674.10902.2.100.5.0',
	'productIDURL'=>'.1.3.6.1.4.1.674.10902.2.100.6.0',
	'productIDDeviceNetworkName'=>'.1.3.6.1.4.1.674.10902.2.100.7.0',
	'productStatusGlobalStatus'=>'.1.3.6.1.4.1.674.10902.2.110.1.0',
	'productStatusLastGlobalStatus'=>'.1.3.6.1.4.1.674.10902.2.110.2.0',
	'productStatusTimeStamp'=>'.1.3.6.1.4.1.674.10902.2.110.3.0',
	'productStatusGetTimeOut'=>'.1.3.6.1.4.1.674.10902.2.110.4.0',
	'productStatusRefreshRate'=>'.1.3.6.1.4.1.674.10902.2.110.5.0',
	'productStatusGeneratingTrapFlag'=>'.1.3.6.1.4.1.674.10902.2.110.6.0',
	'physicalIdentFamilyName'=>'.1.3.6.1.4.1.674.10902.2.120.1.1.0',
	'physicalIdentSerialNumber'=>'.1.3.6.1.4.1.674.10902.2.120.1.2.0',
	'physicalIdentConverterType'=>'.1.3.6.1.4.1.674.10902.2.120.1.3.0',
	'physicalIdentReferenceNumber'=>'.1.3.6.1.4.1.674.10902.2.120.1.4.0',
	'physicalOutputInstantHeadroom'=>'.1.3.6.1.4.1.674.10902.2.120.2.1.0',
	'physicalOutputPeakHeadroom'=>'.1.3.6.1.4.1.674.10902.2.120.2.2.0',
	'physicalOutputPeakHeadroomTimestamp'=>'.1.3.6.1.4.1.674.10902.2.120.2.3.0',
	'physicalOutputPeakConsumption'=>'.1.3.6.1.4.1.674.10902.2.120.2.4.0',
	'physicalOutputPeakConsumptionTimestamp'=>'.1.3.6.1.4.1.674.10902.2.120.2.5.0',
	'physicalOutputPresentConsumption'=>'.1.3.6.1.4.1.674.10902.2.120.2.6.0',
	'physicalOutputCumulativeConsumption'=>'.1.3.6.1.4.1.674.10902.2.120.2.7.0',
	'physicalOutputCumulativeConsumptionTimestamp'=>'.1.3.6.1.4.1.674.10902.2.120.2.8.0',
	'physicalOutputVA'=>'.1.3.6.1.4.1.674.10902.2.120.2.9.0',
	'physicalRectifierPosVoltage'=>'.1.3.6.1.4.1.674.10902.2.120.3.1.0',
	'physicalRectifierNegVoltage'=>'.1.3.6.1.4.1.674.10902.2.120.3.2.0',
	'physicalUPSDateTime'=>'.1.3.6.1.4.1.674.10902.2.120.4.1.0',
	'physicalUPSAlarmsStatus'=>'.1.3.6.1.4.1.674.10902.2.120.4.2.0',
	'physicalUPSRuntimeToShutdown'=>'.1.3.6.1.4.1.674.10902.2.120.4.3.0',
	'physicalUPSOutputSwitchable'=>'.1.3.6.1.4.1.674.10902.2.120.4.4.0',
	'physicalBatteryABMStatus'=>'.1.3.6.1.4.1.674.10902.2.120.5.1.0',
	'physicalBatteryTestStatus'=>'.1.3.6.1.4.1.674.10902.2.120.5.2.0',
	'physicalBatterySecondsRemaining'=>'.1.3.6.1.4.1.674.10902.2.120.5.3.0',
	'physicalLoadSegment1ShutdownAfterDelay'=>'.1.3.6.1.4.1.674.10902.2.120.6.1.0',
	'physicalLoadSegment1StartupAfterDelay'=>'.1.3.6.1.4.1.674.10902.2.120.6.2.0',
	'physicalLoadSegment2ShutdownAfterDelay'=>'.1.3.6.1.4.1.674.10902.2.120.6.3.0',
	'physicalLoadSegment2StartupAfterDelay'=>'.1.3.6.1.4.1.674.10902.2.120.6.4.0',
	'physicalLoadSegment1RuntimeToShutdown'=>'.1.3.6.1.4.1.674.10902.2.120.6.5.0',
	'physicalLoadSegment2RuntimeToShutdown'=>'.1.3.6.1.4.1.674.10902.2.120.6.6.0'
);

my %ERRORS=('OK'=>0,'WARNING'=>1,'CRITICAL'=>2,'UNKNOWN'=>3);
my $o_host=     undef;          # hostname
my $o_community= undef;         # community
my $o_port=     161;            # SNMP port
my $o_help=     undef;          # help option
my $o_verb=     undef;          # verbose mode
my $o_version=  undef;          # version info option
my $o_unit= 	undef;         	# Time Unit to use for reporting
my $o_warn=     undef;          # warning level option
my $o_crit=     undef;          # Critical level option
my $o_reportonly=	undef;      # Report Only option
my $o_timeout=  5;              # Default 5s Timeout
my $o_version2= undef;          # use snmp v2c
# SNMPv3 specific
my $o_login=    undef;          # Login for snmpv3
my $o_passwd=   undef;          # Pass for snmpv3
my $o_attr=     undef;          # What attribute(s) to check (specify more then one separated by '.')
my @o_attrL=    ();             # array for above list
my $o_unkdef=   2;              # Default value to report for unknown attributes
my $o_type=     undef;          # Type of system to check 

sub print_version { print "\n$0\nVersion $Version\n" };

sub print_usage {
	print "Usage: $0 [-v] -H <host> -C <snmp_community> [-2] | (-l login -x password) [-P <port>] [-T <check_type> alarm_status|battery_monitoring_status|battery_remaining|battery_test_status|firmware_version|firmware_version_nic|global_status|model|output_va_consumption|output_watt_consumption|output_watt_remaining|serial_number|ups_mode] [-U <unit> h|m|s] [-w <warning value>] [-c <critical value>] -r [-t <timeout>] [-V]\n";
	print "\nFor detailed help type \"check_dell_ups.pl --help | more\"\n";
}

# Return true if arg is a number
sub isnum {
	my $num = shift;
	if ( $num =~ /^(\d+\.?\d*)|(^\.\d+)$/ ) { return 1 ;}
	return 0;
}

sub help {
	print "\nSNMP Dell UPS Plugin for Nagios version ",$Version,"\n";
	print " by Troy Lea - plugins\@box293.com\n\n";
	print_usage();
	print "\n";
	print <<EOD;
-v, --verbose
    print extra debugging information
-h, --help
    print this help message
-H, --hostname=HOST
    name or IP address of UPS to check
-C, --community=COMMUNITY NAME
    community name for the host's SNMP agent (implies v 1 protocol)
-2, --v2c
    use SNMP v2 (instead of SNMP v1)
-P, --port=PORT
    SNMP port (Default 161)
-t, --timeout=INTEGER
    timeout for SNMP in seconds (Default: 5)
-V, --version
    prints version number
-U, --unit=TIME UNIT
	What unit of measurement to use when reporting time values
	Required for battery_remaining
	s = seconds
	m = minutes
	h = hours
-w, --warn=WARNING VALUE
	Warning value for tiggering alerts, works with:
		battery_remaining, output_va_consumption, 
		output_watt_consumption, output_watt_remaining
-c, --crit=CRITICAL VALUE
	Critical value for tiggering alerts, works with:
		battery_remaining, output_va_consumption,
		output_watt_consumption, output_watt_remaining 
-r, --reportonly
	If warning or critical values have been defined, only use them for
	performance data, status code will be returned as OK
-T, --type
		This is the type of check you want to perform against the UPS
	alarm_status 
		Current traps that are active (only odd traps are listed)
		 Will always return an OK status
	battery_monitoring_status 
		Advanced battery monitoring status
		 Will report a CRITICAL status if traps 11, 13, 15 or 57 are 
		 present (alerting that the UPS is either over/under AC Voltage
		 OR Input Frequency is out of range OR UPS is on battery)
		 (if UPS is On Battery it will NOT report a CRITICAL status if 
		 a Battery Test is in progress)
	battery_remaining
		How much time the battery has remaining before empty
	battery_test_status
		Report the current battery test status
	firmware_version
		Report the full firmware version of the Dell UPS
	firmware_version_nic
		Report the full firmware version of the Network Management Card
	global_status
		Current status of the UPS
		UPS Result	Nagios Status Code
		Other		OK
		Unknown		UNKNOWN
		OK		OK
		Aborted		OK
		Non-Critical	WARNING
		Critical	CRITICAL
		Non-Recoverable	CRITICAL
	model
		Report the model of the Dell UPS
	output_va_consumption
		VA consumption
	output_watt_consumption
		Watt consumption
	output_watt_remaining
		Remaining watt capacity before overload
	serial_number
		Report the serial number of the Dell UPS
	ups_mode
		Report what mode the UPS is configured in
		
Examples:
	check_dell_ups.pl -H 192.168.5.1 -C public -T serial_number
	check_dell_ups.pl -H 192.168.5.1 -C public -T battery_remaining -U m -w 15 -c 8
	check_dell_ups.pl -H 192.168.5.1 -C public -T output_watt_consumption -w 1500 -c 2000
	
EOD
}
#===============================================================================
# For verbose output - don't use it right now
sub verb { my $t=shift; print $t,"\n" if defined($o_verb) ; }
# Get the alarm signal (just in case snmp timout screws up)
$SIG{'ALRM'} = sub {
	print ("ERROR: Alarm signal (Nagios time-out)\n");
	exit $ERRORS{"UNKNOWN"};
};
sub check_options {
    Getopt::Long::Configure ("bundling");
    GetOptions(
		'v'		=> \$o_verb,			'verbose'		=> \$o_verb,
		'h'		=> \$o_help,			'help'			=> \$o_help,
		'H:s'	=> \$o_host,			'hostname:s'	=> \$o_host,
		'P:i'	=> \$o_port,			'port:i'		=> \$o_port,
		'C:s'	=> \$o_community,		'community:s'	=> \$o_community,
		'l:s'	=> \$o_login,			'login:s'		=> \$o_login,
		'x:s'	=> \$o_passwd,			'passwd:s'		=> \$o_passwd,
		't:i'	=> \$o_timeout,			'timeout:i'		=> \$o_timeout,
		'V'		=> \$o_version,			'version'		=> \$o_version,
		'2'		=> \$o_version2,		'v2c'			=> \$o_version2,
		'U:s'	=> \$o_unit,			'unit:s'		=> \$o_unit,
		'w:i'	=> \$o_warn,			'warn:i'		=> \$o_warn,
		'c:i'	=> \$o_crit,			'crit:i'		=> \$o_crit,
		'T:s'	=> \$o_type,			'type:s'		=> \$o_type,
		'r'		=> \$o_reportonly,		'reportonly'	=> \$o_reportonly
    );
    # Print help text
	if (defined($o_help) ) { help(); exit $ERRORS{"UNKNOWN"}; }
    
	# Print version
	if (defined($o_version)) { print_version(); exit $ERRORS{"UNKNOWN"}; }
    
	# Check if the host has been defined
	if (!defined($o_host) ) 
        { print "\nYou have not defined the UPS to check (IP Address or FQDN)\n\n";print_usage(); exit $ERRORS{"UNKNOWN"}; }
    
	# check snmp information
    if (!defined($o_community) && (!defined($o_login) || !defined($o_passwd)) )
        { print "\nYou need to define SNMP connection settings\n\n"; print_usage(); exit $ERRORS{"UNKNOWN"}; }
    
	if (!defined($o_type)) { print "\nCheck type has not been defined\n\n"; print_usage(); exit $ERRORS{"UNKNOWN"}; }
	
	# Critical Value
	if (defined($o_crit)) {
		#print "$o_crit \n";
		# Check to see if the value is blank
			if ($o_crit eq '') {
				print "\nThe \"crit\" value cannot be left blank\n\n";print_usage(); exit $ERRORS{"UNKNOWN"}; 
			} 
	}
	
	# Warning Value
	if (defined($o_warn)) {
		#print "$o_warn \n";
		# Check to see if the unit is blank
			if ($o_warn eq '') {
				print "\nThe \"warn\" value cannot be left blank\n\n";print_usage(); exit $ERRORS{"UNKNOWN"}; 
			}  
	}
	
	if (defined ($o_type)) {
		if (!defined($check_types{$o_type}))  {
			print "\nUnknown check type \"$o_type\"\n\n"; print_usage(); exit $ERRORS{"UNKNOWN"}; 
        }
		# Check to see if the Unit value has been correctly defined
		$unit_type_defined = 0;
		foreach (@unit_dependant_checks) {
			#print "$_ \n";
			# See if we have a check that uses the unit value
			if ($_ eq $o_type) {
				#print "$_ \n";
				# Check to see if the unit has been defined
				if (!defined($o_unit)) {
					print "\nThe \"$_\" check requires the unit type to be defined\n\n";print_usage(); exit $ERRORS{"UNKNOWN"}; 
				} 
				# Check to see if the unit is blank
				elsif ($o_unit eq '') {
					print "\nThe \"$_\" check unit type cannot be left blank\n\n";print_usage(); exit $ERRORS{"UNKNOWN"}; 
				} 
				# Check to see if the unit value is an allowed type
				foreach $unit_type_check (@unit_types) {
					if ($o_unit eq $unit_type_check) {
						$unit_type_defined = 1;
					}
				}
				# Report error if unit value is not allowed
				if ($unit_type_defined != 1) {
					print "\nThe unit \"$o_unit\" is not an allowed type\n\n";print_usage(); exit $ERRORS{"UNKNOWN"}; 
				}
			} 
		}
	}
}
########## MAIN #######
eval "use Net::SNMP";
if ($@) {
  print "\nERROR: You do NOT have the Net:".":SNMP library \n";
  print "  Install it by running: \n";
  print "  perl -MCPAN -e shell \n";
  print "  cpan[1]> install Net::SNMP \n";
  exit 1;
} else {
  verb("The Net:".":SNMP library is available on your server \n");
}


check_options();
# Check global timeout if something goes wrong
if (defined($o_timeout)) {
  verb("Alarm at $o_timeout");
  alarm($o_timeout);
} else {
  verb("no timeout defined : using 5s");
  alarm (5);
}


# SNMP Connection to the host
my ($session,$error);
if (defined($o_login) && defined($o_passwd)) {
  # SNMPv3 login
  verb("SNMPv3 login");
  ($session, $error) = Net::SNMP->session(
      -hostname         => $o_host,
      -version          => '3',
      -username         => $o_login,
      -authpassword     => $o_passwd,
      -authprotocol     => 'md5',
      -privpassword     => $o_passwd,
      -timeout          => $o_timeout
   );
} else {
   if (defined ($o_version2)) {
     # SNMPv2 Login
         ($session, $error) = Net::SNMP->session(
        -hostname  => $o_host,
            -version   => 2,
        -community => $o_community,
        -port      => $o_port,
        -timeout   => $o_timeout
     );
   } else {
    # SNMPV1 login
    ($session, $error) = Net::SNMP->session(
       -hostname  => $o_host,
       -community => $o_community,
       -port      => $o_port,
       -timeout   => $o_timeout
    );
  }
}

# next part of the code builds list of attributes to be retrieved
my $i;
my $oid;
my $line;
my $resp;
my $attr;
my $key;
my %varlist = ();
my $result;
my $statusinfo = "";
my $statuscode = "";
my $unit_string = "";
my $unit_value = "";
my $unit_decimalpoints = "";
my $exit_no_status = 0;

verb("SNMP responses...");
for $attr ( @{ $check_types{$o_type} } ) {
	$result = $session->get_request( 
    -varbindlist => [$ups_oids{$attr}]
	);
 	
	# Checking if verbose mode is enabled
	if (defined $o_verb) {
		if (!defined($result->{$ups_oids{$attr}})) {
			verb("\nRESULT: $attr \n$ups_oids{$attr} = \n");
		}
		else { 
			verb("\nRESULT: $attr \n$ups_oids{$attr} = $result->{$ups_oids{$attr}}\n");
		}
	}
	
	# Check for an empty result
	if (!defined($result->{$ups_oids{$attr}})) {
		#print "\nTesting for no result\n\n"; 
		$statusinfo = "No response from UPS";
		$statuscode = "UNKNOWN";
		$perf_data = "";
	} 
	

# Alarm Status
	elsif ($o_type eq "alarm_status") {
		$statuscode = "OK";
		if ($result->{$ups_oids{$attr}} eq '') {
			$statusinfo = "No Active Traps";
		}
		else { 
			$statusinfo = "Active Traps:" if (!$statusinfo);
			#print "\n$result->{$ups_oids{$attr}}\n\n"; 
			my @result_split = split(',',$result->{$ups_oids{$attr}});
			foreach (@result_split) { 
				#print "\n$_\n\n"; 
				if ($_ == 1) {
					$statusinfo .= " {1: Inverter AC Voltage exceeded Over Voltage Threshold}";
				}
				elsif ($_ == 3) {
					$statusinfo .= " {3: Inverter AC Voltage below Under Voltage Threshold}";
				}
				elsif ($_ == 5) {
					$statusinfo .= " {5: Bypass Frequency out of Range}";
				}
				elsif ($_ == 7) {
					$statusinfo .= " {7: On Buck / Input Voltage Reducer}";
				}
				elsif ($_ == 9) {
					$statusinfo .= " {9: On Boost / Input Voltage Booster}";
				}
				elsif ($_ == 11) {
					$statusinfo .= " {11: Input AC Voltage exceeded Over Voltage Threshold}";
				}
				elsif ($_ == 13) {
					$statusinfo .= " {13: Input AC Voltage below Low Voltage Threshold}";
				}
				elsif ($_ == 15) {
					$statusinfo .= " {15: Input Frequency Out Of Range}";
				}
				elsif ($_ == 17) {
					$statusinfo .= " {17: Remote emergency power off}";
				}
				elsif ($_ == 19) {
					$statusinfo .= " {19: Output exceeded OverLoad Level 1 Threshold}";
				}
				elsif ($_ == 21) {
					$statusinfo .= " {21: Output exceeded OverLoad Level 2 Threshold}";
				}
				elsif ($_ == 23) {
					$statusinfo .= " {23: Output exceeded OverLoad Level 3 Threshold}";
				}
				elsif ($_ == 25) {
					$statusinfo .= " {25: Positive DC link voltage exceeded Over Voltage Threshold}";
				}
				elsif ($_ == 27) {
					$statusinfo .= " {27: Positive DC link voltage below Low Voltage Threshold}";
				}
				elsif ($_ == 29) {
					$statusinfo .= " {29: Negative DC link Voltage exceeded Over Voltage Threshold}";
				}
				elsif ($_ == 31) {
					$statusinfo .= " {31: Negative DC link Voltage below Low Voltage Threshold}";
				}
				elsif ($_ == 33) {
					$statusinfo .= " {33: Rectifier fault}";
				}
				elsif ($_ == 35) {
					$statusinfo .= " {35: Inverter fault}";
				}
				elsif ($_ == 37) {
					$statusinfo .= " {37: Charger failure}";
				}
				elsif ($_ == 39) {
					$statusinfo .= " {39: EEPROM failure}";
				}
				elsif ($_ == 41) {
					$statusinfo .= " {41: Shutdown is imminent}";
				}
				elsif ($_ == 43) {
					$statusinfo .= " {43: Battery Rremaining Capacity below Low Remaining Capacity Threshold}";
				}
				elsif ($_ == 45) {
					$statusinfo .= " {45: Output short circuit}";
				}
				elsif ($_ == 47) {
					$statusinfo .= " {47: Utility is not present}";
				}
				elsif ($_ == 49) {
					$statusinfo .= " {49: Battery DC Voltage exceeded Over Voltage Threshold}";
				}
				elsif ($_ == 51) {
					$statusinfo .= " {51: Temperature exceeded Over Temperature Threshold}";
				}
				elsif ($_ == 53) {
					$statusinfo .= " {53: Bypass is not available}";
				}
				elsif ($_ == 55) {
					$statusinfo .= " {55: On manual / maintenance bypass}";
				}
				elsif ($_ == 57) {
					$statusinfo .= " {57: UPS on battery}";
				}
				elsif ($_ == 59) {
					$statusinfo .= " {59: UPS on bypass}";
				}
				elsif ($_ == 61) {
					$statusinfo .= " {61: Battery manual or automatic test in progress}";
				}
				elsif ($_ == 63) {
					$statusinfo .= " {63: Battery test failed, battery needs to be replaced}";
				}
				elsif ($_ == 65) {
					$statusinfo .= " {65: UPS Fan has failed}";
				}
				elsif ($_ == 67) {
					$statusinfo .= " {67: There is a fault in Site Wiring}";
				}
				elsif ($_ == 69) {
					$statusinfo .= " {69: Batteries have been disconnected from the UPS}";
				}
				elsif ($_ == 71) {
					$statusinfo .= " {71: UPS has been turned Off}";
				}
				elsif ($_ == 73) {
					$statusinfo .= " {73: UPS has a DC link imbalance}";
				}
				elsif ($_ == 79) {
					$statusinfo .= " {79: ABM is POWERED ON}";
				}
				elsif ($_ == 81) {
					$statusinfo .= " {81: Load segment 1 is Switched Off}";
				}
				elsif ($_ == 83) {
					$statusinfo .= " {83: Load segment 2 is Switched Off}";
				}
				elsif ($_ == 85) {
					$statusinfo .= " {85: UPS is running in High Efficiency mode}";
				}
				elsif ($_ == 87) {
					$statusinfo .= " {87: Rectifier Input Current exceeded Input Current Threshold}";
				}
				elsif ($_ == 89) {
					$statusinfo .= " {89: Inverter Output Current exceeded Over Load Threshold}";
				}
				elsif ($_ == 91) {
					$statusinfo .= " {91: Bypass AC Voltage out of Normal Range}";
				}
				elsif ($_ == 93) {
					$statusinfo .= " {93: UPS received command to switch on bypass}";
				}
				elsif ($_ == 95) {
					$statusinfo .= " {95: UPS received command to switch from bypass to inverter}";
				}
				elsif ($_ == 97) {
					$statusinfo .= " {97: Communication restored with UPS}";
				}
			}
		}
		$perf_data = "";
	}
	
	# Battery Monitoring Status
	elsif ($o_type eq "battery_monitoring_status") {
		$statusinfo = "Battery Monitoring Status: " if (!$statusinfo);
		#print "\n$result->{$ups_oids{$attr}}\n\n"; 
		my @result_split = split(',',$result->{$ups_oids{$attr}});
		foreach (@result_split) { 
			#print "\n$_\n\n"; 
			if ($_ == 1) {
				$statusinfo .= "Charging";
				$statuscode = "OK";
			}
			elsif ($_ == 2) {
				$statusinfo .= "Discharging";
				$statuscode = "OK";
			}
			elsif ($_ == 3) {
				$statusinfo .= "Floating";
				$statuscode = "OK";
			}
			elsif ($_ == 4) {
				$statusinfo .= "Resting";
				$statuscode = "OK";
			}
			elsif ($_ == 5) {
				$statusinfo .= "Off";
				$statuscode = "CRITICAL";
			}
			elsif ($_ == 11) {
				$statusinfo .= " {Input AC Over Voltage Threshold}";
				$statuscode = "CRITICAL";
			}
			elsif ($_ == 13) {
				$statusinfo .= " {Input AC Under Voltage Threshold}";
				$statuscode = "CRITICAL";
			}
			elsif ($_ == 15) {
				$statusinfo .= " {Input Frequency Out Of Range}";
				$statuscode = "CRITICAL";
			}
			elsif ($_ == 57) {
				my @result_split_again = split(',',$result->{$ups_oids{$attr}});
				my $test_in_progress = 0;
				foreach (@result_split_again) {
					if ($_ == 61) {
						$test_in_progress = 1;
					}
				}
				if ($test_in_progress == 0) {
					$statusinfo .= " {UPS on battery}";
					$statuscode = "CRITICAL";
				}
			}
		}
		$perf_data = "";
	}
	
	# Battery Remaining	
	elsif ($o_type eq "battery_remaining") {
		$statusinfo = "Battery Remaining: " if (!$statusinfo);
		my $battery_remaining = $result->{$ups_oids{$attr}};
		if ($o_unit eq "s") { 
			$unit_string = "Seconds";
			$unit_value = 1;
			$unit_decimalpoints = "%.0f";
			}
		if ($o_unit eq "m") { 
			$unit_string = "Minutes";
			$unit_value = 60;
			$unit_decimalpoints = "%.2f";
			}
		if ($o_unit eq "h") { 
			$unit_string = "Hours";
			$unit_value = 3600;
			$unit_decimalpoints = "%.2f";
			}
		$battery_remaining = $battery_remaining/$unit_value;
		$battery_remaining = sprintf("$unit_decimalpoints", $battery_remaining);
		$statusinfo .= "$battery_remaining";	
		$statusinfo .= " $unit_string";
		$statuscode = "OK";
		# Check for warning value
		no warnings;
		if (defined($o_warn)) {
			# Check for critical value
			if (defined($o_crit)) {
				# Ensure warning is a larger value than critical
				if ($o_warn < $o_crit) {
					print "\nThe \"warn\" value must be larger than the \"crit\" value\n\n";print_usage(); exit $ERRORS{"UNKNOWN"}; 
				}
				# Check if critical value has been exceeded
				elsif ($battery_remaining <= $o_crit) {
					$statuscode = "CRITICAL";
				}
				# Otherwise check if warning value has been exceeded
				elsif ($battery_remaining <= $o_warn) {
					$statuscode = "WARNING";
				}
			}
			# If no critical value was defined check if warning value has been exceeded
			elsif ($battery_remaining <= $o_warn) {
					$statuscode = "WARNING";
			}
		}
		# Check for critical value
		if (defined($o_crit) && !defined($o_warn)) {
			# Check if critical value has been exceeded
			if ($battery_remaining <= $o_crit) {
				$statuscode = "CRITICAL";
			}
		}
	$perf_data = "|Battery Remaining=$battery_remaining"."$unit_string;$o_warn;$o_crit;;";
	use warnings;
	}

	# Battery Test Status	
	elsif ($o_type eq "battery_test_status") {
		$statusinfo = "Battery Test Status: " if (!$statusinfo);
		if ($result->{$ups_oids{$attr}} == 1) {
			$statusinfo .= "Passed";
			$statuscode = "OK";
		}
		elsif ($result->{$ups_oids{$attr}} == 2) {
			$statusinfo .= "Warning";
			$statuscode = "WARNING";
		}
		elsif ($result->{$ups_oids{$attr}} == 3) {
			$statusinfo .= "Error";
			$statuscode = "CRITICAL";
		}
		elsif ($result->{$ups_oids{$attr}} == 4) {
			$statusinfo .= "Aborted";
			$statuscode = "OK";
		}
		elsif ($result->{$ups_oids{$attr}} == 5) {
			$statusinfo .= "In Progress";
			$statuscode = "OK";
		}
		elsif ($result->{$ups_oids{$attr}} == 6) {
			$statusinfo .= "No Test Initiated";
			$statuscode = "OK";
		}
		elsif ($result->{$ups_oids{$attr}} == 7) {
			$statusinfo .= "Test Scheduled";
			$statuscode = "OK";
		}
		$perf_data = "";
	}
	
	# Firmware Version
	elsif ($o_type eq "firmware_version") {
		$statusinfo = "Firmware Version: " if (!$statusinfo);
		$statusinfo .= "." if ($statusinfo ne "Firmware Version: ");
		$statusinfo .= "$result->{$ups_oids{$attr}}";
		$statuscode = "OK";
		$perf_data = "";
		$exit_no_status = 1;
	}

	# Firmware Version NIC
	elsif ($o_type eq "firmware_version_nic") {
		$statusinfo = "NIC Firmware Version: " if (!$statusinfo);
		$statusinfo .= "$result->{$ups_oids{$attr}}";
		$statuscode = "OK";
		$perf_data = "";
		$exit_no_status = 1;
	}

	# Global Status
	elsif ($o_type eq "global_status") {
		$statusinfo = "Global Status: " if (!$statusinfo);
		if ($result->{$ups_oids{$attr}} == 1) {
			$statusinfo .= "Other";
			$statuscode = "OK";
		}
		elsif ($result->{$ups_oids{$attr}} == 2) {
			$statusinfo .= "Unknown";
			$statuscode = "UNKNOWN";
		}
		elsif ($result->{$ups_oids{$attr}} == 3) {
			$statusinfo .= "OK";
			$statuscode = "OK";
		}
		elsif ($result->{$ups_oids{$attr}} == 4) {
			$statusinfo .= "Non-Critical";
			$statuscode = "WARNING";
		}
		elsif ($result->{$ups_oids{$attr}} == 5) {
			$statusinfo .= "Critical";
			$statuscode = "CRITICAL";
		}
		elsif ($result->{$ups_oids{$attr}} == 6) {
			$statusinfo .= "Non-Recoverable";
			$statuscode = "CRITICAL";
		}
		$perf_data = "";
	}

	# Model
	elsif ($o_type eq "model") {
		$statusinfo = "Model: $result->{$ups_oids{$attr}}";
		$statuscode = "OK";
		$perf_data = "";
		$exit_no_status = 1;
	}
	
	
	# Output VA Consumption
	elsif ($o_type eq "output_va_consumption") {
		$statusinfo = "Output Consumption: " if (!$statusinfo);
		my $output_va_consumption = $result->{$ups_oids{$attr}};
		$statusinfo .= "$output_va_consumption";	
		$statusinfo .= " VA";
		$statuscode = "OK";
		# Check for warning value
		if (defined($o_warn)) {
			# Check for critical value
			if (defined($o_crit)) {
				# Ensure warning is a smaller value than critical
				if ($o_warn > $o_crit) {
					print "\nThe \"warn\" value must be smaller than the \"crit\" value\n\n";print_usage(); exit $ERRORS{"UNKNOWN"}; 
				}
				# Check if critical value has been exceeded
				elsif ($output_va_consumption >= $o_crit) {
					$statuscode = "CRITICAL";
				}
				# Otherwise check if warning value has been exceeded
				elsif ($output_va_consumption >= $o_warn) {
					$statuscode = "WARNING";
				}
			}
			# If no critical value was defined check if warning value has been exceeded
			elsif ($output_va_consumption >= $o_warn) {
					$statuscode = "WARNING";
			}
		}
		# Check for critical value
		if (defined($o_crit) && !defined($o_warn)) {
			# Check if critical value has been exceeded
			if ($output_va_consumption >= $o_crit) {
				$statuscode = "CRITICAL";
			}
		}
		no warnings;
		$perf_data = "|Output VA Consumption=$output_va_consumption"."VA;$o_warn;$o_crit;;";
		use warnings;
	}
	
	# Output Watt Consumption
	elsif ($o_type eq "output_watt_consumption") {
		$statusinfo = "Output Consumption: " if (!$statusinfo);
		my $output_watt_consumption = $result->{$ups_oids{$attr}};
		$statusinfo .= "$output_watt_consumption";	
		$statusinfo .= " Watts";
		$statuscode = "OK";
		# Check for warning value
		if (defined($o_warn)) {
			# Check for critical value
			if (defined($o_crit)) {
				# Ensure warning is a smaller value than critical
				if ($o_warn > $o_crit) {
					print "\nThe \"warn\" value must be smaller than the \"crit\" value\n\n";print_usage(); exit $ERRORS{"UNKNOWN"}; 
				}
				# Check if critical value has been exceeded
				elsif ($output_watt_consumption >= $o_crit) {
					$statuscode = "CRITICAL";
				}
				# Otherwise check if warning value has been exceeded
				elsif ($output_watt_consumption >= $o_warn) {
					$statuscode = "WARNING";
				}
			}
			# If no critical value was defined check if warning value has been exceeded
			elsif ($output_watt_consumption >= $o_warn) {
					$statuscode = "WARNING";
			}
		}
		# Check for critical value
		if (defined($o_crit) && !defined($o_warn)) {
			# Check if critical value has been exceeded
			if ($output_watt_consumption >= $o_crit) {
				$statuscode = "CRITICAL";
			}
		}
		no warnings;
		$perf_data = "|Output Watt Consumption=$output_watt_consumption"."Watts;$o_warn;$o_crit;;";
		use warnings;
	}
		
	# Output Watt Remaining
	elsif ($o_type eq "output_watt_remaining") {
		$statusinfo = "Output Remaining: " if (!$statusinfo);
		my $output_watt_remaining = $result->{$ups_oids{$attr}};
		$statusinfo .= "$output_watt_remaining";	
		$statusinfo .= " Watts";
		$statuscode = "OK";
		# Check for warning value
		if (defined($o_warn)) {
			# Check for critical value
			if (defined($o_crit)) {
				# Ensure warning is a larger value than critical
				if ($o_warn < $o_crit) {
					print "\nThe \"warn\" value must be larger than the \"crit\" value\n\n";print_usage(); exit $ERRORS{"UNKNOWN"}; 
				}
				# Check if critical value has been exceeded
				elsif ($output_watt_remaining <= $o_crit) {
					$statuscode = "CRITICAL";
				}
				# Otherwise check if warning value has been exceeded
				elsif ($output_watt_remaining <= $o_warn) {
					$statuscode = "WARNING";
				}
			}
			# If no critical value was defined check if warning value has been exceeded
			elsif ($output_watt_remaining <= $o_warn) {
					$statuscode = "WARNING";
			}
		}
		# Check for critical value
		if (defined($o_crit) && !defined($o_warn)) {
			# Check if critical value has been exceeded
			if ($output_watt_remaining <= $o_crit) {
				$statuscode = "CRITICAL";
			}
		}
		no warnings;
		$perf_data = "|Output Watt Remaining=$output_watt_remaining"."Watts;$o_warn;$o_crit;;";
		use warnings;
	}
	
	# Serial Number
	elsif ($o_type eq "serial_number") {
		$statusinfo = "Serial Number: $result->{$ups_oids{$attr}}";
		$statuscode = "OK";
		$perf_data = "";
		$exit_no_status = 1;
	}

	# UPS Mode
	elsif ($o_type eq "ups_mode") {
		$statusinfo = "UPS Mode: " if (!$statusinfo);
		if ($result->{$ups_oids{$attr}} == 1) {
			$statusinfo .= "onLine Interactive";	
		}
		elsif ($result->{$ups_oids{$attr}} == 2) {
			$statusinfo .= "OnLine";
		}
		elsif ($result->{$ups_oids{$attr}} == 3) {
			$statusinfo .= "Unitary Parallel";
		}
		elsif ($result->{$ups_oids{$attr}} == 4) {
			$statusinfo .= "Parallel With NS";
		}
		elsif ($result->{$ups_oids{$attr}} == 5) {
			$statusinfo .= "Hot Standby Redundancy";
		}
		$statuscode = "OK";
		$perf_data = "";
	}

}


$session->close();

my $final_output = "";

# Check to see if the Report Only option has been chosen   
if (defined($o_reportonly)) {
	$statuscode = "OK";
}

if ($exit_no_status == 1) {
	$final_output = "$statusinfo" . "$perf_data\n";
}
else {
	$final_output = "$statuscode: " . "$statusinfo" . "$perf_data\n";
}

printf($final_output);

verb("\nEXIT CODE: $ERRORS{$statuscode} STATUS CODE: $statuscode\n");

exit $ERRORS{$statuscode};

