Tonis Bastelkeller - Simple Zeitschaltuhr mit PHP

Hi Community,

manchmal muss man einfach nur etwas zeitabhängig steuern. Dafür gibt es in IPS gefühlte 273 Möglichkeiten. Aber wenn es um mehrere Ein und Aus Befehle zu unterschiedlichen Zeiten geht wird die Angelegenheit schnell unübersichtlich. Inspiriert durch diesen Thread von Andre, wir sind quasi Nachbarn aber nicht persönlich bekannt :), hab ich mir mal ein Thema für diese kleine Bastelstunde auf Anfängerniveau ausgedacht. Die IPSLibrary, auf der Andre’s Projekt basiert, ist eine umfangreiche und mächtige Scriptsammlung. Mehr als das. Aber grad dem Anfänger ist dieses „Codemonster“ oft nicht geheuer und oft einfach zu kompliziert in der Handhabung. Hier also meine kleine Alternative.

Diese kleine und kompakte Zeitschaltuhr hat zwar keine so schicke Bedienoberfläche aber mal ehrlich. Wie oft kommt es vor dass man eine Zeitschaltuhr programmiert? Die von meinem Terrarium fasse ich zwei mal im Jahr an, immer zur Zeitumstellung, die von meiner Kläranlage hab ich noch nie verstellt und die Heizung? Ja, wenn man da nur durchsteigen würde… Selbst die für die Weihnachtsbeleuchtung ist jedes Jahr auf die selben Zeiten programmiert. Brauchen wir alles nicht. Dafür kommt meine Version vollkommen mit Bordmitteln aus und ist sehr leicht installiert und getestet. Ideal für Einsteiger und Puristen.

Als Erstes hab ich mir mal überlegt wie man „das Programm“ der Zeitschaltuhr möglichst einfach, übersichtlich und vor Allem für Laien verständlich festlegen kann. Ich hab mich für einen Programmblock in Form eines Arrays entschieden. Das schöne daran ist, dass man nicht verstehen muss was genau die Zeichen in dieser Zeile bedeuten. Man muss nur eine Zeile kopieren und wiederverwenden. Und so sieht sie aus:


0  => array(10, 20, 'Ein'),
1  => array(12, 00, 'Aus', 'MoMiFrSo'),
2  => array(14, 00, 'Aus', 'DiDoSa')

Ganz vorne steht die Programmnummer beginnend mit der Null, wie beim Programmieren üblich. Der kleine Pfeil (=>) ist Array-Syntax und muss genau so aussehen. Einfach nix bei denken. Danach folgt ein Array mit drei Werten: Die Stunde, die Minute und der Befehl. Diese Zeile lässt also unsere Zeitschaltuhr jeden Tag um 10:20 Uhr etwas einschalten. Am Ende kommt ein Komma, dass diese Zeile von der Nächsten trennt. PHP braucht das so, denn man könnte auch alles in eine einzige Zeile schreiben. Das wäre aber ziemlich unübersichtlich - für uns, nicht für PHP. In die letzten Zeile kommt kein Komma, weil ja nichts mehr getrennt werden muss.

Um der ganzen Geschichte noch ein wenig mehr Flexibilität zu spendieren kann man, wenn man will, noch Wochentage definieren an denen diese Zeile Gültigkeit hat. Dabei ist es egal ob man die Wochentage durch Leerzeichen und/oder Komma trennt. Ich mag es so. In diesen drei Zeilen würde also die Uhr Montags, Mittwochs, Freitags und Sonntags um 12 Uhr abschalten und an den anderen Tagen erst um 14 Uhr.

Ich hab extra ‚Ein‘ und ‚Aus‘ auf deutsch ausgeschrieben, damit es leichter verständlich ist. Programmierer würden hier sicher einen boolschen Ausdruck (true oder false) bevorzugen. Von diesen Zeilen können beliebig viele untereinander weg getippt werden. Jede natürlich mit fortlaufender Programmnummer und bitte in der richtigen zeitlichen Abfolge. Also Morgens, Mittags, Abends und nicht durcheinander. Dabei spielt der Wochentag keine Rolle. Das ist wichtig. Weiter unten ist ein ausführlicheres Beispiel. Man hätte es auch anders lösen können aber das Script sollte ja möglichst einfach bleiben, ne? :wink:

Dann gibt es die Ein- und die Ausschaltfunktionen in der definiert ist was genau unsere Uhr eigentlich schalten soll. Die sehen sich sehr ähnlich und das sollen sie auch.

function Einschalten()
{
  // Hier wird definiert was alles eingeschaltet werden soll. 
  setValue(38797 /*[OPC Bool Test]*/, true);
  LPT_SetPin(1, 1, true);
}

Ich hab hier einfach mal eine Variable geändert, die mir anzeigt ob die Uhr gerade ein- oder ausgeschaltet ist. Ist sicher Geschmackssache und kann man halten wie man will. Es können noch beliebig viele zusätzliche Befehle ausgeführt werden. Etwas handfestes wie zum Beispiel ein Relais einer Relaiskarte einschalten. In der Ausschalten-Funktion analog dazu alles wieder zurück setzen.

Das volle Script:


<?
// Zeitschaltuhr
// -----------------------------------------------------------------------------

  $timer = array(
    0  => array(08, 30, 'Ein', 'MoDiMiDoFr'),
    1  => array(10, 00, 'Ein', 'SaSo'),
    2  => array(12, 00, 'Aus', 'MoDiMiDoFrSaSo'),
    3  => array(17, 00, 'Ein'),
    4  => array(19, 00, 'Aus')  // Letzte Zeile - kein Komma
  );
  // Hier wird etwas Werktags um 8:30 Uhr eingeschaltet und am Wochenende erst um 10. 
  // Ausgeschaltet wird es in jedem Fall um 12 Uhr. 
  // Ebenfalls jeden Tag wird es um 17 Uhr für 2 Stunden eingeschaltet.

  
// -----------------------------------------------------------------------------

function Einschalten()
{
  // Hier wird definiert was alles eingeschaltet werden soll. 
  setValue(38797 /*[OPC Bool Test]*/, true);
  LPT_SetPin(1, 1, true);
}

// -----------------------------------------------------------------------------

function Ausschalten()
{
  // Hier alles wieder ausschalten.
  setValue(38797 /*[OPC Bool Test]*/, false);
  LPT_SetPin(1, 1, false);
}
  
  
// -------------------------------------------------------------------------- \\
// ------------------------- Ab hier Finger weg! ---------------------------- \\
// -------------------------------------------------------------------------- \\

  $Wochentage = array('So','Mo','Di','Mi','Do','Fr','Sa');

  $EventID=0;
  $Eventlist = IPS_GetEventList();
  // Wir suchen uns aus allen IPS-Events unsere EventID herraus...
  for ($i=0; $i<count($Eventlist); $i++)
  {
	 if (IPS_GetParent($Eventlist[$i]) == $_IPS['SELF'])
	   $EventID=$Eventlist[$i];
  }
  // ...Es gibt keine? Dann bauen wir uns eine Neue.
  if ($EventID == 0)
  {
    $EventID=IPS_CreateEvent(1);
    IPS_SetEventCyclic($EventID, 0, 0, 0, 0, 0, 0);
    IPS_SetParent($EventID, $_IPS['SELF']);
    IPS_SetEventActive($EventID, true);
  }
  
  // Ab hier wirds interessant
  $NeuerTimerGesetzt=false;
  for ($i=0; $i<count($timer); $i++)
  {
	// soll heute ein Timer ausgeführt werden...
	$RunToday = true;
    if (count($timer[$i]) > 3)
      if (strpos(strtoupper($timer[$i][3]), strtoupper($Wochentage[date("w")])) === false)
        $RunToday = false;
        
    // ... und müsste er genau jetzt ein Ereignis ausgelösen?
	if ( $RunToday && ( date('H:i') == date('H:i', mktime($timer[$i][0], $timer[$i][1], 0)) ) )
	{
	  // Wenn ja, Welches?
	  if (strtoupper($timer[$i][2]) == 'EIN')
	    Einschalten();
	  else
	    Ausschalten();
	}
	 
    // nächsten Timer für heute setzen
	if ( (time() < mktime($timer[$i][0], $timer[$i][1], 0)) && ($NeuerTimerGesetzt == false) )
	{
      IPS_SetEventCyclicTimeBounds($EventID, mktime($timer[$i][0], $timer[$i][1], 0), 0);
      $NeuerTimerGesetzt=true;
	}
  }
  
  // Wenn wir für heute alle Timer durch haben fangen wir für den nächsten Tag wieder beim Ersten an.
  if ($NeuerTimerGesetzt == false)
    IPS_SetEventCyclicTimeBounds($EventID, mktime($timer[0][0], $timer[0][1], 0), 0);
?>

Das ist dann auch schon Alles. Am weiteren Code braucht normal keine Änderung mehr vorgenommen werden. Das Script installiert sich quasi selbst nachdem ihr es einmal im Editor mit dem Ausführen-Button angestoßen habt. Die Fitteren unter Euch dürfen es gerne noch erweitern, auch wenn ich „Finger weg“ geschrieben hab ;). Wie so oft beim Programmieren sind der Phantasie hier kaum Grenzen gesetzt.

Viel Spaß damit,

Toni

Hallo Toni,

perfekt.

Es fehlen nur noch die Wochentage im Array die geschalten werden sollen.

0 => array( 14, 30, ‚Ein‘, 1, 2, 3, 4, 5, 6, 7 ), oder etwas ähnliches

Hab ich mal nachgepflegt :slight_smile:

Toni

Perfekt

werde ich heute testen.

Danke

Danke für das Script.

Ein kleines Problem:
Wird eine Schaltzeit zwischen 08:00 und 09:59 mit führenden Nullen eingegeben, wird die Stundeneingabe als Oktalzahl interpretiert und auf 00 gesetzt.

Lösung:
Führende Nullen bei den Stunden und Minuten weglassen oder Werte in ’ ’ setzen.


$timer = array(
    0  => array('08', '30', 'Ein', 'MoDiMiDoFr'),
    1  => array('10', '00', 'Ein', 'SaSo'),
    2  => array('12', '00', 'Aus', 'MoDiMiDoFrSaSo'),
    3  => array('17', '00', 'Ein'),
    4  => array('19', '00', 'Aus')  // Letzte Zeile - kein Komma

Erwin

Hat Dich der Weihnachtsrummel geweckt? Grins

Schau mal hier, bevor Du Dir weiter den Kopf zerbrichst.

Viel Spaß

Danke für die Info.

…und nein, geweckt wurde ich nicht. :slight_smile: Ich schalte nur die Weihnachtsbeleuchtung um 09:00 aus.

Könnte man bei der Doku zum Wochenplan nicht noch Schaltuhr/Wochenschaltuhr für die leichtere Auffindbarkeit hinterlegen?

Gruess
Erwin