Fangen wir mit einem zentralen Element meines smartHome Systems an, der Software-Zeitschaltuhr.
Angefangen beim Licht über die Heizung bis hin zu Aquarienpumpen gibt es jede Menge Dinge die wir per festen Zeitplan schalten wollen.
Man kann dafür natürlich eine „normale“ Zeitschaltuhr nutzen oder moderner den Cron-Daemon von Linux nutzen, ich brauche aber eine Lösung die sich per Browser bedienen lässt und halbwegs ansprechend ist.
Da mein UI auf bootstrap 3 beruht habe ich mir passende plugins für die Datum und Zeiteingabe gesucht.
Für das Datum nutze ich folgenden Datepicker und für die Zeiteingabe diesen Timepicker.
Im ersten Schritt werden die Schaltzeiten dann in eine mysql-Datenbank übertragen.
Danach übernimmt ein python-Programm die weitere Arbeit.
Ich arbeite dazu mit diesem scheduler, der läuft mit python 3.4 sowohl unter Linux & Windows, damit ideal für mich.
Das python-Programm kann entweder zentral auf einem Server laufen oder auf einem extra Raspberry Pi.
Ich habe mich da noch nicht entschieden.
Tatsache ist aber, das alle Teile der Zeitschaltuhr locker auf ein und demselben Raspberry Pi laufen können, das liegt alleine an euch.
Okay, nachdem sich das python-Programm die Schaltzeiten aus der mysql-Datenbank geholt hat werden diese in den scheduler eingetragen und selbiger gestartet.
Wenn eine Schaltzeitpunkt erreicht wird sendet das python-Programm einfach den entsprechenden Befehl über das websockets Protokoll oder führt ihn selbst aus, daran arbeite ich noch.
Aktuell habe ich jetzt erst einmal eine halbwegs funktionierende Oberfläche zur Eingabe der Schaltzeiten fertig.
Das Eintragen in eine mysql-Datenbank per php funktioniert auch schon mal halbwegs.
In den nächsten Tagen werde ich jetzt versuchen das python-Programm soweit fertig zu bekommen das der scheduler läuft.
Design Entwurf
Folgendermaßen stelle ich mir den Ablauf vor:
Grundsätzlich benötige ich zwingend nur ein Start-Datum sowie eine Einschalt- und eine Ausschalt-Zeit.
Deshalb werden im Anfangszustand nur diese Felder gezeigt, das Ende-Datum ist bei der Option „einmalig“ nicht wählbar.
Möchte man einen Schaltplan der sich regelmäßig wiederholt, dann hat man 2 x Optionen.
Die erste Möglichkeit besteht darin „Intervall“ auszuwählen, danach erscheinen dann die dazu passenden Eingabefelder.
Hier ist es ein Feld zur Angabe des Wertes (1 – x) und eine Auswahlbox mit den Einheiten (Minuten, Stunden, …).
Ein Beispiel, für eine tägliche Wiederholung würde man eine „1“ eintragen und „Tage“ auswählen.
Die zweite Möglichkeit besteht darin „Wochentage“ zu wählen. Damit kann man dann einen Wochenplan erstellen indem man die einzelnen Wochentage auswählt, an welchem der Schaltplan ausgeführt werden soll.
Soll er nur an Wochenende ausgeführt werden, dann wählt man einfach Samstag und Sonntag aus.
Bei beiden Möglichkeiten besteht die Möglichkeit ein Ende-Datum auszuwählen, ansonsten läuft das Programm quasi ewig.
Dazu nur die Checkbox anklicken und schon erscheint ein neues Datum-Feld.
Anbei Schreenshots
Der nächste Eintrag wird sich dann mit dem python-Programm befassen.
Über konstruktive Kritik, Verbesserungsvorschläge oder noch besser über eure Mitarbeit würde ich mich wie immer sehr freuen.
Am Ende findet Ihr nochmal den html & php Sourcecode.
Der Code ist aber noch nicht „sauber“ und „responsive design“ muss auch noch rein.
Ist aber schon mal eine erster Prototype.
<!DOCTYPE html> <html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content=""> <meta name="author" content=""> <link rel="icon" href="http://getbootstrap.com/favicon.ico"> <title>smartHome Zeitschaltuhr</title> <link href='http://fonts.googleapis.com/css?family=Open+Sans:400,300,600,700,800' rel='stylesheet' type='text/css'> <link href='http://fonts.googleapis.com/css?family=Oswald:400,300,700' rel='stylesheet' type='text/css'> <link href="../css/bootstrap.css" rel="stylesheet"> <link href="../css/custom.css" rel="stylesheet"> <link href="../css/bootstrap-clockpicker.min.css" rel="stylesheet" type="text/css"> <link href="../css/bootstrap-datepicker3.min.css" rel="stylesheet" type="text/css"> <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> <![endif]--> <style type="text/css"> .clockpicker { width: 125px; margin-right: 0px; margin-left: auto; } .row-eq-height { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; } .text_v_center { vertical-align: bottom; line-height: 100%; margin-top: auto; margin-bottom: auto; } .schaltplan-dauer { margin: 0px; padding: 0px; } .no_padding { padding: 0px; } .no_margin { margin: 0px; } </style> </head> <body> <!--Pseudo-Navigationsleiste mit Menu-Button und Anzeige des aktuellen Menu's--> <nav class="navbar-inverse navbar-fixed-top"> <a href="#menu-toggle" class="navbar-toggle" id="menu-toggle"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </a> <div class="navbar-brand">Zeitschaltuhr</div> </nav> <!--Hier beginnt die eigentliche Seite mit dem Inhalt--> <div id="content-wrapper"> <div class="container"> <!--die erste "Zeile" mit den wichtigsten Anzeigen--> <h1>Schaltplan - Neu</h1> <form data-toggle="validator" role="form" method="post" action="new.php"> <div class="row"> <div class="col-lg-6 col-md-6 main-value"> <fieldset> <legend></legend> <div class="row form-group row-eq-height"> <label for="startDatum" class="col-sm-4 control-label text_v_center">Datum:</label> <div class="input-group date col-sm-3"> <input type="text" id="startDatum" class="form-control" name="schaltplanStartDatum" pattern="(0[1-9]|[12][0-9]|3[01])\.(0[1-9]|1[012])\.(19|20)\d\d" required><span class="input-group-addon"><i class="glyphicon glyphicon-th"></i></span> </div> </div> <div class="row form-group row-eq-height"> <label for="startUhrzeit" class="col-sm-4 control-label text_v_center">Uhrzeit:</label> <div class="col-sm-3 no_padding"> <div class="input-group clockpicker"> <input type="text" class="form-control" id="startUhrzeit" name="schaltplanStartUhrzeit" pattern="^(0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$" required><span class="input-group-addon"><i class="glyphicon glyphicon-time"></i></span> </div> </div> <label for="endeUhrzeit" class="col-sm-1 control-label text_v_center">bis</label> <div class="col-sm-3 no_padding"> <div class="input-group clockpicker"> <input type="text" class="form-control" id="endeUhrzeit" name="schaltplanEndeUhrzeit" pattern="^(0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$" required><span class="input-group-addon"><i class="glyphicon glyphicon-time"></i></span> </div> </div> </div> <div class="row"> <label class="col-sm-4 control-label">Dauer</label> <div class="col-sm-8"> <div class="form-group schaltplan-dauer"> <label class="radio-inline"><input name="schaltplanDauerOption" checked id="optionsRadios1" value="einmalig" type="radio">einmalig</label> </div> <div class="form-group schaltplan-dauer"> <label class="radio-inline"><input name="schaltplanDauerOption" id="optionsRadios2" value="intervall" type="radio">Intervall</label> </div> <div class="form-group"> <label class="radio-inline"><input name="schaltplanDauerOption" id="optionsRadios3" value="wochentag" type="radio">Wochentag</label> </div> </div> </div> <fieldset id="fieldsetEndeDatum" disabled> <div class="row form-group row-eq-height"> <label for="endeDatum" class="col-sm-4 control-label text_v_center"><input type="checkbox" id="check_ende" class="text_v_center" name="schaltplanEndeDatumCheckbox" value="true"> Ende-Datum:</label> <div class="input-group date col-sm-3 hidden" id="check_ende_div"> <input type="text" id="endeDatum" class="form-control" name="schaltplanEndeDatum" pattern="(0[1-9]|[12][0-9]|3[01])\.(0[1-9]|1[012])\.(19|20)\d\d"><span class="input-group-addon"><i class="glyphicon glyphicon-th"></i></span> </div> </div> </fieldset> </fieldset> </div> <div class="col-lg-6 col-md-6 main-value"> <fieldset id="interval" class="hidden"> <legend></legend> <div class="row form-group row-eq-height"> <label for="wiederholungWert" class="col-sm-4 control-label text_v_center">wiederhole alle:</label> <div class="input-group col-sm-2"> <input type="number" id="wiederholungWert" class="form-control" value="0" name="schaltplanIntervallWert"> </div> <div class="col-sm-3"> <select class="form-control" name="schaltplanIntervallEinheit"> <option>Minuten</option> <option>Stunden</option> <option>Tage</option> <option>Wochen</option> </select> </div> </div> </fieldset> <fieldset id="wochentag" class="hidden"> <legend></legend> <div class="row"> <div class="col-xs-4"> <div class="checkbox"><label><input type="checkbox" value="true" name="schaltplanWochentagMontag">Montag</label></div> </div> <div class="col-xs-4"> <div class="checkbox"><label><input type="checkbox" value="true" name="schaltplanWochentagDienstag">Dienstag</label></div> </div> <div class="col-xs-4"> <div class="checkbox"><label><input type="checkbox" value="true" name="schaltplanWochentagMittwoch">Mittwoch</label></div> </div> </div> <div class="row"> <div class="col-xs-4"> <div class="checkbox"><label><input type="checkbox" value="true" name="schaltplanWochentagDonnerstag">Donnerstag</label></div> </div> <div class="col-xs-4"> <div class="checkbox"><label><input type="checkbox" value="true" name="schaltplanWochentagFreitag">Freitag</label></div> </div> <div class="col-xs-4"> <div class="checkbox"><label><input type="checkbox" value="true" name="schaltplanWochentagSamstag">Samstag</label></div> </div> </div> <div class="row"> <div class="col-xs-4"> <div class="checkbox"><label><input type="checkbox" value="true" name="schaltplanWochentagSonntag">Sonntag</label></div> </div> </div> </fieldset> <fieldset> <legend></legend> <button type="submit" name="submit" class="btn btn-primary">Schaltplan anlegen</button> </fieldset> </div> </div> </form> </div> </div> <!-- Bootstrap core JavaScript ================================================== --> <!-- Placed at the end of the document so the pages load faster --> <script src="../js/jquery.min.js"></script> <script src="../js/bootstrap.min.js"></script> <script src="../js/bootstrap-clockpicker.min.js"></script> <script src="../js/bootstrap-datepicker.min.js"></script> <script src="../js/validator.js"></script> <!-- IE10 viewport hack for Surface/desktop Windows 8 bug --> <script src="../js/ie10-viewport-bug-workaround.js"></script> <script type="text/javascript"> $('.clockpicker').clockpicker({ donetext: 'Fertig', 'default': 'now' }); $('.input-group.date').datepicker({ format: "dd.mm.yyyy", language: "de", orientation: "top auto", autoclose: true }); $("#check_ende").click(function() { $("#check_ende_div").toggleClass('hidden'); }); $("#optionsRadios1").click(function() { $("#fieldsetEndeDatum").prop("disabled", true); $("#interval").prop("disabled", true); $("#interval").addClass('hidden'); $("#wochentag").prop("disabled", true); $("#wochentag").addClass('hidden'); }); $("#optionsRadios2").click(function() { $("#fieldsetEndeDatum").prop("disabled", false); $("#interval").prop("disabled", false); $("#interval").removeClass('hidden'); $("#wochentag").prop("disabled", true); $("#wochentag").addClass('hidden'); }); $("#optionsRadios3").click(function() { $("#fieldsetEndeDatum").prop("disabled", false); $("#interval").prop("disabled", true); $("#interval").addClass('hidden'); $("#wochentag").prop("disabled", false); $("#wochentag").removeClass('hidden'); }); </script> </body></html>
<?php include('connect.php'); if (isset($_POST["submit"])) { $schaltplanStartDatum = $_POST['schaltplanStartDatum']; $schaltplanStartUhrzeit = $_POST['schaltplanStartUhrzeit']; $schaltplanEndeUhrzeit = $_POST['schaltplanEndeUhrzeit']; $schaltplanDauerOption = $_POST['schaltplanDauerOption']; if ($_POST['schaltplanEndeDatumCheckbox']=="true") { $schaltplanEndeDatumCheckbox=1; } else { $schaltplanEndeDatumCheckbox=0; } if (!$_POST['schaltplanEndeDatum']) { $err="Ende Datum"; } else { $schaltplanEndeDatum = $_POST['schaltplanEndeDatum']; } switch ($schaltplanDauerOption) { case 'einmalig': $schaltplanIntervallWert = 0; $schaltplanIntervallEinheit = ''; $schaltplanWochentagMontag = 0; $schaltplanWochentagDienstag = 0; $schaltplanWochentagMittwoch = 0; $schaltplanWochentagDonnerstag = 0; $schaltplanWochentagFreitag = 0; $schaltplanWochentagSamstag = 0; $schaltplanWochentagSonntag = 0; break; case 'intervall': if (!$_POST['schaltplanIntervallWert']) { $schaltplanIntervallWert = 0; } else { $schaltplanIntervallWert = $_POST['schaltplanIntervallWert']; } $schaltplanIntervallEinheit = $_POST['schaltplanIntervallEinheit']; $schaltplanWochentagMontag = 0; $schaltplanWochentagDienstag = 0; $schaltplanWochentagMittwoch = 0; $schaltplanWochentagDonnerstag = 0; $schaltplanWochentagFreitag = 0; $schaltplanWochentagSamstag = 0; $schaltplanWochentagSonntag = 0; break; case 'wochentag': $schaltplanIntervallWert = 0; $schaltplanIntervallEinheit = ''; if ($_POST['schaltplanWochentagMontag'] == 'true') { $schaltplanWochentagMontag=1; } else { $schaltplanWochentagMontag=0; } if ($_POST['schaltplanWochentagDienstag'] == 'true') { $schaltplanWochentagDienstag=1; } else { $schaltplanWochentagDienstag=0; } if ($_POST['schaltplanWochentagMittwoch']=="true") { $schaltplanWochentagMittwoch=1; } else { $schaltplanWochentagMittwoch=0; } if ($_POST['schaltplanWochentagDonnerstag']=="true") { $schaltplanWochentagDonnerstag=1; } else { $schaltplanWochentagDonnerstag=0; } if ($_POST['schaltplanWochentagFreitag']=="true") { $schaltplanWochentagFreitag=1; } else { $schaltplanWochentagFreitag=0; } if ($_POST['schaltplanWochentagSamstag']=="true") { $schaltplanWochentagSamstag=1; } else { $schaltplanWochentagSamstag=0; } if ($_POST['schaltplanWochentagSonntag']=="true") { $schaltplanWochentagSonntag=1; } else { $schaltplanWochentagSonntag=0; } break; } $connect = mysqli_connect($hostname, $username, $password) or die('Could not connect: ' . mysqli_error()); mysqli_select_db($connect, $database); $query = "INSERT INTO schedulers (start_date, start_time, end_time, end_date_check, end_date, duration_option, intervall_number, intervall_unit, weekday_monday, weekday_tuesday, weekday_wednesday, weekday_thursday, weekday_friday, weekday_saturday, weekday_sunday) VALUES ('".$schaltplanStartDatum."' ,'".$schaltplanStartUhrzeit."' ,'".$schaltplanEndeUhrzeit."',".$schaltplanEndeDatumCheckbox." ,'".$schaltplanEndeDatum."' ,'".$schaltplanDauerOption."',".$schaltplanIntervallWert.",'".$schaltplanIntervallEinheit."',".$schaltplanWochentagMontag.",".$schaltplanWochentagDienstag.",".$schaltplanWochentagMittwoch.",".$schaltplanWochentagDonnerstag.",".$schaltplanWochentagFreitag.",".$schaltplanWochentagSamstag.",".$schaltplanWochentagSonntag.")"; $result = mysqli_query($connect, $query) or die("SQL Error 1: " . mysqli_error()); } ?>