PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : html-Code für nodeMCU mit Arduino IDE + Wifi libs



HaWe
22.06.2017, 14:10
hallo,
ich verwende jetzt meinen nodeMCU für IoT mit html code. Die Website wird korrekt aufgebaut, man kann über 2 Website-Buttons 2 getrennte Verbraucher schalten (2 LEDs D7 und D8 ) und ein paar sonstige Daten betrachten (DHT Sensoren, Datum, Zeit).
Unschön ist aber, dass nach dem Schalten der Verbraucher immer die komplette Website neu aufgebaut werden muss, anstatt nur 1 Zeile zu aktualisieren (genau die, wo der aktuelle LED-Status nach Button-Click angezeigt wird).

Kennt jemand einen Weg, diese Werte direkt auf der Seite zu aktualisieren und den Rest einfach zu lassen, wie er ist?

So sieht die Website-Funktion zur Zeit aus (sie wird über loop() aufgerufen):




#include <ESP8266WiFi.h>
WiFiServer server(80);
IPAddress timeServer(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov
#include <TimeLib.h>
#include <WiFiUdp.h>
#include <Timezone.h>

//...
#define led7 D7
#define led8 D8

String datestr, timestr;

int tempc1, humid1,
tempc2, humid2;

void handleWebsite(){
volatile static int valD7=-1, valD8=-1;

//---------------------------------------
// Check if a client has connected
WiFiClient client = server.available();
if (!client) {
return;
}

//---------------------------------------
// Read the first line of the request
String request = client.readStringUntil('\r');
Serial.println(request);
client.flush();

// Match the request
if (request.indexOf("/LED7=ON") != -1) {
digitalWrite(led7, HIGH);
valD7 = HIGH;
}
if (request.indexOf("/LED7=OFF") != -1) {
digitalWrite(led7, LOW);
valD7 = LOW;
}

if (request.indexOf("/LED8=ON") != -1) {
digitalWrite(led8, HIGH);
valD8 = HIGH;
}
if (request.indexOf("/LED8=OFF") != -1) {
digitalWrite(led8, LOW);
valD8 = LOW;
}

//---------------------------------------
// Return the response

String script="";

script += ("HTTP/1.1 200 OK \n");
script += ("Content-Type: text/html \n");
script += (" \n"); // do not forget this one
script += ("<!DOCTYPE HTML> \n");
script += ("<html> \n");
script += ("<head> \n");

// autom. Aktualisierung alle 30 sec.
script += ("<meta http-equiv=\"refresh\" content=\"30; URL=http://192.168.xxx.yyy\"> \n");
// utf-8 für "°" Zeichen
script += ("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"> \n");
script += ("<title>mysite</title> \n");
script += ("</head> \n");

script += ("<body> \n");
script += ("<h1><p style=""color:rgb(255,0,191);""> hello!</p> </h1> \n");
script += ("<h1><p style=""color:rgb(255,0,191);""> Welcome to my website! </p> </h1> \n");

script += ("<h2><p style=""color:rgb(0,204,102);""> ");
script += (datestr + " &nbsp; <wbr> <wbr> <wbr> " + timestr + "</p> </h2>");
script += ("<br><br> \n");
script += ("Led D7 is now: ");
if(valD7 == HIGH) { script += ("On &nbsp; <wbr> <wbr> <wbr> "); }
else { script += ("Off &nbsp; <wbr> <wbr> <wbr> "); }

script += ("<a href=\" /LED7=ON\"\"><button>Turn On </button></a> \n");
script += ("<a href=\" /LED7=OFF\"\"><button>Turn Off </button></a><br /> \n");

script += ("<br><br> \n");
script += ("Led D8 is now: ");
if(valD8 == HIGH) { script += ("On &nbsp; <wbr> <wbr> <wbr> "); }
else { script += ("Off &nbsp; <wbr> <wbr> <wbr> "); }
script += ("<a href=\" /LED8=ON\"\"><button>Turn On </button></a> \n");
script += ("<a href=\" /LED8=OFF\"\"><button>Turn Off </button></a><br /> \n");

script += ("<br><br> \n");
script += ("<p><font face=""courier""> \n");
script += ("<h2>DHT Sensor 1: Temperat.: "+(String)tempc1 + "°C ");
script += ("&nbsp; <wbr> <wbr> <wbr> Feuchtigk.: "+(String)humid1+" </h2> \n");

script += ("<h2>DHT Sensor 2: Temperat.: "+(String)tempc2 + "°C ");
script += ("&nbsp; <wbr> <wbr> <wbr> Feuchtigk.: "+(String)humid2+" </h2> \n");

script += ("</font></p> \n");

script += ("<body> \n");
script += ("</html> \n");

client.print(script);
script="";

}

Moppi
13.08.2018, 11:44
Es handelt sich um eine Lösung, die man so heute nicht mehr unbedingt heranzieht, aber es ist eine sehr einfache, relativ unkomplizierte Lösung, wenn man nur einen HTML-Server hat:

In die Webseite kann man einen iframe einbauen (<iframe>…</iframe>). Der iframe stellt eine Seite innerhalb einer Seite dar, einen Frame eben. Daher bekommt ein iframe auch eine location-Angabe mit URL, damit der Browser weiß, von welcher Adresse die HTML-Seite für den Frame geladen wird. Den Frame kann man unsichtbar machen. Die Webseite wo die Ausgabe stattfindet, muss die HTML-Elemente mit den Attributen 'id' oder 'name' versehen haben. So kann man die Elemente mittels JavaScript dann auch ansprechen und verändern, also Inhalte ändern, Attribute des Elements ändern. Das funktioniert auch über Frame-Grenzen hinweg. Man kann also aus einem Frame in einer Webseite auf die Elternwebseite zugreifen und dort die Elemente verändern. Wenn man in die Webseite für den Frame die refresh-Zeile einbaut: <meta http-equiv="refresh" content="30; URL=http://192.168.xxx.yyy"> kann man die also auch dauernd im iframe aktualisieren und sich vom Server dann so nur ein JavaScript in den iframe schicken lassen, dass ausgeführt wird, sobald es angekommen ist. In dem JavaScript kann man natürlich alles mitschicken, was man so braucht. Mittels dem refresh wird dann wieder auf den Server zugegriffen, der dann wieder ein JavaScript schickt. Das JavaScript kann man in einer HTML-Seite verpacken, die auch die refresh-Zeile enthält.

Man kann eine Webseite auch mit Parameter aufrufen http://..../bla.htm?parameter
Den Parameter kann man auswerten und entweder die vollständige Original-Seite zum Browser schicken oder eben nur die Minimal-Seite mit JavaScript zur Veränderung des Inhalts.

HaWe
13.08.2018, 12:29
hallo,
dankeschön für die Antwort!
Wie müsste man das denn genau in meinem Beispiel codieren?

Moppi
13.08.2018, 23:27
Ich habe das Ganze kopiert und umgeschrieben. Es ist spät geworden und ich hoffe, dass es vollständig ist. Probieren kann ich nichts. Ich habe das HTML aber auf meinem lokalen Server getestet und das dann übertragen.

Mir sind verschiedene Sachen aufgefallen:

"<br />" - was immer das sein soll, ich kanns nicht deuten, dem Browser ist es egal
Der Übersichtlichkeit halber habe ich statt Gänsefüßchen in manchen Ausdrücken der HTML-Syntax das Hochkomma verwendet. Das sollte übersichtlicher sein und ist in HTML möglich.
Dann gabs ein: font face=""courier"" .... habe ich nicht verstanden und deshalb in .. font face='courier' ... geändert.
Das script=""; am Ende ist eventuell überflüssig. Hab's trotzdem nicht entfernt.
" <wbr> <wbr> <wbr> " - halte ich für überflüssig.

weiter geht's:

Dort, wo die Werte rein sollen, habe ich überall ein span-tag verwendet (wie: <span id='temp'>). Zwischen <span> und </span> steht dann der Wert.
Die Funktion change(a,b) ändert jeweils auf der Seite den Inhalt der <SPAN>s, per "innerHTML". Da die ja eine ID haben, können die angesprochen werden. Wie bei: change('valD8','On'). Das erste ist die ID, das Zweite der Wert.
/GETSTATE dient als Indikator, dass nicht die gesamte Seite aufgebaut werden soll, sondern nur geändert wird. Geändert wird mittels HTML und JavaScript im iframe, den ich hinzugefügt habe.
Warum hier ein Leerzeichen davor steht, bei " /LED7=OFF" und diesen anderen Strings weiß ich nicht. Ich habs so beibehalten, vielleicht hat es einen Sinn?
Die Variable isState dient zur Unterscheidung, was gefordert ist. Ob die gesamte Seite neu aufgebaut werden soll oder eben nicht. Dementsprechend wird entweder der IF-Zweig abgearbeitet (if (isState==-1)...) oder der dazugehörige ELSE-Zweig. Bei ELSE sollen nur die Werte über den iframe aktualisiert werden. Somit soll zu Anfang die Seite vollständig zum Browser geschickt werden und ab dann nur noch aktualisiert werden. Der Refresh findet deshalb im iframe statt, also nur in dem ELSE-Zweig, wo zuvor isState geprüft wird. Wo "gesamte Seite" steht, ist die Refresh-Zeile auskommentiert.



#include <ESP8266WiFi.h>
WiFiServer server(80);
IPAddress timeServer(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov
#include <TimeLib.h>
#include <WiFiUdp.h>
#include <Timezone.h>

//...
#define led7 D7
#define led8 D8

String datestr, timestr;

int tempc1, humid1,
tempc2, humid2;

void handleWebsite(){
volatile static int isState=-1, valD7=-1, valD8=-1;

//---------------------------------------
// Check if a client has connected
WiFiClient client = server.available();
if (!client) {
return;
}

//---------------------------------------
// Read the first line of the request
String request = client.readStringUntil('\r');
Serial.println(request);
client.flush();

// Match the request
if (request.indexOf("/GETSTATE") != -1) {
isState = 1;
}

if (request.indexOf("/LED7=ON") != -1) {
digitalWrite(led7, HIGH);
valD7 = HIGH; isState = 1;
}
if (request.indexOf("/LED7=OFF") != -1) {
digitalWrite(led7, LOW);
valD7 = LOW; isState = 1;
}

if (request.indexOf("/LED8=ON") != -1) {
digitalWrite(led8, HIGH);
valD8 = HIGH; isState = 1;
}
if (request.indexOf("/LED8=OFF") != -1) {
digitalWrite(led8, LOW);
valD8 = LOW; isState = 1;
}

//---------------------------------------
// Return the response

String script="";

script += ("HTTP/1.1 200 OK \n");

if (isState==-1) {
// Gesamte Seite
script += ("Content-Type: text/html \n");
script += (" \n"); // do not forget this one
script += ("<!DOCTYPE HTML> \n");
script += ("<html> \n");
script += ("<head> \n");

// autom. Aktualisierung alle 30 sec.
// script += ("<meta http-equiv=\"refresh\" content=\"30; URL=http://192.168.xxx.yyy\"> \n");
// utf-8 für "°" Zeichen
script += ("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"> \n");
script += ("<meta http-equiv=\"Content-Script-Type\" content=\"text/javascript\"> \n");
script += ("<meta http-equiv=\"Content-Style-Type\" content=\"text/css\"> \n");
script += ("<title>mysite</title> \n");
script += ("</head> \n");

script += ("<body> \n");
script += ("<h1><p style=""color:rgb(255,0,191);""> hello!</p> </h1> \n");
script += ("<h1><p style=""color:rgb(255,0,191);""> Welcome to my website! </p> </h1> \n");

script += ("<h2><p style=""color:rgb(0,204,102);""> ");
script += (datestr + " &nbsp; <wbr> <wbr> <wbr> " + timestr + "</p> </h2>");
script += ("<br><br> \n");
script += ("Led D7 is now: <span id='valD7'>");
if(valD7 == HIGH) { script += ("On </span>&nbsp; <wbr> <wbr> <wbr> "); }
else { script += ("Off </span>&nbsp; <wbr> <wbr> <wbr> "); }

script += ("<button onclick=\"document.myframe.location.href=' /LED7=ON'\">Turn On </button>\n");
script += ("<button onclick=\"document.myframe.location.href=' /LED7=OFF'\">Turn Off </button><br /> \n");

script += ("<br><br> \n");
script += ("Led D8 is now: <span id='valD8'>");
if(valD8 == HIGH) { script += ("On </span>&nbsp; <wbr> <wbr> <wbr> "); }
else { script += ("Off </span>&nbsp; <wbr> <wbr> <wbr> "); }
script += ("<button onclick=\"document.myframe.location.href=' /LED8=ON'\">Turn On </button>\n");
script += ("<button onclick=\"document.myframe.location.href=' /LED8=OFF'\">Turn Off </button><br /> \n");

script += ("<br><br> \n");
script += ("<p><font face='courier'> \n");
script += ("<h2>DHT Sensor 1: Temperat.: <span id='temp1'>"+(String)tempc1 + "</span>°C ");
script += ("&nbsp; <wbr> <wbr> <wbr> Feuchtigk.: <span id='feucht1'>"+(String)humid1+"</span> </h2> \n");

script += ("<h2>DHT Sensor 2: Temperat.: <span id='temp2'>"+(String)tempc2 + "</span>°C ");
script += ("&nbsp; <wbr> <wbr> <wbr> Feuchtigk.: <span id='feucht2'>"+(String)humid2+"</span> </h2> \n");

script += ("</font></p> \n");

script += ("<iframe name='myframe' src=' /GETSTATE' style='visibility:hidden' width='0' height='0'></iframe> \n");

script += ("</body> \n");
script += ("</html> \n");
}
else {
// Aktualisierungsseite
script += ("Content-Type: text/html \n");
script += (" \n"); // do not forget this one
script += ("<!DOCTYPE HTML> \n");
script += ("<html><head>\n");

// autom. Aktualisierung alle 30 sec.
script += ("<meta http-equiv=\"refresh\" content=\"30; URL=http://192.168.xxx.yyy/GETSTATE\"> \n");
// utf-8 für "°" Zeichen
script += ("<meta http-equiv=\"Content-Script-Type\" content=\"text/javascript\"> \n");
script += ("<script type=\"text/javascript\">function change(a,b){parent.document.getElementById(a).inne rHTML=b;}");

if(valD7 == HIGH) { script += ("change('valD7','On');"); }
else { script += ("change('valD7','Off');"); }

if(valD8 == HIGH) { script += ("change('valD8','On');"); }
else { script += ("change('valD8','Off');"); }

script += ("change('temp1','"+(String)tempc1+"');");
script += ("change('temp2'',"+(String)tempc2+"');");
script += ("change('feucht1','"+(String)humid1+"');");
script += ("change('feucht2','"+(String)humid2+"');");

script += ("</script></head><body></body></html> \n");
}
client.print(script);
script="";
isState=-1;
}


Dieser Code und alle ähnlichen, in der Hauptseite könnte auch ersetzt werden:



script += ("Led D7 is now: <span id='valD7'>");
if(valD7 == HIGH) { script += ("On </span>&nbsp; <wbr> <wbr> <wbr> "); }
else { script += ("Off </span>&nbsp; <wbr> <wbr> <wbr> "); }


daraus wird dann:



script += ("Led D7 is now: <span id='valD7'></span>&nbsp;");


Habe dann alles noch ein wenig überarbeitet, aber die <wbr> drin gelassen:



#include <ESP8266WiFi.h>
WiFiServer server(80);
IPAddress timeServer(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov
#include <TimeLib.h>
#include <WiFiUdp.h>
#include <Timezone.h>

//...
#define led7 D7
#define led8 D8

String datestr, timestr;

int tempc1, humid1,
tempc2, humid2;

void handleWebsite(){
volatile static int isState=-1, valD7=-1, valD8=-1;

//---------------------------------------
// Check if a client has connected
WiFiClient client = server.available();
if (!client) {
return;
}

//---------------------------------------
// Read the first line of the request
String request = client.readStringUntil('\r');
Serial.println(request);
client.flush();

// Match the request
if (request.indexOf("/GETSTATE") != -1) {
isState = 1;
}

if (request.indexOf("/LED7=ON") != -1) {
digitalWrite(led7, HIGH);
valD7 = HIGH; isState = 1;
}
if (request.indexOf("/LED7=OFF") != -1) {
digitalWrite(led7, LOW);
valD7 = LOW; isState = 1;
}

if (request.indexOf("/LED8=ON") != -1) {
digitalWrite(led8, HIGH);
valD8 = HIGH; isState = 1;
}
if (request.indexOf("/LED8=OFF") != -1) {
digitalWrite(led8, LOW);
valD8 = LOW; isState = 1;
}

//---------------------------------------
// Return the response

String script="";

script += ("HTTP/1.1 200 OK \n");

if (isState==-1) {
// Gesamte Seite
script += ("Content-Type: text/html \n");
script += (" \n"); // do not forget this one
script += ("<!DOCTYPE HTML> \n");
script += ("<html> \n");
script += ("<head> \n");

// autom. Aktualisierung alle 30 sec.
// script += ("<meta http-equiv=\"refresh\" content=\"30; URL=http://192.168.xxx.yyy\"> \n");
// utf-8 für "°" Zeichen
script += ("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"> \n");
script += ("<meta http-equiv=\"Content-Script-Type\" content=\"text/javascript\"> \n");
script += ("<meta http-equiv=\"Content-Style-Type\" content=\"text/css\"> \n");
script += ("<title>mysite</title></head><body> \n");
script += ("<h1><p style='color:rgb(255,0,191);'> hello! </p></h1> \n");
script += ("<h1><p style='color:rgb(255,0,191);'> Welcome to my website! </p></h1> \n");

script += ("<h2><p style='color:rgb(0,204,102);'> ");
script += (<span id='datum'></span>&nbsp; <wbr> <wbr> <wbr> <span id='zeit'></span></p> </h2><br><br> \n");
script += ("Led D7 is now: <span id='valD7'></span>&nbsp; <wbr>");
script += ("<button onclick=\"document.myframe.location.href=' /LED7=ON'\">Turn On </button> \n");
script += ("<button onclick=\"document.myframe.location.href=' /LED7=OFF'\">Turn Off </button> \n");

script += ("<br><br> \n");
script += ("Led D8 is now: <span id='valD8'></span>&nbsp; <wbr>");
script += ("<button onclick=\"document.myframe.location.href=' /LED8=ON'\">Turn On </button> \n");
script += ("<button onclick=\"document.myframe.location.href=' /LED8=OFF'\">Turn Off </button> \n");

script += ("<br><br> \n");
script += ("<p><font face='courier'> \n");
script += ("<h2>DHT Sensor 1: Temperat.: <span id='temp1'></span>°C ");
script += ("&nbsp; <wbr> <wbr> <wbr> Feuchtigk.: <span id='feucht1'></span> </h2> \n");

script += ("<h2>DHT Sensor 2: Temperat.: <span id='temp2'></span>°C ");
script += ("&nbsp; <wbr> <wbr> <wbr> Feuchtigk.: <span id='feucht2'></span> </h2> \n");

script += ("</font></p> \n");

script += ("<iframe name='myframe' src=' /GETSTATE' style='visibility:hidden' width='0' height='0'></iframe> \n");

script += ("</body></html> \n");
}
else {
// Aktualisierungsseite
script += ("Content-Type: text/html \n");
script += (" \n"); // do not forget this one
script += ("<!DOCTYPE HTML> \n");
script += ("<html><head>\n");

// autom. Aktualisierung alle 30 sec.
script += ("<meta http-equiv=\"refresh\" content=\"30; URL=http://192.168.xxx.yyy/GETSTATE\"> \n");
// utf-8 für "°" Zeichen
script += ("<meta http-equiv=\"Content-Script-Type\" content=\"text/javascript\"> \n");
script += ("<script type=\"text/javascript\">function change(a,b){parent.document.getElementById(a).inne rHTML=b;}");

if(valD7 == HIGH) { script += ("change('valD7','On');"); }
else { script += ("change('valD7','Off');"); }

if(valD8 == HIGH) { script += ("change('valD8','On');"); }
else { script += ("change('valD8','Off');"); }

script += ("change('temp1','"+(String)tempc1+"');");
script += ("change('temp2','"+(String)tempc2+"');");
script += ("change('feucht1','"+(String)humid1+"');");
script += ("change('feucht2','"+(String)humid2+"');");
script += ("change('datum','"+datestr+"');");
script += ("change('zeit','"+timestr+"');");

script += ("</script></head><body></body></html> \n");
}
client.print(script);
script="";
isState=-1;
}

HaWe
14.08.2018, 09:36
ein ganz herzliches Dankeschön für deine Mühe!
Der Code ganz oben im TOP ist ja schon sehr alt (von Juni 2017) und außerdem auch nur eine Unterfunktion, kein kompletter Programmcode, ich hatte nur nach deiner 1. Antwort die auffälligsten Fehler selber korrigiert, aber es mögen tatsächlich noch mehr drin geblieben sein.
Die <wbr> dienten nur dazu, dass er eine bestimmte Anzahl Leerzeichen dazwischensetzt und nicht komprimiert.
Inzwischen ist die website viel größer geworden, aber ich werden deine Änderungen und Erweiterungen versuchen in meinen aktuellen Code einzuarbeiten.
Nochmals vielen Dank!

Moppi
14.08.2018, 09:55
Bitteschön!

wbr bewirkt eigentlich, dass der Browser weiß, dass er Text an der Stelle umbrechen darf. Wenn man was gegen Umbrechen schützen will, nutzt man heute style="white-space:nowrap;". Früher war mal <nobr> .... </nobr>. Ist aber in HTML5 "verboten" worden.

HaWe
14.08.2018, 10:23
ahh ! danke, wieder was neues gelernt! 8)

Moppi
14.08.2018, 19:30
Ich hatte gar nicht nach dem Datum (22.06.2017, 13:10) geschaut, bin nur über den Beitrag gestolpert, weil der ohne Antworten war. Besser spät als gar nicht. Fast 14 Monate ...