Dear colleagues.
I am busy with a weather station, where values of sensors connected to ESP-01S are sent via my wifi network to an ESP8266, which in turn transmits data to an Arduino Uno/ESP-01S for display on a website.
My problem: How to embed the varying sensor values within the html text of the website (e.g. variables tmain, tmainmin, etc. in the code below).
I would appreciate your help. If this question has been answered already, please, point me to the relevant posts.
Addition: I realize now that I cannot use variables if the entire html string is a constant. Maybe I must divide the html code into constants and variables and concatenate them?
```cpp
#include <SoftwareSerial.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
const char* ssid = "***";
const char* password = "!!!";
float tmain = 24.0; // just an example, the value will later be retrieved
float tmainmin;
float tmainmax;
float hmain;
float pmain;
float t2av;
float t2min;
float t2max;
String t2avS;
String t2minS;
String t2maxS;
IPAddress local_IP(192,168,68,107); // to fix the url
IPAddress gateway(192,168,68,1);
IPAddress subnet(255,255,255,0);
ESP8266WebServer server(80);
// Your entire HTML content embedded as a raw string literal
const char htmlContent[] PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>House in Ruimsig</title>
</head>
<body>
<h2>House in Ruimsig</h2>
<h3>Mainstation</h3>
<table>
<tr>
<td>current:</td>
<td style="text-align: right;">tmain<span>°</span>C</td> // the variable tmain needs to be displayed/updated
</tr>
<tr>
<td>minimum:</td>
<td style="text-align: right;">tmainmin<span>°</span>C</td>
</tr>
<tr>
<td>maximum:</td>
<td style="text-align: right;">tmainmax<span>°</span>C</td>
</tr>
<tr><td>--------------</td><td>--------</td></tr>
<tr>
<td>humidity:</td>
<td style="text-align: right;">47 %</td>
</tr>
<tr>
<td>pressure:</td>
<td style="text-align: right;">850 hPa</td>
</tr>
</table>
<h3>Outside</h3>
<table>
<tr>
<td>current:</td>
<td style="text-align: right;">25.3 <span>°</span>C</td>
</tr>
<tr>
<td>minimum:</td>
<td style="text-align: right;">5.3 <span>°</span>C</td>
</tr>
<tr>
<td>maximum:</td>
<td style="text-align: right;">26.0 <span>°</span>C</td>
</tr>
</table>
<!-- Your content goes here -->
</body>
</html>
)rawliteral";
// Function to handle root path
void handleRoot()
{
server.send_P(200, "text/html", htmlContent);
}
void setup()
{
Serial.begin(115200);
delay(10);
WiFi.config(local_IP, gateway, subnet); // configure a fixed IP address for the server
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println();
Serial.print("Connected! IP address: ");
Serial.println(WiFi.localIP());
server.on("/", handleRoot);
server.begin();
Serial.println("HTTP server started");
}
void loop()
{
server.handleClient();
}
There are several techniques for this.
One is to embed place holders in the HTML for the variables in the static HTML then replace the place holders with actual values by editing them before sending. This code uses such a trick: arduino/esp8266-ledclock at master · buxtronix/arduino · GitHub
Another is to embed javascript in the static HTML which, when loaded in the browser, makes a return trip to the server and fetches the variables and populates the HTML fields.
Yet another is to stream out the HTML in interleaved chunks alternating between HTML code and variables.
The "related topics" section appended at the end of this thread also has a few suggestions.
Thank you, horace, for the links! Unfortunately, the events route is above my iq grade :-).
I got another ide from UKHeliBob that was easy enough for me to modify and implement.
Thanks for the idea and the code, UKHeliBob!
I have used it in my sketch after a bit of modification... actually only using "%s" for a string placeholder since "%d" did not work for my float values.
Yes, it helped a lot. Exactly what I was looking for as a newcomer. It was easy enough to understand and integrate in my sketch. Constantly updating via events would maybe be better, but just to difficult for me right now.
I will post the solution later.
I am sure there are some clever ways to do it but I have never been comfortable with the workings of server/client code used by web pages so I kept it simple. Using raw text also helped because it allowed the text to be set out sensibly and using snprintf() was already familiar to me.
Hi kenb4.
Thanks for your suggestion! It looks easy enough for me, and I might try it in future. For now, I took a sketch from UKHeliBob and integrated it into my sketch.
Dear all.
Firstly, thanks for all you replies, much appreciated.
I got a solution using a sketch from UKHeliBob, where placeholders (%s) are used for the temperature values/strings, which then get updated/defined.
See the new sketch below with comments on the changes.
#include <SoftwareSerial.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
const char* ssid = "***"; // fill in your own credentials
const char* password = "!!!";
float tmain = 24.0; // just examples, the values will later be retrieved
float tmainmin = 5.3;
float tmainmax = 30.1;
String tmainS;
String tmainminS;
String tmainmaxS;
float hmain = 47;
float pmain = 850;
String hmainS;
String pmainS;
float t2av = 23.5;
float t2min = 4.2;
float t2max = 27.9;
String t2avS;
String t2minS;
String t2maxS;
IPAddress local_IP(192,168,68,107);
IPAddress gateway(192,168,68,1);
IPAddress subnet(255,255,255,0);
char htmlfullContent[1250];
ESP8266WebServer server(80);
// preliminary html content embedded as a raw string literal with placeholders
const char htmlpreContent[] PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>House in Ruimsig</title>
</head>
<body>
<h2>House in Ruimsig</h2>
<h3>Mainstation</h3>
<table>
<tr>
<td>current:</td>
<td style="text-align: right;">%s <span>°</span>C</td> // %s is placeholder for a string (each time a different one)
</tr>
<tr>
<td>minimum:</td>
<td style="text-align: right;">%s <span>°</span>C</td> // see above
</tr>
<tr>
<td>maximum:</td>
<td style="text-align: right;">%s <span>°</span>C</td>
</tr>
<tr><td>--------------</td><td>--------</td></tr>
<tr>
<td>humidity:</td>
<td style="text-align: right;">%s <span>%</span></td>
</tr>
<tr>
<td>pressure:</td>
<td style="text-align: right;">%s hPa</td>
</tr>
</table>
<h3>Outside</h3>
<table>
<tr>
<td>current:</td>
<td style="text-align: right;">%s <span>°</span>C</td>
</tr>
<tr>
<td>minimum:</td>
<td style="text-align: right;">%s <span>°</span>C</td>
</tr>
<tr>
<td>maximum:</td>
<td style="text-align: right;">%s <span>°</span>C</td>
</tr>
</table>
</body>
</html>
)rawliteral";
// Function to handle root path
void handleRoot()
{
server.send_P(200, "text/html", htmlfullContent);
}
void setup()
{
Serial.begin(115200);
delay(10);
WiFi.config(local_IP, gateway, subnet); // configure a fixed IP address for the server
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println();
Serial.print("Connected! IP address: ");
Serial.println(WiFi.localIP());
server.on("/", handleRoot);
server.begin();
Serial.println("HTTP server started");
//char buffer[1250];
tmainS = String(tmain,1);
tmainminS = String(tmainmin,1);
tmainmaxS = String(tmainmax,1);
hmainS = String(hmain,0);
pmainS = String(pmain,0);
t2avS = String(t2av,1);
t2minS = String(t2min,1);
t2maxS = String(t2max,1);
// generate the full html content by sequentially replacing all placeholders (%s) with the respective strings
snprintf(htmlfullContent, sizeof(htmlfullContent), htmlpreContent, tmainS, tmainminS, tmainmaxS, hmainS, pmainS, t2avS, t2minS, t2maxS);
Serial.println(htmlfullContent); // just to check that all placeholders are now filled
}
void loop()
{
server.handleClient();
}