I have a WeMos D1 connected to an air quality sensor and publishing the value on a self-hosted website.
Initially everything works fine (although router UI does not display WeMos). After an hour or two WiFi connection fails.
Other devices on the network are unaffected. Sensor data is still being polled, serial connection works fine, but the device doesn't respond to the ping and the website obviously doesn't work.
Here's the code:
#include <ESP8266WiFi.h>
#include "SerialCom.h"
#include "Types.h"
//WiFi setup:
const char* ssid = "mySSID"; // Enter SSID here
const char* password = "myPASS"; // Enter Password here
IPAddress ip(192, 168, 0, 101);
IPAddress gateway(192, 168, 0, 1);
IPAddress subnet(255, 255, 255, 0);
WiFiServer server(80); // Server on port 80
String header;
// sensor setup:
uint32_t statusPublishPreviousMillis = 0;
const uint16_t statusPublishInterval = 30000; // 30 seconds = 30000 milliseconds
particleSensorState_t state;
unsigned long currentTime = millis(); // Current time
unsigned long previousTime = 0; // Previous time
const long timeoutTime = 2000; // Define timeout time in milliseconds (example: 2000ms = 2s)
float average;
int rounded;
void setup() {
Serial.begin(115200);
SerialCom::setup();
WiFi.config(ip, gateway, subnet);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password); // Connect to the WiFi router
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(""); // If connection successful show IP address in serial monitor
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP()); // IP address assigned to your ESP
server.begin(); // Start server
Serial.println("HTTP server started");
}
void loop() {
SerialCom::handleUart(state); // communicate with the sensor
average = SerialCom::forward(state); // read sensor value
rounded = round(average); // round the value so that we don't have .00
const uint32_t currentMillis = millis();
if (currentMillis - statusPublishPreviousMillis >= statusPublishInterval) {
statusPublishPreviousMillis = currentMillis;
}
WiFiClient client = server.available();
if (client) { // If a new client connects,
Serial.println("Client connected"); // print a message out in the serial port
String currentLine = ""; // make a String to hold incoming data from the client
currentTime = millis();
previousTime = currentTime;
while (client.connected() && currentTime - previousTime <= timeoutTime) { // loop while the client's connected
currentTime = millis();
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
// Serial.write(c); // print it out the serial monitor
header += c;
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();
// Display the HTML web page
client.println("<!DOCTYPE html><html>");
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client.println("<meta charset='utf-8'>");
// Values in the website title
client.print("<title>");
client.print(rounded);
client.println(" μg/m³</title></head>");
client.println("<script>");
// Automatic refresh script
client.println(" function refresh(refreshPeriod)");
client.println(" {setTimeout('location.reload(true)', refreshPeriod);}");
client.println(" window.onload = refresh(60000);");
client.println("</script>");
// Web Page Heading
client.println("<body>");
client.println(rounded);
client.println("</body></html>");
client.println(""); // The HTTP response ends with another blank line
break; // Break out of the while loop
} else { // if you got a newline, then clear currentLine
currentLine = "";
}
} else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
}
}
header = ""; // Clear the header variable
client.stop(); // Close the connection
}
}
EDIT:
I've read somewhere that String implementation in ESP8266 library is problematic, so I replaced every String
with char*
. That increased the uptime to around 30 hrs.