In a previous post, BME-280 data was exposed as JSON, and that data was made available using a simple API. Once the web server was created and API URL paths were specified, exposing sensor data as JSON became just a problem in string manipulation - we just constructed a string that contained the data, and that string was in valid JSON format.
This same trick can be applied to exposing data in an HTML page - we'll construct a string that includes the sensor data, and that string will be a valid HTML5 document. We return that string with mime type text/html, and it will be rendered in a browser!
Why stop with HTML? We can also use string manipulation to include CSS and JavaScript!
Our goal is to have the ESP8266 serve a page that:
- Presents temperature, humidity, and barometric pressure from the BME-280 sensor
- Includes CSS that makes the page somewhat attractive on both notebook computers and iPhones
- Has button that when clicked will call a JavaScript function that refreshes the page
We could add this to the program in that previous post, but to keep things simple, this functionality will be put in a separate program.
Here's the program:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | /** * BME280-WebServer-HTML * * By: Mike Klepper * Date: 2 September 2017 * * This program exposes BME-280 data in a web page. * * See patriot-geek.blogspot.com * for explanation. */ #include "ESP8266WiFi.h" #include "WiFiClient.h" #include "ESP8266WebServer.h" #include "Adafruit_Sensor.h" #include "Adafruit_BME280.h" const char* SSID = "**********"; const char* PASSWORD = "**********"; const int DELAY = 3000; const int STARTUP_DELAY = 500; const char* MESSAGE_404 = "404 Not Found"; const char* MESSAGE_503 = "503 Service Unavailable"; boolean sensorAvailable; ESP8266WebServer server(80); Adafruit_BME280 bme; void setup(void) { Serial.begin(115200); // Start the BME280 sensor if(!bme.begin()) { Serial.println("Could not find a valid BME280 sensor, check wiring!"); sensorAvailable = false; } else { sensorAvailable = true; delay(STARTUP_DELAY); } WiFi.begin(SSID, PASSWORD); // Wait for the connection while(WiFi.status() != WL_CONNECTED) { delay(STARTUP_DELAY); Serial.print("."); } Serial.println(""); Serial.print("Connected to "); Serial.println(SSID); Serial.print("IP address: "); Serial.println(WiFi.localIP()); server.on("/", returnHtml); server.on("", returnHtml); server.onNotFound(return404Error); server.begin(); Serial.println("HTTP server started"); } void loop(void) { server.handleClient(); yield(); } void return404Error() { server.send(404, "text/plain", MESSAGE_404); } void return503Error() { server.send(500, "text/plain", MESSAGE_503); } void returnHtml() { if(sensorAvailable) { // Get values float tempC = bme.readTemperature(); float humidity = bme.readHumidity(); float pressurePascals = bme.readPressure(); // Convert to British units float tempF = 9.0/5.0 * tempC + 32.0; float pressureInchesOfMercury = 0.000295299830714 * pressurePascals; // Build HTML response String responseHtml = ""; responseHtml += "<!DOCTYPE html>"; responseHtml += "<html>"; responseHtml += " <head>"; responseHtml += " <meta charset=\"UTF-8\">"; responseHtml += " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"; responseHtml += " <title>BME-280 Sensor Data</title>"; responseHtml += " <style>"; responseHtml += " body {font-family: sans-serif}"; responseHtml += " h1 {font-size: 1.0cm}"; responseHtml += " p {font-size: 0.50cm}"; responseHtml += " button {font-size: 1.0cm}"; responseHtml += " </style>"; responseHtml += " <script type=\"text/javascript\">"; responseHtml += " function refreshPage()"; responseHtml += " {"; responseHtml += " location.reload(true);"; responseHtml += " }"; responseHtml += " </script>"; responseHtml += " </head>"; responseHtml += " <body>"; responseHtml += " <h1>BME-280 Sensor Data</h1>"; responseHtml += " <p>Temperature: " + String(tempF) + "° F</p>"; responseHtml += " <p>Humidity: " + String(humidity) + "%</p>"; responseHtml += " <p>Pressure: " + String(pressureInchesOfMercury) + " inHg</p>"; responseHtml += " <button type=\"button\" onclick=\"refreshPage()\">Refresh</button>"; responseHtml += " </body>"; responseHtml += "</html>"; // Return HTML with correct MIME type server.send(200, "text/html; charset=utf-8", responseHtml); } else { return503Error(); } } |
Once the program is running, the IP address that the network assigns to the ESP8266 is displayed in the serial monitor. For example, my IP address is (currently) 192.168.1.8. Open a browser and go to http://192.168.1.8, and the following will be displayed:
On the iPhone, the result is:
Click or tap the "Refresh" button and the page does indeed refresh.
This program functions very similar to the one in the previous post, so I won't do a code walk-through.
Most any web developer will complain about the way I mixed HTML, CSS, and JavaScript in one file. But that is the attitude of one who has the luxury of great bandwidth and fast servers, and we are not in that position.
No comments:
Post a Comment