Hinweis: Der contronics WebServer wird hier nicht benötigt. Meine Lösung stellt einen komplett anderen Weg dar und erfordert entsprechende HMTL- und PHP-Kenntnisse. Das einfache Zusammenklicken einer WebOberfläche für homeputer Studio wie dies im contronics WebServer angedacht ist, ist mit meiner hier vorgestellten Lösung nicht möglich, contronics WebServer wird dadurch also weder ersetzt noch erweitert!
Voraussetzungen zum Betrieb
- Ein PC mit laufender Anwendung contronics homeputer Studio, installiertem TCP/IP, ExecStudio(Co) von contronics (1) sowie ServerExecStudio (2) von Forenmtglied Bruno.
1) http://www.contronics.de/html/download.html
2) http://homematic-forum.de/downloads/ServerExecStudio/
Ein funktionierender WebServer (etwa Apache, IIS) mit installiertem PHP. Betriebssystem und Standort dieses PCs sind unabhängig vom Studio-PC, solange eine TCP/IP-Verbindung zu diesem hergestellt werden kann. Alternativ kann auch auf dem Studio-PC ein WebServer samt PHP installiert werden.
Wer einen gut funktionierenden WebServer unter Windows mit möglichst wenig Aufwand installieren möchte, dem sei das Paket XAMPP* empfohlen, denn dort ist alles notwendige (incl. PHP) bereits enthalten. Die einfachste Variante ist die Installer-Version. Ich habe meine Skripte gerade nochmal in einer VM unter einer frischen XAMPP-Installation getestet, das läuft so ohne Änderungen.
*) http://www.apachefriends.org/de/xampp-windows.html
Kenntnisse in PHP und HTML sowie entsprechendes KnowHow zum Betrieb der entsprechenden zuvor beschriebenen Umgebung.
Damit man sich in PHP mit homeputer Studio unterhalten kann, muss das von contronics zum freien Download angebotene Kommandozeilen-Utility "ExecStudioCo" auf dem Studio-PC installiert sein. Dies erlaubt zwar bereits ein Steuern und Abfragen von Studio aus der Windows Kommandozeile heraus, ist aber in dieser Form noch nicht für die Ansteuerung über einen (entfernten) WebServer geeignet. Hier kommt dann das Tool "ServerExecStudio" von Forenmtglied Bruno ins Spiel, welches über TCP/IP-Kommunikation den Aufruf von "ExecStudioCo" aus der Ferne erlaubt. Genau an dieser Stelle greift meine hier vorgestellte Bibliothek mit enstprechenden selbstprogrammierten PHP-Funktionen, die in eigenen Skripten entsprechend eingesetzt werden können.
Zur Kommunikation mit homeputer Studio bieten also die folgenden vier Funktionen die entsprechenden Möglichkeiten:
- - GetStudio() fragt den Zustand eines Objektes ab
- GetStudioArray() fragt den Zustand mehrerer Objekte mit nur einem Aufruf von ExecStudio ab
- SetStudio() setzt den Zustand eines Objektes
- RunStudio() führt ein Makro aus
studio.inc.php4:
Code: Alles auswählen
<?
//
// studio.inc.php4 / Stefan Hendricks, fhz-forum.de, 11/2006
//
// Funktionen zur Kommunikation mit contronics homeputer Studio
// über TCP/IP via ExecStudio(Co)/ServerExecStudio
//
// Voraussetzungen auf dem Studio-PC:
// - Installation von ExecStudio (contronics)
// - Installation von ServerExecStudio (Forenmtglied Bruno)
//
// Konstanten für die Kommunikation mit ServerExecStudio:
$studio_server = "192.168.0.10"; // IP oder Hostname des Servers
$studio_port = 54711; // Port des Servers
$studio_timeout = 10; // Timeout in Sekunden
$studio_password = "geheim"; // Passwort für ServerExecStudio
//
// Funktion GetStudio($object)
//
// Liefert den Wert von $object als String zurück,
// im Fehlerfalle ist der Rückgabewert "false"
//
// Beispiel: $steckdose1 = GetStudio("Steckdose1");
//
function GetStudio($object) {
global $studio_server, $studio_port, $studio_timeout, $studio_password;
if ($socket = fsockopen($studio_server, $studio_port, $errno, $errstr, $studio_timeout)) {
fputs($socket, trim("$studio_password g$object") ."\r\n");
$data = trim(fgets($socket));
fclose($socket);
if ((substr($data, 0, 5) != "Error") and (substr($data, 0, 13) != "access denied")) {
return substr($data, strpos($data, "=")+1);
} else {
return(false);
}
} else {
return(false);
}
}
//
// Funktion GetStudioArray($objects)
//
// Liefert die Werte von $objects (durch Komma getrennt) als Array zurück,
// im Fehlerfalle ist der Rückgabewert "false"
//
// Beispiel: $zustaende = GetStudioArray("Schalter1, Schalter2, Lampe1");
// ergibt ... $zustaende["Schalter1"] = "an"
// $zustaende["Schalter2"] = "aus"
// $zustaende["Lampe1"] = "an"
//
function GetStudioArray($objects) {
global $studio_server, $studio_port, $studio_timeout, $studio_password;
if ($socket = fsockopen($studio_server, $studio_port, $errno, $errstr, $studio_timeout)) {
$objects_array = explode(",", $objects);
for ($i=0; $i<count($objects_array); $i++) {
$objects_array[$i] = trim($objects_array[$i]);
}
$command = "g" . implode(" g", $objects_array);
fputs($socket, trim("$studio_password $command") ."\r\n");
for ($i=0; $i<count($objects_array); $i++) {
$data = trim(fgets($socket));
if (substr(strtolower($data), 0, strpos($data, "=")) == strtolower($objects_array[$i])) {
$result[$objects_array[$i]] = substr($data, strpos($data, "=")+1);
} else {
fclose($socket);
return(false);
}
}
fclose($socket);
return($result);
} else {
return(false);
}
}
//
// Funktion SetStudio($object, $data)
//
// Setzt $object auf $data, im Fehlerfalle ist der Rückgabewert "false"
//
// Beispiel: SetStudio("Ausgabe", "Hello World");
//
function SetStudio($object, $data) {
global $studio_server, $studio_port, $studio_timeout, $studio_password;
if ($socket = fsockopen($studio_server, $studio_port, $errno, $errstr, $studio_timeout)) {
fputs($socket, trim("$studio_password s$object=\"$data\"") ."\r\n");
$data = trim(fgets($socket));
fclose($socket);
if ((substr($data, 0, 5) != "Error") and (substr($data, 0, 13) != "access denied")) {
return(true);
} else {
return(false);
}
} else {
return(false);
}
}
//
// Funktion RunStudio($macro)
//
// Startet das Makro $macro, im Fehlerfalle ist der Rückgabewert "false"
//
// Beispiel: RunStudio("Makro1");
//
function RunStudio($macro) {
global $studio_server, $studio_port, $studio_timeout, $studio_password;
if ($socket = fsockopen($studio_server, $studio_port, $errno, $errstr, $studio_timeout)) {
fputs($socket, trim("$studio_password r$macro") ."\r\n");
$data = trim(fgets($socket));
fclose($socket);
if ((substr($data, 0, 5) != "Error") and (substr($data, 0, 13) != "access denied")) {
return(true);
} else {
return(false);
}
} else {
return(false);
}
}
?>
Das folgende simple Skript zeigt, wie man unter Verwendung von GetStudioArray() in einem Rutsch alle Daten eines Objektes abholt und als HTML-Tabelle darstellt.
Skript und HTML-Ausgabe sind bewusst simpel gehalten, da sie nur als einfaches Programmierbeispiel dienen sollen. Wenn das Objekt des Wettersensors nicht den Standardnamen "KS300" bekommen hat, dann ist das Skript natürlich entsprechend zu modifizieren.
So sieht's im Browser aus:
ks300.php4:
Code: Alles auswählen
<?
include("studio.inc.php4");
$data = GetStudioArray("KS300_Temp,
KS300_Feuchte,
KS300_Wind,
KS300_Regen,
KS300_RegenAStunde,
KS300_RegenLStunde,
KS300_RegenATag,
KS300_RegenLTag") or die("<br><b>Fehler beim Einlesen");
echo "<table border='1'>";
foreach($data as $objekt => $wert) {
echo "<tr><td>$objekt</td><td>$wert</td></tr>";
}
echo "</table><br>";
?>
Demoanwendung Raumregler FHT08B
Das folgende Skript ist schon etwas komplexer. Es dient dazu, auf alle Raumregler zuzugreifen, deren Daten anzuzeigen sowie die Solltemperatur und/oder den Modus (Automatik/Manuell) umzuschalten.
Ganz oben im Skript sind die Namen der eigenen Raumregler-Objekte entsprechend anzupassen.
Wie im vorherigen Skript werden alle Daten jeweils eines FHTs in einem Rutsch ausgelesen und in einer Tabelle dargestellt.
Im darauf folgenden Formular können die Werte neu gesetzt werden, hier wird also zusätzlich die Funktion SetStudio() demonstriert.
Zu guter Letzt kann zwischen allen im Skript konfigurierten Raumreglern umgeschaltet werden.
So sieht's im Browser aus:
studio.inc.php4:
Code: Alles auswählen
<?
include("studio.inc.php4");
$raumregler[] = "Heizung_Werkkeller";
$raumregler[] = "Heizung_Buero";
$raumregler[] = "Heizung_Wohnzimmer";
$raumregler[] = "Heizung_Wintergarten";
$raumregler[] = "Heizung_Kueche";
$raumregler[] = "Heizung_Flur_EG";
$raumregler[] = "Heizung_Bad_EG";
$raumregler[] = "Heizung_Bibliothek";
$raumregler[] = "Heizung_Schlafzimmer";
$raumregler[] = "Heizung_Kinderzimmer_links";
$raumregler[] = "Heizung_Kinderzimmer_rechts";
$raumregler[] = "Heizung_Bad_OG";
$fht = $_REQUEST[fht];
$neue_temperatur = $_REQUEST[neue_temperatur];
$neuer_modus = $_REQUEST[neuer_modus];
if ($fht) {
echo "<b>$fht:</b><hr>";
if ($neuer_modus) {
SetStudio("$fht.Modus", $neuer_modus);
}
if ($neue_temperatur) {
echo "<i>Setze neue Solltemperatur auf $neue_temperatur °C ...</i><br><br>";
SetStudio($fht, $neue_temperatur);
}
$data = GetStudioArray("$fht,
$fht.Modus,
$fht.Temperatur,
$fht.Ventilpos,
$fht.KomfortTemperatur,
$fht.AbsenkTemperatur,
$fht.Alarm,
$fht.Fenster") or die("<br><b>Fehler beim Einlesen von $fht");
if ($data[$fht] == "5,5") $data[$fht] = "Off";
if ($data[$fht] == "30,5") $data[$fht] = "On";
echo "<table border='1'>";
foreach($data as $objekt => $wert) {
echo "<tr><td>$objekt</td><td>$wert</td></tr>";
}
echo "</table><br>";
echo "<form name='soll_temperatur' action='$PHP_SELF' method='post' target='_self'>";
echo "Neue Temperatur: ";
echo "<select name='neue_temperatur'>";
for ($i=5.5; $i<=30.5; $i=$i+0.5) {
$x = number_format($i, 1, ",", "");
echo "<option value='$x'";
switch($x) {
case "5,5":
if ($data[$fht] == "Off") echo " selected";
echo ">Off";
break;
case "30,5":
if ($data[$fht] == "On") echo " selected";
echo ">On";
break;
default:
if ($data[$fht] == $x) echo " selected";
echo ">$x °C";
}
echo "</option>\n";
}
echo "</select>";
echo "<select name='neuer_modus'>";
echo "<option value='Automatik'";
if ($data["$fht.Modus"] == "Automatik") echo " selected";
echo ">Automatik</option>";
echo "<option value='Manuell'";
if ($data["$fht.Modus"] == "Manuell") echo " selected";
echo ">Manuell</option>";
echo "</select>";
echo "<input type='hidden' name='fht' value='$fht'>";
echo "<input type='submit' value='OK'>";
echo "</form>";
echo "<hr>";
}
for ($i=0; $i<count($raumregler); $i++) {
echo "<a href='$PHP_SELF?fht=$raumregler[$i]'>".str_replace("Heizung ", "", $raumregler[$i])."</a><br>";
}
?>
- Wenn ein Objektname in Studio ein Leerzeichen enthält, so ist dieses bei Nutzung der oben vorgestellten Funktionen durch einen Unterstrich ("_") zu ersetzen. So muss z.B. "KS300 Wind" als "KS300_Wind" angesprochen werden.
Studio verwaltet Dezimalzahlen unglücklicherweise mit einem Komma als Dezimaltrenner, also etwa "23,5" statt wie in Programmiersprachen üblich mit einem Punkt ("23.5"). D.h. wenn man sich Dezimalwerte aus Studio abholt, so sind diese - etwa mit str_replace(",", ".", $wert) - vor einer Weiterbearbeitung in PHP entsprechend umzuwandeln. Umgekehrt gilt natürlich dasselbe, aus Kommas müssen Punkte werden, also etwa str_replace(".", ",", $wert)
Wann immer auf einer HTML-Seite mehrere Objektzustände und/oder Variablen aus Studio angezeigt werden sollen, dann ist aus Performancegründen immer die Funktion GetStudioArray() der Funktion GetStudio() vorzuziehen, da diese mehrere Werte mit nur einem Aufruf von ExecStudioCo auf dem Studio-PC abholt. Andererseits wäre für jedes Objekt / jede Variable ein einzelner Aufruf von ExecStudioCo notwendig, was entsprechend langsamer geht.
- Sollte etwas einmal nicht wie gewünscht funktionieren, dann empfiehlt sich immer ein Blick auf das Monitorfenster von ServerExecStudio auf dem Studio-PC (Rechtsklick auf das Taskleistensymbol der Anwendung und dann "Monitor"). Dort sieht man, welche Befehle dort ausgeführt werden und bei Get-Abfragen auch, welche Werte zurückgegeben werden, was die Fehlersuche deutlich erleichtern kann.
Da bei allen Funktionen bei Nichterfolg (z.B. Abfragen eines nichtdefinierten Objektes) "false" zurückgegeben wird, lauert eine kleine Falle bei GetStudio():
Ist die Variable bzw. der Wert des Objektes = 0 (gilt jedoch nicht für "0,0", wie es etwa bei Temperaturen oder Regenmengen vorkommen kann, da PHP das Komma ja nicht also Dezimaltrenner ansieht und so der String "0,0" zurückgegeben werden würde) oder leer (""), dann würdedie Ausgabe "Error" zur Folge haben, was aber eigentlich in diesem Falle kein Fehler ist. Hier ist also Vorsicht angebracht. Dies gilt aber auch für alle internen Funktionen innerhalb PHP, die "0" oder einen Leerstring als Ergebnis zurückliefern würden.Code: Alles auswählen
$wert = GetStudio("leeres_objekt") or die("Error"); echo "Wert = $wert";
Wer dennoch nach dieser Methode arbeiten möchte, der sollte den Wert wie folgt abfragen:das hätte dann zumindest die Ausgabe "Wert =" zur Folge.Code: Alles auswählen
$wert = GetStudioArray("leeres_objekt") or die("Error"); echo "Wert = $wert[leeres_objekt]";
Ich helfe gerne weiter, wenn wieder Erwarten etwas nicht mit den hier vorgestellten Skripten funktioniert (dies schliesst aber nicht automatisch Nachhilfe in PHP oder HTML ein - wie bereits geschrieben setze ich enstprechende Kenntnisse voraus!). Dennoch soll dies alles eher "Hilfe zur Selbsthilfe" angesehen werden, oder als "Machbarkeitsstudie". Es soll also nur der grundsätzliche Weg anhand von einfachen Programmierbeispielen aufgezeigt werden. Was man daraus macht, bleibt jedem selbst überlassen.
Für etwaige Fehlfunktionen, Folgeschäden etc. übernehme ich keinerlei Haftung.
An dieser Stelle auch besten Dank an Bruno, der ServerExecStudio insofern "interaktiv" mit mir entwickelt hat, als dass er während der Programmierung auf meine Ansprüche für die hier vorgestellten Funktionen Rücksicht genommen hat, was eben jene in dieser Form erst ermöglicht hat. Während der erfreulich kurzen Entwicklungsphase beider Teile standen wir in ständigem Kontakt und konnten so das hier vorgestellte in Rekordzeit auf die Beine stellen
![Smile :-)](./images/smilies/icon_smile.gif)