Added Bosch Sensortec I2C BME280/BMP280 sensor

Added support for additional measurements in addition to the temperature
Fixed handling of default I2C address
Updated documentation for the new I2C sensors (and fixed a few errors)
This commit is contained in:
2019-03-10 13:01:49 +01:00
parent 28daf07d1a
commit 379482e729
2 changed files with 301 additions and 75 deletions

112
README.md
View File

@@ -25,7 +25,8 @@ This repository contains the following scripts:
* [check_otp](#check_otp)
plugin to monitor PrivacyIDEA (and LinOTP) OTP validation
* [check_temperature](#check_temperature)
plugin to monitor the CPU temperature of a RaspberryPi or that of a DS18b20 1-wire sensor on a RaspberryPi
plugin to monitor the RaspberryPi CPU temperature or that of an 1-wire
(DS18b20) or I2C (MCP9080) sensor attached to a RaspberryPi
* [nagiosstatus](#nagiosstatus)
CGI-BIN script to report the status of nagios (to monitor nagios itself)
@@ -239,68 +240,121 @@ define service {
-------------------------------------------------------
Plugin (check) to monitor monitor the Raspberry Pi CPU temperature or that of a
temperature sensor connected to a RaspberryPi. This implementation currently
supports the DS18B20 1-wire temperature sensor. Other methods and interfaces can
be plugged in easily (just raise a request or provide a patch). For information
on how to connect sensor to the RaspberryPi and to get it working please see
[this Adafruit tutorial](
https://learn.adafruit.com/adafruits-raspberry-pi-lesson-11-ds18b20-temperature-sensing).
supports the following sensors:
* 1-wire:
* Maxim Integrated [DS18B20](https://learn.adafruit.com/adafruits-raspberry-pi-lesson-11-ds18b20-temperature-sensing)
* I2C
* Bosch Sensortec [BME280](https://learn.adafruit.com/adafruit-bme280-humidity-barometric-pressure-temperature-sensor-breakout)
* Bosch Sensortec [BMP280](https://learn.adafruit.com/adafruit-bmp280-barometric-pressure-plus-temperature-sensor-breakout)
* Microchip [MCP9080](https://learn.adafruit.com/adafruit-mcp9808-precision-i2c-temperature-sensor-guide)
No setup is required to read the CPU temperature. To enable the 1-wire interface
support on the RaspberryPi one can use the command:
~~~
Other methods and interfaces can be plugged in easily (just raise a request or
provide a patch). For information on how to connect sensor to the RaspberryPi
and to get it working please click on the links in the list above. As per these,
most sensors require some configuration to make them available:
* No setup is required to read the CPU temperature.
* To enable 1-wire interface support on the RaspberryPi use the command:
~~~
sudo raspi-config nonint do_onewire 0
~~~
or use `raspi-config` in interactive mode (9. Advanced Options --> A9. 1-Wire).
Please note that changing this requires a reboot.
Installation for is straightforward, after installing the script on the server
add the following to your Nagios `commands.cmd` configuration file:
~~~
or use `raspi-config` interactively (1. Interfacing Options --> P7. 1-Wire).
Please note that changing this requires a reboot.
* To enable I2C interface support on the RaspberryPi use the command:
~~~
sudo raspi-config nonint do_i2c 0
~~~
or use `raspi-config` interactively (1. Interfacing Options --> P5. I2C).
Please note that changing this requires a reboot.
The I2C interface also requires the `SMBus` or `SMBus2` library, to install
the `SMBus` library on Raspbian Linux run:
~~~
sudo apt install python-smbus
~~~
`SMBus2` is a pure Python implementation that requires system-wide or a
`virtualenv`-based installation, less trivial than installing the package.
Configuration of Nagios to use the script is straightforward, after installing
the script on the server add the following to your Nagios `commands.cmd`
configuration file to enable checking the CPU temperature:
~~~
# 'check_cpu_temperature' command definition to monitor CPU temperature in C
# parameters: warning (ARG1) and critical (ARG2) temperature in Celcius
define command {
command_name check_temperature
command_name check_cpu_temperature
command_line [install_path]/plugins/check_temperature -w $ARG1$ -c $ARG2$ rpi_cpu
}
# 'check_cpu_ftemperature' command definition to monitor CPU temperature in F
# parameters: warning (ARG1) and critical (ARG2) temperature in Celcius
define command {
command_name check_temperature
command_name check_cpu_ftemperature
command_line [install_path]/plugins/check_temperature -F -w $ARG1$ -c $ARG2$ rpi_cpu
}
~~~
To monitor a supported temperature sensor on its default address, add:
~~~
# 'check_temperature' command definition to monitor a single temperature in C
# parameters: warning (ARG1) and critical (ARG2) temperature in Celcius
define command {
command_name check_temperature
command_line [install_path]/plugins/check_temperature -w $ARG1$ -c $ARG2$ w1_ds18b20
command_name check_cpu_temperature
command_line [install_path]/plugins/check_temperature -w $ARG1$ -c $ARG2$ <<sensor>>
}
# 'check_ftemperature' command definition to monitor a single temperature in F
# parameters: warning (ARG1) and critical (ARG2) temperature in Farenheit
define command {
command_name check_ftemperature
command_line [install_path]/plugins/check_temperature -F -w $ARG1$ -c $ARG2$ w1_ds18b20
command_name check_cpu_temperature_f
command_line [install_path]/plugins/check_temperature -F -w $ARG1$ -c $ARG2$ <<sensor>>
}
~~~
With `<<sensor>>` replaced by the sensor, e.g. w1_ds18b20 for a 1-wire DS18B20,
i2c_mcp9808 for an I2C MCP9808 sensor or i2c_bme280 for an I2C BME280. Run the
In case you have multiple sensors, add multiple definitions with different
values for `command_name`.
If you need to pass on additional parameters, e.g. the sensor serial for an
1-wire DS18B20, you can do that like this:
~~~
# 'check_temperature_sensor' command definition to monitor a single temperature in C
# parameters: sensor serial (ARG1), warning (ARG2) and critical (ARG3) temperature in Celcius
define command {
command_name check_temperature_sensor
command_name check_ds18b20_sensor
command_line [install_path]/plugins/check_temperature -w $ARG2$ -c $ARG3$ w1_ds18b20 -s $ARG1$
}
# 'check_ftemperature_sensor' command definition to monitor a single temperature in F
# parameters: sensor serial (ARG1), warning (ARG2) and critical (ARG3) temperature in Farenheit
define command {
command_name check_ftemperature_sensor
command_name check_ds18b20_sensor_f
command_line [install_path]/plugins/check_temperature -F -w $ARG2$ -c $ARG3$ w1_ds18b20 -s $ARG1$
}
~~~
Likewise, to pass the I2C address for an I2C MCP9808 use something like:
~~~
# 'check_temperature_sensor' command definition to monitor a single temperature in C
# parameters: sensor address (ARG1), warning (ARG2) and critical (ARG3) temperature in Celcius
define command {
command_name check_mcp9808_sensor
command_line [install_path]/plugins/check_temperature -w $ARG2$ -c $ARG3$ i2c_mcp9808 -a $ARG1$
}
# 'check_ftemperature_sensor' command definition to monitor a single temperature in F
# parameters: sensor address (ARG1), warning (ARG2) and critical (ARG3) temperature in Farenheit
define command {
command_name check_mcp9808_sensor_f
command_line [install_path]/plugins/check_temperature -F -w $ARG2$ -c $ARG3$ i2c_mcp9808 -a $ARG1$
}
~~~
For the list of available sensors, please run `check_temperature -h` and run
`check_temperature <<sensor>> -h` to get the list of accepted options for sensor
``<<sensor>>``.
Make sure to replace `[install_path]/plugins` with the location of the script.
To use the it define a service check like below:
@@ -313,7 +367,7 @@ define service {
use generic-service
}
# check temperature in Celcius using a DS18B20 sensor connected to a RaspberryPi
# check temperature in Celcius using a sensor connected to a RaspberryPi
define service {
host hostname.mydomain.tld
service_description Check Temperature
@@ -325,7 +379,15 @@ define service {
define service {
host hostname.mydomain.tld
service_description Check Temperature
check_command check_temperature_sensor!0000a31ea3de!30!35
check_command check_ds18b20_sensor!0000a31ea3de!30!35
use generic-service
}
# check temperature with MCP9808 sensor 0x19 connected to a RaspberryPi
define service {
host hostname.mydomain.tld
service_description Check Temperature
check_command check_mcp9808_sensor!0x19!30!35
use generic-service
}
~~~

View File

@@ -33,6 +33,25 @@ PROG_VERSION=PROG_NAME + ' ' + VERSION
CPU_SENSOR_DEV = '/sys/class/thermal/thermal_zone0/temp'
CPU_SENSOR_SCALE=1000
I2C_BMX280_DEFAULT_ADDR=0x77
I2C_BMX280_CALIBRATE_ADDR=0x88
I2C_BMX280_CALIBRATE_LEN=24
I2C_BMX280_CAL_HUM0_ADDR=0xA1
I2C_BMX280_CAL_HUM_ADDR=0xE1
I2C_BMX280_CAL_HUM_LEN=7
I2C_BMX280_CONFIG_ADDR=0xF5
I2C_BMX280_CONFIG = 0xA0 # Stand_by time = 1000 ms
I2C_BMX280_CTRL_MEAS_ADDR=0xF4
I2C_BMX280_CTRL_MEAS=0x27 # Normal mode, Pressure
# and Temperature Oversampling rate = 1
I2C_BMX280_CTRL_HUM_ADDR=0xF2
I2C_BMX280_CTRL_HUM=1 # Humidity Oversampling rate = 1
I2C_BMX280_MEAS_ADDR=0xF7
I2C_BMX280_MEAS_LEN=8
I2C_BMX280_SENSOR_SCALE=5120.0
I2C_MCP9808_DEFAULT_ADDR=0x18
I2C_MCP9808_CONFIG_ADDR=0x1
I2C_MCP9808_CONFIG = [ 0x00, 0x00 ] # continuous conversion (power-up default)
I2C_MCP9808_PRECISION_ADDR=0x08
@@ -89,6 +108,11 @@ class SetLogFile(StoreAction):
###############################################################################
def hex_int(string):
"""Use int()'s auto-detection to parse 10-base and 16-base (0x..) numbers"""
return int(string, 0);
def convert_celcius(temp_read, scale = 1):
"""Converts raw temperature sensore value to degrees Celcius"""
return float(temp_read) / float(scale)
@@ -101,18 +125,9 @@ def convert_farenheit(temp_read, scale = 1):
CONVERT_FARENHEIT = ( convert_farenheit, 'F', 'Farenheit' )
def isempty(string):
"""Checks whether string 'str' provided is unset or empty"""
return string is None or len(string) == 0
def hex_int(string):
"""Use int()'s auto-detection to parse 10-base and 16-base (0x..) numbers"""
return int(string, 0);
####################[ Get CPU temperature of Raspberry Pi ]####################
def read_rpi_cpu_temp(args):
"""Reads CPU temperature and converts it to desired unit, returns temperature"""
"""Reads CPU temperature ands returns it converted to desired unit"""
with open(args.file, 'r') as f:
lines = f.readlines()
logger.debug('Temperature sensor data read from %s: %s', f.name, lines)
@@ -124,9 +139,8 @@ def read_rpi_cpu_temp(args):
return temp, 1
def read_i2c_mcp9808_temp(args):
"""Returns temperature from I2C MCP9808 sensor in desired unit"""
###############[ Get I2C (sm)bus object and I2C device address ]###############
def i2c_get_smbus_devaddr(args):
try:
import smbus
except ImportError:
@@ -134,31 +148,149 @@ def read_i2c_mcp9808_temp(args):
import smbus2 as smbus
except ImportError:
logger.critical("Unable to import either smbus or smbus2 library");
raise ImportError("missing I2C library, please install python-smbus or smbus2");
raise ImportError("missing I2C library, please install smbus2 "
"or Debian python-smbus package ");
try:
bus = smbus.SMBus(args.i2cbus) # Get I2C bus
return (smbus.SMBus(args.i2cbus), # get i2c bus
args.default_address if args.address is None else args.address)
except OSError as e:
logger.critical(e)
raise IOError("Invalid I2C bus: %d" % args.i2cbus)
####################[ Get I2C BME280/BMP280 Sensor values ]####################
# Inspired by https://github.com/ControlEverythingCommunity/BME280
def read_i2c_bmX280(args):
"""Returns temperature from I2C BME280/BMP280 sensor in desired unit"""
i2c_bus, i2c_addr = i2c_get_smbus_devaddr(args)
def convertLE16(data, offset, signed=False):
result = (data[offset + 1] << 8) | data[offset]
if signed and result > 32767:
result -= 65536
return result
try:
bus.write_i2c_block_data(args.address, I2C_MCP9808_CONFIG_ADDR,
# Get Temperature and Pressure Calibration Data
data = i2c_bus.read_i2c_block_data(i2c_addr, I2C_BMX280_CALIBRATE_ADDR,
I2C_BMX280_CALIBRATE_LEN)
dig_T1 = convertLE16(data, 0)
dig_T2 = convertLE16(data, 2, True)
dig_T3 = convertLE16(data, 4, True)
dig_P1 = convertLE16(data, 6)
dig_P2 = convertLE16(data, 8, True)
dig_P3 = convertLE16(data, 10, True)
dig_P4 = convertLE16(data, 12, True)
dig_P5 = convertLE16(data, 14, True)
dig_P6 = convertLE16(data, 16, True)
dig_P7 = convertLE16(data, 18, True)
dig_P8 = convertLE16(data, 20, True)
dig_P9 = convertLE16(data, 22, True)
if args.read_humidity:
# Get Humidity Calibration Data
dig_H1 = i2c_bus.read_byte_data(i2c_addr,I2C_BMX280_CAL_HUM0_ADDR)
data = i2c_bus.read_i2c_block_data(i2c_addr,I2C_BMX280_CAL_HUM_ADDR,
I2C_BMX280_CAL_HUM_LEN)
dig_H2 = convertLE16(data, 0, True)
dig_H3 = data[2]
dig_H4 = (data[3] << 4) | (data[4] & 0x0f)
dig_H5 = (data[5] << 4) | (data[4] >> 4)
dig_H6 = data[6]
if dig_H6 > 127:
dig_H6 -= 256
i2c_bus.write_byte_data(i2c_addr, I2C_BMX280_CTRL_HUM_ADDR,
I2C_BMX280_CTRL_HUM)
# Setup BMP280/BME280 configuration and wait 0.5 seconds for things to settle
i2c_bus.write_byte_data(i2c_addr, I2C_BMX280_CTRL_MEAS_ADDR,
I2C_BMX280_CTRL_MEAS)
i2c_bus.write_byte_data(i2c_addr, I2C_BMX280_CONFIG_ADDR,
I2C_BMX280_CONFIG)
sleep(0.5)
# Read sensor data and and convert using calibration data
data = i2c_bus.read_i2c_block_data(i2c_addr, I2C_BMX280_MEAS_ADDR,
I2C_BMX280_MEAS_LEN)
# Convert 20-bits Temperature and calculate value with calibration data
adc_t = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4)
var1 = ((adc_t) / 16384.0 - (dig_T1) / 1024.0) * (dig_T2)
var2 = (((adc_t) / 131072.0 - (dig_T1) / 8192.0) * ((adc_t)/131072.0 - (dig_T1)/8192.0)) * (dig_T3)
t_fine = (var1 + var2)
# Convert 20-bits Pressure and calculate value with calibration data
adc_p = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4)
var1 = (t_fine / 2.0) - 64000.0
var2 = var1 * var1 * (dig_P6) / 32768.0
var2 = var2 + var1 * (dig_P5) * 2.0
var2 = (var2 / 4.0) + ((dig_P4) * 65536.0)
var1 = ((dig_P3) * var1 * var1 / 524288.0 + ( dig_P2) * var1) / 524288.0
var1 = (1.0 + var1 / 32768.0) * (dig_P1)
p = 1048576.0 - adc_p
p = (p - (var2 / 4096.0)) * 6250.0 / var1
var1 = (dig_P9) * p * p / 2147483648.0
var2 = p * (dig_P8) / 32768.0
pressure = (p + (var1 + var2 + (dig_P7)) / 16.0) / 100
extra_readings = [ ('pressure', pressure, 'hPa'), ]
if args.read_humidity:
# Convert 16-byte Humidity and calculate value with calibration data
adc_h = (data[6] << 8) | data[7]
var_H = ((t_fine) - 76800.0)
var_H = (adc_h - (dig_H4 * 64.0 + dig_H5 / 16384.0 * var_H)) * (dig_H2 / 65536.0 * (1.0 + dig_H6 / 67108864.0 * var_H * (1.0 + dig_H3 / 67108864.0 * var_H)))
humidity = var_H * (1.0 - dig_H1 * var_H / 524288.0)
if humidity > 100.0 :
humidity = 100.0
elif humidity < 0.0 :
humidity = 0.0
extra_readings += ('humidity', humidity, '%', 0, 100),
logger.debug('BME280 sensor data: temperature %#02x: %#x = %d, '
'pressure: %#x, humidity: %#x', i2c_addr, adc_t,
t_fine, adc_p, adc_h)
logger.debug('Sensor Humidity value is %.2f %%', humidity)
else:
logger.debug('BMP280 sensor data: temperature %#02x: %#x = %d, '
'pressure: %#x',i2c_addr, adc_t, t_fine, adc_p)
# convert temperature to right units and scale and return value
temp = args.converter[0](t_fine, I2C_BMX280_SENSOR_SCALE)
logger.debug('Sensor Temperature value %d is %.2f%s',
t_fine, temp, args.converter[1])
logger.debug('Sensor Pressure value is %.2f hPa', pressure)
return (temp, extra_readings), 1
except IOError as e:
logger.critical(e)
raise IOError("Error while communicating with I2C device %#02x" %
i2c_addr)
########################[ Get I2C MCP9808 Temperature ]########################
# Inspired by https://github.com/ControlEverythingCommunity/MCP9808
def read_i2c_mcp9808(args):
"""Returns temperature from I2C mcp9808 sensor in desired unit"""
i2c_bus, i2c_addr = i2c_get_smbus_devaddr(args)
try:
# Setup MCP9808 configuration and wait 0.5 seconds for things to settle
i2c_bus.write_i2c_block_data(i2c_addr, I2C_MCP9808_CONFIG_ADDR,
I2C_MCP9808_CONFIG)
bus.write_byte_data(args.address, I2C_MCP9808_PRECISION_ADDR,
i2c_bus.write_byte_data(i2c_addr, I2C_MCP9808_PRECISION_ADDR,
I2C_MCP9808_PRECISION)
sleep(0.5)
# Read temperature (0x05), 2 bytes (MSB, LSB)
data = bus.read_i2c_block_data(args.address, I2C_MCP9808_TEMP_ADDR, 2)
logger.debug('Temperature sensor data from MCP9808 %#02x: 0x%02x%02x',
args.address, data[0], data[1])
# Convert the data to 13-bits
temp_read = ((data[0] & 0x1F) * 256) + data[1]
if temp_read > 4095 :
temp_read -= 8192
# Read temperature (2 bytes - MSB,LSB) and convert to 13-bit signed int
data = i2c_bus.read_i2c_block_data(i2c_addr,I2C_MCP9808_TEMP_ADDR,2)
temp_read = ((data[0] & 0xF) << 8) | data[1]
if (data[0] & 0x10):
temp_read = -temp_read
logger.debug('MCP9808 sensor data %#02x: 0x%02x%02x = %d',
i2c_addr, data[0], data[1], temp_read)
# convert temperatur to right units and scale and return value
temp = args.converter[0](temp_read, I2C_MCP9808_SENSOR_SCALE)
logger.debug('Temperature sensor value %d is %.2f%s',
temp_read, temp, args.converter[1])
@@ -166,15 +298,16 @@ def read_i2c_mcp9808_temp(args):
except IOError as e:
logger.critical(e)
raise IOError("Error while communicating with I2C device %#02x" %
args.address)
i2c_addr)
#####################[ Get 1-Wire sensor device filename ]#####################
def get_w1_sensor_device_filename(args, dev_dir=W1_SENSOR_DEV_DIR,
prefix=W1_SENSOR_DEV_PREFIX, suffix=W1_SENSOR_DEV_SUFFIX):
"""Auto-determine sensor datafile name (unless args.file is set)"""
if isempty(args.file):
if not args.file:
search_pat = dev_dir + ('/' if dev_dir[-1]!='/' else '')
search_pat+= prefix + '*' if isempty(args.serial) else '*' + args.serial
search_pat+= prefix + ('*' + args.serial if args.serial else '*')
logger.debug('looking for sensors with search pattern %s', search_pat)
device_folders = glob(search_pat)
@@ -196,7 +329,8 @@ def get_w1_sensor_device_filename(args, dev_dir=W1_SENSOR_DEV_DIR,
return filename
def read_w1_ds18b20_temp(args):
###################[ Get 1-Wire DS18b20 sensor temperature ]###################
def read_w1_ds18b20(args):
"""Returns temperature from 1-wire ds18b20 sensor in desired unit"""
device_file = get_w1_sensor_device_filename(args)
lines=[ '' ]
@@ -227,6 +361,7 @@ def read_w1_ds18b20_temp(args):
raise ValueError(errmsg)
#######################[ Parse Command Line parameters ]#######################
def parse_args():
"""Parse command line and get parameters from environment, if present"""
@@ -270,17 +405,34 @@ def parse_args():
' (defaults to %s)' % CPU_SENSOR_DEV)
cmdparser = subparser.add_parser('rpi_cpu', parents=[cpuparser],
help='read built-in Raspberry Pi CPU temperature')
cmdparser.set_defaults(func=read_rpi_cpu_temp, cmdparser=cmdparser, retries=0)
cmdparser.set_defaults(func=read_rpi_cpu_temp,cmdparser=cmdparser,retries=0)
i2cparser = ArgumentParser(add_help=False)
i2cparser.add_argument('-a', '--address', type=hex_int,
help='I2C Address of sensor, use 0x.. for hex (*)')
i2cparser.add_argument('-b', '--i2cbus', default=1, type=int,
help='I2C Bus to use (defaults to 1)')
cmdparser = subparser.add_parser('i2c_bme280', parents=[i2cparser],
help='read I2C connected BME280 sensor',
epilog='(*) default I2C address for an BME280 is %#x' %
I2C_BMX280_DEFAULT_ADDR)
cmdparser.set_defaults(func=read_i2c_bmX280, cmdparser=cmdparser, retries=0,
read_humidity=True, default_address=I2C_BMX280_DEFAULT_ADDR)
cmdparser = subparser.add_parser('i2c_bmp280', parents=[i2cparser],
help='read I2C connected BMP280 sensor',
epilog='(*) default I2C address for an BMP280 is %#x' %
I2C_BMX280_DEFAULT_ADDR)
cmdparser.set_defaults(func=read_i2c_bmX280, cmdparser=cmdparser, retries=0,
read_humidity=False, default_address=I2C_BMX280_DEFAULT_ADDR)
cmdparser = subparser.add_parser('i2c_mcp9808', parents=[i2cparser],
help='read I2C connected MCP9808 sensor',
epilog='(*) default I2C address for an MCP9808 is 0x18')
cmdparser.set_defaults(func=read_i2c_mcp9808_temp, cmdparser=cmdparser, retries=0, address=0x18)
epilog='(*) default I2C address for an MCP9808 is %#x' %
I2C_MCP9808_DEFAULT_ADDR)
cmdparser.set_defaults(func=read_i2c_mcp9808, cmdparser=cmdparser,
retries=0, default_address=I2C_MCP9808_DEFAULT_ADDR)
w1parser = ArgumentParser(add_help=False)
pgroup = w1parser.add_mutually_exclusive_group(required=False)
@@ -288,7 +440,8 @@ def parse_args():
help='(unique part of) temperature sensor serial (*)')
pgroup.add_argument('-f', '--file',
help='input file (or device) to obtain data from (*)')
w1parser.add_argument('-r', '--retries', type=int,default=W1_SENSOR_READ_RETRIES,
w1parser.add_argument('-r', '--retries', type=int,
default=W1_SENSOR_READ_RETRIES,
help='number of times to retry reading sensor data when'
' unstable (defaults to %d)' % W1_SENSOR_READ_RETRIES)
cmdparser = subparser.add_parser('w1_ds18b20', parents=[w1parser],
@@ -297,7 +450,7 @@ def parse_args():
'matches %s* in %s, if multiple entries are found -s or -f must '
'be used to specify which sensor to read.' %
(W1_SENSOR_DEV_PREFIX, W1_SENSOR_DEV_DIR))
cmdparser.set_defaults(func=read_w1_ds18b20_temp, cmdparser=cmdparser)
cmdparser.set_defaults(func=read_w1_ds18b20, cmdparser=cmdparser)
# parse arguments and post-process command line options
args = parser.parse_args()
@@ -306,6 +459,7 @@ def parse_args():
return args
############################[ Exit the Nagios way ]############################
def nagios_exit(status, message, data=None):
"""exit 'nagios-style', print status and message followed by perf. data"""
if logger.isEnabledFor(logging.CRITICAL):
@@ -319,6 +473,7 @@ def nagios_exit(status, message, data=None):
exit(status[1])
#################################[ Main logic ]#################################
if __name__ == '__main__':
try:
args = parse_args()
@@ -333,11 +488,16 @@ if __name__ == '__main__':
temperature, tries = args.func(args)
endtime = time()
if isinstance(temperature, tuple):
temperature, extra_data = temperature
else:
extra_data = ()
except (KeyboardInterrupt) as e:
nagios_exit(NAGIOS_UNKNOWN,'temperature sensor read aborted by user')
nagios_exit(NAGIOS_UNKNOWN,'sensor read aborted by user')
except (IOError, ValueError, ImportError) as e:
nagios_exit(NAGIOS_UNKNOWN,'temperature sensor read failed: %s' % e)
nagios_exit(NAGIOS_UNKNOWN,'sensor read failed: %s' % e)
elapse = endtime-starttime
logger.info('Got temperature reading of %.2f degrees %s in %fs',
@@ -345,6 +505,10 @@ if __name__ == '__main__':
unit = args.converter[1]
message = 'current temperature is %.2f%s' % (temperature, unit)
data = [ ('temperature', [ '%f%s' % (temperature, unit),
args.warn, args.critical, None, None]),
('retries', [ tries-1, None, args.retries, 0, None ]),
('checktime', [ '%fs' % elapse, None, None, 0, None]) ]
if args.critical is not None and temperature > args.critical:
nagiosresult = NAGIOS_CRITICAL
message+= ' and exceeds critical threshold %.2f%s' %(args.critical,unit)
@@ -354,10 +518,10 @@ if __name__ == '__main__':
else:
nagiosresult = NAGIOS_OK
nagios_exit(nagiosresult, message, [
('temperature', [ '%f%s' % (temperature, unit),
args.warn, args.critical, None, None]),
('retries', [ tries-1, None, args.retries, 0, None ]),
('checktime', [ '%fs' % elapse, None, None, 0, None])
])
for e in extra_data:
message += ', %s is %.2f%s' % (e[0], e[1], e[2])
data += (e[0], [ '%f%s' % (e[1], e[2]), None, None,
e[3] if len(e)>3 else None, e[4] if len(e)>4 else None ]),
nagios_exit(nagiosresult, message, data)