Gateways ins Smarthome einbinden


07.04.2017  |  Smarthome Server, Tutorial

Im Artikel "RaZberry Modul auf Raspberry installieren" habe ich dir gezeigt, wie du deinen Raspberry Pi als Z-Wave Zentrale einsetzen kannst. Im heutigen Tutorial wird die Unterstützung für externe Smarthome Zentralen implementiert, damit du auch dein vorhandenes Z-Wave System von deinem Raspberry aus steuern kannst. Doch auch wenn du Z-Wave lokal auf deinem Smarthome-Raspberry eingerichtet hast, solltest du diesem Tutorial folgen, da in Zukunft auch andere Smarthome-Systeme unterstützt werden und die folgenden Tutorials teilweise darauf aufbauen.

Datenbank anpassen

Als erstes wird der Datenbank eine neue Tabelle hinzugefügt, in der die Daten der externen Smarthome-Zentralen gespeichert sind. Dazu rufst du mit deinem Browser die Adresse "http://[IP DEINES RASPBERRY]/database/phpliteadmin.php" auf und klickst im mittleren Bereich auf "Create new table on database 'data.sqlite'". Hier gibst du nun als Name "GATEWAYS" und als Anzahl der Felder 5 ein und klickst auf "Go".
So wird die Tabelle Gateways definiert.
Die Felder der Tabelle sind NAME, IP, PORT, USERNAME und PASSWORD. Bis auf "PORT" sind alle Felder vom Typ "TEXT", "PORT" ist vom Typ "INTEGER". Das Feld "NAME" ist der Primärschlüssel und "NAME" und "PORT" dürfen nicht null sein. Der Defaultwert des Feldes "IP" ist "localhost" und der des Feldes "PORT" ist "80".

Skript zur Unterstützung von externen Zentralen

Anschließend muss noch das Skript zur Abfrage und der Verwaltung der externen Smarthome-Zentralen implementiert werden. Dazu verbindest du dich per FTP mit deinem Server, erstellst im Serverhauptverzeichnis den Ordner "manager" und darin die Datei "gatewayManager.php", die du dann öffnest. In dieser Datei werden nun die folgenden Methoden angelegt. Die Methode addEditGateway() erstellt ein neues oder aktualisiert ein vorhandenes Gateway, je nachdem, ob der Parameter $key leer ist, oder nicht. Gateways können mit der Methode deleteGateway() gelöscht werden. Mit den Methoden getGateway() und getGatewayData() lassen sich die Daten eines bestimmten Gateways abfragen, wobei sich die Rückgabe der Methoden leicht unterscheidet. Die ins System eingebundenen Gateways lassen sich mit getGateways() und die Typen der verfügbaren Gateways, die noch nicht eingebunden wurden, mit getGatewayTypes() abfragen. Speichere das Skript anschließend und lade die Änderungen auf den Server hoch.
<?php

/**
*Erstellt ein neues Gateway bzw. aktualisiert das Gateway mit dem Key $key
*/
function addEditGateway($key, $ip, $port, $usr, $psw, $changepw, $db){
	if(!hasPermission("admin", $db)){
		return "noadmin";
	}
	
	$paramArray = array("name" => $key, "ip" => $ip, "port" => $port, "usr" => $usr);
	
	if($changepw === "true"){
		$paramArray['psw'] = $psw;
		
		//Gateway bearbeiten bzw. hinzuf&uuml;gen
		$updateQuery = $db->prepare("UPDATE OR IGNORE 'GATEWAYS' SET IP = :ip, PORT = :port, USERNAME = :usr, PASSWORD = :psw WHERE NAME = :name;");
	
		$insertQuery = $db->prepare("INSERT OR IGNORE INTO 'GATEWAYS' (NAME, IP, PORT, USERNAME, PASSWORD) VALUES (:name, :ip, :port, :usr, :psw);");
	}
	else{
		//Gateway bearbeiten bzw. hinzuf&uuml;gen
		$updateQuery = $db->prepare("UPDATE OR IGNORE 'GATEWAYS' SET IP = :ip, PORT = :port, USERNAME = :usr WHERE NAME = :name;");
	
		$insertQuery = $db->prepare("INSERT OR IGNORE INTO 'GATEWAYS' (NAME, IP, PORT, USERNAME) VALUES (:name, :ip, :port, :usr);");
	}
	
	$updateQuery->execute($paramArray);
	$insertQuery->execute($paramArray);
	
	if($updateQuery == true && $insertQuery == true) return "ok";
	else return "error";
}

/**
*L&ouml;scht das Gateway mit dem Key $key
*/
function deleteGateway($key, $db){
	if(!hasPermission("admin", $db)){
		return "noadmin";
	}
	
	$result = $db->prepare("DELETE FROM GATEWAYS WHERE NAME == :key");
	$result->execute(array("key" => $key));
	
	if($result == true){
		return "ok";
	}
	else return "error";
}

/**
*Gibt alle Daten eines bestimmten Gateways zur&uuml;ck
*/
function getGateway($key, $db){
	$results = $db->prepare("SELECT * FROM 'GATEWAYS' WHERE NAME == :key");
	$results->execute(array('key' => $key));
	
	//Alle Server durchlaufen
	foreach($results->fetchAll(PDO::FETCH_ASSOC) as $row){
		return $row;
	}
}

/**
*Gibt Namen, IP, Port und Nutzername eines bestimmten Gateways zur&uuml;ck
*/
function getGatewayData($key, $db){
	if(!hasPermission("admin", $db)){
		return "noadmin";
	}
	
	$results = $db->prepare("SELECT * FROM 'GATEWAYS' WHERE NAME == :key");
	$results->execute(array('key' => $key));
	
	//Alle Server durchlaufen
	foreach($results->fetchAll(PDO::FETCH_ASSOC) as $row){
		return json_encode(array("gatewaydata" => array("name" => $row['NAME'], "ip" => $row['IP'], "port" => $row['PORT'],
		"username" => $row['USERNAME'])));
	}
}

/**
*Gibt die zum System hinzugef&uuml;gten Gateways zur&uuml;ck
*/
function getGateways($db){
	if(!hasPermission("admin", $db)){
		return "noadmin";
	}
	
	$results = $db->prepare("SELECT * FROM 'GATEWAYS'");
	$results->execute();
	
	$gateways = array();
	
	//Alle Server durchlaufen
	foreach($results->fetchAll(PDO::FETCH_ASSOC) as $row){
		array_push($gateways, array("name" => $row['NAME'], "ip" => $row['IP'], "port" => $row['PORT'], "username" => $row['USERNAME']));
	}
	
	return json_encode(array("gateways" => $gateways, "gatewaytypes" => getGatewayTypes($db)));
}

/**
*Gibt die Gatewaytypen zur&uuml;ck, die noch nicht zum System hinzugef&uuml;gt wurden
*/
function getGatewayTypes($db){
	if(!hasPermission("admin", $db)){
		return "noadmin";
	}
	
	$gatewayTypes = array("Z-Wave");
	
	$query = $db->prepare("SELECT NAME FROM GATEWAYS");
	$query->execute();
	
	foreach($query->fetchAll() as $row){
		$index = array_search($row['NAME'], $gatewayTypes);
		if($index !== FALSE){
			unset($gatewayTypes[$index]);
		}
	}
	
	return array_values($gatewayTypes);
}

?>

Schnittstelle bearbeiten

Als letztes muss noch die Schnittstelle bearbeitet werden. Dazu öffnest du die Datei "api.php" im Serverhauptverzeichnis. Hier fügst du in Zeile 26 einen include-Befehl für die Datei "gatewayManager.php" hinzu und erstellst die neuen Fälle für die Methoden (Zeilen 83 - 94). Speichere das Skript anschließend und lade die Änderungen auf den Server hoch.
<?php
 
//Datenbankverbindung herstellen
$SQLITEdb = "database/data.sqlite";
$db = new PDO("sqlite:".$SQLITEdb);
 
//Funksteckdosen
include "getModes.php";
include "setModes.php";
   
//Andere
include "getRooms.php";
include "getSensorData.php";
include "getSystemInfo.php";
include "getRoomData.php";
include "getGraphData.php";
include "events.php";
include "permissions.php";
 
//Szenen
include "scenes/getScenes.php";
include "scenes/runScene.php";
include "scenes/createScene.php";
 
//Diese Zeile wurde hinzugef&uuml;gt
include "manager/gatewayManager.php";
 
$validUser = validateUser($_POST['username'], $_POST['password'], $db);
 
if($validUser){
    switch($_POST['action']){
        case "getrooms":
            echo getRooms($db);
            break;
        case "getevents":
            echo getEvents($_POST['username'], $_POST['type'], $_POST['limit'], $_POST['offset'], $db);
            break;
        case "geteventtypes":
            echo getEventTypes($db);
            break;
        case "addevent":
            echo addEvent($_POST['type'], $_POST['text'], $db);
            break;
        case "getunseenevents":
            echo getUnseenEvents($_POST['username'], $db);
            break;
        case "getpermissions":
            echo getPermissions($_POST['user'], $db);
            break;
        case "setpermissions":
            echo setPermissions($_POST['user'], $_POST['permissions'], $db);
            break;
        case "getgraphdata":
            echo getGraphData($_POST['type'], $_POST['id'], $_POST['von'], $_POST['bis'], $db);
            break;
        case "getroomdata":
            echo getRoomData($_POST['room'], $db);
            break;
        case "getmodes":
            echo getModes($_POST['room'], $_POST['type'], $_POST['device'], $db);
            break;
        case "setmodes":
            echo setModes($_POST['room'], $_POST['type'], $_POST['device'], $_POST['zustand'], $db);
            break;
        case "getsensordata":
            echo getSensorData($_POST['room'], $_POST['type'], $_POST['id'], $_POST['showeinheit'], $db);
            break;
        case "runscene":
            echo runScene($_POST['room'], $_POST['name'], $db);
            break;
        case "createscene":
            echo createScene($_POST['devices'], $_POST['rooms'], $_POST['types'], $_POST['values'],
                $_POST['conditions'], $_POST['room'], $_POST['name'], $db);
            break;
        case "getscenes":
            echo getScenes($_POST['room'], $db);
            break;
        case "getsysteminfo":
            echo getSystemInfo();
            break;
         
        //Diese Cases wurden hinzugef&uuml;gt
        case "deletegateway":
            echo deleteGateway($_POST['key'], $db);
            break;
        case "getgateways":
            echo getGateways($db);
            break;
        case "getgatewaydata":
            echo getGatewayData($_POST['type'], $db);
            break;
        case "addeditgateway":
            echo addEditGateway($_POST['type'], $_POST['ip'], $_POST['port'], $_POST['usr'], $_POST['psw'], $_POST['changepw'], $db);
            break;
    }
}
 
function validateUser($username, $password, $db){
    //Wird noch implementiert
     
    return true;
}
 
function hasPermission($action, $db){
    $permissions = getPermissions($_POST['username'], $db);
    $permissions = json_decode($permissions, true)['permissions'];
     
    return (in_array($action, $permissions) || in_array("admin", $permissions));
}

?>
Bei Fragen oder Problemen kannst du mir einen Kommentar hinterlassen.

Über den Autor


Sascha Huber

Hallo, ich bin Sascha, der Gründer von Smarthome Blogger.

Mit einer Leidenschaft für Technologie und einem Hintergrund als Software Engineer habe ich 2016 Smarthome Blogger gegründet. Mein Ziel war es schon immer, innovative Lösungen zu entdecken, die unser Leben einfacher und intelligenter gestalten können. In meinem beruflichen Leben arbeite ich täglich mit Software und Technik, aber auch in meiner Freizeit bin ich stets auf der Suche nach neuen technischen Spielereien und Möglichkeiten, mein Zuhause zu automatisieren und zu verbessern.

Auf Smarthome Blogger teile ich mein Wissen, meine Erfahrungen und meine Begeisterung für alles rund um das Thema Smarthome.



Dieser Beitrag hat dir gefallen?

Dann abonniere doch unseren Newsletter!