diff --git a/plugins/environmental/snmp__poseidon-sensors b/plugins/environmental/snmp__poseidon-sensors
new file mode 100755
index 00000000..08cc7072
--- /dev/null
+++ b/plugins/environmental/snmp__poseidon-sensors
@@ -0,0 +1,402 @@
+#!/bin/bash
+#==============================================================================#
+# #
+# Check the sensor status of HW Group Poseidon family. For more info refer to:#
+# http://www.hw-group.com/products/poseidon/poseidon_3268_en.html #
+# 2012 by Florian Lechner (flo-github@catbull.com) #
+# #
+#==============================================================================#
+# #
+# 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 2 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 . #
+# #
+#==============================================================================#
+# #
+# This plugin requires snmpget to work propperly #
+# #
+#==============================================================================#
+
+# Munin autoconf and snmpautoconf magic
+#%# family=auto snmpauto contrib
+#%# capabilities=snmpconf
+
+#==============================================================================#
+# Config Section #
+#==============================================================================#
+
+# SNMP Config
+MIBS=":" # we don't use any configured MIBs so we don't
+ #+ have to deal with errors in the MIBs
+SNMPVERSION="1" # as of firmware 3.1.5 only SNMPv1 is supported
+SNMPCOMUNITY="public" # SNMP community string to read from the device
+
+#==============================================================================#
+# No configuration beyonde this line! #
+#==============================================================================#
+
+E_OK="0" # everything went allright
+E_UNKNOWN="1" # "catch all" for otherwise unhandled errors
+
+E_ARG="81" # invalid argument
+E_USAGE="82" # wrong program name or arguments
+E_SNMPGET="83" # error while executing the 'snmpget' utility
+
+E_ICINGA_OK="0" # Icinga exitcodes for states 'ok',
+E_ICINGA_WARN="1" #+ 'warning', and
+E_ICINGA_CRIT="2" #+ 'critical'
+
+E_COMMANDNOTFOUND="127" # unable to locate binary
+
+#==============================================================================#
+# SNMP OIDs from the Poseidon MIB #
+#==============================================================================#
+
+SYS_LOC_OID=".1.3.6.1.2.1.1.6.0" # SNMP-location
+SYS_NAME_OID=".1.3.6.1.2.1.1.5.0" # device name (string)
+SYS_DESCR_OID=".1.3.6.1.2.1.1.1" # text describing the device
+SYS_UPTIME_OID=".1.3.6.1.2.1.1.3.0" # time(in tens of milliseconds
+ #+ since the last reboot
+IN_NAME_OID=".1.3.6.1.4.1.21796.3.3.1.1.3." # binary input name (string)
+IN_STATE_OID=".1.3.6.1.4.1.21796.3.3.1.1.2." # binary input states(integer)
+IN_ALARM_OID=".1.3.6.1.4.1.21796.3.3.1.1.4." # alarm for the binary input,
+ #+ generated by the device
+ #+ under defined conditions
+ #+ 0=Invalid, 1=Normal,
+ #+ 2=AlarmState, 3=Alarm
+SENS_NAME_OID=".1.3.6.1.4.1.21796.3.3.3.1.2." # sensor name (string)
+SENS_STATE_OID=".1.3.6.1.4.1.21796.3.3.3.1.4." # binary input states(integer)
+SENS_VALUE_OID=".1.3.6.1.4.1.21796.3.3.3.1.6." # integer (decimal * 10)
+SENS_ID_OID=".1.3.6.1.4.1.21796.3.3.99.1.2.1.4." # unique sensor ID (integer)
+ #+ representation of the
+ #+ temperature (integer)
+SENS_UNIT_OID=".1.3.6.1.4.1.21796.3.3.3.1.9." # 0=°C,1=°F,2=°K,3=%,4=V,5=mA,
+RTS_OUTPUT_OID=".1.3.6.1.4.1.21796.3.3.2.1.2." # binary input state (integer)
+ #+ 6=unknown, 7=pulse, 8=switch
+
+# define some Poseidon specific stuff:
+STATE_OK="1"
+STATE_WARN="2"
+STATE_CRIT="3"
+UNITS=("C" "F" "K" "%" "V" "mA" "unknown" "pulse" "switch")
+TYPES=("Temp" "Temp" "Temp" "Hum" "Volt" "Curr" "Unkn" "Pulse" "Switch")
+
+declare -A sensorsOfType
+IFS="
+"
+
+#==============================================================================#
+
+# printIcingaStatus (sensorNumber)
+# print status output for icinga/icinga
+printIcingaStatus () {
+ _sensorNumber="$1"
+ getSensorData $_sensorNumber
+ _name="$sensorType$_sensorNumber" # long name
+ _value="$(($sensorValue/10)),$(($sensorValue%10))" # decimal rep.
+
+ if [ "$sensorState" = "$STATE_OK" ]; then
+ echo "$_name OK - $sensorName is $_value $sensorUnit."
+ return $E_ICINGA_OK
+ else
+ echo "$_name Critical - $sensorName is "$_value $sensorUnit"."
+ return $E_ICINGA_CRIT
+ fi
+}
+
+# printMuninConfig ()
+# print output for munin auto configuration
+printMuninConfig () {
+ if [ ! $hostAddr = 'localhost' ]; then
+ cat <<- EOT
+host_name $hostAddr
+EOT
+ fi
+
+ for ((_sensorType=0; _sensorType<=${#UNITS[*]};_sensorType++)); do
+ # skip graphs without sensors
+ if [ -z "${sensorsOfType[$_sensorType]}" ]; then
+ continue
+ fi
+
+ _firstSensor="1"
+ # print specific config for each sensor
+ for _sensorNr in ${sensorsOfType[$_sensorType]}; do
+ getSensorData $_sensorNr
+ getSystemInfo
+
+ if [ $_firstSensor = "1" ]; then
+ # graph headers
+ cat <<- EOT
+multigraph $sensorType
+graph_title $sensorLocation - $sensorType [$sensorUnit]
+graph_args --base 1000 -l 0
+graph_vlabel $sensorUnit
+graph_category environment
+graph_info This graph shows $sensorType history.
+EOT
+ fi
+ _firstSensor="0"
+ cat <<- EOT
+$sensorType$_sensorNr.label $sensorName
+$sensorType$_sensorNr.info This graph shows $sensorType$_sensorNr history.
+$sensorType$_sensorNr.draw LINE2
+EOT
+ done
+ done
+}
+
+# printMuninSnmpConfig ()
+# print output for munin snmp auto configuration
+printMuninSnmpConfig () {
+ cat <<- EOT
+require $SENS_VALUE_OID$sensorNumber [0-9]
+require $SENS_STATE_OID$sensorNumber
+EOT
+ return 0;
+}
+
+# printMuninStatus ()
+# print status output for munin
+printMuninStatus () {
+ for ((_sensorType=0; _sensorType<=${#UNITS[*]};_sensorType++)); do
+ # skip graphs without sensors
+ if [ -z "${sensorsOfType[$_sensorType]}" ]; then
+ continue
+ fi
+ _firstSensor="1"
+
+ # print config section
+ for _sensorNr in ${sensorsOfType[$_sensorType]}; do
+ getSensorData $_sensorNr
+ if [ $_firstSensor = "1" ]; then
+ # graph headers
+ cat <<- EOT
+multigraph $sensorType
+EOT
+ fi
+ _firstSensor="0"
+
+ # print graph details
+ cat <<- EOT
+$sensorType$_sensorNr.value $(( $sensorValue / 10 ))
+EOT
+ done
+ echo ""
+ done
+}
+
+# getSensorData(sensorNr)
+# fetch state, value, name unit and sensor type for the sensor
+#+ with the number "sensorNr"
+getSensorData() {
+ _sensorNr=$1
+ sensorState=`snmpGet $hostAddr $SENS_STATE_OID$_sensorNr || err \
+ "Fatal: snmpget failed with code \"$?\"! Exiting..." $E_SNMPGET`
+ sensorValue=`snmpGet $hostAddr $SENS_VALUE_OID$_sensorNr || err \
+ "Fatal: snmpget failed with code \"$?\"! Exiting..." $E_SNMPGET`
+ sensorName=`snmpGet $hostAddr $SENS_NAME_OID$_sensorNr || err \
+ "Fatal: snmpget failed with code \"$?\"! Exiting..." $E_SNMPGET`
+ sensorUnit=`getSensorUnitString $_sensorNr`
+ sensorType=`getSensorType $_sensorNr`
+}
+
+# getSystemInfo()
+# fetch general information about the system
+getSystemInfo() {
+ sensorLocation="`snmpGet $hostAddr $SYS_LOC_OID`"
+}
+
+# snmpGet (hostAddr, OID)
+# use snmpget to fetch a given OID, using above configuration
+snmpGet () {
+ _oid="$2"
+
+ _host="$1"
+ _exit="0"
+
+ # fetch the requested OID
+ _longValue="`snmpget -O v\
+ -m $MIBS\
+ -v $SNMPVERSION\
+ -c $SNMPCOMUNITY\
+ $_host $_oid 2>/dev/null`"
+
+ _exitStatus="$?"
+
+ echo ${_longValue#*:} # remove the type from the answer
+ return $_exitStatus
+}
+
+# get unit (string)
+#+ find out the unit of the output of a given sensor. possible units are:
+#+ "C" "F" "K" "%" "V" "mA" "unknown" "pulse" "switch"
+getSensorUnitString () {
+ _sensorNr=$1
+ _sensorUnit=`snmpGet $hostAddr $SENS_UNIT_OID$_sensorNr || err \
+ "Fatal: snmpget failed with code \"$?\"! Exiting..." $E_SNMPGET`
+ echo ${UNITS[$_sensorUnit]}
+}
+
+# get type (string)
+#+ find out what type of sensor we are dealing with. possible types are:
+#+ "Temp" "Hum" "Volt" "Curr" "Unkn" "Pulse" "Switch"
+getSensorType () {
+ _sensorNr=$1
+ _sensorUnit=`snmpGet $hostAddr $SENS_UNIT_OID$_sensorNr || err \
+ "Fatal: snmpget failed with code \"$?\"! Exiting..." $E_SNMPGET`
+ echo ${TYPES[$_sensorUnit]}
+}
+
+# getAvailableSensorsByType ()
+# check what sensors are available and store them
+#+ in the array for the respective unit
+getAvailableSensorsByType () {
+ _thisSensorNr="1"
+
+ # initial fetch
+ _snmpget=`snmpGet $hostAddr $SENS_UNIT_OID$_thisSensorNr`
+ _nextSensorExits=$?
+ _unit=`echo "$_snmpget" | tr -d " "`
+
+ # add next sensor if it exists
+ while [ true ]; do
+ # add sensors of the same type to a list
+ sensorsOfType[$_unit]="${sensorsOfType[$_unit]} $_thisSensorNr"
+
+ # fetch next sensor
+ _thisSensorNr=$(($_thisSensorNr+1))
+ _snmpget=`snmpGet $hostAddr $SENS_UNIT_OID$_thisSensorNr`
+ _nextSensorExits=$?
+
+ # are we done?
+ if [ $_nextSensorExits -ne 0 ]; then
+ break
+ fi
+
+ _unit=`echo "$_snmpget" |cut -d" " -f 4`
+ done
+}
+
+# sanitize ()
+# use bash builtin substitutions to sanitize string
+#+ allowed chars are: a-z,A-Z,0-9 and "."
+#+ if chars have been removed return 1, else return 0
+sanitize () {
+ input="$1"
+ sanitizedInput="${1//[^a-zA-Z0-9.]/}"
+ echo "$sanitizedInput"
+ if [ "$input" = "$sanitizedInput" ]; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+# usage ([munin|icinga])
+# print either specific usage for use as munin/icinga plugin or long usage
+usage () {
+ case $1 in
+ munin) echo "usage: snmp__poseidon-sensors [config|snmpconf]" 1>&2
+ exit $E_USAGE
+ ;;
+ icinga) echo "usage: check_snmp_poseidon " 1>&2
+ exit $E_USAGE
+ ;;
+ *) echo "usage: check_snmp_poseidon
+for nagios/icinga compatible output.
+usage: snmp__poseidon-sensors [config|snmpconf]
+for munin compatible output" 1>&2
+ exit $E_USAGE
+ ;;
+ esac
+}
+
+# err (ErrorMsg, Exitcode)
+# basic error handling
+err () {
+ if [ $# -eq 2 -a "$2" -lt 256 ]; then
+ _errorMsg="$1"
+ _exitCode="$2"
+ else
+ _errorMsg="Fatal: An unknown error occured! Exiting..."
+ _exitCode="$E_UNKNOWN"
+
+ fi
+
+ # print error message to STDERR ...
+ echo "$_errorMsg" >&2
+ # ... and exit with error code.
+ exit $_exitCode
+}
+
+#==============================================================================#
+
+# handle -h option
+while getopts ":h" opt; do
+ case $opt in
+ h) usage
+ ;;
+ \?) echo "Invalid option: -$OPTARG" >&2
+ usage
+ ;;
+ esac
+done
+
+# check for snmpget binary
+if [ ! -x `which snmpget` ]; then
+ err "Fatal: unable to locate \'snmpget\'! Exiting..." $E_COMMANDNOTFOUND
+fi
+
+# analyze how we have been called and...
+myName="`basename "$0"`"
+
+hostAddr="`echo $myName | cut -d "_" -f 2`"
+muninName="`echo $myName | cut -d "_" -f 1,3`"
+icingaName="`echo $myName | cut -d "_" -f 1,2,3`"
+
+# ...and behave like a munin/icinga plugin...
+if [ "$icingaName" = "check_snmp_poseidon" ]; then
+ # IP address of the Poseidon device
+ hostAddr=`sanitize $1 || err
+ "Fatal: Invalid argument \"$1\"! Exiting..." $E_ARG`
+ # number of the sensor
+ sensorNr=`sanitize $2 || err
+ "Fatal: Invalid argument \"$2\"! Exiting..." $E_ARG`
+ if [[ -n ${sensorNr//[0-9]/} ]]; then err \
+ "Fatal: Invalid argument \"$sensorNr\"\! Exiting..." $E_ARG
+ fi
+
+ printIcingaStatus "$sensorNr"
+ exit $?
+# ...or as a munin plugin
+elif [ "$muninName" = "snmp_poseidon-sensors" ]; then
+ hostAddr=`sanitize $hostAddr || err \
+ "Fatal: Invalid argument \"$hostAddr\"! Exiting..." $E_ARG`
+ if [ -z "$hostAddr" ]; then
+ usage munin
+ fi
+ getAvailableSensorsByType
+ if [ "$1" = "config" ]; then
+ printMuninConfig
+ exit $E_OK
+ elif [ "$1" = "snmpconfig" ]; then
+ printMuninSnmpConfig
+ exit $E_OK
+ else
+ printMuninStatus
+ exit $E_OK
+ fi
+else
+ usage
+fi
+