{"id":517,"date":"2015-12-24T09:44:24","date_gmt":"2015-12-24T08:44:24","guid":{"rendered":"http:\/\/chriskrz.selfhost.bz\/?p=517"},"modified":"2020-12-17T11:35:07","modified_gmt":"2020-12-17T10:35:07","slug":"iot-heizungssteuerung-2-web-interface","status":"publish","type":"post","link":"https:\/\/www.rustimation.eu\/index.php\/iot-heizungssteuerung-2-web-interface\/","title":{"rendered":"IoT Heizungssteuerung 2 (Web Interface)"},"content":{"rendered":"<p>Ein Web Interface ist besonders hilfreich, wenn man seinen Pi von unterwegs steuern m\u00f6chte. Ich habe hier eine sehr einfach gehaltene L\u00f6sung f\u00fcr meinen Anwendungsfall <a href=\"http:\/\/www.rustimation.eu\/index.php\/iot-heizungssteuerug-lcd-panel\/\">IoT Heizungssteuerung (LCD Panel)<\/a> erstellt.<br \/>\nDiese L\u00f6sung l\u00e4sst sich beliebig anpassen. Was allerdings noch fehlt, ist ein responsive\u00a0 Design, das auch auf Smartphones und Tablets ohne Zoomen gut aussieht.<\/p>\n<p><a href=\"http:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2015\/12\/rustimation_php.jpg\" rel=\"attachment wp-att-461\"><img loading=\"lazy\" decoding=\"async\" class=\" wp-image-461 aligncenter\" src=\"http:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2015\/12\/rustimation_php.jpg\" alt=\"rustimation_php\" width=\"309\" height=\"505\" \/><\/a><\/p>\n<p>Damit das funktioniert, m\u00fcsst ihr einen Webserver sowie php installieren. Welchen Webserver ihr verwendet ist eigentlich egal. Ich verwende Lighttpd. Er ist relativ schlank und trotzdem leistungsf\u00e4hig. Anleitungen zur Installation gibts im Web zuhauf.<\/p>\n<p><!--more--><\/p>\n<p>Ich habe mich an diese hier gehalten:<a href=\"http:\/\/www.penguintutor.com\/linux\/light-webserver\" target=\"_blank\" rel=\"noopener noreferrer\"> http:\/\/www.penguintutor.com\/linux\/light-webserver<\/a>. Die Anleitung enth\u00e4lt auch die Schritte zur Installation von PHP. Mysql braucht ihr nicht zu installieren. Eine sehr gute Anleitung auf Deutsch gibt es auch bei <a href=\"http:\/\/kampis-elektroecke.de\/?page_id=1626\" target=\"_blank\" rel=\"noopener noreferrer\">Kampis Elektroecke<\/a>.<\/p>\n<p>PHP mag ich nicht besonders. Zumal das Debuggen nicht ganz einfach ist. Hat man einen schwerwiegenderen Fehler gemacht (und sei es nur ein vergessenes Semicolon am Ende einer Programmzeile) gibt es einfach ein wei\u00dfes Browserfenster.<\/p>\n<p>Wem das Editieren mit einem der im Pi eingebauten Editoren (nano, vi) oder auf dem Desktop z.B. mit Idle zu m\u00fchsam ist, dem empfehle ich diesen <a href=\"http:\/\/www.rustimation.eu\/index.php\/einfache-entwicklungsumgebung\/\" target=\"_blank\" rel=\"noopener noreferrer\">Artikel <\/a>hier.<\/p>\n<h3>Programmstruktur<\/h3>\n<p>Okay, ich gebs zu, meine html Skripte sind nicht besonders sch\u00f6n. Au\u00dferdem habe ich aus Bequemlichkeit teilweise mit Frames (gelten als veraltet) gearbeitet und auch noch iFrames dazugemischt.<\/p>\n<p>Im Prinzip gibt es 5 einzelne Seiten, die miteinander \u00fcber die Frame Definitionsseite <em>index.html<\/em> oder das PHP Formular verbunden sind:<\/p>\n<ul>\n<li><em>index.html<\/em> enth\u00e4lt die Frame Definitions<\/li>\n<li><em>top Frame.html<\/em> einen beliebigen Seitenkopf<\/li>\n<li>leftFrame.php das Men\u00fc und die Buttons inklusive einem iFrame, der ein Log der Ein- und ausschaltvorg\u00e4nge anzeigt<\/li>\n<li><em>log.php<\/em> zum Auslesen und anzeigen der vergangenen Schaltvorg\u00e4nge in oben erw\u00e4hntem iFrame<\/li>\n<li><em>set_temp.php<\/em> zum Wegspeichern der Werte nachdem der \"Speichern\" Button geklickt wurde.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<h4>Index.html<\/h4>\n<p>Das Ganze ist wie folgt aufgebaut, zuersteinmal kommt die Datei<strong> <em>index.html<\/em><\/strong> zum Zug, die den Seitenaufbau im Bereich &lt;frameset &#8230;.&gt; bis &lt;\/frameset&gt; definiert. Oben wird ein sch\u00f6ner \u00dcberschriftsbereich namens <em>topFrame.html<\/em> definiert, darunter kommt der eigentliche Eingabebereich <em>leftFrame.php<\/em> und dann noch ein Ausgabebereich <em>set_temp.php<\/em><\/p>\n<pre class=\"scroll:true lang:xhtml mark:11-15 decode:true \" title=\"index.html\">&lt;!DOCTYPE html PUBLIC \"-\/\/W3C\/\/DTD XHTML 1.0 Frameset\/\/EN\" \"http:\/\/www.w3.org\/TR\/xhtml1\/DTD\/xhtml1-frameset.dtd\"&gt;\r\n&lt;html xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\"&gt;\r\n&lt;head&gt;\r\n&lt;meta http-equiv=\"Content-Type\" content=\"text\/html; charset=utf-8\" \/&gt;\r\n&lt;META HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\"&gt;\r\n&lt;META HTTP-EQUIV=\"Expires\" CONTENT=\"-1\"&gt;\r\n\r\n&lt;title&gt;Rustimation Heizung&lt;\/title&gt;\r\n&lt;\/head&gt;\r\n\r\n&lt;frameset rows =\"80,525,*\" cols=\"220\" framespacing=\"0\" frameborder=\"NO\" border=\"0\" &gt;\r\n          &lt;frame src=\"topFrame.html\" name=\"header\" scrolling=\"NO\" title=\"topFrame\" \/&gt;\r\n          &lt;frame src=\"leftFrame.php\" name=\"combos\" scrolling=\"NO\" noresize title=\"leftFrame\" \/&gt;\r\n          &lt;frame src=\"set_temp.php\" name=\"settemp\" scrolling=\"no\" noresize title=\"Temperature\" \/&gt;\r\n&lt;\/frameset&gt;\r\n\r\n&lt;body&gt;\r\n&lt;\/body&gt;&lt;\/noframes&gt;\r\n&lt;\/html&gt;<\/pre>\n<h4>topFrame.html<\/h4>\n<p>Diese Seite hat lediglich eine gestalterische Funktion und kann nach eigenen W\u00fcnschen angepasst werden.<\/p>\n<pre class=\"scroll:true lang:xhtml decode:true \" title=\"topFrame.html\">&lt;!DOCTYPE html PUBLIC \"-\/\/W3C\/\/DTD XHTML 1.0 Transitional\/\/EN\" \"http:\/\/www.w3.org\/TR\/xhtml1\/DTD\/xhtml1-transitional.dtd\"&gt;\r\n&lt;html xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\"&gt;\r\n&lt;head&gt;\r\n&lt;meta http-equiv=\"Content-Type\" content=\"text\/html; charset=utf-8\" \/&gt;\r\n&lt;title&gt;Rustimation&lt;\/title&gt;\r\n&lt;style type=\"text\/css\"&gt;\r\nbody,td,th {\r\n        font-size: 18px;\r\n        font-weight: bold;\r\n        color: #FFFFFF;\r\n}\r\nbody {\r\n        background-color: #003366;\r\n        font-family:Verdana,Arial,Helvetica,sans-serif;\r\n}\r\n&lt;\/style&gt;\r\n&lt;\/head&gt;\r\n\r\n&lt;body&gt;\r\n&lt;div align=\"left\"&gt;\r\n&lt;strong&gt;Rustimation Heizung&lt;\/strong&gt;&lt;br \/&gt;\r\n&lt;p&gt;&lt;strong&gt;served by RaspberryZwei&lt;\/strong&gt;&lt;\/p&gt;&lt;\/div&gt;\r\n&lt;\/body&gt;\r\n\r\n&lt;\/html&gt;<\/pre>\n<h3>LeftFrame.php<\/h3>\n<p>Die wesentlichen Punkte sind unterhalb des Programmlistings erkl\u00e4rt<\/p>\n<pre class=\"height-set:true scroll:true lang:php decode:true \" title=\"leftFrame.php\">&lt;!DOCTYPE html PUBLIC \"-\/\/W3C\/\/DTD XHTML 1.0 Transitional\/\/EN\" \"http:\/\/www.w3.org\/TR\/xhtml1\/DTD\/xhtml1-transitional.dtd\"&gt;\r\n&lt;html xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\"&gt;\r\n&lt;head&gt;\r\n&lt;meta http-equiv=\"Content-Type\" content=\"text\/html; charset=utf-8\" \/&gt;\r\n&lt;title&gt;Raspberry Pi Heizungssteuerung&lt;\/title&gt;\r\n\r\n&lt;style type=\"text\/css\"&gt;\r\nbody {\r\n       background-color: #A6A6A6;\r\n       font-family:Verdana,Arial,Helvetica,sans-serif;\r\n       font-size:12px\r\n    }\r\n&lt;\/style&gt;\r\n&lt;\/head&gt;\r\n\r\n&lt;body&gt;\r\n\r\n&lt;?php\r\n\/\/debug setting\r\nerror_reporting (E_ALL | E_STRICT);\r\nini_set ('display_errors' , 1);\r\n\/\/ Ende Debug\r\n\r\n$filename = \"settings.dat\";\r\n\r\nif (file_exists($filename))\r\n{ \r\n$f=fopen($filename, \"r\");\r\n\r\n   for($i=0;$i&lt;5;$i++)\r\n  {\r\n   $preset[$i]=fgets($f);\r\n  }\r\n  fclose($f);\r\n\r\n  $presetnightstart=trim($preset[0]);\r\n  $presetdaystart=trim($preset[1]);\r\n  $presetdaytemp=trim($preset[2]);\r\n  $presetnighttemp=trim($preset[3]);\r\n\r\n } else\r\n\r\n {\r\n  $presetnightstart=\"22:00\";\r\n  $presetdaystart=  \"06:00\";\r\n  $presetdaytemp=    \"21.0\";\r\n  $presetnighttemp=  \"19.0\";\r\n  echo \"using defaults\";\r\n  \r\n } \r\n?&gt;\r\n\r\n&lt;?php \r\n$act_temp=shell_exec(\"sudo \/home\/pi\/heizung\/get_temperature.py\");\r\n$status = shell_exec(\"cat \/tmp\/status.dat\");\r\n\r\n$timestamp = time();\r\n$datum = date(\"d.m.Y\",$timestamp);\r\n$uhrzeit = date(\"H:i:s\",$timestamp);\r\n?&gt;\r\n\r\n&lt;h3&gt;\r\n&lt;?php echo $datum.\" \".$uhrzeit; ?&gt;&lt;br&gt;\r\nAktuelle Temperatur: &lt;?php echo $act_temp; ?&gt; \u00b0C&lt;br&gt;\r\nPumpe ist &lt;?php echo $status; ?&gt;&lt;br&gt;\r\n&lt;\/h3&gt;\r\n\r\n&lt;form action=\"set_temp.php\" target=\"settemp\" method=\"get\" enctype=\"text\/plain\"&gt;\r\n\r\n&lt;table width=\"220\" border=\"0\"&gt;\r\n &lt;tr&gt;\r\n   &lt;td&gt;&lt;label for=\"nightstart\"&gt;Nachtabsenkung von&lt;\/label&gt;&lt;\/td&gt;\r\n   &lt;td&gt;  &lt;select name=\"nightstart\" style=\"width:75px\"&gt;\r\n\r\n   &lt;option &lt;?php if ($presetnightstart == \"20:00\") echo \"selected\"; ?&gt;&gt;20:00&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetnightstart == \"20:15\") echo \"selected\"; ?&gt;&gt;20:15&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetnightstart == \"20:30\") echo \"selected\"; ?&gt;&gt;20:30&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetnightstart == \"20:45\") echo \"selected\"; ?&gt;&gt;20:45&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetnightstart == \"21:00\") echo \"selected\"; ?&gt;&gt;21:00&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetnightstart == \"21:15\") echo \"selected\"; ?&gt;&gt;21:15&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetnightstart == \"21:30\") echo \"selected\"; ?&gt;&gt;21:30&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetnightstart == \"21:45\") echo \"selected\"; ?&gt;&gt;21:45&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetnightstart == \"22:00\") echo \"selected\"; ?&gt;&gt;22:00&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetnightstart == \"22:15\") echo \"selected\"; ?&gt;&gt;22:15&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetnightstart == \"22:30\") echo \"selected\"; ?&gt;&gt;22:30&lt;\/option&gt;   \r\n &lt;\/select&gt;&lt;\/td&gt;\r\n &lt;\/tr&gt;\r\n &lt;tr&gt;\r\n   &lt;td&gt;&lt;label for=\"daystart\"&gt;Nachtabsenkung bis&lt;\/label&gt;&lt;\/td&gt;\r\n   &lt;td&gt;  &lt;select name=\"daystart\" style=\"width:75px\"&gt;\r\n   &lt;option &lt;?php if ($presetdaystart == \"05:00\") echo \"selected\"; ?&gt;&gt;05:00&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaystart == \"05:15\") echo \"selected\"; ?&gt;&gt;05:15&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaystart == \"05:30\") echo \"selected\"; ?&gt;&gt;05:30&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaystart == \"05:45\") echo \"selected\"; ?&gt;&gt;05:45&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaystart == \"06:00\") echo \"selected\"; ?&gt;&gt;06:00&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaystart == \"06:15\") echo \"selected\"; ?&gt;&gt;06:15&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaystart == \"06:30\") echo \"selected\"; ?&gt;&gt;06:30&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaystart == \"06:45\") echo \"selected\"; ?&gt;&gt;06:45&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaystart == \"07:00\") echo \"selected\"; ?&gt;&gt;07:00&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaystart == \"07:15\") echo \"selected\"; ?&gt;&gt;07:15&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaystart == \"07:30\") echo \"selected\"; ?&gt;&gt;07:30&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaystart == \"07:45\") echo \"selected\"; ?&gt;&gt;07:45&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaystart == \"08:00\") echo \"selected\"; ?&gt;&gt;08:00&lt;\/option&gt;   \r\n &lt;\/select&gt;&lt;\/td&gt;\r\n &lt;\/tr&gt;\r\n  &lt;tr&gt;\r\n   &lt;td&gt;&lt;label for=\"nighttemp\"&gt;Nachttemperatur&lt;\/label&gt;&lt;\/td&gt;\r\n   &lt;td&gt;  &lt;select name=\"nighttemp\" style=\"width:75px\"&gt;\r\n   &lt;option &lt;?php if ($presetnighttemp == \"15.0\") echo \"selected\"; ?&gt;&gt;15.0&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetnighttemp == \"15.5\") echo \"selected\"; ?&gt;&gt;15.5&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetnighttemp == \"16.0\") echo \"selected\"; ?&gt;&gt;16.0&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetnighttemp == \"16.5\") echo \"selected\"; ?&gt;&gt;16.5&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetnighttemp == \"17.0\") echo \"selected\"; ?&gt;&gt;17.0&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetnighttemp == \"17.5\") echo \"selected\"; ?&gt;&gt;17.5&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetnighttemp == \"18.0\") echo \"selected\"; ?&gt;&gt;18.0&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetnighttemp == \"18.5\") echo \"selected\"; ?&gt;&gt;18.5&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetnighttemp == \"19.0\") echo \"selected\"; ?&gt;&gt;19.0&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetnighttemp == \"19.5\") echo \"selected\"; ?&gt;&gt;19.5&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetnighttemp == \"20.0\") echo \"selected\"; ?&gt;&gt;20.0&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetnighttemp == \"20.5\") echo \"selected\"; ?&gt;&gt;20.5&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetnighttemp == \"20.0\") echo \"selected\"; ?&gt;&gt;20.0&lt;\/option&gt;\r\n   \r\n &lt;\/select&gt;&lt;\/td&gt;\r\n &lt;\/tr&gt; \r\n &lt;tr&gt;&lt;td&gt;---------------------&lt;br&gt;&lt;\/td&gt;&lt;\/tr&gt;\r\n &lt;tr&gt;\r\n   &lt;td&gt;&lt;label for=\"daytemp\"&gt;Tagestemperatur&lt;\/label&gt;&lt;\/td&gt;\r\n   &lt;td&gt;  &lt;select name=\"daytemp\" style=\"width:75px\"&gt;\r\n   &lt;option &lt;?php if ($presetdaytemp == \"15.0\") echo \"selected\"; ?&gt;&gt;15.0&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaytemp == \"15.5\") echo \"selected\"; ?&gt;&gt;15.5&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaytemp == \"16.0\") echo \"selected\"; ?&gt;&gt;16.0&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaytemp == \"16.5\") echo \"selected\"; ?&gt;&gt;16.5&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaytemp == \"17.0\") echo \"selected\"; ?&gt;&gt;17.0&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaytemp == \"17.5\") echo \"selected\"; ?&gt;&gt;17.5&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaytemp == \"18.0\") echo \"selected\"; ?&gt;&gt;18.0&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaytemp == \"18.5\") echo \"selected\"; ?&gt;&gt;18.5&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaytemp == \"19.0\") echo \"selected\"; ?&gt;&gt;19.0&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaytemp == \"19.5\") echo \"selected\"; ?&gt;&gt;19.5&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaytemp == \"20.0\") echo \"selected\"; ?&gt;&gt;20.0&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaytemp == \"20.5\") echo \"selected\"; ?&gt;&gt;20.5&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaytemp == \"21.0\") echo \"selected\"; ?&gt;&gt;21.0&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaytemp == \"21.5\") echo \"selected\"; ?&gt;&gt;21.5&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaytemp == \"22.0\") echo \"selected\"; ?&gt;&gt;22.0&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaytemp == \"22.5\") echo \"selected\"; ?&gt;&gt;22.5&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaytemp == \"23.0\") echo \"selected\"; ?&gt;&gt;23.0&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaytemp == \"23.5\") echo \"selected\"; ?&gt;&gt;23.5&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaytemp == \"24.0\") echo \"selected\"; ?&gt;&gt;24.0&lt;\/option&gt;\r\n   &lt;option &lt;?php if ($presetdaytemp == \"24.5\") echo \"selected\"; ?&gt;&gt;24.5&lt;\/option&gt;   \r\n &lt;\/select&gt;&lt;\/td&gt;\r\n &lt;\/tr&gt; \r\n &lt;tr&gt;&lt;td&gt;---------------------&lt;br&gt;&lt;\/td&gt;&lt;\/tr&gt;\r\n&lt;\/table&gt;\r\n\r\n&lt;br&gt;\r\n&lt;div align=\"left\"&gt;\r\n    &lt;input type=\"Submit\" name=\"settemp\" value=\"Einstellung speichern\"&gt;\r\n    &lt;br&gt;&lt;br&gt;\r\n    &lt;input type=\"Reset\" &lt;br&gt;&lt;br&gt;\r\n&lt;\/div&gt;\r\n&lt;br&gt;\r\n\r\n&lt;\/form&gt;\r\n&lt;iframe src=\"log.php\" height=\"200\" width=\"300\" name=\"Historie\" frameborder=\"0\"&gt;&lt;\/iframe&gt;\r\n\r\n&lt;\/body&gt;\r\n&lt;\/html&gt;\r\n<\/pre>\n<p><strong>Was passiert da?<\/strong><br \/>\nNach den Headerinformationen \u00fcber Schriftart und so weiter folgt ein PHP Abschnitt mit einem kurzen Debug Snippet, das wenigstens die gr\u00f6bsten Fehler auswirft.<\/p>\n<p>Dann wird die Datei settings.dat ge\u00f6ffnet und ausgelesen. Ist diese nicht vorhanden, werden Default Werte genommen. Anschlie\u00dfend werden aktuelle Temperatur und\u00a0 aktueller Status ausgelesen.<\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #808080;\">Wenn ihr mit Raspbian Wheezy arbeitet, muss das Python Skript <em>get_temperature.py<\/em> als sudo aufgerufen werden. Das geht aber nicht so ohne weiteres, weil der Webserver-User www-data aus Sicherheitsgr\u00fcnden nicht als sudo arbeiten darf. Deshalb m\u00fcsst ihr eine Ausnahme einstellen. Das geschieht mit dem Befehl <\/span><\/p>\n<pre class=\"lang:default decode:1 inline:1 \">sudo visudo<\/pre>\n<p>.<br \/>\nDort tragt ihr als Letztes <span style=\"color: #808080;\">folgende Zeile ein:<\/span><\/p>\n<pre class=\"lang:default decode:1 inline:1 \">www-data ALL=(ALL) NOPASSWD: \/home\/pi\/heizung\/get_temperature.py<\/pre>\n<p><span style=\"color: #808080;\">(nat\u00fcrlich m\u00fcsst ihr den Pfad eintragen, der zu eurem Python Programm f\u00fchrt.)<\/span><br \/>\n<span style=\"color: #808080;\">Visudo ist nicht ohne. Wenn ihr hier einen Fehler macht, und diesen wegspeichert, kann es sein, dass ihr den Superuser get\u00f6tet habt und so auch keinen sudo mehr verwenden k\u00f6nnt. Visudo ist aber so nett und warnt einen, dass die Datei so nicht funktionieren wird. In diesem Fall lieber abbrechen, kontrollieren und neu eingeben. Mit Strg-X speichert ihr eure Eingabe und kommt auf den Prompt zur\u00fcck.<br \/>\nAll das ist bei Raspbian Jessie nicht mehr n\u00f6tig, der Sensor kann ohne sudo abgefragt werden..<\/span><\/p>\n<p><span style=\"color: #000000;\">Dann kommt der Formularbereich mit den Drop Down Feldern f\u00fcr Temperatur und Uhrzeit. Die vorbelegten bzw. ausgelesenen Parameter f\u00fcr Temperatur- und Nachtzeiteinstellung werden dabei als Voreinstellung \u00fcbernommen. Das Ganze ist etwas m\u00fchsam und mit viel Schreibarbeit verbunden.<\/span><\/p>\n<p>In das Skript ist noch ein iFrame zur Anzeige des Logs eingebettet, welches wir \u00fcber das folgende Skript erzeugen:<\/p>\n<h3>log.php<\/h3>\n<pre class=\"scroll:true lang:php decode:true\" title=\"log.php\">&lt;html&gt;\r\n&lt;style type=\"text\/css\"&gt;\r\n\r\nbody {\r\n       background-color: #A6A6A6;\r\n       font-family:Verdana,Arial,Helvetica,sans-serif;\r\n       font-size:12px\r\n    }\r\n&lt;\/style&gt;\r\n&lt;body&gt;\r\n&lt;script type=\"text\/javascript\"&gt;\r\nwindow.onload=toBottom;\r\n\r\nfunction toBottom()\r\n{\r\nwindow.scrollTo(0, document.body.scrollHeight);\r\n}\r\n\r\n&lt;\/script&gt;\r\n&lt;?php\r\n$loglist = shell_exec(\"tail -n250 \/var\/log\/heizung.log\");\r\n$loglist=str_replace(chr(10),\"&lt;br&gt;\",$loglist);\r\necho $loglist;\r\n?&gt;\r\n&lt;\/body&gt;\r\n&lt;\/html&gt;<\/pre>\n<p>Im PHP Teil werden \u00fcber den Shell Befehl <em>tail<\/em> die letzten 250 Zeilen des vom Python Programm erzeugte Logs eingelesen. Da normale Zeilenumbr\u00fcche <em>chr(10)<\/em> in html nicht funktionieren, werden sie noch \u00fcber die Funktion <em>str_replace<\/em> in den html Zeilenumbruch &lt;br&gt; umgewandelt.<\/p>\n<p>\u00dcber den Javascript Teil wird erreicht, dass im Iframe ganz nach unten gescrollt wird.<\/p>\n<h3>set_temp.php<\/h3>\n<p>Dieses Skript wird nach dem Klicken auf \"Einstellungen speichern\" erneut aufgerufen und speichert dann die in den Drop Down Feldern (auch Comboboxen genannt) eingestellten Werte in der Datei settings.dat. Diese Steuerdatei wird wiederum von der Python Routine verwendet um den Temperatur Soll-\/Istvergleich vorzunehmen.<\/p>\n<pre class=\"height-set:true scroll:true lang:php decode:true\" title=\"set_temp.php\">&lt;!DOCTYPE html PUBLIC \"-\/\/W3C\/\/DTD XHTML 1.0 Transitional\/\/EN\" \"http:\/\/www.w3.org\/TR\/xhtml1\/DTD\/xhtml1-transitional.dtd\"&gt;\r\n&lt;html xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\"&gt;\r\n&lt;head&gt;\r\n&lt;meta http-equiv=\"Content-Type\" content=\"text\/html; charset=utf-8\" \/&gt;\r\n&lt;title&gt;Raspberry Pi Heizungssteuerung Result Page&lt;\/title&gt;\r\n&lt;style type=\"text\/css\"&gt;\r\n\r\nbody {\r\n       background-color: #A6A6A6;\r\n       font-family:Verdana,Arial,Helvetica,sans-serif;\r\n       font-size:12px\r\n    }\r\n&lt;\/style&gt;\r\n&lt;\/head&gt;\r\n\r\n&lt;body&gt;\r\n&lt;?php\r\nif (isset($_GET[\"nightstart\"])) \/\/save parameters only if they have been set\r\n{\r\n\t$nightstart=$_GET[\"nightstart\"];\r\n\t$daystart=$_GET[\"daystart\"];\r\n\t$daytemp=$_GET[\"daytemp\"];\r\n\t$nighttemp=$_GET[\"nighttemp\"];\r\n\t$settings = $nightstart.\"\\n\".$daystart.\"\\n\".$daytemp.\"\\n\".$nighttemp;\r\n\techo \"Einstellung wird innerhalb 60 Sekunden \u00fcbernommen\";\r\n\t$datei = fopen(\"settings.dat\",\"w\");\r\n\tfwrite($datei, $settings);\r\n\tfclose($datei);\r\n}\r\n\r\n?&gt;\r\n&lt;\/body&gt;\r\n&lt;\/html&gt;<\/pre>\n<p>Die Werte werden nur gespeichert, wenn der Parameter \"<em>nightstart<\/em>\" vom aufrufenden Programm gesetzt wurde. Beim ersten Aufruf der Website wird set_temp.php zwar auch geladen, <em>nightstart<\/em> ist jedoch leer und es findet deshalb keine Speicherung und keine Anzeige statt.<\/p>\n<p>Das wars eigentlich schon. Ganz sch\u00f6n viel Holz f\u00fcr so eine kleine Anwendung!<\/p>\n<h2>Abschluss und Optimierung<\/h2>\n<h3>Autostart<\/h3>\n<p>Das Python Programm &#8211; bei mir hei\u00dft es<\/p>\n<pre class=\"lang:default decode:1 inline:1 \">lcd_menu_integrated.py<\/pre>\n<p>&#8211; muss jetzt noch beim Systemstart automatisch hochgefahren werden. Das geschieht \u00fcber die Crontab welche ihr mit<\/p>\n<pre class=\"lang:default decode:1 inline:1 \">sudo crontab -e<\/pre>\n<p>aufruft und dann am Ende folgende Zeile eintragt:<\/p>\n<p><a href=\"http:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2015\/12\/reboot.jpg\" rel=\"attachment wp-att-548\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-548 size-medium\" src=\"http:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2015\/12\/reboot-300x17.jpg\" alt=\"reboot\" width=\"300\" height=\"17\" \/><\/a><\/p>\n<p>Mit Strg-X wird gespeichert und ihr verlasst den Editor.<\/p>\n<p>Wie immer m\u00fcsste ihr den korrekten Pfad und Skriptnamen verwenden.<\/p>\n<h3>SD Kartenverschlei\u00df vermeiden<\/h3>\n<p>Da auch hier wieder laufend Flags und Statusinformationen (z.B. die Datei settings.dat) weggeschrieben werden, empfiehlt es sich diese in eine RAMdisk auszulagern., um einem vorzeitigen Tod der SD-Karte vorzubeugen. Wie das geht, steht in diesem Beitrag: <a href=\"https:\/\/www.rustimation.eu\/index.php\/sd-karten-verschleiss-vermeiden\/\" target=\"_blank\" rel=\"noopener noreferrer\">SD-Karten Verschlei\u00df vermeiden<\/a><\/p>\n<h4>Passwortschutz f\u00fcr das Webinterface<\/h4>\n<p>Wenn ihr bis hierher gekommen seid, liegt der Gedanke nahe, das Webinterface auch von unterwegs aufzurufen. Dazu m\u00fcsst ihr euren Router so konfigurieren, dass eine von euch gew\u00e4hlte Portadresse auf den Pi umgeleitet wird. Wie das mit einer Fritzbox funktioniert, habe ich im Kapitel <em>Portfreischaltung<\/em> meines Artikels \"<a href=\"http:\/\/www.rustimation.eu\/index.php\/dynamische-ip-mit-bordmitteln\/\" target=\"_blank\" rel=\"noopener noreferrer\">Dynamische IP Adresse mit Bordmitteln<\/a>\" beschrieben. Weiter unten in demselben Artikel steht auch, wie man das Verzeichnis eures Webinterfaces mit einem Passwortschutz versieht. Ihr wollt ja sicher nicht, dass irgend welche b\u00f6sen Buben eure Heizung manipulieren.<\/p>\n<p>Eine weitere, sehr gute M\u00f6glichkeit einzelne Webseiten Verzeichnisse mit einem verschl\u00fcsselten Passort zu sichern, ist im nachfolgenden Link beschrieben: <a href=\"https:\/\/jacobsalmela.com\/2014\/05\/25\/password-protect-a-lighttpd-web-server-on-a-raspberry-pi-using-mod-auth\/\" target=\"_blank\" rel=\"noopener noreferrer\">http:\/\/jacobsalmela.com\/password-protect-a-lighttpd-web-server-on-a-raspberry-pi-using-mod-auth\/<\/a><\/p>\n<p>Viel Spa\u00df und gutes Gelingen!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ein Web Interface ist besonders hilfreich, wenn man seinen Pi von unterwegs steuern m\u00f6chte. Ich habe hier eine sehr einfach gehaltene L\u00f6sung f\u00fcr meinen Anwendungsfall IoT Heizungssteuerung (LCD Panel) erstellt. Diese L\u00f6sung l\u00e4sst sich beliebig anpassen. Was allerdings noch fehlt, ist ein responsive\u00a0 Design, das auch auf Smartphones und Tablets ohne Zoomen gut aussieht. Damit &hellip; <a href=\"https:\/\/www.rustimation.eu\/index.php\/iot-heizungssteuerung-2-web-interface\/\" class=\"more-link\"><span class=\"screen-reader-text\">IoT Heizungssteuerung 2 (Web Interface)<\/span> weiterlesen <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[54,3,53,8,10],"tags":[13,14,57,55,34,36],"class_list":["post-517","post","type-post","status-publish","format-standard","hentry","category-433mhz","category-fernsteuern","category-iot","category-php","category-raspberry-pi","tag-433mhz","tag-bmp085","tag-bmp180","tag-programmieren","tag-python-2","tag-raspberry-pi"],"_links":{"self":[{"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/posts\/517","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/comments?post=517"}],"version-history":[{"count":1,"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/posts\/517\/revisions"}],"predecessor-version":[{"id":1503,"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/posts\/517\/revisions\/1503"}],"wp:attachment":[{"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/media?parent=517"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/categories?post=517"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/tags?post=517"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}