Es ist praktisch, jederzeit abrufen zu können, wie warm es gerade in einem Raum ist oder wie hoch die Luftfeuchtigkeit ist. Doch manchmal möchte man nicht nur den aktuellen Wert sehen, sondern auch einen Verlauf der letzten Tage, Wochen und sogar Monate. Um dies zu realisieren, wird eine Datenbank benötigt, in die regelmäßig die Werte geschrieben werden. Dann können diese jederzeit einfach per URL-Aufruf abgefragt werden. Wie man so eine Datenbank einrichtet und die Werte eintragen lässt, erfährst du hier. Um dem Tutorial folgen zu können, benötigst du einen fertig eingerichteten Raspberry Pi und solltest außerdem das RaZberry Modul auf deinem Raspberry Pi installiert haben.
Benötigte Teile
Um die Werte zu messen, benötigt man natürlich auch einen Sensor. Ich benutze den folgenden, da er nicht nur die Temperatur angibt, sondern auch die Luftfeuchtigkeit & Helligkeit, und weil er gleichzeitig als Bewegungsmelder fungiert.
Datenbank anlegen
Um eine Datenbank anzulegen und Sensorwerte darin abspeichern zu können, solltest du dir das Tutorial "Datenbank anlegen" ansehen.Tabellen anlegen
Damit du die Sensorwerte in eine Datenbank schreiben kannst, musst du dir in deiner Datenbank noch ein paar Tabellen anlegen. Die 3 Tabellen sind folgende:- ROOMS: Hier werden alle Räume deines Hauses hinterlegt, die ins Smarthome integriert werden sollen
- ZWAVE_SENSOREN: Hier werden alle Z-Wave Sensorenmit ihrer ID hinterlegt
- SENSOR_DATA: In diese Tabelle werden regelmäßig die Sensorwerte geschrieben
http://[IP-ADRESSE]/database/phpliteadmin.php
ROOMS anlegen
In dieser Tabelle sind alle Räume deines Smarthomes hinterlegt. Dies ist nötig, damit das Script die Sensoren aus jedem angelegten Raum abfragen und deren Werte abspeichern kann. Außerdem greift die Smarthome App, die im Laufe dieser Tutorialreihe noch programmiert wird, auf diese Tabelle zu, um dynamisch für jeden angelegten Raum einen Menüpunkt anzulegen. Das Feld NAME enthält den Namen eines Raumes. Dieser wird in der oben erwähnten Smarthome App als Menüpunkt angezeigt. Das Feld LOCATION enthält den KEY eines Raumes, damit der Server beispielsweise erkennt, in welchem Raum ein Befehl ausgeführt werden soll. Die beiden Felder haben den Datentyp TEXT.ZWAVE_SENSOREN anlegen
Damit der Server alle vorhandenen Sensoren abfragen kann, sind in der Tabelle ZWAVE_SENSOREN alle angelernten Sensoren hinterlegt. Die 5 Felder dieser Tabelle stehen für folgendes:- RAUM: der Key des Raumes, in dem sich der Sensor befindet
- SENSORART: die Art des Wertes, der vom Sensor gemessen wird
- ID: die Z-Wave ID des Sensors
- SHORTFORM: eine Abkürzung des gemessenen Wertes (zb. Temp statt Temperatur oder Hygro statt Luftfeuchtigkeit) - wird später zur App-Programmierung benötigt
- EINHEIT: die Einheit, in der der Wert gemessen wird
SENSOR_DATA anlegen
In der Tabelle SENSOR_DATA werden alle gesammelten Sensorwerte abgespeichert. Die 4 Felder werden folgendermaßen verwendet:- RAUM: der Key des Raumes, zu dem der Sensorwert gehört
- VALUE: der gemessene Wert des Sensors
- SENSORART: die Art des gemessenen Wertes (zb. temperatur, luftfeuchtigkeit, helligkeit, usw.)
- DATETIME: Datum und Uhrzeit der Messung
Tabellen mit Daten füllen
Um Datensätze in die Tabellen einzufügen, klickst du auf der phpLiteAdmin-Startseite bei der entsprechenden Tabelle auf 'Insert'. In der Tabelle ROOMS legst du einen Raum an und gibst diesem Raum einen Key - zum Beispiel den Raumnamen auf Englisch und kleingeschrieben. Mit einem Klick auf 'Insert' wird die Reihe hinzugefügt. Der Tabelle ZWAVE_SENSOREN fügst du eine neue Reihe ein und gibst als RAUM den Key des Raumes an, in dem sich der Sensor befindet. Als SENSORART gibst du einen Key für den gemessenen Wert an (zb. 'temperatur' für den Temperatur-Sensor). Die Z-Wave ID des Sensors findest du heraus, indem du mit deinem Browser den folgenden Link aufrufst und dich mit den admin-Daten einloggst:http://[IP DEINES RASPBERRY]:8083/smarthome/
Z-Wave API für Scripts verfügbar machen
Damit das PHP-Script auf die Sensorwerte zugreifen kann, muss die Z-Wave API für HTTP-Aufrufe zugänglich gemacht werden. Dazu loggst du dich unter folgender Adresse mit deinen admin-Daten ein und öffnest oben rechts über das Options-Menü den Menüpunkt 'Management':http://[IP DEINES RASPBERRY]:8083/smarthome/
Sensorwerte abfragen
Bevor wir die Werte in die Datenbank eintragen können, schreiben wir uns noch ein PHP-Script, dass uns den gewünschten Sensorwert des gewünschten Raumes ausgibt. Um das Script anzulegen, erstellst du im Hauptverzeichnis der Servers eine Datei namens 'getSensorData.php' und fügst den folgenden Quellcode ein:<?php
function getSensorData($room, $val, $show_einheit, $db){
$ipAddress = $_SERVER['SERVER_ADDR'];
if($val == null){ //Alle Werte werden abgefragt
//Räume laden
if($room == "all"){
$results = $db->prepare("SELECT * FROM 'ROOMS'");
$results->execute();
}
else{
$results = $db->prepare("SELECT * FROM 'ROOMS' WHERE LOCATION == :room");
$results->execute(array('room' => $room));
}
//Ausgabearray erzeugen
$values = array();
//Alle Räume durchlaufen
foreach($results->fetchAll(PDO::FETCH_ASSOC) as $row){
//Wertearray erzeugen
$value_array = array();
//Sensoren im aktuellen Raum laden
$ergebnisse = $db->prepare("SELECT * FROM 'ZWAVE_SENSOREN' WHERE RAUM == :location");
$ergebnisse->execute(array('location' => $row['LOCATION']));
//Alle Sensoren im Raum durchlaufen
foreach($ergebnisse->fetchAll(PDO::FETCH_ASSOC) as $reihe){
//Wert für jeden Sensor zusammen mit Sensorart in Wertearray schreiben
$value = array('shortform' => $reihe['SHORTFORM'], 'sensorart' => $reihe['SENSORART'], 'wert' => getSensorData($reihe['RAUM'], $reihe['SENSORART'], 1, $db));
array_push($value_array, $value);
}
//Daten für aktuellen Raum in Ausgabearray schreiben
$value_item = array('name' => $row['NAME'], 'location' => $row['LOCATION'], 'value_array' => $value_array);
array_push($values, $value_item);
}
//JSON-Objekt zurückgeben
return json_encode(array('values' => $values));
}
else{ //Ein spezieller Wert wird abgefragt
//ID des gesuchten Sensors im gesuchten Raum ermitteln
$id = getZwaveId($room, $val, $db);
if($id !== "N/A"){
//Z-Wave API aufrufen
$link = "http://".$ipAddress.":8083/ZAutomation/api/v1/devices/".$id;
//curl mit URL initialisieren
$cURL = curl_init($link);
//Port setzen
curl_setopt($cURL, CURLOPT_PORT, 8083);
//Ausgabe einstellen
curl_setopt($cURL, CURLOPT_RETURNTRANSFER, true);
//Abfrage ausführen
$result = curl_exec($cURL);
//wert je nach Wunsch mit/ohne Einheit ausgeben
$array = json_decode($result, true);
if($show_einheit == "1"){
return $array['data']['metrics']['level']." ".$array['data']['metrics']['scaleTitle'];
}
else{
return $array['data']['metrics']['level'];
}
}
else return "N/A"; //Sensor-ID nicht gefunden?
}
}
function getZwaveId($room, $val, $db){
//Z-Wave ID des gesuchten Sensors im gesuchten Raum laden
$query = $db->prepare("SELECT * FROM 'ZWAVE_SENSOREN' WHERE RAUM == :room AND SENSORART == :sensorart");
$query->execute(array('room' => $room, 'sensorart' => $val));
//ID zurückgeben, wenn gefunden
if($result = $query->fetch(PDO::FETCH_ASSOC)){
return $result['ID'];
}
else return "N/A"; //ID nicht gefunden?
}
?>
Erklärung des PHP-Scripts
Das Script besteht aus den Methoden getSensorData() und getZwaveID(). Die Methode getSensorData() erhält als Parameter 3 Strings und eine Referenz auf das Datenbank-Objekt:- $room: der Key des Raumes, dessen Sensorwert ausgegeben werden soll ("all", wenn alle Daten zu allen Räumen als JSON-Objekt ausgegeben werden soll)
- $val: Die Sensorart die ausgegeben werden soll
- $show_einheit: 1, wenn Sensorwert mit Einheit ausgegeben werden soll, ansonsten beliebiger anderer Wert (auch nicht definiert)
- $db: Referenz auf das Datenbank-Objekt
Schnittstelle für Python-Script anlegen
Damit das Python-Skript auf die Funktion zugreifen kann, erstellen wir eine Schnittstelle, die später auch von der App verwendet wird. Dazu legst du im Server-Hauptverzeichnis eine Datei namens "api.php" an und fügst dort folgenden Code ein:<?php
//Datenbankverbindung herstellen
$SQLITEdb = "database/data.sqlite";
$db = new PDO("sqlite:".$SQLITEdb);
include "getSensorData.php";
$validUser = validateUser($_POST['username'], $_POST['password'], $db);
if($validUser){
switch($_POST['action']){
case "getsensordata":
echo getSensorData($_POST['room'], $_POST['value'], $_POST['showeinheit'], $db);
break;
}
}
function validateUser($username, $password, $db){
//wird noch implementiert
return true;
}
?>
Das Python-Script
Um die Sensorwerte in die Datenbank zu schreiben, wird nun ein Python-Script erstellt. Dieses Script kann später in gewünschten Abständen oder zu bestimmten Uhrzeiten ausgeführt werden. Um das Script zu erstellen musst du im Ordner 'python' auf deinem Server eine Datei namens 'saveSensorData.py' erstellen und den folgenden Quellcode hineinkopieren:#!/usr/bin/python
# -*- coding: utf-8 -*-
import sqlite3 as lite #Für die Datenbankverbindung
import datetime #Um Datum und Uhrzeit zu ermitteln
import urllib #Um die URL aufzurufen
import httplib #Um die URL aufzurufen
import sys #Um Kommandozeilenargumente zu lesen
#Um die IP-Adresse zu ermitteln
import socket
import fcntl
import struct
now = datetime.datetime.now()
con = lite.connect('/var/www/html/database/data.sqlite')
#Nutzerdaten, da API im weiteren Verlauf der Tutorials noch geschützt werden
username = 'client'
password = 'clientpassword'
#IP-Adresse des Servers feststellen und zurückgeben
#Parameter: ifname - 'wlan0' falls per WLAN verbunden und 'eth0' falls per LAN verbunden
def get_ip_address(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915, # SIOCGIFADDR
struct.pack('256s', ifname[:15])
)[20:24])
#Daten aus Datenbank laden
def getData():
with con:
cur = con.cursor()
cur.execute("SELECT * FROM ZWAVE_SENSOREN")
return cur.fetchall()
#Sensorwerte abfragen und Wert in Datenbank schreiben
#Parameter:
#room: Raum, in dem der Wert gesucht werden soll
#sensor: Art des zu suchenden Sensors
def saveSensorData(room, sensor, ip):
#entsprechenden Sensorwert abfragen
params = urllib.urlencode({'action': 'getsensordata', 'room': room, 'value': sensor, 'username': username, 'password': password})
headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"}
conn = httplib.HTTPConnection(ip)
conn.request("POST", "/api.php", params, headers)
response = conn.getresponse()
sensorwert = response.read()
conn.close()
#Datum und Uhrzeit ermitteln
uhrzeit = now.strftime("%d.%m.%y %H:%M") #Datum und Uhrzeit im Format TT.MM.JJ HH:MM
#Daten in Datenbank schreiben
cur = con.cursor()
cur.execute("INSERT INTO SENSOR_DATA (ROOM, VALUE, SENSORART, DATETIME) VALUES ('"+room+"','"+sensorwert+"','"+sensor+"','"+uhrzeit+"')")
con.commit()
#Für jeden Sensor in jedem Raum den Wert in die Datenbank schreiben
for data in getData():
saveSensorData(data[0], data[1], get_ip_address(sys.argv[1])) #data[0] enthält den KEY des Raumes und data[1] die Art des Sensors
Erklärung des Python-Scripts
Dieses Python-Script fragt bei jedem Aufruf alle vorhandenen Z-Wave Sensoren ab und speichert die Sensorwerte in der Datenbnak in der Tabelle SENSOR_DATA ab. Dabei wird außerdem der Key des Raumes, in dem sich der Sensor befindet mit abgespeichert und zusätzlich das Datum der Messung und der Key der Sensorart, damit beispielsweise zwischen Temperaur und Luftfeuchtigkeit unterschieden werden kann. Das Python-Script erhält ein Kommandozeilenargument: 'wlan0', falls euer Pi per WLAN mit dem Netzwerk verbunden ist und 'eth0', fall er per LAN am Netz hängt. Dieses Argument wird an die Methode get_ip_adress(ifname) übergeben, welche die entsprechende IP-Adresse des Netzwerkmoduls zurückgibt.Regelmäßige Ausführung des Scripts
Damit die Sensorwerte automatisiert regelmäßig in die Datenbank geschrieben werden, muss auf dem Raspberry ein Cronjob angelegt werden. Dieser ruft den angegebenen Befehl in angegebenen Zeitabständen auf (bei mir: alle 3 Stunden). Um einen solchen Cronjob anzulegen, musst du in die Kommandozeile den folgenden Befehl eingeben:
crontab -e
* * * * * Befehl
- 1. Stern: Die Minuten von 0 bis 60
- 2. Stern: Die Stunden von 0 bis 24
- 3. Stern: Die Tage von 1 bis 31 des Monats
- 4. Stern: Die Monate von 1 bis 12
- 5. Stern: Die Wochentage von 0 bis 7 (0 & 7 enstprechen Sonntag)
0 0,3,6,9,12,15,18,21 * * * sudo python /var/www/html/python/saveSensorData.py [VERBINDUNGSART]
sudo reboot
Das Video zum Tutorial
Du kannst dir das Tutorial auch als Video auf meinem YouTube-Kanal ansehen.Teil 1 von 2
Teil 2 von 2
Dieser Beitrag hat dir gefallen?
Dann abonniere doch unseren Newsletter!