Node Red MQTT
https://hackmd.io/@joe94113/node-red_mqtt_esp32_and_open_api
wokwi程式 修改mqtt_server = "broker.mqtt-dashboard.com"; // MQTT 服務器地址
#include <WiFi.h>
#include <PubSubClient.h>
#include <DHTesp.h>
const int DHT_PIN = 15; // DHT 感測器的連接 PIN
DHTesp dht;
const char* ssid = "Wokwi-GUEST"; // WiFi SSID
const char* password = ""; // WiFi 密碼
const char* mqtt_server = "broker.mqtt-dashboard.com"; // MQTT 服務器地址
WiFiClient espClient;
PubSubClient client(espClient);
unsigned long lastMsg = 0; // 記錄上一次消息發送的時間
float temp = 0; // 溫度變量
float hum = 0; // 濕度變量
// 設置 WiFi 連接
void setup_wifi() {
delay(10);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
// 等待 WiFi 連接
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
randomSeed(micros());
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
// MQTT 消息回調函數
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
}
// 重連 MQTT 服務器
void reconnect() {
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
String clientId = "ESP32Client-";
clientId += String(random(0xffff), HEX);
if (client.connect(clientId.c_str())) {
Serial.println("Connected");
client.publish("/ThinkIOT/Publish", "Welcome");
client.subscribe("/ThinkIOT/Subscribe");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
// 初始化設置
void setup() {
pinMode(2, OUTPUT);
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
dht.setup(DHT_PIN, DHTesp::DHT22); // 初始化 DHT22
}
// 主循環
void loop() {
// 如果未連接 MQTT,則嘗試重新連接
if (!client.connected()) {
reconnect();
}
client.loop();
unsigned long now = millis();
if (now - lastMsg > 2000) { // 每 2 秒發布一次數據
lastMsg = now;
TempAndHumidity data = dht.getTempAndHumidity();
String temp = String(data.temperature, 2);
client.publish("/Thinkitive/temp", temp.c_str()); // 發布溫度數據
String hum = String(data.humidity, 1);
client.publish("/Thinkitive/hum", hum.c_str()); // 發布濕度數據
Serial.print("Temperature: ");
Serial.println(temp);
Serial.print("Humidity: ");
Serial.println(hum);
}
}
看到這個提示別擔心,這通常是因為瀏覽器基於安全性考量暫時關閉了腳本功能。只要幾個簡單的步驟就能重新開啟。
以下是針對目前主流瀏覽器的開啟教學:
1. Google Chrome (電腦版)
點擊瀏覽器右上角的 「三個點」 圖示,選擇 「設定」。
在左側選單點擊 「隱私權和安全性」。
點擊 「網站設定」。
向下滑動找到「內容」區塊,點擊 「JavaScript」。
勾選 「網站可以使用 JavaScript」。
回到原本的網頁並 重新整理 (F5)。
2. Microsoft Edge
點擊右上角的 「三個點」 圖示,選擇 「設定」。
在左側選單選擇 「Cookie 和網站權限」。
在「所有權限」清單中找到並點擊 「JavaScript」。
將 「允許 (建議)」 的開關切換為 開啟狀態。
重新整理網頁。
Node-RED 中安裝 MQTT broker 的步驟,並可以開始使用 MQTT 進行消息傳輸[{"id":"073cac6e5e434d41","type":"mqtt out","z":"de93e29c07cca82f","name":"","topic":"sensors/livingroom/temp","qos":"","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"841df58d.ee5e98","x":310,"y":180,"wires":[]},{"id":"ceb8068819adc757","type":"inject","z":"de93e29c07cca82f","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":"","topic":"","payload":"22","payloadType":"num","x":110,"y":180,"wires":[["073cac6e5e434d41"]]},{"id":"5fc97feb1b566004","type":"mqtt in","z":"de93e29c07cca82f","name":"","topic":"sensors/livingroom/temp","qos":"2","datatype":"auto-detect","broker":"841df58d.ee5e98","nl":false,"rap":false,"inputs":0,"x":150,"y":260,"wires":[["6c6dc58f97ab8f86"]]},{"id":"6c6dc58f97ab8f86","type":"debug","z":"de93e29c07cca82f","name":"","active":true,"console":"false","complete":"false","x":350,"y":260,"wires":[]},{"id":"bcca028dd9cde448","type":"debug","z":"de93e29c07cca82f","name":"debug 19","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":340,"y":40,"wires":[]},{"id":"20f600cc71d280e5","type":"debug","z":"de93e29c07cca82f","name":"debug 20","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":340,"y":100,"wires":[]},{"id":"a4ee27d876e6c883","type":"aedes broker","z":"de93e29c07cca82f","name":"","mqtt_port":"1884","mqtt_ws_bind":"port","mqtt_ws_port":"","mqtt_ws_path":"","cert":"","key":"","ca":"","certname":"","keyname":"","caname":"","persistence_bind":"memory","dburl":"","persist_to_file":false,"usetls":false,"x":130,"y":80,"wires":[["bcca028dd9cde448"],["20f600cc71d280e5"]]},{"id":"841df58d.ee5e98","type":"mqtt-broker","name":"","broker":"broker.hivemq.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":""}]
Node-RED 中配置 MQTT 並訂閱 ESP32 發送資料
[{"id":"06616414d9f0a6f3","type":"aedes broker","z":"3b843e74e7ab6ef8","name":"","mqtt_port":"1884","mqtt_ws_bind":"port","mqtt_ws_port":"","mqtt_ws_path":"","cert":"","key":"","certname":"","keyname":"","dburl":"","usetls":false,"x":130,"y":80,"wires":[["866a2384f6992b64"],["b013bf4fca5a488e"]]},{"id":"866a2384f6992b64","type":"debug","z":"3b843e74e7ab6ef8","name":"debug 19","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":340,"y":40,"wires":[]},{"id":"b013bf4fca5a488e","type":"debug","z":"3b843e74e7ab6ef8","name":"debug 20","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":340,"y":100,"wires":[]},{"id":"ceb3112cd35e970e","type":"mqtt in","z":"3b843e74e7ab6ef8","name":"","topic":"/Thinkitive/temp","qos":"0","datatype":"auto-detect","broker":"b9efc827e98bf7f9","nl":false,"rap":true,"rh":0,"inputs":0,"x":120,"y":180,"wires":[["7c6bdec976aab81d"]]},{"id":"a51c937face296dc","type":"mqtt in","z":"3b843e74e7ab6ef8","name":"","topic":"/Thinkitive/hum","qos":"0","datatype":"auto-detect","broker":"b9efc827e98bf7f9","nl":false,"rap":true,"rh":0,"inputs":0,"x":120,"y":240,"wires":[["f06f1d6381b63b69"]]},{"id":"7c6bdec976aab81d","type":"ui_gauge","z":"3b843e74e7ab6ef8","name":"TRMP","group":"70d1d491db52e4fe","order":7,"width":6,"height":4,"gtype":"gage","title":"ESP32溫度","label":"","format":"{{value}}","min":0,"max":"150","colors":["#00b500","#e6e600","#ec2727"],"seg1":"","seg2":"","diff":false,"className":"","x":330,"y":180,"wires":[]},{"id":"f06f1d6381b63b69","type":"ui_gauge","z":"3b843e74e7ab6ef8","name":"","group":"70d1d491db52e4fe","order":12,"width":6,"height":4,"gtype":"gage","title":"ESP32濕度","label":"","format":"{{value}}","min":0,"max":"60","colors":["#15cb15","#e6e600","#ca3838"],"seg1":"","seg2":"","diff":false,"className":"","x":350,"y":240,"wires":[]},{"id":"b9efc827e98bf7f9","type":"mqtt-broker","name":"broker.mqtt-dashboard.com","broker":"broker.mqtt-dashboard.com","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"autoUnsubscribe":true,"birthTopic":"","birthQos":"0","birthRetain":"false","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closeRetain":"false","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willRetain":"false","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""},{"id":"70d1d491db52e4fe","type":"ui_group","name":"esp32圖表","tab":"2156c1cf7f043d72","order":2,"disp":true,"width":"6","collapse":false,"className":""},{"id":"2156c1cf7f043d72","type":"ui_tab","name":"天氣圖表","icon":"dashboard","disabled":false,"hidden":false}]
Node-RED 中連接到一個公開的氣象資料 API,並抓取各地區的溫度等氣象資訊
[{"id":"84974e3b6b184603","type":"aedes broker","z":"ee949a679aeaac8d","name":"","mqtt_port":"1883","mqtt_ws_bind":"port","mqtt_ws_port":"","mqtt_ws_path":"","cert":"","key":"","ca":"","certname":"","keyname":"","caname":"","persistence_bind":"memory","dburl":"","persist_to_file":false,"usetls":false,"x":110,"y":60,"wires":[["d3d0db98037eb5a0"],["221c64cb507138ba"]]},{"id":"d3d0db98037eb5a0","type":"debug","z":"ee949a679aeaac8d","name":"debug 19","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":320,"y":40,"wires":[]},{"id":"221c64cb507138ba","type":"debug","z":"ee949a679aeaac8d","name":"debug 20","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":320,"y":80,"wires":[]},{"id":"7a50625e9de576f5","type":"mqtt out","z":"ee949a679aeaac8d","name":"","topic":"sensors/livingroom/temp","qos":"","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"9aa0e63a7fe55694","x":590,"y":160,"wires":[]},{"id":"bf5d80bdee7081a3","type":"mqtt in","z":"ee949a679aeaac8d","name":"","topic":"sensors/livingroom/temp","qos":"2","datatype":"auto-detect","broker":"9aa0e63a7fe55694","nl":false,"rap":false,"inputs":0,"x":130,"y":220,"wires":[["b5a377175f3a3413","80fc5a39dcdee086","90567bb2394770f0","a54071ebf5b7899e","8210955ad042a18f"]]},{"id":"b5a377175f3a3413","type":"debug","z":"ee949a679aeaac8d","name":"mqTT_In","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":420,"y":220,"wires":[]},{"id":"ea0a92334afe9e73","type":"ui_dropdown","z":"ee949a679aeaac8d","name":"","label":"選擇地區","tooltip":"","place":"點擊選擇","group":"f1ec0c040bdd2739","order":37,"width":6,"height":1,"passthru":true,"multiple":false,"options":[{"label":"桃園","value":"桃園","type":"str"},{"label":"苗栗","value":"苗栗","type":"str"},{"label":"南投","value":"南投","type":"str"},{"label":"彰化","value":"埤頭","type":"str"},{"label":"台中","value":"中坑","type":"str"},{"label":"雲林","value":"斗六","type":"str"},{"label":"嘉義","value":"水上","type":"str"},{"label":"台南","value":"安南","type":"str"},{"label":"屏東","value":"九如","type":"str"},{"label":"台東","value":"延平","type":"str"},{"label":"花蓮","value":"豐濱","type":"str"},{"label":"宜蘭","value":"三星","type":"str"},{"label":"高雄","value":"三民","type":"str"},{"label":"台北","value":"平等","type":"str"}],"payload":"","topic":"topic","topicType":"msg","className":"","x":80,"y":160,"wires":[["1610a92a9b0c39de"]]},{"id":"1610a92a9b0c39de","type":"http request","z":"ee949a679aeaac8d","name":"","method":"GET","ret":"txt","paytoqs":"ignore","url":"https://opendata.cwa.gov.tw/api/v1/rest/datastore/O-A0001-001?Authorization=CWB-40C25FFF-1224-4250-B9D9-3735AAE17DBF&limit=10&format=JSON&StationName={{payload}}&WeatherElement=Weather,Now,WindSpeed,AirTemperature,RelativeHumidity,AirPressure&GeoInfo=CountyName","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":240,"y":160,"wires":[["aa1c124b347003ba"]]},{"id":"aa1c124b347003ba","type":"json","z":"ee949a679aeaac8d","name":"","property":"payload","action":"","pretty":false,"x":390,"y":160,"wires":[["7a50625e9de576f5"]]},{"id":"80fc5a39dcdee086","type":"ui_gauge","z":"ee949a679aeaac8d","name":"","group":"f1ec0c040bdd2739","order":39,"width":6,"height":4,"gtype":"gage","title":"氣溫","label":"度","format":"{{payload.records.Station[0].WeatherElement.AirTemperature}}","min":0,"max":"40","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","diff":false,"className":"","x":410,"y":260,"wires":[]},{"id":"90567bb2394770f0","type":"ui_gauge","z":"ee949a679aeaac8d","name":"","group":"f1ec0c040bdd2739","order":40,"width":6,"height":4,"gtype":"gage","title":"風速","label":"m/s","format":"{{payload.records.Station[0].WeatherElement.WindSpeed}}","min":0,"max":"10","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","diff":false,"className":"","x":410,"y":300,"wires":[]},{"id":"a54071ebf5b7899e","type":"ui_gauge","z":"ee949a679aeaac8d","name":"","group":"f1ec0c040bdd2739","order":41,"width":6,"height":4,"gtype":"gage","title":"相對濕度","label":"%","format":"{{payload.records.Station[0].WeatherElement.RelativeHumidity}}","min":"50","max":"100","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","diff":false,"className":"","x":420,"y":340,"wires":[]},{"id":"8210955ad042a18f","type":"ui_gauge","z":"ee949a679aeaac8d","name":"","group":"f1ec0c040bdd2739","order":42,"width":6,"height":4,"gtype":"gage","title":"空氣壓力","label":"atm","format":"{{payload.records.Station[0].WeatherElement.AirPressure}}","min":"900","max":"1100","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","diff":false,"className":"","x":420,"y":380,"wires":[]},{"id":"9aa0e63a7fe55694","type":"mqtt-broker","name":"","broker":"localhost","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"autoUnsubscribe":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""},{"id":"f1ec0c040bdd2739","type":"ui_group","name":"天氣","tab":"2156c1cf7f043d72","order":1,"disp":true,"width":12,"collapse":false,"className":""},{"id":"2156c1cf7f043d72","type":"ui_tab","name":"天氣圖表","icon":"dashboard","disabled":false,"hidden":false}]
兩個圖表一起顯示 Node-Red
[{"id":"229d489a86aaea93","type":"mqtt out","z":"8c31de38cd0a6981","name":"","topic":"sensors/livingroom/temp","qos":"","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"78f412356543fd12","x":630,"y":220,"wires":[]},{"id":"adaec6df5a6580fb","type":"mqtt in","z":"8c31de38cd0a6981","name":"","topic":"sensors/livingroom/temp","qos":"2","datatype":"auto-detect","broker":"78f412356543fd12","nl":false,"rap":false,"inputs":0,"x":630,"y":260,"wires":[["ae695b84fba5fc23","9ed7c60684d641e1","518b5e5ea5836bdd","61ae7765a9f9edf5","0b113fc7b52cbfdb"]]},{"id":"ae695b84fba5fc23","type":"debug","z":"8c31de38cd0a6981","name":"mqTT_In","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":880,"y":200,"wires":[]},{"id":"e2e6628b7bde7a1b","type":"aedes broker","z":"8c31de38cd0a6981","name":"","mqtt_port":1883,"mqtt_ws_bind":"port","mqtt_ws_port":"","mqtt_ws_path":"","cert":"","key":"","certname":"","keyname":"","dburl":"","usetls":false,"x":150,"y":60,"wires":[["f0ae9594e8fe0786"],["0243ee57c33cba12"]]},{"id":"f0ae9594e8fe0786","type":"debug","z":"8c31de38cd0a6981","name":"debug 19","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":360,"y":40,"wires":[]},{"id":"0243ee57c33cba12","type":"debug","z":"8c31de38cd0a6981","name":"debug 20","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":360,"y":80,"wires":[]},{"id":"f50edc83dba4da17","type":"ui_dropdown","z":"8c31de38cd0a6981","name":"","label":"選擇地區","tooltip":"","place":"點擊選擇","group":"f1ec0c040bdd2739","order":2,"width":6,"height":1,"passthru":true,"multiple":false,"options":[{"label":"桃園","value":"桃園","type":"str"},{"label":"苗栗","value":"苗栗","type":"str"},{"label":"南投","value":"南投","type":"str"},{"label":"彰化","value":"埤頭","type":"str"},{"label":"台中","value":"中坑","type":"str"},{"label":"雲林","value":"斗六","type":"str"},{"label":"嘉義","value":"水上","type":"str"},{"label":"台南","value":"安南","type":"str"},{"label":"屏東","value":"九如","type":"str"},{"label":"台東","value":"延平","type":"str"},{"label":"花蓮","value":"豐濱","type":"str"},{"label":"宜蘭","value":"三星","type":"str"},{"label":"高雄","value":"三民","type":"str"},{"label":"台北","value":"平等","type":"str"}],"payload":"","topic":"topic","topicType":"msg","className":"","x":120,"y":220,"wires":[["14e3088564d30c0c","cb6bc9284f648b45"]]},{"id":"e51d55930ce8853e","type":"json","z":"8c31de38cd0a6981","name":"","property":"payload","action":"","pretty":false,"x":430,"y":220,"wires":[["229d489a86aaea93"]]},{"id":"9ed7c60684d641e1","type":"ui_gauge","z":"8c31de38cd0a6981","name":"","group":"f1ec0c040bdd2739","order":6,"width":5,"height":3,"gtype":"gage","title":"氣溫","label":"度","format":"{{payload.records.Station[0].WeatherElement.AirTemperature}}","min":0,"max":"40","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","diff":false,"className":"","x":870,"y":240,"wires":[]},{"id":"518b5e5ea5836bdd","type":"ui_gauge","z":"8c31de38cd0a6981","name":"","group":"f1ec0c040bdd2739","order":4,"width":5,"height":3,"gtype":"gage","title":"風速","label":"m/s","format":"{{payload.records.Station[0].WeatherElement.WindSpeed}}","min":0,"max":"10","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","diff":false,"className":"","x":870,"y":280,"wires":[]},{"id":"61ae7765a9f9edf5","type":"ui_gauge","z":"8c31de38cd0a6981","name":"","group":"f1ec0c040bdd2739","order":10,"width":5,"height":3,"gtype":"gage","title":"相對濕度","label":"%","format":"{{payload.records.Station[0].WeatherElement.RelativeHumidity}}","min":"50","max":"100","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","diff":false,"className":"","x":880,"y":320,"wires":[]},{"id":"0b113fc7b52cbfdb","type":"ui_gauge","z":"8c31de38cd0a6981","name":"","group":"f1ec0c040bdd2739","order":12,"width":5,"height":3,"gtype":"gage","title":"空氣壓力","label":"atm","format":"{{payload.records.Station[0].WeatherElement.AirPressure}}","min":"900","max":"1100","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","diff":false,"className":"","x":880,"y":360,"wires":[]},{"id":"14e3088564d30c0c","type":"debug","z":"8c31de38cd0a6981","name":"debug 22","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":280,"y":140,"wires":[]},{"id":"d17279b29e0e15aa","type":"http in","z":"8c31de38cd0a6981","name":"","url":"/weather-app","method":"get","upload":false,"swaggerDoc":"","x":150,"y":320,"wires":[["19625023b6920da9"]]},{"id":"19625023b6920da9","type":"template","z":"8c31de38cd0a6981","name":"JS版本氣象html","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Weather Display</title>\n <style>\n body {\n font-family: 'Arial', sans-serif;\n margin: 0;\n padding: 0;\n background-color: #f4f4f4;\n color: #333;\n }\n\n .weather-container {\n margin-top: 20px;\n background-color: white;\n padding: 20px;\n border-radius: 8px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n width: 300px; /* 固定寬度 */\n }\n\n #stationSelect {\n padding: 8px;\n border-radius: 4px;\n border: 1px solid #ddd;\n margin-top: 20px;\n }\n\n h1, p {\n margin: 10px 0;\n }\n\n #city {\n font-size: 1.5em;\n color: #0275d8;\n }\n\n #weather {\n font-size: 1.2em;\n color: #5cb85c;\n }\n\n #temperature {\n font-size: 1.4em;\n color: #f0ad4e;\n }\n\n /* 響應式布局 */\n @media (max-width: 600px) {\n .weather-container {\n width: 90%;\n margin: 20px auto;\n }\n }\n\n </style>\n</head>\n<body>\n <div>\n <label for=\"stationSelect\">Choose a station:</label>\n <select id=\"stationSelect\">\n <option value=\"桃園\">桃園</option>\n <option value=\"苗栗\">苗栗</option>\n <option value=\"南投\">南投</option>\n <option value=\"埤頭\">彰化</option>\n <option value=\"中坑\">台中</option>\n <option value=\"安南\">台南</option>\n <!-- 更多選項 -->\n </select>\n </div>\n <div class=\"weather-container\">\n <h1 id=\"city\"></h1>\n <p id=\"weather\"></p>\n <p id=\"temperature\"></p>\n </div>\n <script>\n document.getElementById('stationSelect').addEventListener('change', (event) => {\n fetchWeatherData(event.target.value);\n });\n\n function fetchWeatherData(stationName) {\n const apiUrl = `https://opendata.cwa.gov.tw/api/v1/rest/datastore/O-A0001-001?Authorization=your-token&limit=10&format=JSON&StationName=${stationName}&WeatherElement=Weather,Now,WindSpeed,AirTemperature,RelativeHumidity,AirPressure&GeoInfo=CountyName`;\n\n fetch(apiUrl)\n .then(response => {\n if (!response.ok) {\n throw new Error('Network response was not ok');\n }\n return response.json();\n })\n .then(data => {\n console.log(data)\n updateWeatherDisplay(data);\n })\n .catch(error => {\n console.error('There has been a problem with your fetch operation:', error);\n });\n }\n\n function updateWeatherDisplay(data) {\n const temperature = data.records.Station[0]['WeatherElement']['AirTemperature'];\n document.getElementById('temperature').textContent = temperature;\n const weather = data.records.Station[0]['WeatherElement']['Weather'];\n document.getElementById('weather').textContent = weather;\n const city = data.records.Station[0]['GeoInfo']['CountyName'];\n document.getElementById('city').textContent = city;\n }\n\n // 初始化,載入頁面時自動加載預設站點的天氣數據\n fetchWeatherData(document.getElementById('stationSelect').value);\n\n </script>\n</body>\n</html>","output":"str","x":340,"y":320,"wires":[["1e0d037f5b8791d1"]]},{"id":"1e0d037f5b8791d1","type":"http response","z":"8c31de38cd0a6981","name":"","statusCode":"","headers":{},"x":510,"y":320,"wires":[]},{"id":"b9319af08c19eec4","type":"mqtt in","z":"8c31de38cd0a6981","name":"","topic":"/Thinkitive/temp","qos":"0","datatype":"auto-detect","broker":"b9efc827e98bf7f9","nl":false,"rap":true,"rh":0,"inputs":0,"x":140,"y":400,"wires":[["da1f699dede14640"]]},{"id":"9aca9e818558523e","type":"mqtt in","z":"8c31de38cd0a6981","name":"","topic":"/Thinkitive/hum","qos":"0","datatype":"auto-detect","broker":"b9efc827e98bf7f9","nl":false,"rap":true,"rh":0,"inputs":0,"x":140,"y":460,"wires":[["fff84846812b56a8"]]},{"id":"da1f699dede14640","type":"ui_gauge","z":"8c31de38cd0a6981","name":"TRMP","group":"70d1d491db52e4fe","order":1,"width":0,"height":0,"gtype":"gage","title":"ESP32溫度","label":"","format":"{{value}}","min":0,"max":"150","colors":["#00b500","#e6e600","#ec2727"],"seg1":"","seg2":"","diff":false,"className":"","x":350,"y":400,"wires":[]},{"id":"fff84846812b56a8","type":"ui_gauge","z":"8c31de38cd0a6981","name":"","group":"70d1d491db52e4fe","order":2,"width":0,"height":0,"gtype":"gage","title":"ESP32濕度","label":"","format":"{{value}}","min":0,"max":"60","colors":["#15cb15","#e6e600","#ca3838"],"seg1":"","seg2":"","diff":false,"className":"","x":370,"y":460,"wires":[]},{"id":"cb6bc9284f648b45","type":"http request","z":"8c31de38cd0a6981","name":"","method":"GET","ret":"txt","paytoqs":"ignore","url":"https://opendata.cwa.gov.tw/api/v1/rest/datastore/O-A0001-001?Authorization=CWB-40C25FFF-1224-4250-B9D9-3735AAE17DBF&limit=10&format=JSON&StationName={{payload}}&WeatherElement=Weather,Now,WindSpeed,AirTemperature,RelativeHumidity,AirPressure&GeoInfo=CountyName","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":280,"y":220,"wires":[["e51d55930ce8853e"]]},{"id":"78f412356543fd12","type":"mqtt-broker","name":"","broker":"localhost","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"autoUnsubscribe":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""},{"id":"f1ec0c040bdd2739","type":"ui_group","name":"天氣","tab":"2156c1cf7f043d72","order":1,"disp":true,"width":12,"collapse":false,"className":""},{"id":"b9efc827e98bf7f9","type":"mqtt-broker","name":"broker.mqtt-dashboard.com","broker":"broker.mqtt-dashboard.com","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"autoUnsubscribe":true,"birthTopic":"","birthQos":"0","birthRetain":"false","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closeRetain":"false","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willRetain":"false","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""},{"id":"70d1d491db52e4fe","type":"ui_group","name":"esp32圖表","tab":"2156c1cf7f043d72","order":2,"disp":true,"width":"6","collapse":false,"className":""},{"id":"2156c1cf7f043d72","type":"ui_tab","name":"天氣圖表","icon":"dashboard","disabled":false,"hidden":false}]


























沒有留言:
張貼留言