Temperaturüberwachung für Server-Schrank (Teil 1)
Für ein Teil meiner Hardware habe ich mir ein Serverschrank zugelegt. Dort laufen unter anderem mein HP Microserver Gen 8, ein Terramaster F2-420 NAS und ein paar Netzwerkkomponenten. Gerade im Sommer kann die Temperatur im Rack schnell ansteigen. Damit ich automatisch informiert werde, wenn die Temperatur in den unangenehmen Bereicht kommt, muss eine Temperatur-Überwachung her. Insgesamt soll es später mal folgendermaßen funktionieren:
- Einer der Server im Rack soll die Temperatur im Schrank dauerhaft überwachen und per MQTT an Home Assistant schicken.
- Home Assistant wertet die Temperatur aus und passt die Farbe der RGB-LEDs im Serverrack entsprechend der aktuellen Temperatur an. Wird das Licht eingeschaltet, kann ich so direkt sehen, ob es Temperaturprobleme im Schrank gibt.
- Wird die Temperatur zu hoch, so soll durch Home Assistant zunächst die RGB-LED als optische Warnung automatisch eingeschaltet werden. Parallel dazu sollte eine Warnung an mein Handy gesendet werden.
- Steigt die Temperatur noch weiter, so sollen nacheinander die Server heruntergefahren werde, um thermische Probleme zu vermeiden. Darüber möchte ich dann natürlich ebenfalls über eine Push-Nachricht informiert werden.
In diesem Teil der Artikel-Serie wird beschrieben, wie ein I2C-Temperatursensor per USB an einen der Server angebunden und wie die Temperaturdaten per MQTT an Home Assistant gesendet werden.
Es wird davon ausgegangen, dass Home Assistant und ein MQTT-Broker (z.B. mosquitto) bereits erfolgreich eingerichtet sind.
1| Temperatursensor vorbereiten
Da ich mein Terramaster F2-420 als Video-Station nutze, läuft dieses System in der Regel permanent. Daher soll dieser Rechner auch die Temperatur im Server Rack überwachen. Allerdings habe ich keinen USB-Temperatursensor im angemessenen Preisrahmen gefunden. Es gibt aber die Möglichkeit I2C-Sensoren über einen digispark USB Dev Board oder Adafruit Trinket zu nutzen. Mit der Anleitung von Till Harbaum's I²C-Tiny-USB Projekt auf GitHub) ist die Hardware schnell zusammengebaut. Alles was man braucht sind folgende Komponenten:
- 1 x digispark USB Dev Board oder Adafruit Trinket
- 1 x BME280 Temperatur und Luftfeuchtigkeitssensor
- 2 x 10kΩ Widerstand
Beim I2C-Sensor (z.B. dem BME280) am Besten gleich eine PCB-Version mit Spannungsregler und Logik-Shifter kaufen. Damit sollte es dann egal sein, ob der Sensor mit 3,3V oder mit 5V Logik betrieben wird.
Der Anschluss des BME an den digispark USB Dev Board oder Adafruit Trinket ist denkbar einfach:
┌─────────────────┐
│ Digispark │ ┌──────────────┐
│ P5 │ │ BME280 │
│ P4 │ │ │
│ P3 │ ┌───────────────┤ SLC │
│ G P2 ├──────────┬─┘ ┌────────────┤ SDA │
│ 5 N P1 │ │ │ ┌─────────┤ GND │
│ V D P0 ├────┬─────(────┘ │ ┌──────┤ VCIN/VCC │
└──┬──┬───────────┘ ┌┴┐ ┌┴┐ │ │ └──────────────┘
│ │ │R│ │R│ │ │
│ │ │1│ │2│ │ │
│ │ └┬┘ └┬┘ │ │
│ └────────────────(─────(───────┘ │
└───────────────────┴─────┴──────────┘
Funktioniert der Pull-Up-Widerstand nicht korrekt, so kann es zu einem Timeout beim Zugriff auf den I2C-Bus kommen. Gibt es eine Fehlermeldung i2c i2c-4: failure writing data
im syslog, sollten die Widerstände überprüft werden.
Grundsätzlich können die Pull-Up-Widerstände auch weggelassen werden.
Stattdessen muss dann aber die Option I2C_IS_AN_OPEN_COLLECTOR_BUS
in der Datei main.c der Firmware aktiviert werden. Dadurch wird ein CPU-interner Pull-Up-Widerstand aktiviert.
Natürlich können an den I2C-Bus auch noch weitere Sensoren angeschlossen werden. Dabei muss lediglich sichergestellt werden, dass alle I2C-Devices eine eindeutige Adresse auf dem Bus verwenden. Im Zweifelsfall finden sich im Datenblatt des jeweiligen Devices, wie die Standard-Adresse geändert werden kann, wenn beispielsweise zwei gleiche Sensoren an einem I2C-Bus betrieben werden sollen..
Mit den folgenden Befehlen kann die Firmware unter Linux übersetzt werden:
apt install gcc-avr avr-libc
cd /usr/src
git clone https://github.com/harbaum/I2C-Tiny-USB
cd I2C-Tiny-USB/digispark
make hex
Werden externe Pull-Up-Widerstände verwendet kann man sich diesen Schritt aber auch sparen und direkt die vor-kompilierte Firmware main.hex herunterladen.
Geflasht wird die Firmware mit dem Tool micronucleus
, das ebenfalls noch übersetzt werden muss:
apt install libusb-dev
cd /usr/src
git clone https://github.com/micronucleus/micronucleus
cd micronucleus/commandline
make CONFIG=t85_default
make install
War das erfolgreich, so wird das Tool mit dem Kommando micronucleus --run --dump-progress --type intel-hex main.hex
gestartet.
Danach wird der digispark an einen USB-Port angeschlossen und man muss nur noch warten, bis der Flash-Prozess abgeschlossen ist. Jetzt sollte der Temperatursensor einsatzbereit sein.
2| Temperatursensor unter Linux ansprechen
Zunächst muss sichergestellt werden, dass das Kernelmodul geladen ist und zukünftig auch beim Booten geladen wird:
modprobe i2c-dev
echo "i2c-dev" >> /etc/modules
Wenn alles korrekt funktioniert hat und das Device vom Kernel korrekt erkannt wurde, dann sollte in den syslogs ungefähr folgender Eintrag auftauchen:
dmesg | grep 'connected i2c-tiny-usb device'
[ 4.703591] i2c i2c-1: connected i2c-tiny-usb device
Wichtig ist dabei die Device-Nummer, also die Zahl hinter i2c-#. Diese kann beispielsweise auch mit folgendem Kommando extrahiert werden:
dmesg | grep 'connected i2c-tiny-usb device' | head -n1 | sed -r 's/.*\s+i2c-([0-9]+).*/\1/'
Ob der BME280 Temperatursensor richtig erkannt wird kann mit dem Kommando i2detect
ermittelt werden:
i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- 23 -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- 76 77
In meinem Beispiel sind drei Sensoren an den I2C-Bus angeschlossen.
Adresse | Sensortyp | Zweck |
0x26 | BH17150 | Helligkeitsmessung außerhalb des Serverschranks. |
0x76 | BME280 | Temperatur, Luftfeuchtigkeit und Luftdruck im Serverschrank |
0x77 | BME280 | Temperatur, Luftfeuchtigkeit und Luftdruck außerhalb des Serverschranks |
Die Sensoren können mittels Python einfach angesprochen werden. In der Regel hilft eine kurze Google-Suche um eine entsprechende Python-Bibliothek zu finden. Für dieses Beispiel habe ich folgende Bibliotheken verwendet:
Sensor | Bibliothek |
BME280 | BME280.py Bibliothek von Matt Hawkins auf raspberrypi-spy.co.uk (Download) |
BH1750 | BH1750 Bibliothek von Matt Hawkins auf raspberrypi-spy.co.uk (Download) |
Damit die Bibliotheken genutzt werden können, müssen sie lediglich heruntergeladen und im selben Verzeichnis wie das folgende Python-Script gespeichert werden:
#!/usr/bin/python3
import paho.mqtt.client as mqtt
import json
import time
import bme280
import bh1750
import ssl
# Adressen entsprechend der Ausgabe von i2cdetect -y 1 (s.o.) anpassen
addr_int_bme = 0x76
addr_ext_bme = 0x77
addr_bh1750 = 0x23
values = {}
values['internal'] = {}
# Internen Sensor auslesen
temperature,pressure,humidity = bme280.readBME280All(addr_int_bme)
values['internal']['temperature'] = temperature
values['internal']['pressure'] = pressure
values['internal']['humidity'] = humidity
# HINWEIS: Dieser Teil liest die Daten aus den externen Sensoren aus.
# Wird nur ein Sensor verwendet, kann dieser Block gelöscht werden.
values['external'] = {}
# Externen Sensor auslesen
temperature,pressure,humidity = bme280.readBME280All(addr_ext_bme)
values['external']['temperature'] = temperature
values['external']['pressure'] = pressure
values['external']['humidity'] = humidity
# Lichtwert auslesen und speichern
bh1750.initSensor(addr_bh1750)
time.sleep(0.5)
values['external']['light'] = bh1750.readLight(addr_bh1750)
# Werte zur Kontrolle auf der Konsole ausgeben
print(str(values))
# Daten an den MQTT-Server senden (inkl. TLS-Verschlüsselung
mqtt = mqtt.Client()
# Die CA gegen die das MQTT-Server Cert geprüft werden soll muss ggf.
# angepasst werden (Parameter ca_certs)
mqtt.tls_set(ca_certs="/etc/ssl/CA/your-ca.crt", tls_version=ssl.PROTOCOL_TLSv1_2)
# Username und Password für den MQTT-Zugang anpassen
mqtt.username_pw_set("user", "password")
# MQTT-Server-Name und Port entsprechend anpassen
mqtt.connect("iot", 8883, 60)
# Der Pfad server/i2c/usb unter dem die Daten publiziert werden, kann
# beliebig angepasst werden.
mqtt.publish("server/i2c/usb", json.dumps(values), retain=True)
Damit das Script funktioniert müssen natürlich Python3, pip3 und auch die andere verwendeten Bibliotheken installiert sein:
apt update
apt install python3 python3-pip
pip3 install paho-mqtt
pip3 install smbus2
Wird das Script fehlerfrei ausgeführt, so sollte ungefähr folgende Meldung ausgegeben werden:
{'internal': {'humidity': 25.374787119363187, 'temperature': 24.69, 'pressure': 1007.5919028001564}, 'external': {'humidity': 34.55252117228301, 'temperature': 20.51, 'pressure': 1007.2839753274676, 'light': 210.0}}
3| Cron-Job einrichten
Damit die Daten nun regelmäßig aktualisiert werden, muss nur noch ein Cron-Job eingerichtet werden. Soll beispielsweise die Temperatur alle 3 Minuten aktualisiert werden, so muss folgender Eintrag in die crontab
eingetragen werden (crontab -e
):
*/3 * * * * /pfad/zum/script.py > /dev/null 2>&1 || true
Jetzt sollten die Daten über den MQTT-Server abrufbar sein. Im nächsten Teil werden die entsprechenden MQTT-Sensor in Home Assistant angelegt.
4| Quellen
[01] https://github.com/harbaum/I2C-Tiny-USB/tree/master/digispark
[02] https://github.com/nopdotcom/i2c_tiny_usb-on-Little-Wire/wiki/BuildingOnLinux
[03] https://petermolnar.net/article/linux-i2c-iio-collectd/
[04] https://www.raspberrypi-spy.co.uk/2016/07/using-bme280-i2c-temperature-pressure-sensor-in-python/
[05] https://bitbucket.org/MattHawkinsUK/rpispy-misc/raw/master/python/bme280.py
[06] https://www.raspberrypi-spy.co.uk/2015/03/bh1750fvi-i2c-digital-light-intensity-sensor/
[07] https://bitbucket.org/MattHawkinsUK/rpispy-misc/raw/master/python/bh1750.py
Kommentare