ESP32 — MQTT 基本範例 (Node-Red , MQTT, SQLite)
ESP32 arduino程式 (WOKWI)
// Wifi 與 MQttClient 程式庫
#include <ArduinoMqttClient.h>
#include <WiFi.h>
int LED = 2; //定義LED接腳
char ssid[]="Wokwi-GUEST";
char pass[]="";
WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);
//const char broker[] = "test.mosquitto.org";
const char broker[] = "broker.mqtt-dashboard.com";
int port = 1883;
String json = "";
const char *SubTopic1 = "alex9ufo/led/led_event";
const char *PubTopic2 = "alex9ufo/led/led_status";
const char willTopic[] = "alex9ufo/led/Starting";
//===========================================================
//布林代數 LED狀態 是否連上網路ESP32 ready ?
bool ledState = false;
bool atwork = false;
bool Send = false; //true
String LEDjson = "";
int Count= 0;
bool Flash = false; //true
bool Timer = false; //true
//===========================================================
void onMqttMessage(int messageSize) {
// we received a message, print out the topic and contents
Serial.print("Received a message with topic '");
Serial.print(mqttClient.messageTopic());
String Topic= mqttClient.messageTopic();
Serial.print("', duplicate = ");
Serial.print(mqttClient.messageDup() ? "true" : "false");
Serial.print(", QoS = ");
Serial.print(mqttClient.messageQoS());
Serial.print(", retained = ");
Serial.print(mqttClient.messageRetain() ? "true" : "false");
Serial.print("', length ");
Serial.print(messageSize);
Serial.println(" bytes:");
String message="";
// use the Stream interface to print the contents
while (mqttClient.available()) {
//Serial.print((char)mqttClient.read());
message += (char)mqttClient.read();
}
Serial.println(message);
message.trim();
Topic.trim();
if (Topic=="alex9ufo/led/led_event") {
if (message == "on") {
digitalWrite(LED, LOW); // Turn on the LED
//ledState = true; //ledState = ture HIGH
//設定 各個 旗號
LEDjson ="ON";
Send = true ;
Serial.print("LED =");
Serial.println(LEDjson);
}
if (message == "off" ) {
digitalWrite(LED, HIGH); // Turn off the LED
//ledState = false; //ledState = false LOW
LEDjson ="OFF";
Send = true ;
Serial.print("LED =");
Serial.println(LEDjson);
}
if (message == "flash" ) {
digitalWrite(LED, HIGH); // Turn off the LED
Flash = true;
Timer = false;
LEDjson ="FLASH";
Send = true ;
Serial.print("LED =");
Serial.println(LEDjson);
}
if (message == "timer" ) {
digitalWrite(LED, LOW); // Turn off the LED
Flash = false;
Timer = true;
LEDjson ="TIMER";
Send = true ;
Count= 11;
Serial.print("LED =");
Serial.println(LEDjson);
}
Serial.println();
Serial.println("-----------------------");
}
}
//===========================================================
//副程式 setup wifi
void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid); //print ssid
WiFi.begin(ssid, pass); //初始化WiFi 函式庫並回傳目前的網路狀態
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
} //假設 wifi 未連接 show ………
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
//===========================================================
//判斷 旗號Flash , Timer 是否為真
void LED_Message() {
//判斷 旗號 Flash / timer 是否為真 ? 閃爍 定時
if (Flash){
digitalWrite(LED, !digitalRead(LED));
delay(500);
if (digitalRead(LED))
ledState = true;
else
ledState = false;
} //(Flash)
if (Timer) {
digitalWrite(LED, LOW);
delay(500);
if (digitalRead(LED))
ledState = true;
else
ledState = false;
Count=Count-1;
if (Count == 0 ){
Timer=false;
digitalWrite(LED, HIGH);
ledState = false;
}
} //(Timer)
////判斷 旗號 Send 是否為真 回傳MQTT訊息到MQTT Broker
if (Send) {
// Convert JSON string to character array
Serial.print("Publish message: ");
Serial.println(LEDjson);
LEDjson.trim();
bool retained = false;
int qos = 1;
bool dup = false;
// Publish JSON character array to MQTT topic
mqttClient.beginMessage(PubTopic2, LEDjson.length(), retained, qos, dup); //LED Status
mqttClient.print(LEDjson);
mqttClient.endMessage();
Send = false; //處理過後 旗號 Send為假
}
}
//===========================================================
void setup() {
pinMode(LED, OUTPUT);
digitalWrite(LED, HIGH); // Turn off the LED initially
//Initialize serial and wait for port to open:
Serial.begin(115200); // Initialize serial communications with the PC
while (!Serial); // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
setup_wifi();
Serial.println("You're connected to the network");
Serial.println();
String willPayload = "ESP32 Start working....!";
bool willRetain = true;
int willQos = 1;
mqttClient.beginWill(willTopic, willPayload.length(), willRetain, willQos);
mqttClient.print(willPayload);
mqttClient.endWill();
Serial.print("Attempting to connect to the MQTT broker: ");
Serial.println(broker);
if (!mqttClient.connect(broker, port)) {
Serial.print("MQTT connection failed! Error code = ");
Serial.println(mqttClient.connectError());
while (1);
}
Serial.println("You're connected to the MQTT broker!");
Serial.println();
// set the message receive callback
mqttClient.onMessage(onMqttMessage);
Serial.print("Subscribing to topic: ");
Serial.println(SubTopic1);
// subscribe to a topic
// the second parameter sets the QoS of the subscription,
// the the library supports subscribing at QoS 0, 1, or 2
int subscribeQos = 1;
mqttClient.subscribe(SubTopic1, subscribeQos);
}
//===========================================================
void loop() {
// call poll() regularly to allow the library to receive MQTT messages and
// send MQTT keep alives which avoids being disconnected by the broker
mqttClient.poll();
LED_Message();
}
////===========================================================
Node-Red程式
[{"id":"6db0792d589a26e2","type":"mqtt in","z":"c9d071441c94c0e7","name":"","topic":"alex9ufo/led/led_status","qos":"1","datatype":"auto","broker":"841df58d.ee5e98","nl":false,"rap":false,"inputs":0,"x":200,"y":120,"wires":[["a1cd3276635a9a62","738716cf2f80f8f7","64502c34c702da2c"]]},{"id":"a93f7ceda0044d1f","type":"ui_text","z":"c9d071441c94c0e7","group":"2025d633009cdf6e","order":1,"width":0,"height":0,"name":"","label":"ESP32發行到MQTT的資料","format":"{{msg.payload}}","layout":"col-center","className":"","x":600,"y":160,"wires":[]},{"id":"a4c4e644a52c93aa","type":"ui_button","z":"c9d071441c94c0e7","name":"","group":"2025d633009cdf6e","order":2,"width":3,"height":1,"passthru":false,"label":"LED 開","tooltip":"","color":"white","bgcolor":"","className":"","icon":"fa-circle","payload":"on","payloadType":"str","topic":"","topicType":"str","x":160,"y":480,"wires":[["23945966b4a86a62","43535048f522eeba","0e871c9b208638f4"]]},{"id":"2a584c35ac3d4198","type":"ui_button","z":"c9d071441c94c0e7","name":"","group":"2025d633009cdf6e","order":3,"width":3,"height":1,"passthru":false,"label":"LED 關","tooltip":"","color":"black","bgcolor":"","className":"","icon":"fa-circle-o","payload":"off","payloadType":"str","topic":"","topicType":"str","x":160,"y":520,"wires":[["23945966b4a86a62","43535048f522eeba","0e871c9b208638f4"]]},{"id":"23945966b4a86a62","type":"mqtt out","z":"c9d071441c94c0e7","name":"","topic":"alex9ufo/led/led_event","qos":"1","retain":"true","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"841df58d.ee5e98","x":440,"y":540,"wires":[]},{"id":"a1cd3276635a9a62","type":"function","z":"c9d071441c94c0e7","name":"Format timestamp","func":"var date = new Date();\nvar h = date.getHours()+8;\nvar m = date.getMinutes();\nvar s = date.getSeconds();\nif(h<10){\n h = '0'+h;\n}\nif(m<10){\n m = '0' + m;\n}\nif(s<10){\n s = '0' + s;\n}\nmsg.payload = msg.payload + ' --> Time:(' + h + ':' + m + ':' + s + ')' ;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":310,"y":300,"wires":[["ee09d17a600f5750"]]},{"id":"ee09d17a600f5750","type":"function","z":"c9d071441c94c0e7","name":"Set Line API ","func":"msg.headers = {'content-type':'application/x-www-form-urlencoded','Authorization':'Bearer A4wwPNh2WqB7dlfeQyyIAwtggn1kfZSI5LkkCdia1gB'};\nmsg.payload = {\"message\":msg.payload};\nreturn msg;\n\n//oR7KdXvK1eobRr2sRRgsl4PMq23DjDlhfUs96SyUBZu","outputs":1,"noerr":0,"x":490,"y":300,"wires":[["8ae42888b0eda1c3"]]},{"id":"8ae42888b0eda1c3","type":"http request","z":"c9d071441c94c0e7","name":"","method":"POST","ret":"txt","paytoqs":false,"url":"https://notify-api.line.me/api/notify","tls":"","persist":false,"proxy":"","authType":"","x":640,"y":300,"wires":[["db7f3839ab3d8949"]]},{"id":"db7f3839ab3d8949","type":"debug","z":"c9d071441c94c0e7","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":790,"y":300,"wires":[]},{"id":"738716cf2f80f8f7","type":"debug","z":"c9d071441c94c0e7","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":450,"y":120,"wires":[]},{"id":"e1120ef4f7246745","type":"ui_audio","z":"c9d071441c94c0e7","name":"","group":"2025d633009cdf6e","voice":"Microsoft Hanhan - Chinese (Traditional, Taiwan)","always":true,"x":540,"y":200,"wires":[]},{"id":"64502c34c702da2c","type":"function","z":"c9d071441c94c0e7","name":"","func":"var st1;\nif (msg.payload === \"ON\") {\n st1=\"LED開\"; \n} \nelse if (msg.payload === \"OFF\") {\n st1=\"LED關\";\n}\nelse if (msg.payload === \"FLASH\") {\n st1=\"LED閃爍\";\n}\nelse if (msg.payload === \"TIMER\") {\n st1=\"LED開五秒鐘\";\n}\nelse if (msg.payload === \"TOGGLE\") {\n st1=\"LED ON OFF 交換\";\n}\n\nmsg.payload=st1;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":370,"y":200,"wires":[["e1120ef4f7246745","a93f7ceda0044d1f","a786898f9d4ec211"]]},{"id":"66ca15b53c7abef6","type":"ui_button","z":"c9d071441c94c0e7","name":"","group":"2025d633009cdf6e","order":4,"width":3,"height":1,"passthru":false,"label":"LED 開5秒鐘","tooltip":"","color":"purple","bgcolor":"","className":"","icon":"fa-circle-o","payload":"timer","payloadType":"str","topic":"","topicType":"str","x":170,"y":600,"wires":[["23945966b4a86a62","43535048f522eeba","0e871c9b208638f4"]]},{"id":"a786898f9d4ec211","type":"function","z":"c9d071441c94c0e7","name":"INSERT","func":"//msg.topic = \"INSERT INTO LED (time_led, led_status) VALUES (?,?)\";\n\nvar status= msg.payload;\n\nvar Today = new Date();\nvar yyyy = Today.getFullYear(); //年\nvar MM = Today.getMonth()+1; //月\nvar dd = Today.getDate(); //日\nvar h = Today.getHours(); //時\nvar m = Today.getMinutes(); //分\nvar s = Today.getSeconds(); //秒\n\nif(MM<10)\n{\n MM = '0'+MM;\n}\n\nif(dd<10)\n{\n dd = '0'+dd;\n}\n\nif(h<10)\n{\n h = '0'+h;\n}\n\nif(m<10)\n{\n m = '0' + m;\n}\n\nif(s<10)\n{\n s = '0' + s;\n}\n\nvar hms= yyyy + '/'+ MM + '/'+ dd + ' ' + h + ':' + m + ':' + s ;\n// Create a Params variable\n// with a time and value component\n//\nmsg.params = { $thetime: hms, $thestatus:msg.payload }\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":540,"y":240,"wires":[["8bb87a4be04a5509"]]},{"id":"8bb87a4be04a5509","type":"sqlite","z":"c9d071441c94c0e7","mydb":"19f59ce9.3edc23","sqlquery":"prepared","sql":"insert into LED (time_led, led_status) values ($thetime , $thestatus)","name":"LED Status","x":690,"y":240,"wires":[["75a3547496ae3f33","13b3be8f4aa11d89"]]},{"id":"75a3547496ae3f33","type":"debug","z":"c9d071441c94c0e7","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":870,"y":240,"wires":[]},{"id":"35ae4925ad06e2a7","type":"comment","z":"c9d071441c94c0e7","name":"Node-Red publish 到 HiveMQ Broker , ESP32訂閱","info":"將 alex9ufo/inTopic 到(publish)HiveMQ Broker \n給 Arduino 訂閱(Subscribe)","x":290,"y":640,"wires":[]},{"id":"673a65ce219a2776","type":"comment","z":"c9d071441c94c0e7","name":"ESP32向 HiveMQ Broker發行 Node-Red 訂閱subscribe","info":"將 Arduino 發行到(publish)HiveMQ Broker alex9ufo/led/led_status \n給 Node-red 或 MQTTB-Box 訂閱(Subscribe)","x":300,"y":80,"wires":[]},{"id":"46bef94da56e9e35","type":"ui_button","z":"c9d071441c94c0e7","name":"","group":"2025d633009cdf6e","order":5,"width":3,"height":1,"passthru":false,"label":"LED 閃爍","tooltip":"","color":"yellow","bgcolor":"","className":"","icon":"fa-circle-o","payload":"flash","payloadType":"str","topic":"","topicType":"str","x":160,"y":560,"wires":[["23945966b4a86a62","43535048f522eeba","0e871c9b208638f4"]]},{"id":"43535048f522eeba","type":"ui_audio","z":"c9d071441c94c0e7","name":"","group":"2025d633009cdf6e","voice":"Microsoft Hanhan - Chinese (Traditional, Taiwan)","always":true,"x":420,"y":600,"wires":[]},{"id":"0e871c9b208638f4","type":"ui_text","z":"c9d071441c94c0e7","group":"2025d633009cdf6e","order":8,"width":0,"height":0,"name":"","label":"Node-RED發行到MQTT的資料","format":"{{msg.payload}}","layout":"row-center","className":"","x":470,"y":480,"wires":[]},{"id":"8c5d0970feee3d0a","type":"function","z":"c9d071441c94c0e7","name":"產生資料庫TABLE","func":"msg.topic = ' CREATE TABLE \"LED\" (\t\"id\"\tINTEGER,\t\"time_led\"\tTEXT,\"led_status\"\tTEXT,PRIMARY KEY(\"id\" AUTOINCREMENT))';\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":490,"y":400,"wires":[["cb600b16db5ab028"]]},{"id":"ce0b5a66dea91b1c","type":"inject","z":"c9d071441c94c0e7","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":290,"y":380,"wires":[["8c5d0970feee3d0a"]]},{"id":"acd66448686808e1","type":"ui_button","z":"c9d071441c94c0e7","name":"建立LED資料庫(只能執行一次)","group":"2025d633009cdf6e","order":7,"width":6,"height":1,"passthru":false,"label":"建立LED資料庫(只能執行一次)","tooltip":"","color":"","bgcolor":"","className":"","icon":"","payload":"","payloadType":"str","topic":"","topicType":"str","x":230,"y":420,"wires":[["8c5d0970feee3d0a"]]},{"id":"cb600b16db5ab028","type":"sqlite","z":"c9d071441c94c0e7","mydb":"19f59ce9.3edc23","sqlquery":"msg.topic","sql":"","name":"LED Status","x":710,"y":400,"wires":[["b24d5177b932f26d","5b354bf0fac7500b"]]},{"id":"b24d5177b932f26d","type":"debug","z":"c9d071441c94c0e7","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":870,"y":480,"wires":[]},{"id":"5b354bf0fac7500b","type":"ui_template","z":"c9d071441c94c0e7","group":"2025d633009cdf6e","name":"","order":9,"width":12,"height":5,"format":"<table style=\"width:100%\">\n <tr>\n <th>Index</th> \n <th> Time</th> \n <th>Status</th>\n </tr>\n <tr ng-repeat=\"x in msg.payload | limitTo:100\">\n <td> {{$index}}</td>\n <td> {{msg.payload[$index].time_led }}</td>\n <td> {{msg.payload[$index].led_status}}</td> \n </tr>\n</table>\n","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":false,"templateScope":"local","className":"","x":860,"y":400,"wires":[[]]},{"id":"ea79e094492fca0a","type":"ui_button","z":"c9d071441c94c0e7","name":"","group":"2025d633009cdf6e","order":6,"width":6,"height":1,"passthru":false,"label":"檢視LED資料庫","tooltip":"","color":"","bgcolor":"","className":"","icon":"","payload":"檢視LED資料庫","payloadType":"str","topic":"SELECT * FROM LED ORDER BY id DESC LIMIT 100;","topicType":"str","x":500,"y":440,"wires":[["cb600b16db5ab028"]]},{"id":"81806107feb4aff6","type":"mqtt in","z":"c9d071441c94c0e7","name":"","topic":"alex9ufo/led/led_event","qos":"1","datatype":"auto","broker":"841df58d.ee5e98","nl":false,"rap":false,"inputs":0,"x":200,"y":680,"wires":[["b260d4e2a11c596b"]]},{"id":"b260d4e2a11c596b","type":"debug","z":"c9d071441c94c0e7","name":"debug 302","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":430,"y":680,"wires":[]},{"id":"66b239493f69d8ac","type":"comment","z":"c9d071441c94c0e7","name":"Line API","info":"","x":280,"y":260,"wires":[]},{"id":"13b3be8f4aa11d89","type":"function","z":"c9d071441c94c0e7","name":"function View","func":"msg.topic = \"SELECT * FROM LED ORDER BY id DESC LIMIT 100\";\nreturn msg;\n\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":490,"y":360,"wires":[["cb600b16db5ab028"]]},{"id":"841df58d.ee5e98","type":"mqtt-broker","name":"","broker":"broker.mqtt-dashboard.com","port":"1883","clientid":"","autoConnect":true,"usetls":false,"compatmode":false,"protocolVersion":"4","keepalive":"15","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""},{"id":"2025d633009cdf6e","type":"ui_group","name":"LED","tab":"2eed7cc3b24b8f69","order":1,"disp":true,"width":"12","collapse":false,"className":""},{"id":"19f59ce9.3edc23","type":"sqlitedb","db":"C:\\Users\\User\\.node-red\\EX2_1_2024.db","mode":"RWC"},{"id":"2eed7cc3b24b8f69","type":"ui_tab","name":"WOKWI_LED","icon":"dashboard","order":125,"disabled":false,"hidden":false}]
沒有留言:
張貼留言