Temperaturen messen mit OneWire via USB

Eine der einfachsten Möglichkeiten mit einem Linux-System Temperaturen zu erfassen und auszuwerten, ist der Einsatz des One-Wire-Bussystems. Eigentlich ist dieser Begriff etwas irreführend, denn es sollte besser Drei-Draht- oder im parasitären Betrieb Zwei-Draht-Bussystem heißen. Dieses Bussystem wird ursprünglich direkt an eine serielle Schnittstelle angeschlossen. Da aber die heutigen PC's nicht mehr über derartige Schnittstellen verfügen, empfiehlt sich ein entsprechender USB-Adapter.

An diesen Adapter werden dann Temperatursensoren vom Typ DS18S20 angeschlossen. Ich habe mich für den Drei-Draht-Betrieb entschlossen, da ich in dieser Betriebsart einen größeren und sichereren Messbereich erhalte.

Die Temperaturfühler werden an den UBS-Adapter mit einem RJ11-Stecker verbunden. Ich habe ein altes Telefonkabel missbraucht und von den sechs Adern werden nur die ersten drei Adern benötig. Bei mir ist:

- weiß mit 5V
- braun mit Masse (GND)
- grün mit Daten

belegt. Wer mehr Details benötig, der sollte einen Blick in das Datenblatt werfen.

Dieser One-Wire-Bus darf 100 m lang werden und kann auch Abzweigungen/Verästelungen haben. Für den normalen Hausgebrauch sollten 100 m eigentlich reichen. Wer will, kann ja noch zusätzlich jedem Temperaturfühler eine Pufferkapazität von ca. 10 nF für die Stromversorgung spendieren.

Um unter Linux Daten aus dem One-Wire-Bus auszulesen, scheint es mehrere grundsätzliche Wege zu geben:

- DigiTemp
- OWFS 1-WireFilesystem
- w1retap

Ich habe mich für das OWFS 1-WireFilesystem entschieden, denn ich hatte keine Lust Kernel-Treiber zu entfernen und einen anderen zu installieren. Dafür habe ich auch eine brauchbare Anleitung gefunden. Ich selbst setze derzeit OpenSuSE 11.2 ein und habe wie in der Anleitung beschrieben als Erstes folgende Pakete installiert:

Die Pakete werden mit rpm -i paketname.rpm installiert. Normalerweise sollte dies ohne Probleme vonstatten gehen.

Als nächstes wird ein Verzeichnis erstellt, in welches die Sensoren gemappt werden sollen. Da ich meine Bastel-Scripte in /myjob liegen habe, erstelle ich auch dort das Verzeichnis owfs. Auf dieses Verzeichnis werden dann noch die Schreibrechte mit chmod 777 zurechtgerückt.

Im nächsten Schritt wird das frisch erstellte Verzeichnis gemountet. Um den Mountpoint zu ermitteln ist der USB-Host einzustecken und ein lsusb einzugeben. Bei mir sieht es dann so aus:

Sensor:~ # lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 002: ID 04fa:2490 Dallas Semiconductor DS1490F 2-in-1 Fob, 1-Wire adapter
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub

Somit ist dann folgendes Kommando einzugeben:

/usr/sbin/owfs .Celsius -m /myjob/owfs -u /dev/bus/usb/004

Jetzt sollte das eigens dafür erstelle Verzeichnis /myjob/owfs gemountet sein. Mit dem Befehl ls -la /myjob/owfs kann man sich den gemappten Inhalt ansehen. Auffallen sollte nun der USB-Host-Adapter mit eigener Kennung (Hier 81.47AD30000000).

Ein unmounten dieses Filesystems erreicht man mit dem Kommando:
fusermount -u /myjob/owfs
Dies ist besonders interessant, wenn das mounten oder unmounten automatisiert in einem init-Script stattfinden soll.

Sensor:~ # ls -la /myjob/owfs/
total 4
drwxr-xr-x 1 root root    8 May 20 20:23 .
drwxr-xr-x 3 root root 4096 May 18 20:06 ..
drwxrwxrwx 1 root root    8 May 20 20:25 81.47AD30000000
drwxr-xr-x 1 root root    8 May 20 20:23 bus.0
drwxr-xr-x 1 root root    8 May 20 20:23 bus.1
drwxr-xr-x 1 root root    8 May 20 20:23 settings
drwxr-xr-x 1 root root    8 May 20 20:23 statistics
drwxr-xr-x 1 root root   30 May 20 20:23 structure
drwxr-xr-x 1 root root    8 May 20 20:23 system
drwxr-xr-x 1 root root    8 May 20 20:23 uncached

Wird jetzt der erste Sensor an den One-Wire-Bus angeschlossen, dann erscheint dieser mit seiner Kennung im gemappten Verzeichnis:

Sensor:~ # ls -la /myjob/owfs/
total 4
drwxr-xr-x 1 root root    8 May 20 20:23 .
drwxr-xr-x 3 root root 4096 May 18 20:06 ..
drwxrwxrwx 1 root root    8 May 20 20:32 10.0E6055020800
drwxrwxrwx 1 root root    8 May 20 20:32 81.47AD30000000
drwxr-xr-x 1 root root    8 May 20 20:23 alarm
drwxr-xr-x 1 root root    8 May 20 20:23 bus.0
drwxr-xr-x 1 root root    8 May 20 20:23 bus.1
drwxr-xr-x 1 root root    8 May 20 20:23 settings
drwxrwxrwx 1 root root    8 May 20 20:32 simultaneous
drwxr-xr-x 1 root root    8 May 20 20:23 statistics
drwxr-xr-x 1 root root   30 May 20 20:23 structure
drwxr-xr-x 1 root root    8 May 20 20:23 system
drwxr-xr-x 1 root root    8 May 20 20:23 uncached

Soll nun der Temperaturwert dieses Sensors angezeigt werden, dann ist folgender Befehl einzugeben:

Sensor:~ # cat /myjob/owfs/10.0E6055020800/temperature
     22.1875

Wer nun auf dieser Basis Abfrage- und Regelscripte schreibt, der wird feststellen, dass nur root berechtigt ist, diese Abfrage durchzuführen. Da ich die Temperatursensoren für Nagios bereitstellen wollte, musste ich in die Trickkiste greifen und per Crontab alle zwei Minuten eine Kopie der Messwerte anlegen, die dann der System-User Nagios lesen darf. Und so sieht dann das Script zum Kopieren der Temperaturwerte aus:

cp /myjob/owfs/10.* -R /myjob/owfs_nagios/
chmod 755 -R /myjob/owfs_nagios/

Beim von mir erstellten Nagios-Plugin muss die Variable OWFS_DIR angepasst werden:

Damit dieses Plugin in Nagios auch funktionieren kann, muss noch eine Section in der command.cfg eingebaut werden:

# 'check_owfs' command definition
define command{
	command_name	check_owfs
	command_line	$USER1$/check_owfs $ARG1$ $ARG2$ $ARG3$ $ARG4$ $ARG5$
	}

Und die passende Service-Section sieht dann so aus:

define service{
        use                             local-service
        host_name                       localhost
        service_description             Temperatur Zimmer
	check_command			check_owfs!10.0E6055020800 -w 26 -c 37
	notifications_enabled		1
        }