2022年1月3日 星期一

ESP32 Relay Module & MQTT

 ESP32 Relay Module & MQTT

源自於https://randomnerdtutorials.com/esp32-relay-module-ac-web-server/








// Import required libraries

#include "WiFi.h"

#include "ESPAsyncWebServer.h"


//================MQTT=====================

#include <PubSubClient.h>  //MQTT


// Set to true to define Relay as Normally Open (NO)

#define RELAY_NO    true


// Set number of relays

#define NUM_RELAYS  5


// Assign each GPIO to a relay

int relayGPIOs[NUM_RELAYS] = {2, 26, 27, 25, 33};


// 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 = "relay";  

const char* PARAM_INPUT_2 = "state";


//================MQTT=====================

String inputMessage;

String inputMessage2;


String output2State;

String output26State;

String output27State;

String output25State;

String output33State;


// 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];


// relayGPIOs[NUM_RELAYS] = {2, 26, 27, 25, 33};

const int output2 = 2;

const int output26 = 26;

const int output27 = 27;

const int output25 = 25;

const int output33 = 33;



//=========================================

const char index_html[] PROGMEM = R"rawliteral(

<!DOCTYPE HTML><html>

<head>

  <meta name="viewport" content="width=device-width, initial-scale=1">

  <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: 34px}

    .slider:before {position: absolute; content: ""; height: 52px; width: 52px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 68px}

    input:checked+.slider {background-color: #2196F3}

    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?relay="+element.id+"&state=1", true); }

  else { xhr.open("GET", "/update?relay="+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 ="";

    for(int i=1; i<=NUM_RELAYS; i++){

      String relayStateValue = relayState(i);

      buttons+= "<h4>Relay #" + String(i) + " - GPIO " + relayGPIOs[i-1] + "</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"" + String(i) + "\" "+ relayStateValue +"><span class=\"slider\"></span></label>";

    }

    return buttons;

  }

  return String();

}

//=========================================

String relayState(int numRelay){

  if(RELAY_NO){

    if(digitalRead(relayGPIOs[numRelay-1])){

      return "";

    }

    else {

      return "checked";

    }

  }

  else {

    if(digitalRead(relayGPIOs[numRelay-1])){

      return "checked";

    }

    else {

      return "";

    }

  }

  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

  

  //******* relayGPIOs[NUM_RELAYS] = {2, 26, 27, 25, 33};

   

  if (String(topic)=="alex9ufo/esp32/input/LED2") {

           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/LED26") {  

          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)=="alex9ufo/esp32/input/LED27") {           

          if(messageTemp == "on"){

              Serial.println("on");

              output27State = "on";

              digitalWrite(output27, HIGH);

          }

          else if(messageTemp == "off"){

              Serial.println("off");

              output27State = "off";

              digitalWrite(output27, LOW);

          }

  }

  

  if (String(topic)=="alex9ufo/esp32/input/LED25") {   

          if(messageTemp == "on"){

              Serial.println("on");

              output25State = "on";

              digitalWrite(output25, HIGH);

          }

          else if(messageTemp == "off"){

              Serial.println("off");

              output25State = "off";

              digitalWrite(output25, LOW);

          }

  }

  

  if (String(topic)=="alex9ufo/esp32/input/LED33") {   

          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

      //******* relayGPIOs[NUM_RELAYS] = {2, 26, 27, 25, 33};

      client.subscribe("alex9ufo/esp32/input/LED2");

      client.subscribe("alex9ufo/esp32/input/LED26");

      client.subscribe("alex9ufo/esp32/input/LED27"); 

      client.subscribe("alex9ufo/esp32/input/LED25");

      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;

    //******* relayGPIOs[NUM_RELAYS] = {2, 26, 27, 25, 33};

    client.publish("alex9ufo/esp32/output/LED2", String(output2State).c_str());

    client.publish("alex9ufo/esp32/output/LED26", String(output26State).c_str());

    client.publish("alex9ufo/esp32/output/LED27", String(output27State).c_str());

    client.publish("alex9ufo/esp32/output/LED25", String(output25State).c_str());        

    client.publish("alex9ufo/esp32/output/LED33", String(output33State).c_str());  

     

  }  

}

//=========================================

void setup(){

  // Serial port for debugging purposes

  Serial.begin(115200);


  // Set all relays to off when the program starts - if set to Normally Open (NO), the relay is off when you set the relay to HIGH

  for(int i=1; i<=NUM_RELAYS; i++){

    pinMode(relayGPIOs[i-1], OUTPUT);

    if(RELAY_NO){

      digitalWrite(relayGPIOs[i-1], HIGH);

    }

    else{

      digitalWrite(relayGPIOs[i-1], LOW);

    }

  }

  

  // Connect to Wi-Fi

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {

    delay(1000);

    Serial.println("Connecting to WiFi..");

  }


  // Print ESP32 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?relay=<inputMessage>&state=<inputMessage2>

  server.on("/update", HTTP_GET, [] (AsyncWebServerRequest *request) {

    //String inputMessage;

    String inputParam;

    //String inputMessage2;

    String inputParam2;

    // GET input1 value on <ESP_IP>/update?relay=<inputMessage>

    if (request->hasParam(PARAM_INPUT_1) & request->hasParam(PARAM_INPUT_2)) {

      inputMessage = request->getParam(PARAM_INPUT_1)->value();

      inputParam = PARAM_INPUT_1;

      inputMessage2 = request->getParam(PARAM_INPUT_2)->value();

      inputParam2 = PARAM_INPUT_2;

      if(RELAY_NO){

        Serial.print("NO ");

        digitalWrite(relayGPIOs[inputMessage.toInt()-1], !inputMessage2.toInt());

      }

      else{

        Serial.print("NC ");

        digitalWrite(relayGPIOs[inputMessage.toInt()-1], inputMessage2.toInt());

      }

    }

    else {

      inputMessage = "No message sent";

      inputParam = "none";

    }

    Serial.println(inputMessage + inputMessage2);

    

    //******* relayGPIOs[NUM_RELAYS] = {2, 26, 27, 25, 33};

    //==================MQTT=======================

    int in=inputMessage.toInt();

    Serial.println(in);

    switch  (in) {

      case 1 :

                if (inputMessage2.substring(0,1)=="1") {

                      output2State="on";

                 } else {

                      output2State="off"; 

                 }     

                break;

      case 2 :

                if (inputMessage2.substring(0,1)=="1") {

                      output26State="on";

                 } else {

                      output26State="off";

                 }

                break;

      case 3 :

                if (inputMessage2.substring(0,1)=="1") {

                      output27State="on";

                 } else {

                      output27State="off";

                 }     

                break;

      case 4 :

                if (inputMessage2.substring(0,1)=="1") {

                      output25State="on";

                 } else {

                      output25State="off";

                 }

                break;

      case 5 :

                if (inputMessage2.substring(0,1)=="1") {

                      output33State="on";

                 } else {

                      output33State="off";

                 }

                break;

      default:

                break; 

     

    }

    


   //=============================================

    request->send(200, "text/plain", "OK");

  });

  // Start server

  server.begin();

  //================MQTT===================== 

  client.setServer(mqtt_server, 1883);

  client.setCallback(callback);

  

}


//=========================================  

void loop() {

  loop_mqtt();

}




[{"id":"d0b8941894fcac4f","type":"mqtt in","z":"ae224a672bf6f825","name":"","topic":"alex9ufo/esp32/output/LED2","qos":"2","datatype":"auto","broker":"3d43a51a.c133a2","nl":false,"rap":true,"rh":0,"x":260,"y":100,"wires":[["7884092d41d3605b"]]},{"id":"7884092d41d3605b","type":"function","z":"ae224a672bf6f825","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":490,"y":100,"wires":[["15570dc2f08eece8"]]},{"id":"15570dc2f08eece8","type":"ui_led","z":"ae224a672bf6f825","order":20,"group":"fc89dc38.347898","width":"4","height":"3","label":"LED2","labelPlacement":"left","labelAlignment":"right","colorForValue":[{"color":"#000000","value":"false","valueType":"bool"},{"color":"#008000","value":"true","valueType":"bool"}],"allowColorForValueInMessage":false,"shape":"circle","showGlow":true,"name":"","x":690,"y":100,"wires":[]},{"id":"7bbbd1bdd369a37d","type":"mqtt in","z":"ae224a672bf6f825","name":"","topic":"alex9ufo/esp32/output/LED26","qos":"2","datatype":"auto","broker":"3d43a51a.c133a2","nl":false,"rap":true,"rh":0,"x":260,"y":180,"wires":[["438a8a1f7ba3952f"]]},{"id":"438a8a1f7ba3952f","type":"function","z":"ae224a672bf6f825","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":490,"y":180,"wires":[["992ce231f08e29c4"]]},{"id":"992ce231f08e29c4","type":"ui_led","z":"ae224a672bf6f825","order":20,"group":"fc89dc38.347898","width":"4","height":"3","label":"LED26","labelPlacement":"left","labelAlignment":"right","colorForValue":[{"color":"#000000","value":"false","valueType":"bool"},{"color":"#008000","value":"true","valueType":"bool"}],"allowColorForValueInMessage":false,"shape":"circle","showGlow":true,"name":"","x":690,"y":180,"wires":[]},{"id":"b1c7205cad2dc6f5","type":"mqtt in","z":"ae224a672bf6f825","name":"","topic":"alex9ufo/esp32/output/LED27","qos":"2","datatype":"auto","broker":"3d43a51a.c133a2","nl":false,"rap":true,"rh":0,"x":260,"y":240,"wires":[["e7170ace3e1b3a36"]]},{"id":"e7170ace3e1b3a36","type":"function","z":"ae224a672bf6f825","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":490,"y":240,"wires":[["48deae67419ff560"]]},{"id":"48deae67419ff560","type":"ui_led","z":"ae224a672bf6f825","order":20,"group":"fc89dc38.347898","width":"4","height":"3","label":"LED27","labelPlacement":"left","labelAlignment":"right","colorForValue":[{"color":"#000000","value":"false","valueType":"bool"},{"color":"#008000","value":"true","valueType":"bool"}],"allowColorForValueInMessage":false,"shape":"circle","showGlow":true,"name":"","x":690,"y":240,"wires":[]},{"id":"423ccd9d89be85ce","type":"mqtt in","z":"ae224a672bf6f825","name":"","topic":"alex9ufo/esp32/output/LED25","qos":"2","datatype":"auto","broker":"3d43a51a.c133a2","nl":false,"rap":true,"rh":0,"x":260,"y":300,"wires":[["f3bdebe0b5c0c6a7"]]},{"id":"f3bdebe0b5c0c6a7","type":"function","z":"ae224a672bf6f825","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":490,"y":300,"wires":[["be3ed9b7ab81c788"]]},{"id":"be3ed9b7ab81c788","type":"ui_led","z":"ae224a672bf6f825","order":20,"group":"fc89dc38.347898","width":"4","height":"3","label":"LED25","labelPlacement":"left","labelAlignment":"right","colorForValue":[{"color":"#000000","value":"false","valueType":"bool"},{"color":"#008000","value":"true","valueType":"bool"}],"allowColorForValueInMessage":false,"shape":"circle","showGlow":true,"name":"","x":690,"y":300,"wires":[]},{"id":"edcad47603ef9895","type":"mqtt in","z":"ae224a672bf6f825","name":"","topic":"alex9ufo/esp32/output/LED33","qos":"2","datatype":"auto","broker":"3d43a51a.c133a2","nl":false,"rap":true,"rh":0,"x":260,"y":360,"wires":[["a4fc899b944d4f4a"]]},{"id":"a4fc899b944d4f4a","type":"function","z":"ae224a672bf6f825","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":490,"y":360,"wires":[["5f5d5e66ec3c75d6"]]},{"id":"5f5d5e66ec3c75d6","type":"ui_led","z":"ae224a672bf6f825","order":20,"group":"fc89dc38.347898","width":"4","height":"3","label":"LED33","labelPlacement":"left","labelAlignment":"right","colorForValue":[{"color":"#000000","value":"false","valueType":"bool"},{"color":"#008000","value":"true","valueType":"bool"}],"allowColorForValueInMessage":false,"shape":"circle","showGlow":true,"name":"","x":690,"y":360,"wires":[]},{"id":"f470efa36426b1ca","type":"ui_switch","z":"ae224a672bf6f825","name":"","label":"switch LED2","tooltip":"","group":"fc89dc38.347898","order":36,"width":"4","height":"3","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":210,"y":460,"wires":[["e2380f5bf60ccd05"]],"info":"<i class=\"fa fa-camera-retro fa-3x\"></i> fa-3x"},{"id":"9f208840a41f233c","type":"mqtt out","z":"ae224a672bf6f825","name":"","topic":"alex9ufo/esp32/input/LED2","qos":"1","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"3d43a51a.c133a2","x":580,"y":460,"wires":[]},{"id":"e2380f5bf60ccd05","type":"function","z":"ae224a672bf6f825","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":370,"y":460,"wires":[["9f208840a41f233c"]]},{"id":"5b377b9abad9fc2f","type":"ui_switch","z":"ae224a672bf6f825","name":"","label":"switch LED26","tooltip":"","group":"fc89dc38.347898","order":36,"width":"4","height":"3","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":220,"y":520,"wires":[["894471f45c067144"]],"info":"<i class=\"fa fa-camera-retro fa-3x\"></i> fa-3x"},{"id":"9b720ae9ec9ea40e","type":"mqtt out","z":"ae224a672bf6f825","name":"","topic":"alex9ufo/esp32/input/LED26","qos":"1","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"3d43a51a.c133a2","x":580,"y":520,"wires":[]},{"id":"894471f45c067144","type":"function","z":"ae224a672bf6f825","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":370,"y":520,"wires":[["9b720ae9ec9ea40e"]]},{"id":"400fc53b166ea6e1","type":"ui_switch","z":"ae224a672bf6f825","name":"","label":"switch LED27","tooltip":"","group":"fc89dc38.347898","order":36,"width":"4","height":"3","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":220,"y":580,"wires":[["ab51d9d29ed9fe3f"]],"info":"<i class=\"fa fa-camera-retro fa-3x\"></i> fa-3x"},{"id":"446fb02eaefcbf22","type":"mqtt out","z":"ae224a672bf6f825","name":"","topic":"alex9ufo/esp32/input/LED27","qos":"1","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"3d43a51a.c133a2","x":580,"y":580,"wires":[]},{"id":"ab51d9d29ed9fe3f","type":"function","z":"ae224a672bf6f825","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":370,"y":580,"wires":[["446fb02eaefcbf22"]]},{"id":"6dc37f173e79fb6d","type":"ui_switch","z":"ae224a672bf6f825","name":"","label":"switch LED25","tooltip":"","group":"fc89dc38.347898","order":36,"width":"4","height":"3","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":220,"y":640,"wires":[["d248bac888b3e3cf"]],"info":"<i class=\"fa fa-camera-retro fa-3x\"></i> fa-3x"},{"id":"46c5da1e1ad080e5","type":"mqtt out","z":"ae224a672bf6f825","name":"","topic":"alex9ufo/esp32/input/LED25","qos":"1","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"3d43a51a.c133a2","x":580,"y":640,"wires":[]},{"id":"d248bac888b3e3cf","type":"function","z":"ae224a672bf6f825","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":370,"y":640,"wires":[["46c5da1e1ad080e5"]]},{"id":"65b69175691226e0","type":"ui_switch","z":"ae224a672bf6f825","name":"","label":"switch LED33","tooltip":"","group":"fc89dc38.347898","order":36,"width":"4","height":"3","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":220,"y":700,"wires":[["e09e09f4ca63ecf5"]],"info":"<i class=\"fa fa-camera-retro fa-3x\"></i> fa-3x"},{"id":"99f98c9b32e2ab2b","type":"mqtt out","z":"ae224a672bf6f825","name":"","topic":"alex9ufo/esp32/input/LED33","qos":"1","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"3d43a51a.c133a2","x":580,"y":700,"wires":[]},{"id":"e09e09f4ca63ecf5","type":"function","z":"ae224a672bf6f825","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":370,"y":700,"wires":[["99f98c9b32e2ab2b"]]},{"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":"RELAY","tab":"ec4c23e9246d7836","order":1,"disp":true,"width":"20","collapse":false,"className":""},{"id":"ec4c23e9246d7836","type":"ui_tab","name":"RELAY WEB","icon":"dashboard","disabled":false,"hidden":false}]

沒有留言:

張貼留言

2024產專班 作業2 (純模擬)

2024產專班 作業2  (純模擬) 1) LED ON,OFF,TIMER,FLASH 模擬 (switch 控制) 2)RFID卡號模擬 (buttom  模擬RFID UID(不從ESP32) Node-Red 程式 [{"id":"d8886...