Anpassung der Schaltmethoden an neue Struktur


10.03.2017  |  Smarthome Server, Tutorial

Nachdem im vorletzten Beitrag die Struktur der Datenbank optimiert wurde, müssen nun alle Funktionen des Systems auf die neue Struktur umgestellt werden. Dazu werden im folgenden einige Skripte ein wenig angepasst. Verbinde dich als erstes per FTP mit deinem Server und öffne im Serverhauptverzeichnis die Datei "setModes.php".

setModes.php

Dem Methodenkopf wurde der Parameter $type hinzugefügt, mit dem der Gerätetyp definiert wird, der geschalten werden soll. Außerdem wurde ein switch-Block erstellt, in dem ein Fall für jeden Gerätetypen angelegt wird. Somit kann für jeden Gerätetypen die entsprechende Aktion ausgeführt werden. Als nächstes wird der bereits vorhandene Code zur Schaltung einer Funksteckdose in den Fall für den Gerätetypen "Funksteckdose" verschoben (Zeilen 14 - 29). Zusätzlich wird ein default-Fall erstellt, der "nosuchtype" zurückgibt. Speichere das Skript und lade die Änderungen hoch.
<?php

//Der Parameter $type wurde hinzugef&uuml;gt
function setModes($room, $type, $device, $zustand, $db){
	
	if(!hasPermission($room, $db)){
		return "nopermission";
	}
	
	//Ein switch-Block f&uuml;r verschiedene Ger&auml;tetypen wurde erstellt
	switch($type){
		case "Funksteckdose":
			//Die Zeilen 14-29 wurden dem Fall "Funksteckdose" zugeordnet
			//Hauscode und Steckdosennummer aus Datenbank laden
			$query = $db->prepare("SELECT * FROM 'funksteckdosen' WHERE DEVICE == :device");
			$query->execute(array('device' => $device));
			 
			//Abfrageergebnisse speichern
			if($result = $query->fetch(PDO::FETCH_ASSOC)){
				$hauscode = $result['HAUSCODE'];
				$steckdosennummer = $result['STECKDOSENNUMMER'];
			}
			 
			//Schaltbefehl f&uuml;r Steckdosen
			shell_exec("/usr/local/bin/send  ".$hauscode." ".$steckdosennummer." ".$zustand);
		  
			//Status der geschalteten Steckdose aktualisieren
			$query = $db->prepare("UPDATE 'funksteckdosen' SET 'ZUSTAND' = :zustand WHERE DEVICE == :device");
			$query->execute(array('zustand' => $zustand, 'device' => $device));
			break;
		default:
			return "nosuchtype";
	}
  
    //R&uuml;ckgabe
    return "ok";
}
  
?>

getModes.php

Als nächstes wird die Abfrage der Schaltzustände angepasst, inndem die Datei "getModes.php" im Serverhauptverzeichnis geöffnet wird. Auch dort wird dem Methodenkopf der Parameter $type hinzugefügt. Falls kein bestimmtes Gerät angegeben wurde, wird für jeden Gerätetypen jedes Gerät ausgegeben. Für den Fall, dass ein bestimmtes Gerät abgefragt werden soll, wird ein switch-Block hinzugefügt, mit dem auf jeden Gerätetypen individuell reagiert werden kann. Der bisher vorhandene Ausgabecode der Funksteckdosen wird in den Fall für "Funksteckdose" kopiert (Zeile 33 - 39) und es wird ein default-Fall erstellt, der "nosuchtype" zurückgibt.
<?php

//Der Parameter $type wurde hinzugef&uuml;gt
function getModes($room, $type, $device, $db){
	
	if(!hasPermission($room, $db)){
		return "nopermission";
	}
	
	if($device==""){
		//Funksteckdosen laden
		$results = $db->prepare("SELECT * FROM 'funksteckdosen' WHERE ROOM == :room");
		$results->execute(array('room' => $room));
		
		$modi = array();
		
		foreach($results->fetchAll(PDO::FETCH_ASSOC) as $row){
			$mode_item = array('device' => $row['DEVICE'], 'mode' => $row['ZUSTAND'],
			'icon' => $row['ICON'], 'name' => $row['NAME']);
			array_push($modi, $mode_item);
		}
		
		//Weitere Ger&auml;tetypen laden
		
		header('Content-type: application/json');
		return json_encode(array('modi' => $modi));
	}
	else{
		//Ein switch-Block f&uuml;r die einzelnen Ger&auml;tetypen wurde erstellt
		switch($type){
			case "Funksteckdose":
				//Die Zeilen 33-39 wurden dem Fall f&uuml;r den Ger&auml;tetypen "Funksteckdose" zugeordnet
				$results = $db->prepare("SELECT * FROM 'funksteckdosen' WHERE DEVICE == :device");
				$results->execute(array('device' => $device));
				
				foreach($results->fetchAll(PDO::FETCH_ASSOC) as $row){
					return $row['ZUSTAND'];
				}
				break;
				
				//Weitere Cases
				
			default:
				return "nosuchtype";
		}
	}
}

?>

getRoomData.php

Auch die Abfrage der Raumdaten muss an die neue Struktur angepasst werden. Dazu wird die Datei "getRoomData.php" geöffnet. Die erste Neuerung ist das initialisieren eines Arrays mit den Gerätetypen für Schalter (Zeile 12). Die Ausgabe der Geräte mit Schalterfunktion wird anschließend in eine foreach-Schleife gepackt und für jeden Schalter-Gerätetypen durchlaufen, wie in den Zeilen 15 - 29 zu sehen. Die Abfrage der Schalterzustände wurde an die neue Struktur angepasst, indem der Parameter $type dem Methodenaufruf übergeben wird (Zeile 17). In Zeile 26 wurde dem Array ein neuer Wert namens "device_type" hinzugefügt, der den Gerätetypen des Schalters enthält.
<?php
 
function getRoomData($room, $db){
	
	if(!hasPermission($room, $db)){
		return "nopermission";
	}
	
    $roomdata = array();
    
	//Diese Zeile wrde hinzugef&uuml;gt
	$types = array("Funksteckdose");
	
	//Die Zeilen 16-28 wurden in eine foreach-Schleife gepackt
	foreach($types as $type){
		//Die Parameter wurden angepasst
		$switchdata = json_decode(getModes($room, $type, "", $db), true);
		foreach($switchdata['modi'] as $switch){
			if($switch['mode'] === "1"){
				$mode = true;
			}
			else{
				$mode = false;
			}
			//Die Werte des Arrays wurden angepasst
			array_push($roomdata, array('name' => $switch['name'], 'device' => $switch['device'], 'device_type' => $type,
			'icon' => $switch['icon'], 'type' => "switch", 'value' => ($mode) ? 'true' : 'false'));
		}
	}
	
	//Die Parameter wurden angepasst
    $sensordata = json_decode(getSensorData($room, "", "", "", $db), true);
    foreach($sensordata['values'][0]['value_array'] as $sensor){
		//Die Werte des Arrays wurden angepasst
        array_push($roomdata, array('name' => $sensor['shortform'], 'device' => $sensor['id'],
		'icon' => $sensor['icon'], 'type' => "value", 'device_type' => $sensor['device_type'], 'value' => $sensor['wert']));
    }
     
    $scenedata = json_decode(getScenes($room, $db), true);
    if(sizeOf($scenedata['scenes']) > 0){
        array_push($roomdata, array('name' => "Szenen", 'device' => "scenes", 'icon' => "scenes", 'type' => "scenes", 'value' => ""));
    }
     
    //Heizungs-Item implementieren
     
    return json_encode(array('roomdata' => $roomdata));
}
 
?>

api.php

Die einzige nötige Änderung an der Schnittstellendatei "api.php" ist das Hinzufügen des Parameters "type" zu den Methodenaufrufen von getModes() und setModes() (Zeile 58 & 62).
<?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";

$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":
			//Hier wurden die Parameter angepasst
            echo getModes($_POST['room'], $_POST['type'], $_POST['device'], $db);
            break;
        case "setmodes":
			//Hier wurden auch die Parameter angepasst
            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;
    }
}

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));
}

?>

runScene.php bearbeiten

In der Datei "runScene.php" im Verzeichnis "scenes" wurde lediglich der Parameter"type" zum Methodenaufruf von setModes() hinzugefügt, wie in Zeile 23 zu sehen.
<?php

function runScene($room, $scene, $db){
	
	//Diese Zeilen wurden hinzugef&uuml;gt
	if(!hasPermission($room, $db) && $room !== "NONE"){
		continue;
	}
	
	//Szenen aus Datenbank laden
	$results = $db->prepare("SELECT * FROM 'SCENES' WHERE ROOM == :room AND NAME == :scene");
	$results->execute(array('room' => $room, 'scene' => $scene));
	
	foreach($results->fetchAll(PDO::FETCH_ASSOC) as $row){
		$array = json_decode($row['ACTIONS'], true);
		foreach($array['actions'] as $action){
			//Wenn Bedingung erf&uuml;llt ist oder keine Bedingung angegeben, f&uuml;hre Befehl aus
			if($action['if']==null || conditionTrue($action['if'])){
				//Verarbeitung der Aktion anhand des Aktionstyps (Schalter, Heizung, etc.)
				switch($action['type']){
					case 'switch':
						//Hier wurden Parameter angepasst
						setModes($action['location'], $action['type'],  $action['device'], $action['value'], $db);
						break;
					case 'heizung':
						//Heizungssteuerung wird noch implementiert
						break;
				}
			}
		}
	}
	
	return "ok";
}

//Pr&uuml;ft die &uuml;bergebene Bedingung auf Wahrheit und gibt dementsprechend true/false zur&uuml;ck
function conditionTrue($condition){
	switch($condition['type']){
		//Sensorwert abfragen
		case 'sensor':
			$value = getData($condition['room'], $condition['sensorart'], '', $db);
			break;
		//Schalter abfragen
		case 'switch':
			//Hier wurden Parameter angepasst
			$value = getModes($condition['room'], $condition['type'], $condition['device'], $db);
			break;
	}
	
	//vergleicht den abgefragten Wert mit dem &uuml;bergebenen Wert
	switch($condition['comparator']){
		case '<':
			return ($value < $condition['value']);
		case '<=':
		case '=<':
			return ($value <= $condition['value']);
		case '>':
			return ($value > $condition['value']);
		case '>=':
		case '=>':
			return ($value >= $condition['value']);
		case '==':
		case '=':
			return ($value == $condition['value']);
		default:
			return false;
	}
}

?>
Bei Fragen oder Problemen kannst du mir gerne 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!