Beitragsbild

DS18B20 mit Openhab am Raspberry Pi: Von Bash zu Python

1
0

Werbung:

Stand der Dinge:

Nachdem ich mittlerweile alles ziemlich gut im Griff hatte, gab es immer wieder Punkte, die mich gestört haben. Zum Beispiel hatte ich die Onewire (1-Wire)-Sensoren vom Typ DS18B20 immer über ein Shellscript aufgerufen. Der im Netz zu findende Aufruf ist im Prinzip immer ähnlich und es gibt nur feine Nuancen die sich ändern. Das „klassische“ Beispiel ist folgende onewire.sh:

#Temperatur des Sensors auslesen
INPUT=`cat /sys/bus/w1/devices/$1/w1_slave | tail -n1 | cut -d '=' -f2`
TEMP=`echo "scale=2; $INPUT / 1000" | bc`

#INPUT=$(cat "/sys/bus/w1/devices/$1/w1_slave" |tail -n1 |cut -d\"=\" -f2)
#TEMP=$(echo "scale=2; $INPUT / 1000" | bc)

# Wert ausgeben
echo $TEMP

Erläuterung des klassischen Skripts:

Dabei wird per CAT-Befehl die Datei aufgerufen, in der derDS18B20- Sensor seinen Temperaturwert ablegt. Um das Skript nicht für jeden Sensor neu auflegen zu müssen wird die Sensornummer über einen Aufrufparameter an das Skript übergeben. Da jeder Sensor sein eigenes Verzeichnis hat kann der Übergabeparameter (im Skript ‚$1‘) also einfach in den Pfad eingefügt werden, die Datei mit dem Gewünschten Inhalt ist die „w1_slave“. Mit dem „tail“ Befehl wird die letzte Zeile der Datei ausgewählt und mit „cut“ Befehl alles nach dem „=“ Zeichen Ausgeschnitten und an die Variable „Input“ übergeben. Im nächsten Schritt wird die Zahl mit „scale“ und „bc“ noch etwas zurechtgestutzt, weil sie mehrstellig ist, aber der tatsächliche °C-Wert erst durch die Division mit 1000 erzeugt wird. Mit dem Echo wird das Ergebnis letztendlich ausgegeben.

Was das Problem ist:

So weit so gut. Aber dieses Shellskript hat einen kleinen Haken: Auf vielen Installationen von Openhab, besonders auf dem Raspberry Pi oft anzutreffen, liefert dieses Skript kein Ergebnis! Warum das so ist, liegt an den Dateirechten, die man nach jedem Neustart von Openhab neu setzen müsste. Das wäre zwar mit einer Zeile Code geregelt, aber was wenn man das mal Vergisst? Oder man möchte einfach das System so einfach wie möglich halten ohne zu viele kleine Anpassungen und Skripte zu schreiben, die dann bei einer Neuinstallation neu gelernt und erinnert werden müssen?

Werbung:

Änderung der Item Deklaration:

Dann gibt es den Ausweg das Skript in Python umzusetzen, dann kann es nämlich auch von der ITEM – Deklaration aus direkt aufgerufen werden. Um es so einfach wie möglich zu halten wird aus dem Aufruf:

Number TEMP_Dachboden "Dachboden [%.1f °C]" (temperaturen) {exec="<[/usr/bin/sh /usr/share/openhab/configurations/scripts/onewire.sh 28-000006xxxxx:20000:REGEX((.*?))]" }

der Aufruf:

Dachboden [%.1f °C]" <temperature> (temperaturen) {exec="<[/usr/bin/python /usr/share/openhab/configurations/scripts/onewire.py 28-000006xxxxx:20000:REGEX((.*?))]" }

Es ändert sich also erstmal nicht viel. Zu beachten ist, dass der Teil nach onewire.py die ID des DS18B20 Sensors ist. Diese muss bekannt sein.

Die Umsetzung in Python (2.7)

Da nun aber weder cut noch tail oder bc in Python zur Verfügung stehen und ich weitere Aufrufe externer Programme verhindern möchte setze ich folgendes Skript auf:

import sys
import re

pfad = '/sys/bus/w1/devices/' + str(sys.argv[1]) +'/'
datei = pfad + 'w1_slave'

fobj = open(datei, "r")
fobj2 = fobj.read()

result = re.search(r"t=(\d+)",fobj2)

fobj.close()

if result:
output = float(result.group(1)) / 1000
print output
else:
result = 0
print result

Erläuterung des Pythonskripts:

Ich werde jetzt im einzelnen noch erläutern was ich warum gemacht habe:

Zunächst importiere ich sys und re, damit ich Dateiaufrufe tätigen kann und „Regular Expressions“ verwenden kann. Regular Expressions oder REGEX-Befehle sind eine sehr elegante Möglichkeit nach Mustern zu suchen und das Ergebnis schnell verarbeiten und ausgeben zu können.

Als nächstes setze ich den Pfad zur Datei zusammen. Die etwas sperrig anmutende Variable „sys.argv[1]“ ist das Abfangen des Übergabeparameters (also die eindeutige ID des DS18B20 Sensors) beim Aufruf von onewire.py.
Nach dem Zusammensetzen des Pfades hänge ich die Datei die geöffnet werden soll hinten an. Die nächste Zeile mit „fobj“ öffnet die Datei mit Leserechten, die folgende Zeile mit fobj2 liest die Datei ein.

Spannend wird es jetzt, denn mit „result = re.search“ übergebe ich das Ergebnis einer regex-Mustersuche an die variable result. der erste Klammerteil r“t=(\d+)“ sagt aus: „suche nach ‚t=‘, danach kommen beliebig viele Zahlen (also keine Buchstaben). Das gesuchte Ergebnis wird gleichzeitig durch die Klammern gekennzeichnet.
Und weil es wichtig ist hinter sich „aufzuräumen“ wird die eben geöffnete Datei mit fobj.close() auch wieder geschlossen.
Mit dem IF-Block „if result:“ wird überprüft, ob die Abfrage erfolgreich war. Ist dies der Fall wird das Ergebnis der Regexabfrage result.group(1) in den Datentyp float umgewandelt und durch 1000 geteilt um den tatsächlichen Temperaturwert zu erhalten. In der nächsten Zeile wird das Ergebnis dann lediglich noch ausgegeben. Sollte die Regexabfrage nicht erfolgreich sein, dann wird der else Teil angesprungen und als Ergebnis der Wert 0 ausgegeben.

1
0

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.