Ab und zu möchte man eine Aktion programmieren, die erst zu einem späteren Zeitpunkt ausgeführt werden soll. Z.B. das Heimkino ausfahren…
Die naheliegende Lösung ist die Funktion IPS_Sleep(). Doch bekanntlich darf man die nicht verwenden für Verzögerungen länger als eine Sekunde.
Die „offizielle“ Lösung wird auf http://www.ip-symcon.de/service/dokumentation/vorgehensweisen/wie-kann-ich/ erklärt. Aber wirklich anfreunden konnte ich damit nie - ist mir ehrlich gesagt viel zu fummlig.
Wie schön wäre es doch, man hätte eine Lösung von der Eleganz und Einfachheit von IPS_Sleep()…
Nun, hier ist sie…
Zunächst das Beispiel eines Aufrufs:
<?
include('mylib.php');
exec_delayed("+10 sec", 'mylog("done");');
?>
Davor und danach kann selbstverständlich beliebiger anderer Code stehen, wie bei IPS_Sleep() auch.
mylib.php
Sehr oft hat man ja irgend eine Datei mit allerlei hilfreichen Funktionen.
Im Beispiel hier wäre das die Datei ‚mylib.php‘. Darin ist z.B. die Hilfsfunktion ‚mylog()‘, aber natürlich auch exec_delayed() selbst, sowie einige weitere. Die Idee ist, dass jeder die Library nach seinen Ansprüchen zurechtschneidert bzw. erweitert.
exec_delayed($delay /sec/, $code)
$delay kann entweder ein Integer sein (=Zeit in Sekunden) oder ein String, wie er von strtotime() interpretiert werden kann.
Damit ist fast alles möglich, wie „+10 Min“ oder „19:31“ etc.
$code enthält den auszuführenden Code.
Beachte: der Daemon lädt vorher automatisch mit ‚require_once(‚mylib.php‘);‘ die Library, das muss man also nicht mehr selber tun.
clear_scheduled_tasks()
→ löscht alle Aufträge, welche von diesem Script bisher aufgegeben worden sind.
Setzt man also diesen Aufruf vor exec_delayed(), so hat man eine Art „retriggerbares“ Verhalten.
clear_all_scheduled_tasks()
→ löscht sämtliche Aufträge, egal von welchem Script aufgegeben.
Zu beachten:
In der mylib.php muss man die erste Zeile anpassen, $daemon_id muss die IPS-ID des Ausführungs-Scriptes ‚DelayedExec_Daemon.php‘ enthalten.
Installation
[ol]
[li]an geeigneter Stelle im Objektbaum ein Script erzeugen mit dem Code von DelayedExec_Daemon.php
[/li][li]die Datei mylib.php ins Verzeichnis scripts\ kopieren (ggf. auch als Script in den Objektbaum einfügen)
[/li][li]die ObjektID des DelayedExec_Daemon’s in mylib.php einsetzen
[/li][li]Test-Script ausführen.
[/li][/ol]
Funktionsweise
exec_delayed() schreibt den Code in eine temporäre Variable unterhalb des DelayedExec_Daemon’s.
Ausserdem erzeugt es einen Timer für die gewünschte Zeit, welcher den DelayedExec_Daemon aufweckt.
Der DelayedExec_Daemon checkt alle Code-Variablen und prüft, ob deren Aufrufzeit erreicht (bzw. überschritten) ist, führt den Code aus und löscht Variable und Timer.
Viel Erfolg!
Dieter
mylib.php
<?
$daemon_id = 0; /* Modify: replace with ID of Daemon */
//-------------------------------------------------------------------------
function exec_delayed($delay /*sec*/, $code) {
global $daemon_id, $IPS_SELF;
$callers_name = getObjName($IPS_SELF);
if (is_string($delay)) {
$delay = intval(strtotime($delay)-time());
if ($delay < 0) {
$delay += 86400;
}
}
if (!$daemon_id) {die("you need to set \$daemon_id first.");}
$varname = date('Y_m_d_H_i_s', time()+$delay);
$code .= " /*origin: $callers_name*/";
$vID = IPS_CreateVariable(3);
IPS_SetParent($vID, $daemon_id);
IPS_SetName($vID, $varname);
SetValueString($vID, $code);
$eid = IPS_CreateEvent(1);
IPS_SetParent($eid, $daemon_id);
IPS_SetName($eid, "T{$varname}_$callers_name");
IPS_SetEventScript($eid, $daemon_id);
IPS_SetEventCyclic($eid, 0,0,0,0,1,$delay);
IPS_SetEventActive($eid, true);
if (strlen($code) > 40) {
$code = substr($code, 0, 37).'...';
}
if ($delay < 600) {
mylog(">>> Cmd delayed for {$delay}s: $code");
} else {
mylog(">>> Cmd due at ".date('Y-m-d H:i:s', time()+$delay).": $code");
}
} // exec_delayed
//-------------------------------------------------------------------------
function clear_scheduled_tasks() {
global $daemon_id, $IPS_SELF;
$identifier = "($IPS_SELF)";
$vars = IPS_GetChildrenIDs($daemon_id);
foreach ($vars as $id) {
$obj = IPS_GetObject($id);
if ($obj['ObjectType'] == 2) { // Variable
$code = GetValueString($id);
if ($code && (strpos($code, $identifier) !== false)) {
IPS_DeleteVariable($id);
}
} elseif ($obj['ObjectType'] == 4) { // Event
if (strpos($obj['ObjectName'], $identifier) !== false) {
IPS_DeleteEvent($id);
}
}
}
mylog("Scheduled actions cleared for ".getObjName($IPS_SELF));
} // clear_scheduled_tasks
//-------------------------------------------------------------------------
function clear_all_scheduled_tasks() {
global $daemon_id;
$vars = IPS_GetChildrenIDs($daemon_id);
foreach ($vars as $id) {
$obj = IPS_GetObject($id);
if ($obj['ObjectType'] == 2) {
IPS_DeleteVariable($id);
} elseif ($obj['ObjectType'] == 4) {
IPS_DeleteEvent($id);
}
}
mylog("All scheduled actions cleared");
} // clear_all_scheduled_tasks
//-----------------------------------------------------------------------
function mylog($text) {
global $IPS_SELF;
$objID = IPS_GetObject($IPS_SELF);
$scriptName = $objID['ObjectName'];
IPS_LogMessage($scriptName, $text);
} // mylog
//-------------------------------------------------------------------------
function getObjName($id = false) {
global $IPS_SELF;
if ($id == false) {
$id = $IPS_SELF;
}
$obj = IPS_GetObject($id);
$parentOjb = IPS_GetObject($obj['ParentID']);
return "{$parentOjb['ObjectName']}/{$obj['ObjectName']}($id)";
} // getObjName
?>
DelayedExec_Daemon
<?
// DelayedExec_Daemon
$now = date('Y_m_d_H_i_s');
$vars = IPS_GetChildrenIDs($IPS_SELF);
foreach ($vars as $id) {
$obj = IPS_GetObject($id);
if ($obj['ObjectType'] == 2) { // Variable
if ($now > substr($obj['ObjectName'],0,19)) {
$code = GetValueString($id);
if ($code) {
if (substr($code,-1) != ';') {
$code = $code.';';
}
require_once('mylib.php');
eval($code);
}
IPS_DeleteVariable($id);
}
} elseif ($obj['ObjectType'] == 4) { // Event
if (substr($obj['ObjectName'],0,20) < 'T'.$now) {
IPS_DeleteEvent($id);
}
}
}
?>