1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
|
# encoding: utf-8
#
# Run snmp_temper.py as a pass-persist module for NetSNMP.
# See README.md for instructions.
#
# Copyright 2012-2020 Philipp Adelt <info@philipp.adelt.net>
#
# This code is licensed under the GNU public license (GPL). See LICENSE.md for details.
import os
import sys
import syslog
import threading
import snmp_passpersist as snmp
from temperusb.temper import TemperHandler, TemperDevice
ERROR_TEMPERATURE = 9999
def _unbuffered_handle(fd):
return os.fdopen(fd.fileno(), 'w', 0)
class LogWriter():
def __init__(self, ident='temper-python', facility=syslog.LOG_DAEMON):
syslog.openlog(ident, 0, facility)
def write_log(self, message, prio=syslog.LOG_INFO):
syslog.syslog(prio, message)
class Updater():
def __init__(self, pp, logger, testmode=False):
self.logger = logger
self.pp = pp
self.testmode = testmode
self.usb_lock = threading.Lock() # used to stop reinitialization interfering with update-thread
self._initialize()
def _initialize(self):
with self.usb_lock:
try:
self.th = TemperHandler()
self.devs = self.th.get_devices()
self.logger.write_log('Found %i thermometer devices.' % len(self.devs))
for i, d in enumerate(self.devs):
self.logger.write_log('Initial temperature of device #%i: %0.1f degree celsius' % (i, d.get_temperature()))
except Exception as e:
self.logger.write_log('Exception while initializing: %s' % str(e))
def _reinitialize(self):
# Tries to close all known devices and starts over.
self.logger.write_log('Reinitializing devices')
with self.usb_lock:
for i,d in enumerate(self.devs):
try:
d.close()
except Exception as e:
self.logger.write_log('Exception closing device #%i: %s' % (i, str(e)))
self._initialize()
def update(self):
if self.testmode:
# APC Internal/Battery Temperature
self.pp.add_int('318.1.1.1.2.2.2.0', 99)
# Cisco devices temperature OIDs
self.pp.add_int('9.9.13.1.3.1.3.1', 97)
self.pp.add_int('9.9.13.1.3.1.3.2', 98)
self.pp.add_int('9.9.13.1.3.1.3.3', 99)
else:
try:
with self.usb_lock:
temperatures = [d.get_temperature() for d in self.devs]
self.pp.add_int('318.1.1.1.2.2.2.0', int(max(temperatures)))
for i, temperature in enumerate(temperatures[:3]): # use max. first 3 devices
self.pp.add_int('9.9.13.1.3.1.3.%i' % (i+1), int(temperature))
except Exception as e:
self.logger.write_log('Exception while updating data: %s' % str(e))
# Report an exceptionally large temperature to set off all alarms.
# snmp_passpersist does not expose an API to remove an OID.
for oid in ('318.1.1.1.2.2.2.0', '9.9.13.1.3.1.3.1', '9.9.13.1.3.1.3.2', '9.9.13.1.3.1.3.3'):
self.pp.add_int(oid, ERROR_TEMPERATURE)
self.logger.write_log('Starting reinitialize after error on update')
self._reinitialize()
def main():
sys.stdout = _unbuffered_handle(sys.stdout)
pp = snmp.PassPersist(".1.3.6.1.4.1")
logger = LogWriter()
upd = Updater(pp, logger, testmode=('--testmode' in sys.argv))
pp.start(upd.update, 5) # update every 5s
if __name__ == '__main__':
main()
|