Ich steuere heute mal wieder ein Skript bei aus der Abteilung „Dinge auslesen“. Diesmal geht es um die Haushaltsgeräte wie z.B. Spülmaschine, Waschmaschine, Trockner.
Ein verbreiteter Weg, um konventionelle Geräte dieser Art auszulesen ist der, über Master-Slave-Schaltungen, Stromsensoren etc. zu gehen. Das Prinzip ist eigentlich recht simpel: Im Betrieb verbraucht so ein Gerät relativ viel Strom, wenn es fertig ist, erkennt man das daran dass es nur noch sehr wenig Strom zieht.
Man kann so eine Überwachung z.B. mit dem FS20 FMS lösen. Das Teil ist, sagen wir mal, nervig zu programmieren, aber wenn man das hinter sich hat dann tut es meist was es soll.
Leider ist die Sache in der Praxis dann oft komplizierter als man es sich zunächst vorstellt. Folgende Probleme stellen sich ein:
-Das FMS ist ein Funksender. Es bemerkt nicht, ob sein Schaltsignal in IPS angekommen ist, es dürfte ihm auch herzlich egal sein. Wenn ein Schaltsignal ausbleibt, schlimmstenfalls das Ausschaltsignal am Ende des Durchlaufs, dann unterbleibt die Fertigmeldung.
-Haushaltsgeräte verbrauchen nicht kontinuierlich Strom bis sie fertig sind. Stichwort Einweichphase. Es gibt also zu erwartende Pausen, in denen der FMS dann einen Ausschaltbefehl sendet, obwohl der Durchlauf noch lange nicht abgeschlossen ist.
Das kann einem schon reichlich Kopfzerbrechen bereiten. Natürlich gibt es Quick&Dirty-Workarounds, um der Problematik beizukommen. Man kann bspw. dafür sorgen, dass immer erst 15 Minuten nach dem letzten Ausschaltbefehl die Fertigmeldung erfolgt. Oder man legt ein Timeout fest, nach dem die Fertigmeldung auf jeden Fall erfolgt, egal ob der Ausschaltbefehl empfangen wurde oder nicht.
Schön ist das aber nicht. Wenn es zum Beispiel unterschiedliche Waschprogramme gibt, etwa den Schnellwaschgang und die 90° Kochwäsche, dann möchte man in beiden Fällen sinnvolle Meldungen erzeugen und nicht unpräzise Schätzungen.
Mein Skript nutzt eine Handvoll Einstellparameter, um den Durchlauf eines Haushaltsgeräts halbwegs intelligent und sinnvoll zu überwachen. Ich würde mal behaupten, dass man mit noch mehr Komplexität noch genauere Ergebnisse erzielen könnte, aber es sollte so bereits wesentlich besser funktionieren als ein einfaches FMS+Timeout.
Zunächst das Skript:
<?
// es müssen folgende Variablen angelegt und die IDs hier ersetzt werden!
// Variablen für die Mindest- und Höchstdauer eines Durchlaufs, in Minuten (integer)
$minCycleDuration = GetValue(51473 /*[Setup\Fertigmelder\Spülmaschine\Mindestdauer eines Durchlaufs]*/);
$maxCycleDuration = GetValue(56333 /*[Setup\Fertigmelder\Spülmaschine\Höchstdauer eines Durchlaufs]*/);
// Variablen für das Zählen erwarteter Gerätepausen, sowie die längste Pause die nicht als Ende des
// Durchlaufs gewertet werden soll.
// die Anzahl erwarteter Pausen ist wichtig, da nach dem Erreichen dieser Anzahl eine längere Unterbrechung
// (>= $minPauseDuration) als Durchlauf-Ende gewertet wird.
$minPauseDuration = GetValue(27873 /*[Setup\Fertigmelder\Spülmaschine\Mindestdauer einer mitgezählten Pause]*/);
$maxPauseDuration = GetValue(11914 /*[Setup\Fertigmelder\Spülmaschine\Längste zu erwartende Pause]*/);
$expectedPauses = GetValue(42870 /*[Setup\Fertigmelder\Spülmaschine\Anzahl erwarteter Pausen]*/);
// Variablen zum aktuellen Durchlauf. Für $deviceStatusId gelten folgende Werte:
// 0 = läuft nicht
// 1 = läuft
// 2 = läuft, bald fertig (erwartete Anzahl gezählter Pausen erreicht)
// 3 = fertig
$pauseCounterId = 58145 /*[Setup\Fertigmelder\Spülmaschine\Aktueller Durchlauf\Pausenzähler]*/;
$deviceStatusId = 43880 /*[Setup\Fertigmelder\Spülmaschine\Aktueller Durchlauf\Gerätestatus]*/;
$cycleStartTimeId = 11819 /*[Setup\Fertigmelder\Spülmaschine\Aktueller Durchlauf\Startzeitpunkt des Durchlaufs]*/;
$pauseStartTimeId = 19857 /*[Setup\Fertigmelder\Spülmaschine\Aktueller Durchlauf\Startzeitpunkt der letzten Pause]*/;
function deviceIsDone()
{
// hier die Fertigmeldung auslösen!
}
// ab hier nichts mehr ändern!
$deviceStatus = GetValue($deviceStatusId);
$pauses = GetValue($pauseCounterId);
if($_IPS['SENDER'] == 'Variable')
{
$rawState = $_IPS['VALUE'];
switch($deviceStatus)
{
case 3: // fertig
case 0: // läuft nicht
if($rawState) // neuer Durchlauf beginnt
{
SetValue($cycleStartTimeId, time());
$pauses = 0;
$deviceStatus = 1;
IPS_SetScriptTimer($_IPS['SELF'], $maxCycleDuration * 60);
}
break;
case 1: // läuft
case 2: // läuft, bald fertig
if($rawState) // Pause zu ende
{
$thisPauseDuration = time() - GetValue($pauseStartTimeId);
if($thisPauseDuration >= $minPauseDuration * 60)
{
$pauses++;
if($pauses >= $expectedPauses && $expectedPauses > 0)
{
$deviceStatus = 2;
}
}
$remainingTimeout = $maxCycleDuration * 60 -
(time() - GetValue($cycleStartTimeId));
if($remainingTimeout > 0)
IPS_SetScriptTimer($_IPS['SELF'], $remainingTimeout);
else
IPS_RunScript($_IPS['SELF']);
}
else // Pause beginnt
{
SetValue($pauseStartTimeId, time());
if($pauses >= $expectedPauses)
IPS_SetScriptTimer($_IPS['SELF'], $minPauseDuration * 60);
else
IPS_SetScriptTimer($_IPS['SELF'], $maxPauseDuration * 60);
}
break;
}
}
else // timeout durch zu lange Gesamtdauer des Durchlaufs, zu lange Pause bzw. am regulären Ende des Durchlaufs
{
if($deviceStatus == 1 || $deviceStatus == 2)
{
// falls Mindestdauer des Durchlaufs noch nicht erreicht ist, zurücksetzen ohne Fertigmeldung!
if(time() - GetValue($cycleStartTimeId) < $minCycleDuration)
{
$deviceStatus = 0;
IPS_SetScriptTimer($_IPS['SELF'], 0);
}
else
{
$deviceStatus = 3;
IPS_SetScriptTimer($_IPS['SELF'], 0);
deviceIsDone();
}
}
else if($deviceStatus == 3) $deviceStatus = 0;
}
SetValue($deviceStatusId, $deviceStatus);
SetValue($pauseCounterId, $pauses);
?>
Um das Skript nutzen zu können, muss zunächst die Variable (boolean) des FMS (oder anderem Gerät ähnlicher Funktionsweise) geloggt werden, so dass man sich einen Eindruck von der Durchlauflänge, den Pausen etc. machen kann.
Hierzu macht es Sinn, zunächst einige Durchläufe mitzuloggen, bevor man das Skript in Betrieb nimmt. Um es in Betrieb zu nehmen, hängt man ein Ereignis an, das auf Änderung der Fertigmelder-Statusvariable reagiert.
Anschließend sollte man anhand der Kurve der Fertigmelder-Variable im Webfront Pausenzeiten und -anzahl einstellen (hierzu die Konfigurationsvariablen verwenden). Sinnvollerweise visualisiert man diese im Webfront.
Um den Gerätestatus zurückzusetzen, muss das Skript einmal manuell z.B. aus dem Webfront aufgerufen werden.