// Import required libraries
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.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";
const char* PARAM_INPUT_1 = "output";
const char* PARAM_INPUT_2 = "state";
String inputMessage1;
String inputMessage2;
const int output2 = 2;
const int output4 = 4;
const int output33 = 33;
// Auxiliar variables to store the current output state
String output2State = "off";
String output4State = "off";
String output33State = "off";
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
//================MQTT=====================
const char* mqtt_server = "broker.mqtt-dashboard.com" ; //MQTT
//================MQTT=====================
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
//=========================================
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
<title>ESP Web Server</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
<style>
html {font-family: Arial; display: inline-block; text-align: center;}
h2 {font-size: 3.0rem;}
p {font-size: 3.0rem;}
body {max-width: 600px; margin:0px auto; padding-bottom: 25px;}
.switch {position: relative; display: inline-block; width: 120px; height: 68px}
.switch input {display: none}
.slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 6px}
.slider:before {position: absolute; content: ""; height: 52px; width: 52px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 3px}
input:checked+.slider {background-color: #b30000}
input:checked+.slider:before {-webkit-transform: translateX(52px); -ms-transform: translateX(52px); transform: translateX(52px)}
</style>
</head>
<body>
<h2>ESP Web Server</h2>
%BUTTONPLACEHOLDER%
<script>function toggleCheckbox(element) {
var xhr = new XMLHttpRequest();
if(element.checked){ xhr.open("GET", "/update?output="+element.id+"&state=1", true); }
else { xhr.open("GET", "/update?output="+element.id+"&state=0", true); }
xhr.send();
}
</script>
</body>
</html>
)rawliteral";
//=========================================
// Replaces placeholder with button section in your web page
String processor(const String& var){
//Serial.println(var);
if(var == "BUTTONPLACEHOLDER"){
String buttons = "";
buttons += "<h4>Output - GPIO 2</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"2\" " + outputState(2) + "><span class=\"slider\"></span></label>";
buttons += "<h4>Output - GPIO 4</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"4\" " + outputState(4) + "><span class=\"slider\"></span></label>";
buttons += "<h4>Output - GPIO 33</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"33\" " + outputState(33) + "><span class=\"slider\"></span></label>";
return buttons;
}
return String();
}
//=========================================
String outputState(int output){
if(digitalRead(output)){
return "checked";
}
else {
return "";
}
}
//================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) == "alex9ufo/esp32/input/LED2") {
Serial.print("Changing output to ");
if(messageTemp == "on"){
Serial.println("on");
output2State = "on";
digitalWrite(output2, HIGH);
}
else if(messageTemp == "off"){
Serial.println("off");
output2State = "off";
digitalWrite(output2, LOW);
}
}
if (String(topic) == "alex9ufo/esp32/input/LED4") {
Serial.print("Changing output to ");
if(messageTemp == "on"){
Serial.println("on");
output4State = "on";
digitalWrite(output4, HIGH);
}
else if(messageTemp == "off"){
Serial.println("off");
output4State = "off";
digitalWrite(output4, LOW);
}
}
if (String(topic) == "alex9ufo/esp32/input/LED33") {
Serial.print("Changing output to ");
if(messageTemp == "on"){
Serial.println("on");
output33State = "on";
digitalWrite(output33, HIGH);
}
else if(messageTemp == "off"){
Serial.println("off");
output33State = "off";
digitalWrite(output33, 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/LED2");
client.subscribe("alex9ufo/esp32/input/LED4");
client.subscribe("alex9ufo/esp32/input/LED33");
} 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;
client.publish("alex9ufo/esp32/output/LED2", String(output2State).c_str());
client.publish("alex9ufo/esp32/output/LED4", String(output4State).c_str());
client.publish("alex9ufo/esp32/output/LED33", String(output33State).c_str());
}
}
//=========================================
void setup(){
// Serial port for debugging purposes
Serial.begin(115200);
pinMode(2, OUTPUT);
digitalWrite(2, LOW);
pinMode(4, OUTPUT);
digitalWrite(4, LOW);
pinMode(33, OUTPUT);
digitalWrite(33, LOW);
// Connect to Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
// Print ESP Local IP Address
Serial.println(WiFi.localIP());
// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html, processor);
});
// Send a GET request to <ESP_IP>/update?output=<inputMessage1>&state=<inputMessage2>
server.on("/update", HTTP_GET, [] (AsyncWebServerRequest *request) {
//String inputMessage1;
//String inputMessage2;
// GET input1 value on <ESP_IP>/update?output=<inputMessage1>&state=<inputMessage2>
if (request->hasParam(PARAM_INPUT_1) && request->hasParam(PARAM_INPUT_2)) {
inputMessage1 = request->getParam(PARAM_INPUT_1)->value();
inputMessage2 = request->getParam(PARAM_INPUT_2)->value();
digitalWrite(inputMessage1.toInt(), inputMessage2.toInt());
}
else {
inputMessage1 = "No message sent";
inputMessage2 = "No message sent";
}
Serial.print("GPIO: ");
Serial.print(inputMessage1);
Serial.print(" - Set to: ");
Serial.println(inputMessage2);
Serial.println(inputMessage1.substring(0,1));
Serial.println(inputMessage2.substring(0));
//=========================================
if (inputMessage1.substring(0,1)=="2"){
if (inputMessage2.substring(0,1)=="1") {
output2State="on";
//client.publish("alex9ufo/esp32/output/LED2", String("on").c_str());
} else {
output2State="off";
client.publish("alex9ufo/esp32/output/LED2", String("off").c_str());
}
}
//=========================================
if (inputMessage1.substring(0,1)=="4"){
if (inputMessage2.substring(0,1)=="1") {
output4State="on";
//client.publish("alex9ufo/esp32/output/LED4", String("on").c_str());
} else {
output4State="off";
client.publish("alex9ufo/esp32/output/LED4", String("off").c_str());
}
}
//=========================================
if (inputMessage1.substring(0,2)=="33"){
if (inputMessage2.substring(0,1)=="1" ){
output33State="on";
//client.publish("alex9ufo/esp32/output/LED33", String("on").c_str());
} else {
output2State="off";
//client.publish("alex9ufo/esp32/output/LED33", String("off").c_str());
}
}
//=========================================
request->send(200, "text/plain", "OK");
});
// Start server
server.begin();
//================MQTT=====================
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}
//=========================================
void loop() {
loop_mqtt();
}
[{"id":"5e289c8ea4044b2c","type":"mqtt in","z":"9f46f02887319d42","name":"","topic":"alex9ufo/esp32/output/LED2","qos":"1","datatype":"auto","broker":"3d43a51a.c133a2","nl":false,"rap":true,"rh":0,"x":380,"y":80,"wires":[["33bfcb1ee767c120","fcfcca7aa513e04a"]]},{"id":"0e80ae8c04659e32","type":"mqtt in","z":"9f46f02887319d42","name":"","topic":"alex9ufo/esp32/output/LED4","qos":"1","datatype":"auto","broker":"3d43a51a.c133a2","nl":false,"rap":true,"rh":0,"x":380,"y":140,"wires":[["2381afd0958ddec5","33bfcb1ee767c120"]]},{"id":"100d4757648edfe6","type":"ui_switch","z":"9f46f02887319d42","name":"","label":"switch LED2","tooltip":"","group":"fc89dc38.347898","order":19,"width":"5","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":330,"y":360,"wires":[["17337d056f64cfac"]],"info":"<i class=\"fa fa-camera-retro fa-3x\"></i> fa-3x"},{"id":"1c64f4deecb782d4","type":"ui_switch","z":"9f46f02887319d42","name":"","label":"switch LED4","tooltip":"","group":"fc89dc38.347898","order":21,"width":"5","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":330,"y":400,"wires":[["372d7cf1744c2ade"]],"info":"<i class=\"fa fa-camera-retro fa-3x\"></i> fa-3x"},{"id":"8c66feccb8ba7465","type":"ui_led","z":"9f46f02887319d42","order":2,"group":"fc89dc38.347898","width":"5","height":4,"label":"LED2","labelPlacement":"left","labelAlignment":"left","colorForValue":[{"color":"#000000","value":"false","valueType":"bool"},{"color":"#0000ff","value":"true","valueType":"bool"}],"allowColorForValueInMessage":false,"shape":"circle","showGlow":true,"name":"","x":770,"y":80,"wires":[],"info":".led {\r\n float: right;\r\n padding: 3px;\r\n width: 10px;\r\n height: 10px;\r\n margin: 5px 5px 5px 5px;\r\n border-radius: 50%;\r\n \r\n}\r\n</style>\r\n\r\n<div><span class=\"led\" style=\"background-color: {{msg.payload}}; box-shadow: black 0 -1px 1px 0px, inset black 0 -1px 4px, {{msg.payload}} 0 3px 15px;\"></span></div>```"},{"id":"6a8fe6d2114888b3","type":"ui_led","z":"9f46f02887319d42","order":4,"group":"fc89dc38.347898","width":"5","height":4,"label":"LED4","labelPlacement":"left","labelAlignment":"left","colorForValue":[{"color":"#000000","value":"false","valueType":"bool"},{"color":"#ff0000","value":"true","valueType":"bool"}],"allowColorForValueInMessage":false,"shape":"circle","showGlow":true,"name":"","x":770,"y":140,"wires":[]},{"id":"f0ee2c75a75392bb","type":"mqtt in","z":"9f46f02887319d42","name":"","topic":"alex9ufo/esp32/output/LED33","qos":"1","datatype":"auto","broker":"3d43a51a.c133a2","nl":false,"rap":true,"rh":0,"x":380,"y":200,"wires":[["04cefb96dcc34818","33bfcb1ee767c120"]]},{"id":"06cc6e28dc7c6bee","type":"ui_led","z":"9f46f02887319d42","order":4,"group":"fc89dc38.347898","width":"5","height":4,"label":"LED33","labelPlacement":"left","labelAlignment":"left","colorForValue":[{"color":"#000000","value":"false","valueType":"bool"},{"color":"#ffff00","value":"true","valueType":"bool"}],"allowColorForValueInMessage":false,"shape":"circle","showGlow":true,"name":"","x":770,"y":200,"wires":[]},{"id":"d37a12e1f2ca3f44","type":"ui_switch","z":"9f46f02887319d42","name":"","label":"switch LED33","tooltip":"","group":"fc89dc38.347898","order":21,"width":"5","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":340,"y":440,"wires":[["146d17408dd1ff9f"]],"info":"<i class=\"fa fa-camera-retro fa-3x\"></i> fa-3x"},{"id":"8fd5ff06add949bd","type":"mqtt out","z":"9f46f02887319d42","name":"","topic":"alex9ufo/esp32/input/LED2","qos":"1","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"3d43a51a.c133a2","x":700,"y":360,"wires":[]},{"id":"81b060facfdb6348","type":"mqtt out","z":"9f46f02887319d42","name":"","topic":"alex9ufo/esp32/input/LED4","qos":"1","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"3d43a51a.c133a2","x":700,"y":400,"wires":[]},{"id":"e0067ec1eb8d37a5","type":"mqtt out","z":"9f46f02887319d42","name":"","topic":"alex9ufo/esp32/input/LED33","qos":"1","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"3d43a51a.c133a2","x":700,"y":440,"wires":[]},{"id":"17337d056f64cfac","type":"function","z":"9f46f02887319d42","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":490,"y":360,"wires":[["8fd5ff06add949bd"]]},{"id":"372d7cf1744c2ade","type":"function","z":"9f46f02887319d42","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":490,"y":400,"wires":[["81b060facfdb6348"]]},{"id":"146d17408dd1ff9f","type":"function","z":"9f46f02887319d42","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":490,"y":440,"wires":[["e0067ec1eb8d37a5"]]},{"id":"2381afd0958ddec5","type":"function","z":"9f46f02887319d42","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":590,"y":140,"wires":[["6a8fe6d2114888b3"]]},{"id":"04cefb96dcc34818","type":"function","z":"9f46f02887319d42","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":590,"y":200,"wires":[["06cc6e28dc7c6bee"]]},{"id":"33bfcb1ee767c120","type":"debug","z":"9f46f02887319d42","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":610,"y":240,"wires":[]},{"id":"fcfcca7aa513e04a","type":"function","z":"9f46f02887319d42","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":590,"y":80,"wires":[["8c66feccb8ba7465"]]},{"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":"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}]
沒有留言:
張貼留言