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:

  1. Einer der Server im Rack soll die Temperatur im Schrank dauerhaft überwachen und per MQTT an Home Assistant schicken. 
  2. 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.
  3. 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.
  4. 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:

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. 

AdresseSensortypZweck
0x26BH17150Helligkeitsmessung außerhalb des Serverschranks.
0x76BME280Temperatur, Luftfeuchtigkeit und Luftdruck im Serverschrank
0x77BME280Temperatur, 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:

SensorBibliothek
BME280BME280.py Bibliothek von Matt  Hawkins auf raspberrypi-spy.co.uk (Download)
BH1750BH1750 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

PostadresseE-MailadresseFestnetzMobiltelefonSMS/SignalThreemaTwitter DirektnachrichtFAXWeb Page