ESP32 Web Server & MQTT &Node-RED
#include <WiFi.h>
//================MQTT=====================
#include <PubSubClient.h> //MQTT
// Replace with your network credentials
//const char* ssid = "REPLACE_WITH_YOUR_SSID";
//const char* password = "REPLACE_WITH_YOUR_PASSWORD";
const char* ssid = "TOTOLINK_A3002MU";
const char* password = "24063173";
//================MQTT=====================
const char* mqtt_server = "broker.mqtt-dashboard.com" ; //MQTT
// Set web server port number to 80
WiFiServer server(80);
// Variable to store the HTTP request
String header;
//================MQTT=====================
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
// Auxiliar variables to store the current output state
String output26State = "off";
String output27State = "off";
// Assign output variables to GPIO pins
const int output26 = 26;
const int output27 = 27;
// Current time
unsigned long currentTime = millis();
// Previous time
unsigned long previousTime = 0;
// Define timeout time in milliseconds (example: 2000ms = 2s)
const long timeoutTime = 2000;
//================MQTT=====================
void callback(char* topic, byte* message, unsigned int length) {
Serial.print("Message arrived on topic: ");
Serial.print(topic);
Serial.print(". Message: ");
String messageTemp;
for (int i = 0; i < length; i++) {
Serial.print((char)message[i]);
messageTemp += (char)message[i];
}
Serial.println();
// Feel free to add more if statements to control more GPIOs with MQTT
// If a message is received on the topic esp32/output, you check if the message is either "on" or "off".
// Changes the output state according to the message
if (String(topic) == "alex96ufo/esp32/input/26") {
Serial.print("Changing output to ");
if(messageTemp == "on"){
Serial.println("on");
output26State = "on";
digitalWrite(output26, HIGH);
}
else if(messageTemp == "off"){
Serial.println("off");
output26State = "off";
digitalWrite(output26, LOW);
}
}
if (String(topic) == "alex96ufo/esp32/input/27") {
Serial.print("Changing output to ");
if(messageTemp == "on"){
Serial.println("on");
output27State = "on";
digitalWrite(output27, HIGH);
}
else if(messageTemp == "off"){
Serial.println("off");
output27State = "off";
digitalWrite(output27, LOW);
}
}
loop_mqtt();
}
//================MQTT=====================
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect("ESP32Client")) {
Serial.println("connected");
// Subscribe
client.subscribe("alex9ufo/esp32/input/26");
client.subscribe("alex9ufo/esp32/input/27");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
//================MQTT=====================
void loop_mqtt(){
if (!client.connected()) {
reconnect();
}
client.loop();
long now = millis();
if (now - lastMsg > 5000) {
lastMsg = now;
char tempString26[4];
char tempString27[4];
output26State.toCharArray(tempString26, 4);
output27State.toCharArray(tempString27, 4);
// Convert the value to a char array
client.publish("alex96ufo/esp32/output/26", tempString26);
client.publish("alex96ufo/esp32/output/27", tempString27);
}
}
//=========================================
void setup() {
Serial.begin(115200);
// Initialize the output variables as outputs
pinMode(output26, OUTPUT);
pinMode(output27, OUTPUT);
// Set outputs to LOW
digitalWrite(output26, LOW);
digitalWrite(output27, LOW);
// Connect to Wi-Fi network with SSID and password
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
// Print local IP address and start web server
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
server.begin();
//================MQTT=====================
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}
void loop(){
loop_mqtt();
WiFiClient client = server.available(); // Listen for incoming clients
if (client) { // If a new client connects,
currentTime = millis();
previousTime = currentTime;
Serial.println("New Client."); // print a message out in the serial port
String currentLine = ""; // make a String to hold incoming data from the client
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();
// turns the GPIOs on and off
if (header.indexOf("GET /26/on") >= 0) {
Serial.println("GPIO 26 on");
output26State = "on";
digitalWrite(output26, HIGH);
} else if (header.indexOf("GET /26/off") >= 0) {
Serial.println("GPIO 26 off");
output26State = "off";
digitalWrite(output26, LOW);
} else if (header.indexOf("GET /27/on") >= 0) {
Serial.println("GPIO 27 on");
output27State = "on";
digitalWrite(output27, HIGH);
} else if (header.indexOf("GET /27/off") >= 0) {
Serial.println("GPIO 27 off");
output27State = "off";
digitalWrite(output27, LOW);
}
// 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("<link rel=\"icon\" href=\"data:,\">");
// CSS to style the on/off buttons
// Feel free to change the background-color and font-size attributes to fit your preferences
client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
client.println(".button2 {background-color: #555555;}</style></head>");
// Web Page Heading
client.println("<body><h1>ESP32 Web Server</h1>");
// Display current state, and ON/OFF buttons for GPIO 26
client.println("<p>GPIO 26 - State " + output26State + "</p>");
// If the output26State is off, it displays the ON button
if (output26State=="off") {
client.println("<p><a href=\"/26/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/26/off\"><button class=\"button button2\">OFF</button></a></p>");
}
// Display current state, and ON/OFF buttons for GPIO 27
client.println("<p>GPIO 27 - State " + output27State + "</p>");
// If the output27State is off, it displays the ON button
if (output27State=="off") {
client.println("<p><a href=\"/27/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/27/off\"><button class=\"button button2\">OFF</button></a></p>");
}
client.println("</body></html>");
// The HTTP response ends with another blank line
client.println();
// Break out of the while loop
break;
} 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
}
}
}
// Clear the header variable
header = "";
// Close the connection
client.stop();
Serial.println("Client disconnected.");
Serial.println("");
}
}
[{"id":"19e786ee6973478d","type":"mqtt in","z":"1c234d4ad776c8ec","name":"","topic":"alex9ufo/esp32/output/26","qos":"1","datatype":"auto","broker":"3d43a51a.c133a2","nl":false,"rap":true,"rh":0,"x":290,"y":100,"wires":[["bdd73930f1e50c3b","346b0d30d302b689"]]},{"id":"02ef7f91d529b1ee","type":"mqtt out","z":"1c234d4ad776c8ec","name":"","topic":"alex9ufo/esp32/input/26","qos":"1","retain":"true","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"2e162217.bc2456","x":650,"y":280,"wires":[]},{"id":"7ed34d6113cb7cd5","type":"ui_led","z":"1c234d4ad776c8ec","order":2,"group":"fc89dc38.347898","width":4,"height":4,"label":"LED26","labelPlacement":"left","labelAlignment":"left","colorForValue":[{"color":"#ff0000","value":"false","valueType":"bool"},{"color":"#008000","value":"true","valueType":"bool"}],"allowColorForValueInMessage":false,"shape":"circle","showGlow":true,"name":"","x":690,"y":100,"wires":[]},{"id":"43556ac91a1a45ed","type":"mqtt in","z":"1c234d4ad776c8ec","name":"","topic":"alex9ufo/esp32/output/27","qos":"1","datatype":"auto","broker":"3d43a51a.c133a2","nl":false,"rap":true,"rh":0,"x":290,"y":140,"wires":[["b3d5d81a8a2664d0"]]},{"id":"ef5083294f837232","type":"ui_led","z":"1c234d4ad776c8ec","order":4,"group":"fc89dc38.347898","width":4,"height":4,"label":"LED27","labelPlacement":"left","labelAlignment":"left","colorForValue":[{"color":"#ff0000","value":"false","valueType":"bool"},{"color":"#008000","value":"true","valueType":"bool"}],"allowColorForValueInMessage":false,"shape":"circle","showGlow":true,"name":"","x":690,"y":140,"wires":[]},{"id":"a9f6cb58bb14d00c","type":"mqtt out","z":"1c234d4ad776c8ec","name":"","topic":"alex9ufo/esp32/input/27","qos":"1","retain":"true","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"2e162217.bc2456","x":650,"y":340,"wires":[]},{"id":"bdd73930f1e50c3b","type":"function","z":"1c234d4ad776c8ec","name":"","func":"var onoff=msg.payload;\n\nif (onoff === \"on\") {\n\n//if (onoff === \"on\\n\") { \n\tmsg.payload=true;\n} \nelse {\n msg.payload=false;\n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":510,"y":100,"wires":[["7ed34d6113cb7cd5","7835c6a54441f735"]]},{"id":"b3d5d81a8a2664d0","type":"function","z":"1c234d4ad776c8ec","name":"","func":"var onoff=msg.payload;\n\nif (onoff === 'on') {\n//if (onoff === 'on\\n') {\n\tmsg.payload=true;\n} \nelse {\n msg.payload=false;\n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":510,"y":140,"wires":[["ef5083294f837232","bf227fa4789ed536"]]},{"id":"f170f8739308b6fb","type":"ui_switch","z":"1c234d4ad776c8ec","name":"","label":"switch LED26","tooltip":"","group":"fc89dc38.347898","order":19,"width":4,"height":4,"passthru":true,"decouple":"false","topic":"topic","topicType":"msg","style":"","onvalue":"true","onvalueType":"bool","onicon":"","oncolor":"","offvalue":"false","offvalueType":"bool","officon":"","offcolor":"","animate":false,"className":"","x":260,"y":280,"wires":[["17e893efc6d06e7d"]],"info":"<i class=\"fa fa-camera-retro fa-3x\"></i> fa-3x"},{"id":"65640a8134150229","type":"ui_switch","z":"1c234d4ad776c8ec","name":"","label":"switch LED27","tooltip":"","group":"fc89dc38.347898","order":21,"width":4,"height":4,"passthru":true,"decouple":"false","topic":"topic","topicType":"msg","style":"","onvalue":"true","onvalueType":"bool","onicon":"","oncolor":"","offvalue":"false","offvalueType":"bool","officon":"","offcolor":"","animate":false,"className":"","x":260,"y":340,"wires":[["97563dbef69e66e6"]],"info":"<i class=\"fa fa-camera-retro fa-3x\"></i> fa-3x"},{"id":"17e893efc6d06e7d","type":"function","z":"1c234d4ad776c8ec","name":"","func":"var onoff=msg.payload;\n\nif (onoff === true) {\n\tmsg.payload='on';\n} \nelse {\n msg.payload='off';\n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":430,"y":280,"wires":[["02ef7f91d529b1ee","8fe9679230897829","bdd73930f1e50c3b"]]},{"id":"7835c6a54441f735","type":"debug","z":"1c234d4ad776c8ec","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":710,"y":60,"wires":[]},{"id":"bf227fa4789ed536","type":"debug","z":"1c234d4ad776c8ec","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":710,"y":180,"wires":[]},{"id":"8fe9679230897829","type":"debug","z":"1c234d4ad776c8ec","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":630,"y":220,"wires":[]},{"id":"b76b8efd4d10d806","type":"debug","z":"1c234d4ad776c8ec","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":630,"y":400,"wires":[]},{"id":"97563dbef69e66e6","type":"function","z":"1c234d4ad776c8ec","name":"","func":"var onoff=msg.payload;\n\nif (onoff === true) {\n\tmsg.payload='on';\n} \nelse {\n msg.payload='off';\n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":430,"y":340,"wires":[["a9f6cb58bb14d00c","b76b8efd4d10d806","b3d5d81a8a2664d0"]]},{"id":"346b0d30d302b689","type":"debug","z":"1c234d4ad776c8ec","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":500,"y":60,"wires":[]},{"id":"3d43a51a.c133a2","type":"mqtt-broker","name":"broker.mqtt-dashboard.com","broker":"broker.mqtt-dashboard.com","port":"1883","clientid":"","usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthRetain":"false","birthPayload":"","birthMsg":{},"closeTopic":"","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willRetain":"false","willPayload":"","willMsg":{},"sessionExpiry":""},{"id":"2e162217.bc2456","type":"mqtt-broker","name":"broker.mqtt-dashboard.com","broker":"broker.mqtt-dashboard.com","port":"1883","clientid":"","usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthRetain":"false","birthPayload":"","birthMsg":{},"closeTopic":"","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willRetain":"false","willPayload":"","willMsg":{},"sessionExpiry":""},{"id":"fc89dc38.347898","type":"ui_group","name":"LED show","tab":"ec4c23e9246d7836","order":1,"disp":true,"width":16,"collapse":false,"className":""},{"id":"ec4c23e9246d7836","type":"ui_tab","name":"Home","icon":"dashboard","disabled":false,"hidden":false}]