Info (25.11.2020): Vor einigen Tagen wurde Openhab 3 offiziell veröffentlicht! Dieses Tutorial ist ausschließlich für Openhab 2.5!
Vor einiger Zeit hatte ich bereits einen Beitrag zu diesem Thema verfasst, jedoch hat sich aufgrund diverser Versuche und Erfahrungen einiges geändert. Daher möchte ich mit diesem Beitrag erläutern, was ich nun anders mache und warum ich diesen Weg gehe.
Dezentraler Aufbau
In einem Haus sind die Kabelwege teilweise doch länger, wie sich bei einigen Versuchen herausstellte sorgt das für Probleme. Wenn man sich über Google bemüht die maximale Kabellänge der DHT-Sensoren heraus zu bekommen, stößt man auf unglaublich viele Meinungen, aber wenig handfeste Informationen. Es bleibt also nur der Selbstversuch übrig um ein Setup zu finden, das auch zuverlässig funktioniert. Hierzu habe ich ein 15 Meter langes 4×0,25mm² Kabel mit Schirmung zwischen Sensor und Raspberry gebaut. Hiermit waren so gut wie keine brauchbaren Messergebnisse zu erzielen. Auch mit verschiedenen Pullup-Widerständen wurde es bei dieser Leitungslänge nicht besser. Brauchbare und zuverlässige Ergebnisse bekam ich erst bei einer Leitungslänge von maximal 10 Metern und einem Pullup-Widerstand von 1,2k Ohm. Mit dieser Länge kommt man jedoch in einem normalen Einfamilienhaus nicht weit. Daher habe ich mich mittlerweile für einen dezentralen Aufbau entschieden. Hierfür verwende ich zwei Raspberrys, welche ich in den Heizkreisverteilern der Fußbodenheizung einbauen werde. Somit habe ich eine maximale Leitungslänge von fünf Metern und bin im sicheren Bereich.
LolDHT löst Adafruit_DHT ab
Bei meinen Versuchen hat sich ebenfalls noch herausgestellt, das die Pythonscripte von Adafruit nur bedingt für solche Aufgaben geeignet sind. Die Laufzeiten der Adafruit-Scripte sind recht lang und die Fehlerquote ist sehr hoch, sobald sich der Leitungsweg verlängert. Auf der Suche nach einer Alternative stolperte ich über LolDHT. Es lässt sich genau so simpel installieren und wiederholt die Messung selbstständig, sollte das Ergebnis unplausibel sein. Auch die Fehlerquote und die Geschwindigkeit sind hier deutlich besser.
Sensoren hängen sich auf
Ein weiteres Problem was sich ergab, war dass sich die Sensoren nach einiger Zeit aufhingen und keine Informationen mehr vom Sensor kamen. Via Google fand ich viele verschiedene Ursachen und Lösungsansätze für dieses Problem. Von weiteren Widerständen direkt am Sensor, bis hin zu Kondensatoren diverser Größen war alles Mögliche dabei. Geholfen hat natürlich nichts davon. Mit dem Oszilloskop konnte ich dann feststellen, das der Sensor sich während der Antwort aufhängt und diese dann permanent wiederholt. Auch wenn keine Abfrage mehr seitens des Raspberrys erfolgt und sogar das Datenkabel abgezogen ist, versucht der DHT weiter eine Antwort zu senden. Das Problem behob sich erst, wenn die Versorgungsspannung zum Sensor unterbrochen wurde. Dies habe ich dann mithilfe der GPIOs am Raspberry automatisiert. Einen Schaltplan gibt es im Kapitel „Sensoren anschließen und testen“.
Der Weg ins OpenHab System
Natürlich musste ich auch einen neuen Weg finden die Messwerte sauber in das OpenHab-System zu bekommen. Da die Sensoren nun nicht mehr direkt am Server angeschlossen sind, müssen die Werte übertragen werden. Eine MySQL-Datenbank zur Zwischenspeicherung war für mich hier der einfachste und schnellste Weg. Ein MySQL-Server hab ich bereits auf dem OpenHab-System laufen, um Daten aufzuzeichnen. Also habe ich kurzerhand eine neue Datenbank angelegt mit zwei Tabellen. In die erste Tabelle werden die Temperaturen eingetragen, in die Zweite die Luftfeuchtigkeit. Das macht alles etwas flexibler und es wäre somit auch möglich mit anderen Systemen auf die Datenbank zuzugreifen und die Werte zu lesen. In OpenHab sorgt dann wieder das Exec-Binding dafür, dass alle Werte zyklisch aus der Datenbank gelesen und in mehrere Items geschrieben werden.
Voraussetzungen
Bevor ich nun erkläre wie alles genau umgesetzt ist, möchte ich kurz die Voraussetzungen für diesen Aufbau erläutern:
- Funktionierende OpenHab installation
- Laufende SQL-Datenbank
- Einen Raspberry zum Auslesen der Sensoren
- Einen oder mehrere DHT Sensoren
- Bei der Verwendung von längeren Sensorleitungen entsprechende Vorwiderstände, bei 5 Metern Leitungslänge verwende ich 6,8k Ohm
- Kentnisse zur SSH-Verbindung auf deinen Raspberry
- Grundlegende Kenntnisse zu SQL
- Erfahrung mit OpenHab und Kenntnisse zum Aufbau
- Git-Core bereits installiert
MySQL-Datenbank vorbereiten
In der SQL-Datenbank werden wie erwähnt zwei Tabellen benötigt. Diese haben bei mir folgende Spalten:
- ID – dies ist eine fortlaufende von der Datenbank vergebene Zahl. Die Zahl ist nur einmal pro Tabelle vorhanden und dient dazu die richtige Tabellenzeile ansprechen zu können.
- Sensorname – diese Spalte ist nicht zwingend notwendig, sorgt aber für eine bessere Übersicht
- Sensorwert – da ich meine Werte später als Gleitpunktzahl weiter verarbeiten muss, habe ich mich dafür entschieden die Sensorwerte nur als Ganzzahl einzutragen
Zum Anlegen der Tabellen habe ich folgenden Code für dich vorbereitet:
CREATE TABLE `feuchtigkeitssensoren` (
`ID` int(2) NOT NULL,
`luftfeuchte` int(11) NOT NULL,
`messort` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `temperatursensoren` (
`ID` int(2) NOT NULL,
`temperatur` int(11) NOT NULL,
`Sensorort` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Nun musst du noch die einzelnen Sensoren in den Tabellen anlegen. Hierzu kannst du in die Tabelle wechseln oder eine neue Zeile über folgenden Code anlegen:
INSERT INTO `feuchtigkeitssensoren` (`ID`, `luftfeuchte`, `messort`) VALUES
(1, 0, 'Sensorort 1'),
(2, 0, 'Sensorort 2'),
(3, 0, 'Sensorort 3');
INSERT INTO `temperatursensoren` (`ID`, `temperatur`, `Sensorort`) VALUES
(1, 0, 'Sensorort 1'),
(2, 0, 'Sensorort 2'),
(3, 0, 'Sensorort 3');
Denk bitte daran den Code für deine Bedürfnisse anzupassen. Mehr Arbeit ist in der Datenbank nicht notwendig.
Raspberry für Sensoren vorbereiten
Als erstes installierst du auf deinem Raspberry, mit welchem du die Sensoren auslesen möchtest, das LolDHT- und WiringPI-Paket. Als Basis für den Raspberry genügt ein Raspbian.
LolDHT kannst du schnell und einfach mit diesen Codezeilen installieren:
sudo git clone git://git.drogon.net/wiringPi
cd wiringPi
sudo ./build
cd ..
sudo git clone https://github.com/technion/lol_dht22
cd lol_dht22
sudo ./configure
sudo make
Nun benötigst du noch einen Client, um dich mit der Datenbank verbinden zu können. Dieser kann einfach mit folgendem Befehl installiert werden:
sudo apt-get install mysql-client
Damit ist die Installation deines Raspberrys fertiggestellt und es kann mit dem Anschließen der Sensoren weiter gehen.
Sensoren anschließen und Testen
Nun schließt du deine Sensoren an den Raspberry an. Möchtest du den Raspberry nur mit kurzen Leitungen von wenigen Zentimetern anschließen, so benötigst du einen höheren Pullup-Widerstand von zirka 10k Ohm. Je nach Leitungslänge kannst du den Widerstand variieren, jedoch solltest du den Wert von 1k Ohm nicht unterschreiten!
Achtung: Solltest du bei den Pullup-Widerständen einen Fehler machen, könntest du damit deinen Raspberry beschädigen! Hier ist Vorsicht geboten! Lieber höhere Widerstandswerte ansetzen, denn zu viel Strom schadet den Eingängen!
Persönlich habe ich mich für folgende Beschaltung entschieden:
- Versorgung der Sensoren erfolgt via GPIO
- Minus und Schirm lege ich an GND an
- Den Pullup-Widerstand mit 6,8k Ohm für 5 Meter Leitungslänge hänge ich zwischen den gewünschten GPIO und 3,3 Volt, zusammen mit der Datenleitung des Sensors
Wichtig ist hier, das du dir die Nummer des GPIOs merkst und nicht die Pinnummer. Entsprechende Zuordnungstabellen und Bilder für dein Raspberry Modell kannst du schnell und einfach via Google finden. Die GPIO-Nummer der Datenleitung wird vom LolDHT-Script benötigt um den entsprechenden Eingang anzustoßen und auszulesen. Die GPIO-Nummer für die Versorgung benötigst du um den Sensor ein- und auszuschalten. Als Beispiel habe ich hier eine Schemazeichnung für dich, wie ich alles angeschlossen habe:
Sobald alles angeschlossen ist, kannst du deinen Sensor ansprechen und Testen. Gehe hierzu einfach via SSH in das lol_dht Verzeichnis welches du vorhin runtergeladen hast und führe folgenden Befehl aus:
./loldht <Daten GPIO-Nummer>
Du solltest als Ausgabe einen Temperatur- und Luftfeuchtigkeitswert erhalten. Es kann sein, dass das Script mehrere Zyklen durchläuft bis es plausible Werte erhält. Dies ist bedingt durch die Leitungslänge. Hier musst du also testen, ob die Auslesegeschwindigkeit deinen Anforderungen genügt. Bedenke bitte den Sensor mit einem Abstand von einigen Sekunden anzusprechen, da er sich sonst aufhängt. Hat alles geklappt und du hast ordentliche Werte erhalten, kannst du mit dem Script zur Übertragung in die Datenbank fortfahren.
Werte in Datenbank übertragen
Nun geht es darum die ausgelesenen Werte in die Datenbank zu bekommen. Hierzu habe ich mir folgendes Script programmiert:
#!/bin/bash
sudo killall -q loldht > /dev/null 2>&1
string=$(sudo /home/pi/lol_dht22/loldht <GPIO-ID-SENSORDATA>)
IFS='='
array=( $string )
humidity=${array[1]}
temperature=${array[2]}
humidity_clear=$(tr -cd 0-9 <<<"$humidity")
temperature_clear=$(tr -cd 0-9 <<<"$temperature")
if [ $temperature_clear -gt 1200 ]
then
mysql -u <DB-Benutzer> -<DB-Passwort> -h <DB-HOST-IP> -D <DB-NAME> -e "UPDATE temperatursensoren SET temperatur = '${temperature_clear}' WHERE id = <DHT-ID>"
fi
if [ 11000 -gt $humidity_clear ]
then
mysql -u temperpi -pX29fw7E1 -h 192.168.178.3 -D temperpi -e "UPDATE feuchtigkeitssensoren SET luftfeuchte = '${humidity_clear}' WHERE id = <DHT-ID>"
fi
Denk daran im Script die in den „<>“-Klammern stehenden Daten entsprechend deiner Gegebenheiten anzupassen. Hierzu zählen Nutzer und Passwort für die Datenbank, sowie die Datenbank und der Hostname. Auch die Tabellen ID und der GPIO deines Sensors müssen hier für deine Konfiguration angegeben werden. Anschließend kannst du das Script als .sh-Datei im Homeverzeichnis deines Servers abspeichern.
Als nächstes muss diese Datei ausführbar gemacht werden. Wechsle dazu via SSH in das Verzeichnis und gebe folgenden Code ein:
chmod u+x Dein-Sensor-1.sh
Jetzt legen wir noch eine ausführbare Datei an um die Sensoren ein- und auszuschalten. Das sorgt auch im späteren Verlauf dafür, das mehrere Sensoren angeschlossen werden können. In diese Datei habe ich bei mir folgenden Inhalt programmiert:
sudo gpio -g mode <GPIO-ID-VERSORGUNG> out
sudo gpio -g write <GPIO-ID-VERSORGUNG> 0
sleep 2
sudo gpio -g write <GPIO-ID-VERSORGUNG> 1
sleep 2
sudo /home/pi/Dein-Sensor-1.sh
sudo gpio -g write <GPIO-ID-VERSORGUNG> 0
Auch diese Datei machst du wieder ausführbar. Wichtig ist hier ebenfalls wieder den GPIO-Wert auf deinen benutzten Anzupassen. Die Aufgabe dieses Scripts ist es, den entsprechenden GPIO als Ausgang zu setzen, ihn anschließend auszuschalten und kurz vor der Scriptausführung wieder einzuschalten. Dadurch kann im Fehlerfall der Sensor zurückgesetzt werden.
Danach kannst du das Script schon ausprobieren und in der Datenbank nachsehen ob die Werte dort ankommen:
./deineDatei.sh
Nun kannst du das Script mit Crontab noch Zyklisch von deinem Raspberry ausführen lassen und schon bekommst du immer aktuelle Sensorwerte in deine Datenbank. Möchtest du mehrere Sensoren abfragen, so lege das erste Script passend für deinen neuen Sensor an und füge die Werte in das zweite Script hinzu. Bedenke jedoch das sich durch mehrere Sensoren die Scriptlaufzeit verlängert. Du solltest also bei automatischer Ausführung via Crontab genügend Abstand zwischen den Aufrufen lassen, um auch alle Sensoren abzufragen. Ich habe an jedem meiner Raspberrys fünf Sensoren angeschlossen und lasse zwischen den Aufrufen fünf Minuten Zeit.
OpenHab einrichten
Um via OpenHab nun die Werte auszulesen sind einige Bindings notwendig. Außerdem müssen Regeln zum zyklischen Auslesen definiert und die Werte entsprechend lesbar gemacht werden.
Folgende Bindings sind notwendig:
– Exec Binding
– Regex Binding
Sind die Bindings installiert, so kannst du damit beginnen die notwendigen Scripte für OpenHab anzulegen. Zuerst legst du eine Datei für deinen Sensor im Verzeichnis /etc/openhab2/scipts/ mit der Endung „.py“ an. Diese füllst du mit folgendem Inhalt, die Werte in den „<>“-Klammern musst du auch hier wieder auf deine Gegebenheiten anpassen:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys, time
import mysql.connector
mydb = mysql.connector.connect(
host="<DB-HOST-IP>",
user="<DB-BENUTZER>",
passwd="<DB-PASSWORT>",
database="<DB-NAME>"
)
if __name__ == '__main__':
if len(sys.argv) > 1:
call = sys.argv[1].lower()
if call == 'temperature':
connection = mydb.cursor()
connection.execute("SELECT temperatur FROM temperatursensoren WHERE id = <DB-SENSOR-ID>")
temperature = connection.fetchone()
temp_val = float(temperature[0])
connection.close()
print int(temp_val)
elif call == 'humidity':
connection = mydb.cursor()
connection.execute("SELECT luftfeuchte FROM feuchtigkeitssensoren WHERE id = <DB-SENSOR-ID>")
humidity = connection.fetchone()
hum_val = float(humidity[0])
connection.close()
print int(hum_val)
Diese Datei muss nun ebenfalls über SSH als Ausführbar berechtigt werden. Wie das geht ist oben beschrieben. Zum Test kannst du diese Datei auch mal via SSH ausführen. Du solltest als Ausgabe dann die in der Datenbank eingetragenen Werte erhalten.
Für mehrere Sensoren musst du diese Datei auch mehrfach anlegen und die Datenbank-ID für deinen Sensor immer wieder anpassen.
Um diese Datei zyklisch aufzurufen nutzen wir Things. Lege dir also im Ordner /etc/openhab2/things/ eine Datei mit „.things“-Endung an. Meine habe ich „raumklima.things“ genannt.
Füge in diese Datei folgenden Inhalt ein:
Thing exec:command:sensor1_temperature "Sensor 1 - Temperatur" @ "<OPENHAB-RAUM>" [command="python -W ignore /etc/openhab2/scripts/<SENSORDATEI>.py temperature", transform="REGEX((.*?))", interval=60, timeout=10, autorun=true]
Thing exec:command:sensor1_humidity "Sensor 1 - Luftfeuchtigkeit" @ "<OPENHAB-RAUM>" [command="python -W ignore /etc/openhab2/scripts/<SENSORDATEI.py humidity", transform="REGEX((.*?))", interval=60, timeout=10, autorun=true]
Bitte passe die Daten in den „<>“-Klammern entsprechend deinen Gegebenheiten an. Auch den Sensornamen kannst du zur Übersicht noch anpassen.
Diese Datei sorgt nun dafür das die Werte aus der Datenbank alle 60 Sekunden ausgelesen werden. Dauert die Antwort des Pythonscripts länger als 10 Sekunden, wird die Anfrage abgebrochen.
Achtung: Ab Version 2.5.2 von Openhab wird eine Whitelist für das Exec-Binding benötigt, da die Befehle sonst nicht ausgeführt werden. Dies dient der Systemsicherheit! Sind die Befehle nicht in der Whitelist so werden diese nicht ausgeführt, aber ebenfalls keine Fehlermeldungen generiert. Kopiere also die Befehle hinter „command“ in deine Whitelist! Genaueres dazu in der Dokumentation des Bindings!
Du hast es fast geschafft und musst nur noch die Items zur weiteren Verarbeitung oder Visualisierung und eine kleine Regel zum Umrechnen der Werte anlegen. Doch beginnen wir mit den Items. Lege dir im /etc/openhab2/items/ Verzeichnis eine Datei mit der „.items“-Endung an und füge dort folgende Items ein:
Number sensor1_Temperature "Sensor 1 - Temperatur [%.1f C]" <temperature>
Number sensor1_Humidity "Sensor 1 - Luftfeuchtigkeit [%.1f %%]" <humidity>
String sensor1_temperature_out { channel="exec:command:sensor1_temperature:output" }
String sensor1_humidity_out { channel="exec:command:sensor1_humidity:output" }
Damit werden nun die Werte aus der „.things“-Datei ausgelesen und in die entsprechenden Strings geladen. Die Number-Items sind zur anschließenden Visualisierung. Da die Werte im String noch nicht passen und umgerechnet werden müssen, habe ich hierzu eine „.rules“-Datei in /etc/openhab2/rules/ angelegt und dort folgende Regeln angelegt:
rule "Klima - Sensor 1 - Temperatur"
when
Item sensor1_temperature_out received update
then
sensor1_Temperature.postUpdate(( ( Float::parseFloat(sensor1_temperature_out.state.toString) as Number ) / 100 ))
end
rule "Klima - Sensor 1 - Luftfeuchtigkeit"
when
Item sensor1_humidity_out received update
then
sensor1_Humidity.postUpdate(( ( Float::parseFloat(sensor1_humidity_out.state.toString) as Number ) / 100 ))
end
Diese Regel wird immer dann ausgeführt, sobald neue Werte aus der Datenbank geladen wurden.
Schlusswort
Mir ist klar, dass dieser Aufbau für Leien nicht einfach umzusetzen ist. Ich habe versucht alles so einfach zu halten wie notwendig um dir das Leben zu erleichtern. Solltest du dennoch Probleme haben, so scheu dich nicht das Forum oder die Kommentarfunktion zu nutzen. Solang es meine Zeit zulässt, werde ich versuchen dir so gut es geht weiter zu helfen.
Leider habe ich selbst in diversen Versuchen auch keine einfachere Variante gefunden diese Sensoren wirklich zuverlässig auszulesen. Sobald etwas Kabellänge dazwischen kommt, wird es immer schwierig sein. Doch mit der beschriebenen Variante funktioniert das Auslesen bei mir wirklich zuverlässig und ich habe über einen längeren Zeitraum keine Fehlmessungen erhalten.