2023年12月8日 星期五

實習 2-1 , 2-2 ,2-3 Arduino 程式說明

 實習 2-1 , 2-2 ,2-3 Arduino 程式說明

 

部落格位置

https://alex9ufoexploer.blogspot.com/2023/11/2-arduino-2-1-2-2-2-3.html

https://alex9ufoexploer.blogspot.com/2023/11/2-arduino-2-1-2-2-2-3.html



//wifi &  MQTT

#include <WiFi.h>             //定義Wifi 程式庫

#include <PubSubClient.h>      //定義MQTT Pub發行 Sub 訂閱 程式庫

 

//RC522 SPI Mode

#include <SPI.h>              //定義MFRC522 RFID read ESP32 介面

#include <MFRC522.h>          //定義MFRC522 RFID read程式庫

 

 

//GPIO 2 D1 Build in LED

#define LED 2                //定義LED接腳

 

//定義MFRC522 RFID read ESP32 介面 接腳連接Pin assign

/* Wiring RFID RC522 module  

=============================================================================

GND     = GND   3.3V    = 3.3V

The following table shows the typical pin layout used:

 *             MFRC522      ESP32     Arduino       Arduino   Arduino    Arduino          Arduino

 *             Reader/PCD             Uno/101       Mega      Nano v3    Leonardo/Micro   Pro Micro

 * Signal      Pin          Pin       Pin           Pin       Pin        Pin              Pin

 * -----------------------------------------------------------------------------------------

 * RST/Reset   RST          GPIO27    9             5         D9         RESET/ICSP-5     RST

 * SPI SS      SDA(SS)      GPIO5     10            53        D10        10               10

 * SPI MOSI    MOSI         GPIO23    11 / ICSP-4   51        D11        ICSP-4           16

 * SPI MISO    MISO         GPIO19    12 / ICSP-1   50        D12        ICSP-1           14

 * SPI SCK     SCK          GPIO18    13 / ICSP-3   52        D13        ICSP-3           15

 *

[1] (1, 2) Configurable, typically defined as RST_PIN in sketch/program.

[2] (1, 2) Configurable, typically defined as SS_PIN in sketch/program.

[3] The SDA pin might be labeled SS on some/older MFRC522 boards

=============================================================================

*/

 

 

#define SS_PIN  5  // ESP32 pin GIOP5 //MFRC522 SS接腳 與 ESP32 的連接Pin

#define RST_PIN 27 // ESP32 pin GIOP27    //MFRC522 RST接腳 與 ESP32 的連接Pin



// WiFi SSID password , SSID 和密碼進行Wi-Fi 設定 

const char *ssid = "alex9ufo"; // Enter your Wi-Fi name

const char *password = "alex9981";  // Enter Wi-Fi password

 

// MQTT Broker伺服器名稱 使用者名稱 密碼 發行主題 訂閱主題的定義

const char *mqtt_broker = "broker.mqtt-dashboard.com";

const char *topic1 = "alex9ufo/esp32/led";

const char *topic2 = "alex9ufo/esp32/RFID";

const char *topic = "alex9ufo/esp32/Starting";

const char *topic3 = "alex9ufo/esp32/led_status";

 

const char *mqtt_username = "alex9ufo";

const char *mqtt_password = "public";

const int mqtt_port = 1883;

 

//布林代數 LED狀態 是否連上網路ESP32 ready ?

bool ledState = false;

bool atwork = false;


//
定義WiFiClient 別名
//PubSubClient 物件名稱(網路用戶端物件)  
//初始化MFRC522

WiFiClient espClient;

PubSubClient client(espClient);

MFRC522 rfid(SS_PIN, RST_PIN); // Create MFRC522 instance

 

//定義long 變數

long lastMsg = 0;

long lastMsg1= 0;

 

//定義 MQTT 發行及訂閱需要的變數

char msg[50];

String json = "";

bool Flash = false;  //true

bool Timer = false;  //true

bool Send = false;  //true

int Count= 0;

 

//定義 MQTT 發行及訂閱需要的變數

char jsonChar1[50];  //client.publish("alex9ufo/Esp32/RFID"

//宣告任務Task1

TaskHandle_t Task1;

 

// Wifi reconnect 重新連線需要的變數

unsigned long previousMillis = 0;

unsigned long interval = 30000;

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

//任務1副程式Task1_senddata

 

//由於ESP32有著240/160MHz的雙核心CPU

//一般我們的程式都僅在ESP32的核心1執行(核心編號1),

//所以根本沒用到第二個核心(核心編號0

 

void Task1_senddata(void * pvParameters ) {

 //無窮迴圈

  for (;;) {

    //偵測上傳旗標是否為true

    Serial.println("Reading RFID tag");

    if (rfid.PICC_IsNewCardPresent()) { // new tag is available

      if (rfid.PICC_ReadCardSerial()) { // NUID has been readed

        MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);

        Serial.print("RFID/NFC Tag Type: ");

        Serial.println(rfid.PICC_GetTypeName(piccType));

        String rfidno="";

        // print UID in Serial Monitor in the hex format

        Serial.print("UID:");

        for (int i = 0; i < rfid.uid.size; i++) {

          Serial.print(rfid.uid.uidByte[i] < 0x10 ? " 0" : " ");

          Serial.print(rfid.uid.uidByte[i], HEX);

        }

        Serial.println(); 

 

        String json = printHex(rfid.uid.uidByte, rfid.uid.size);

        json.trim();

        json.toUpperCase();

        // Convert JSON string to character array

        json.toCharArray(jsonChar1, json.length()+1);

   

        if  (client.connected()) {

            Serial.print("Publish message: ");

            Serial.println(json);

            // Publish JSON character array to MQTT topic

            client.publish(topic2,jsonChar1);

             

          rfid.PICC_HaltA(); // halt PICC

          rfid.PCD_StopCrypto1(); // stop encryption on PCD

        }  

        else

        {

          Serial.print("MQTT not connected ");

        }

     

      }

    }



    else  

    {

      // PN532 probably timed out waiting for a card

      Serial.println("Timed out waiting for a card");

    }      

    //Task1休息,delay(X)不可省略

    delay(1000);

  }

}

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

//副程式 UID No. in the hex format

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

String printHex(byte *buffer, byte bufferSize) {

      String id = "";

      for (byte i = 0; i < bufferSize; i++) {

        id += buffer[i] < 0x10 ? "0" : "";

        id += String(buffer[i], HEX);

        id +=" ";

      }

      return id;

    }

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

//副程式  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, password);  //初始化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());

}    

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

// 接收MQTT主題後呼叫運行程式

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

void callback(char *topic, byte *payload, unsigned int length) {

    Serial.print("Message arrived in topic: ");

    Serial.println(topic);

    Serial.print("Message: ");

    String message;

   //將接收資料轉成字串以利後續判斷

    for (int i = 0; i < length; i++) {

        message += (char) payload[i];  // Convert *byte to string

    }

    Serial.print(message); 

   //判斷是否為 on , off , toggle , flash , timer

    if (message == "on" && !ledState) {

        digitalWrite(LED, HIGH);  // Turn on the LED

        ledState = true;  //ledState = ture HIGH

       //設定 各個 旗號

        Flash = false;

        Timer = false;

        json ="ON";

        Send = true ;

    }

    if (message == "off" && ledState) {

        digitalWrite(LED, LOW); // Turn off the LED

        ledState = false; //ledState = false LOW

        Flash = false;

        Timer = false;

        json ="OFF";

        Send = true ;

 

    }

    if (message == "flash" ) {

        digitalWrite(LED, LOW); // Turn off the LED

        Flash = true;

        Timer = false;

        json ="FLASH";

        Send = true ;        

 

    }

    if (message == "timer" ) {

        digitalWrite(LED, LOW); // Turn off the LED

        Flash = false;

        Timer = true;

        json ="TIMER";

        Send = true ;

        Count= 11;

    }

 

    if (message == "toggle" ) {

        digitalWrite(LED, !digitalRead(LED));   // Turn the LED toggle

        if (digitalRead(LED))

            ledState = true;

        else

            ledState = false;

       

        Flash = false;

        Timer = false;

        json ="TOGGLE";

        Send = true ;        

    }

 

    Serial.println();

    Serial.println("-----------------------");

}

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

//  若目前沒有和伺服器相連,則反覆執行直到連結成功

void reconnect() {

  // Loop until we're reconnected

  while (!client.connected()) {

    Serial.print("Attempting MQTT connection...");

    // Attempt to connect

 

    if (client.connect("esp32-client-")) {

      Serial.println("connected");

      // Subscribe

      client.subscribe("alex9ufo/esp32/led");

      client.subscribe("alex9ufo/esp32/RFID");      

    } else {

      Serial.print("failed, rc=");

      Serial.print(client.state());

      Serial.println(" try again in 5 seconds");

      // Wait 5 seconds before retrying

      delay(5000);

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

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

        WiFi.disconnect();

        WiFi.reconnect();

      }

    }

  }

}

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

//判斷 旗號Flash , Timer 是否為真

void LED_Message() {

    if (Flash){

        digitalWrite(LED, !digitalRead(LED));

        delay(500);

        if (digitalRead(LED))

            ledState = true;

        else

            ledState = false;

    } //(Flash)

       

    if (Timer) {

        digitalWrite(LED, HIGH);

        delay(500);

        if (digitalRead(LED))

            ledState = true;

        else

            ledState = false;

 

        Count=Count-1;

        if (Count == 0 ){

            Timer=false;

            digitalWrite(LED, LOW);

            ledState = false;

        }

    } //(Timer)

   

   ////判斷 旗號 Send 是否為真 回傳MQTT訊息到MQTT Broker 

    if (client.connected()) {        

        if (Send) {

          // Convert JSON string to character array

          json.toCharArray(jsonChar1, json.length()+1);

          Serial.print("Publish message: ");

          Serial.println(json);

          // Publish JSON character array to MQTT topic

          client.publish(topic3,jsonChar1);

        }

        Send = false;    //處理過後 旗號 Send為假

    }

    else

    {

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

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

        WiFi.disconnect();

        WiFi.reconnect();

      }

    }

 

}

 

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

//setup()這個函式只會執行大括號裡面的程式一遍, 主要就是在Arduino一開機後,//將所有初始該設置的東西先設置好

 

void setup() {

    // Set software serial baud to 115200;

    Serial.begin(115200);

    delay(1000); // Delay for stability

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

    // Connecting to a WiFi network

    setup_wifi();

    // Setting LED pin as output

    pinMode(LED, OUTPUT);

    digitalWrite(LED, LOW);  // Turn off the LED initially

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

    SPI.begin();           // Init SPI bus

    rfid.PCD_Init();       // Init MFRC522

 

    Serial.println(F("Ready!"));

    Serial.println(F("==================================================="));

    Serial.println("Tap an RFID/NFC tag on the RFID-RC522 reader");


    // Connecting to an MQTT broker

    client.setServer(mqtt_broker, mqtt_port);

    client.setCallback(callback);

    while (!client.connected()) {

        String client_id = "esp32-client-";

        client_id += String(WiFi.macAddress());

        Serial.printf("The client %s connects to the public MQTT broker\n", client_id.c_str());

        if (client.connect(client_id.c_str(), mqtt_username, mqtt_password)) {

            Serial.println("Public HiveMQ MQTT broker (broker.mqtt-dashboard.com) connected");

        } else {

            Serial.print("Failed with state ");

            Serial.print(client.state());

            delay(2000);

        }

    }

 

    // MQTT Publish and subscribe

    client.subscribe(topic1);

    client.publish(topic,"ESP32 at work");

 

    //在核心0啟動任務1

    xTaskCreatePinnedToCore(

    Task1_senddata,   /*任務實際對應的Function*/

      "Task1",        /*任務名稱*/

      10000,          /*堆疊空間*/

      NULL,           /*無輸入值*/

      0,              /*優先序0*/

      &Task1,         /*對應的任務變數位址*/

      0);             /*指定在核心0執行 */

}

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

//重複循環執行你所寫入loop()內的程式碼

void loop()

{

 if (!client.connected()) { //假設未連接的處理程序

      reconnect();

      Serial.print(" client not connected  reconnect ");

      delay(200);

    } 

  client.loop();

  // Process LED message

  LED_Message();

 

  unsigned long currentMillis = millis();

  // if WiFi is down, try reconnecting

  if ((WiFi.status() != WL_CONNECTED) && (currentMillis - previousMillis >=interval)) {

    Serial.print(millis());

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

    WiFi.disconnect();

    WiFi.reconnect();

    previousMillis = currentMillis;

 

    client.setCallback(callback);

  }

 

}

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

 


2023年12月1日 星期五

Uploading sensor data to ThingSpeak with Node-RED

Uploading sensor data to ThingSpeak with Node-RED


利用亂數產生 溫度與濕度 並發行至MQTT

從MQTT 訂閱溫度與濕度數據並Show 在Chart節點上 及 發行至ThinkSpeak Channel 上 儲存於SQLite DataBase C:\Users\User\.node-red\Temp_and_Humidity.db 


TEMPERATURE TABLE

msg.topic = CREATE TABLE TEMPERATURE

ID INTEGER PRIMARY KEY AUTOINCREMENT, 

TIMESTAMP TEXT , VALUE INT )


HUMIDITY TABLE

msg.topic = CREATE TABLE HUMIDITY

ID INTEGER PRIMARY KEY AUTOINCREMENT, 

TIMESTAMP TEXT , VALUE INT )













var Today = new Date();

var yyyy = Today.getFullYear(); //年

var MM = Today.getMonth()+1;    //月

var dd = Today.getDate();       //日

var h = Today.getHours();       //時

var m = Today.getMinutes();     //分

var s = Today.getSeconds();     //秒


if(MM<10)

{

   MM = '0'+MM;

}


if(dd<10)

{

   dd = '0'+dd;

}


if(h<10)

{

   h = '0'+h;

}


if(m<10)

{

  m = '0' + m;

}


if(s<10)

{

  s = '0' + s;

}


var var_date = yyyy+'/'+MM+'/'+dd+' '+h+':'+m+':'+s;

var randomNum = msg.payload;


msg.topic = "INSERT INTO TEMPERATURE (TIMESTAMP , VALUE ) VALUES ($var_date ,  $randomNum ) " ;

msg.payload = [var_date, randomNum ]


return msg;




[{"id":"85b43f335fa700a8","type":"function","z":"16576ce1f4418417","name":"function random","func":"function between(min, max) {  \n    return Math.floor(\n    (Math.random() * (max - min) + min)\n  )\n}\nvar min=20;\nvar max=90;\n\nmsg.payload =  between(min, max);\nmsg.color=\"red\";\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":360,"y":120,"wires":[["89047e7d460ad319","de285b62e9de7ef5","a1c51aafbf4d017d"]]},{"id":"3d8d25203e3cca07","type":"inject","z":"16576ce1f4418417","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"120","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":180,"y":120,"wires":[["85b43f335fa700a8"]]},{"id":"ee7a2a72cc3de903","type":"ui_chart","z":"16576ce1f4418417","name":"","group":"44c23a63b5a5e055","order":1,"width":"6","height":"6","label":"訂閱humidity的濕度","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"0","ymax":"99","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"useUTC":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"outputs":1,"useDifferentColor":false,"className":"","x":430,"y":560,"wires":[[]]},{"id":"89047e7d460ad319","type":"mqtt out","z":"16576ce1f4418417","name":"humidity","topic":"alex9ufo/thinkspeak/humidity","qos":"1","retain":"true","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"70940176.2b2d3","x":540,"y":100,"wires":[]},{"id":"a3f56c29f9364612","type":"inject","z":"16576ce1f4418417","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"120","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":180,"y":220,"wires":[["eec0766dce83a895"]]},{"id":"eec0766dce83a895","type":"function","z":"16576ce1f4418417","name":"function random","func":"function between(min, max) {  \n    return Math.floor(\n    (Math.random() * (max - min) + min)\n  )\n}\nvar min=15;\nvar max=55;\n\nmsg.payload =  between(min, max);\nmsg.color=\"red\";\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":360,"y":220,"wires":[["63e9401ab13a0cb6","8ea516b321a815e2","6a9a1b8e4a783808"]]},{"id":"ef70fad26d41f6c0","type":"mqtt in","z":"16576ce1f4418417","name":"humidity","topic":"alex9ufo/thinkspeak/humidity","qos":"1","datatype":"auto-detect","broker":"70940176.2b2d3","nl":false,"rap":true,"rh":0,"inputs":0,"x":160,"y":520,"wires":[["ee7a2a72cc3de903","623e5a6222a1c0b1","d3dfc2eeb416833f","56794064f36fd93c"]]},{"id":"b08c1ec1f7a5319c","type":"mqtt in","z":"16576ce1f4418417","name":"temperature","topic":"alex9ufo/thinkspeak/temperature","qos":"1","datatype":"auto-detect","broker":"70940176.2b2d3","nl":false,"rap":true,"rh":0,"inputs":0,"x":170,"y":360,"wires":[["ee39943bcd7da84b","376c28ad739ee796","546eb1a30978b1cd","8ec6249da1f0d12d"]]},{"id":"ee39943bcd7da84b","type":"ui_chart","z":"16576ce1f4418417","name":"","group":"21f342b756626a6b","order":2,"width":"6","height":"6","label":"訂閱temperature的溫度","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"15","ymax":"55","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"useUTC":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"outputs":1,"useDifferentColor":false,"className":"","x":450,"y":320,"wires":[[]]},{"id":"de285b62e9de7ef5","type":"ui_text","z":"16576ce1f4418417","group":"6321a2b9a7a07dbe","order":3,"width":"6","height":"3","name":"","label":"dumidity發行的溼度","format":"<font color= {{msg.color}} > {{msg.payload}} </font>","layout":"row-left","className":"","x":570,"y":60,"wires":[]},{"id":"63e9401ab13a0cb6","type":"ui_text","z":"16576ce1f4418417","group":"6321a2b9a7a07dbe","order":4,"width":"6","height":"3","name":"","label":"temperature發行的溫度","format":"<font color= {{msg.color}} > {{msg.payload}} </font>","layout":"row-left","className":"","x":590,"y":220,"wires":[]},{"id":"69d20429e68c51dd","type":"comment","z":"16576ce1f4418417","name":"發行 room/humidity","info":"","x":190,"y":80,"wires":[]},{"id":"2a9dc05e9e5e4309","type":"comment","z":"16576ce1f4418417","name":"發行 room/temperature","info":"","x":200,"y":180,"wires":[]},{"id":"59863940bf9c6959","type":"comment","z":"16576ce1f4418417","name":"訂閱 alex9ufo/thinkspeakroom/temperature","info":"","x":200,"y":640,"wires":[]},{"id":"8466e2229899dfe2","type":"comment","z":"16576ce1f4418417","name":"訂閱 alex9ufo/thinkspeak/humidity","info":"","x":180,"y":680,"wires":[]},{"id":"376c28ad739ee796","type":"ThingspeakSendSimple","z":"16576ce1f4418417","name":"Send to Thinkspeak 溫度","writekey":"8U1H2OD8L4P9L718","fieldid":"1","x":450,"y":360,"wires":[]},{"id":"623e5a6222a1c0b1","type":"ThingspeakSendSimple","z":"16576ce1f4418417","name":"Send to Thinkspeak 濕度","writekey":"8U1H2OD8L4P9L718","fieldid":"2","x":450,"y":520,"wires":[]},{"id":"8ea516b321a815e2","type":"mqtt out","z":"16576ce1f4418417","name":"temperature","topic":"alex9ufo/thinkspeak/temperature","qos":"1","retain":"true","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"70940176.2b2d3","x":550,"y":260,"wires":[]},{"id":"546eb1a30978b1cd","type":"function","z":"16576ce1f4418417","name":"function  INSERT   Temperature ","func":"var 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 var_date = yyyy+'/'+MM+'/'+dd+' '+h+':'+m+':'+s;\nvar randomNum = msg.payload;\n\nmsg.topic = \"INSERT INTO TEMPERATURE (TIMESTAMP , VALUE ) VALUES ($var_date ,  $randomNum ) \" ;\nmsg.payload = [var_date, randomNum ]\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":470,"y":400,"wires":[["666106e4be9de7e1"]]},{"id":"666106e4be9de7e1","type":"sqlite","z":"16576ce1f4418417","mydb":"987979dcb5a4d733","sqlquery":"msg.topic","sql":"","name":"Temp_and_Humidity","x":820,"y":440,"wires":[["e7d968de1837f23d"]]},{"id":"e7d968de1837f23d","type":"debug","z":"16576ce1f4418417","name":"debug  ","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1010,"y":440,"wires":[]},{"id":"d3dfc2eeb416833f","type":"function","z":"16576ce1f4418417","name":"function  INSERT HUMIDITY","func":"var 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 var_date = yyyy+'/'+MM+'/'+dd+' '+h+':'+m+':'+s;\nvar randomNum = msg.payload;\n\nmsg.topic = \"INSERT INTO HUMIDITY (TIMESTAMP , VALUE ) VALUES ($var_date ,  $randomNum ) \" ;\nmsg.payload = [var_date, randomNum ]\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":460,"y":480,"wires":[["666106e4be9de7e1"]]},{"id":"b23e6980cd8ae0ee","type":"inject","z":"16576ce1f4418417","name":"Create Humidity Table","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"CREATE TABLE HUMIDITY(  ID INTEGER PRIMARY KEY AUTOINCREMENT,  TIMESTAMP TEXT , VALUE INT )","payload":"","payloadType":"date","x":520,"y":680,"wires":[["666106e4be9de7e1","c072af6adfbcc426"]]},{"id":"a399984def27c6cf","type":"inject","z":"16576ce1f4418417","name":"Create Temperature Table","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"CREATE TABLE TEMPERATURE(  ID INTEGER PRIMARY KEY AUTOINCREMENT,  TIMESTAMP TEXT , VALUE INT )","payload":"","payloadType":"date","x":530,"y":640,"wires":[["666106e4be9de7e1","c072af6adfbcc426"]]},{"id":"1619047eda217c3e","type":"comment","z":"16576ce1f4418417","name":"TEMPERATURE TABLE","info":"msg.topic = CREATE TABLE TEMPERATURE( \nID INTEGER PRIMARY KEY AUTOINCREMENT, \nTIMESTAMP TEXT , VALUE INT )","x":830,"y":400,"wires":[]},{"id":"295bc734a38d31b8","type":"comment","z":"16576ce1f4418417","name":"HUMIDITY  TABLE","info":"msg.topic = CREATE TABLE HUMIDITY( \nID INTEGER PRIMARY KEY AUTOINCREMENT, \nTIMESTAMP TEXT , VALUE INT )","x":810,"y":500,"wires":[]},{"id":"c072af6adfbcc426","type":"debug","z":"16576ce1f4418417","name":"debug  topic","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"topic","targetType":"msg","statusVal":"","statusType":"auto","x":770,"y":620,"wires":[]},{"id":"a1c51aafbf4d017d","type":"debug","z":"16576ce1f4418417","name":"debug 236","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":690,"y":140,"wires":[]},{"id":"8ec6249da1f0d12d","type":"debug","z":"16576ce1f4418417","name":"debug 237","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":410,"y":440,"wires":[]},{"id":"6a9a1b8e4a783808","type":"debug","z":"16576ce1f4418417","name":"debug 238","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":690,"y":180,"wires":[]},{"id":"56794064f36fd93c","type":"debug","z":"16576ce1f4418417","name":"debug 239","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":410,"y":600,"wires":[]},{"id":"44c23a63b5a5e055","type":"ui_group","name":"MQTT HUMIDITY","tab":"564e3c93eeb0489d","order":3,"disp":true,"width":"6","collapse":false,"className":""},{"id":"70940176.2b2d3","type":"mqtt-broker","name":"","broker":"broker.mqtt-dashboard.com","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":4,"keepalive":"15","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"21f342b756626a6b","type":"ui_group","name":"MQTT TEMPERATURE","tab":"564e3c93eeb0489d","order":2,"disp":true,"width":"6","collapse":false,"className":""},{"id":"6321a2b9a7a07dbe","type":"ui_group","name":"MQTT out","tab":"564e3c93eeb0489d","order":1,"disp":true,"width":"6","collapse":false,"className":""},{"id":"987979dcb5a4d733","type":"sqlitedb","db":"C:\\Users\\User\\.node-red\\Temp_and_Humidity.db","mode":"RWC"},{"id":"564e3c93eeb0489d","type":"ui_tab","name":"ThinkSpeak","icon":"dashboard","order":93,"disabled":false,"hidden":false}]


Node-Red --> MQTT --> Fuxa

Node-Red --> MQTT --> Fuxa      FUXA(一個開源的 Web HMI / SCADA 自動化監控軟體)的專案設定檔 。 這份設定檔完整定義了 HMI 監控畫面的 後端通訊(MQTT 連線、點位標籤) 與 前端網頁圖形介面(SVG 畫布...