2021年12月9日 星期四

ESP32 BME680 MQTT LINE Webserver Node-Red

ESP32 BME680 MQTT LINE Webserver Node-Red

BME680 多功能環境感測器 博世 Bosch Sensortec MEMS 多功能 VOC(揮發性有機物)、溫度、濕度、氣壓

BME680 多功能環境感測器 是一款四合一 MEMS 環境感測器,可測 量VOC(揮發性有機物)、溫度、濕度、氣壓這四個參數,非常適用於監測空氣品質。由於採用了 MEMS 技術,該感測器體積小、功耗低,因此也適用於低功耗場合,如可穿戴等。 












#include <Wire.h>

extern "C" {

  #include "freertos/FreeRTOS.h"

  #include "freertos/timers.h"

}

#include <AsyncMqttClient.h>

#include <SPI.h>

#include <Adafruit_Sensor.h>

#include "Adafruit_BME680.h"

#include "ESPAsyncWebServer.h"


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


//Uncomment if using SPI

/*#define BME_SCK 18

#define BME_MISO 19

#define BME_MOSI 23

#define BME_CS 5*/


// Raspberry Pi Mosquitto MQTT Broker

#define MQTT_HOST "broker.mqtt-dashboard.com"

// For a cloud MQTT broker, type the domain name

//#define MQTT_HOST "example.com"


#define MQTT_PORT 1883


// Temperature MQTT Topics

#define MQTT_PUB_TEMP "alex9ufo/esp32/bme680/temperature"

#define MQTT_PUB_HUMI "alex9ufo/esp32/bme680/humidity"

#define MQTT_PUB_GASR "alex9ufo/esp32/bme680/gasResistance"

#define MQTT_PUB_PRES "alex9ufo/esp32/bme680/pressure"

#define MQTT_PUB_ALTI "alex9ufo/esp32/bme680/altitude"


AsyncMqttClient mqttClient;

TimerHandle_t mqttReconnectTimer;

TimerHandle_t wifiReconnectTimer;


Adafruit_BME680 bme; // I2C

//Adafruit_BME680 bme(BME_CS); // hardware SPI

//Adafruit_BME680 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK);

#define SEALEVELPRESSURE_HPA (1013.25)


float temperature;

float humidity;

float pressure;

float gasResistance;

float altitude;


AsyncWebServer server(80);

AsyncEventSource events("/events");


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

unsigned long lastTime = 0;  

unsigned long timerDelay = 10*60000;  // send readings timer


void connectToWifi() {

  Serial.println("Connecting to Wi-Fi & MQTT Server...");

  WiFi.begin(ssid,password);

}


void connectToMqtt() {

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

  mqttClient.connect();

}


void WiFiEvent(WiFiEvent_t event) {

  Serial.printf("[WiFi-event] event: %d\n", event);

  switch(event) {

    case SYSTEM_EVENT_STA_GOT_IP:

      Serial.println("WiFi connected");

      Serial.println("IP address: ");

      Serial.println(WiFi.localIP());

      connectToMqtt();

      break;

    case SYSTEM_EVENT_STA_DISCONNECTED:

      Serial.println("WiFi lost connection");

      xTimerStop(mqttReconnectTimer, 0); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi

      xTimerStart(wifiReconnectTimer, 0);

      break;

  }

}


void onMqttConnect(bool sessionPresent) {

  Serial.println("Connected to MQTT.");

  Serial.print("Session present: ");

  Serial.println(sessionPresent);

}


void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {

  Serial.println("Disconnected from MQTT.");

  if (WiFi.isConnected()) {

    xTimerStart(mqttReconnectTimer, 0);

  }

}

void onMqttPublish(uint16_t packetId) {

  Serial.print("Publish acknowledged.");

  Serial.print("  packetId: ");

  Serial.println(packetId);

}

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

void getBME680Readings(){

  // Tell BME680 to begin measurement.

  unsigned long endTime = bme.beginReading();

  if (endTime == 0) {

    Serial.println(F("Failed to begin reading :("));

    return;

  }

  if (!bme.endReading()) {

    Serial.println(F("Failed to complete reading :("));

    return;

  }

  temperature = bme.temperature;

  pressure = bme.pressure / 100.0;

  humidity = bme.humidity;

  gasResistance = bme.gas_resistance / 1000.0;

  altitude = bme.readAltitude(SEALEVELPRESSURE_HPA);

}


String processor(const String& var){

  getBME680Readings();

  //Serial.println(var);

  if(var == "TEMPERATURE"){

    return String(temperature);

  }

  else if(var == "HUMIDITY"){

    return String(humidity);

  }

  else if(var == "PRESSURE"){

    return String(pressure);

  }

 else if(var == "GAS"){

    return String(gasResistance);

  }

 else if(var == "ALT"){

    return String(altitude);

  }

    

}


const char index_html[] PROGMEM = R"rawliteral(

<!DOCTYPE HTML><html>

<head>

  <title>BME680 Web Server</title>

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

  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">

  <link rel="icon" href="data:,">

  <style>

    html {font-family: Arial; display: inline-block; text-align: center;}

    p {  font-size: 1.2rem;}

    body {  margin: 0;}

    .topnav { overflow: hidden; background-color: #4B1D3F; color: white; font-size: 1.7rem; }

    .content { padding: 20px; }

    .card { background-color: white; box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5); }

    .cards { max-width: 700px; margin: 0 auto; display: grid; grid-gap: 2rem; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }

    .reading { font-size: 2.8rem; }

    .card.temperature { color: #0e7c7b; }

    .card.humidity { color: #17bebb; }

    .card.pressure { color: #3fca6b; }

    .card.gas { color: #d62246; }

  </style>

</head>

<body>

  <div class="topnav">

    <h3>BME680 WEB SERVER</h3>

  </div>

  <div class="content">

    <div class="cards">

      <div class="card temperature">

        <h4><i class="fas fa-thermometer-half"></i> TEMPERATURE</h4><p><span class="reading"><span id="temp">%TEMPERATURE%</span> &deg;C</span></p>

      </div>

      <div class="card humidity">

        <h4><i class="fas fa-tint"></i> HUMIDITY</h4><p><span class="reading"><span id="hum">%HUMIDITY%</span> &percnt;</span></p>

      </div>

      <div class="card pressure">

        <h4><i class="fas fa-angle-double-down"></i> PRESSURE</h4><p><span class="reading"><span id="pres">%PRESSURE%</span> hPa</span></p>

      </div>

      <div class="card gas">

        <h4><i class="fas fa-wind"></i> GAS</h4><p><span class="reading"><span id="gas">%GAS%</span> K&ohm;</span></p>

      </div>


      <div class="card map-marker-alt">

        <h4><i class="fas fa-map-marker-alt"></i> ALTITUDE</h4><p><span class="reading"><span id="alt">%ALT%</span> Meter </span></p>

      </div>

      

    </div>

  </div>

<script>

if (!!window.EventSource) {

 var source = new EventSource('/events');

 

 source.addEventListener('open', function(e) {

  console.log("Events Connected");

 }, false);

 source.addEventListener('error', function(e) {

  if (e.target.readyState != EventSource.OPEN) {

    console.log("Events Disconnected");

  }

 }, false);

 

 source.addEventListener('message', function(e) {

  console.log("message", e.data);

 }, false);

 

 source.addEventListener('temperature', function(e) {

  console.log("temperature", e.data);

  document.getElementById("temp").innerHTML = e.data;

 }, false);

 

 source.addEventListener('humidity', function(e) {

  console.log("humidity", e.data);

  document.getElementById("hum").innerHTML = e.data;

 }, false);

 

 source.addEventListener('pressure', function(e) {

  console.log("pressure", e.data);

  document.getElementById("pres").innerHTML = e.data;

 }, false);

 

 source.addEventListener('gas', function(e) {

  console.log("gas", e.data);

  document.getElementById("gas").innerHTML = e.data;

 }, false);

}

</script>

</body>

</html>)rawliteral";


void setup() {

  Serial.begin(115200);


  // Set the device as a Station and Soft Access Point simultaneously

  WiFi.mode(WIFI_AP_STA);

  

  // Set device as a Wi-Fi Station

  WiFi.begin(ssid, password);

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

    delay(1000);

    Serial.println("Setting as a Wi-Fi Station..");

  }

  Serial.print("Station IP Address: ");

  Serial.println(WiFi.localIP());

  Serial.println();


  // Init BME680 sensor

  if (!bme.begin(0x76)) {

    Serial.println(F("Could not find a valid BME680 sensor, check wiring!"));

    while (1);

  }

  Serial.println(F("BME680 sensor is working!"));

  // Set up oversampling and filter initialization

  bme.setTemperatureOversampling(BME680_OS_8X);

  bme.setHumidityOversampling(BME680_OS_2X);

  bme.setPressureOversampling(BME680_OS_4X);

  bme.setIIRFilterSize(BME680_FILTER_SIZE_3);

  bme.setGasHeater(320, 150); // 320*C for 150 ms


  // Handle Web Server

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

    request->send_P(200, "text/html", index_html, processor);

  });


  // Handle Web Server Events

  events.onConnect([](AsyncEventSourceClient *client){

    if(client->lastId()){

      Serial.printf("Client reconnected! Last message ID that it got is: %u\n", client->lastId());

    }

    // send event with message "hello!", id current millis

    // and set reconnect delay to 1 second

    client->send("hello!", NULL, millis(), 10000);

  });

  server.addHandler(&events);

  server.begin();

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

 mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToMqtt));

  wifiReconnectTimer = xTimerCreate("wifiTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToWifi));


  WiFi.onEvent(WiFiEvent);


  mqttClient.onConnect(onMqttConnect);

  mqttClient.onDisconnect(onMqttDisconnect);

  //mqttClient.onSubscribe(onMqttSubscribe);

  //mqttClient.onUnsubscribe(onMqttUnsubscribe);

  mqttClient.onPublish(onMqttPublish);

  mqttClient.setServer(MQTT_HOST, MQTT_PORT);

  // If your broker requires authentication (username and password), set them below

  //mqttClient.setCredentials("REPlACE_WITH_YOUR_USER", "REPLACE_WITH_YOUR_PASSWORD");

  connectToWifi();


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

  

}


void loop() {

  if ((millis() - lastTime) > timerDelay) {

    getBME680Readings();

    //Serial.printf("Temperature = %.2f ºC \n", temperature);

    //Serial.printf("Humidity = %.2f % \n", humidity);

    //Serial.printf("Pressure = %.2f hPa \n", pressure);

    //Serial.printf("Gas Resistance = %.2f KOhm \n", gasResistance);

    

    Serial.print("Temperature CELSIUS 攝氏溫度= ");

    Serial.printf("Temperature = %.2f ºC \n", temperature);

    

    Serial.print("Humidity 濕度= ");   

    Serial.printf("Humidity = %.2f % \n", humidity);

    

    Serial.print("Gas Resistance 氣壓阻值= ");   

    Serial.printf("Gas Resistance = %.2f KOhm \n", gasResistance);


    Serial.print("Approx Altitude 大概海拔高度= ");

    Serial.printf("Altitude = %.2f Meter \n", altitude);

    

    Serial.print("Pressure 大氣壓力百帕(hPa)= ");

    Serial.printf("Pressure = %.2f hPa \n", pressure);

    

    Serial.println();


    // Send Events to the Web Server with the Sensor Readings

    events.send("ping",NULL,millis());

    events.send(String(temperature).c_str(),"temperature",millis());

    events.send(String(humidity).c_str(),"humidity",millis());

    events.send(String(pressure).c_str(),"pressure",millis());

    events.send(String(gasResistance).c_str(),"gas",millis());

    

    //mqtt process

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

    // Temperature MQTT Topics

    //#define MQTT_PUB_TEMP "alex9ufo/esp32/bme680/temperature"

    //#define MQTT_PUB_HUMI "alex9ufo/esp32/bme680/humidity"

    //#define MQTT_PUB_GASR "alex9ufo/esp32/bme680/gasResistance"

    //#define MQTT_PUB_PRES "alex9ufo/esp32/bme680/pressure"

    //#define MQTT_PUB_ALTI "alex9ufo/esp32/bme680/altitude"

    

    // Publish an MQTT message on topic alex9ufo/esp32/bmp680/temperature

    uint16_t packetIdPub1 = mqttClient.publish(MQTT_PUB_TEMP, 1, true, String(temperature).c_str());

    Serial.printf("Publishing on topic %s at QoS 1, packetId: %i", MQTT_PUB_TEMP, packetIdPub1);

    Serial.printf("Message: %.2f \n", temperature);


    // Publish an MQTT message on topic alex9ufo/esp32/bmp680/humidity

    uint16_t packetIdPub2 = mqttClient.publish(MQTT_PUB_HUMI, 1, true, String(humidity).c_str());

    Serial.printf("Publishing on topic %s at QoS 1, packetId %i: ", MQTT_PUB_HUMI, packetIdPub2);

    Serial.printf("Message: %.2f \n", humidity);


    // Publish an MQTT message on topic alex9ufo/esp32/bmp680/gasResistance

    uint16_t packetIdPub3 = mqttClient.publish(MQTT_PUB_GASR, 1, true, String(gasResistance).c_str());

    Serial.printf("Publishing on topic %s at QoS 1, packetId %i: ", MQTT_PUB_GASR, packetIdPub3);

    Serial.printf("Message: %.2f \n", gasResistance);

    

    // Publish an MQTT message on topic alex9ufo/esp32/bmp680/pressure

    uint16_t packetIdPub4 = mqttClient.publish(MQTT_PUB_PRES, 1, true, String(pressure).c_str());

    Serial.printf("Publishing on topic %s at QoS 1, packetId %i: ", MQTT_PUB_PRES, packetIdPub4);

    Serial.printf("Message: %.2f \n", pressure);


    // Publish an MQTT message on topic alex9ufo/esp32/bmp680/pressure

    uint16_t packetIdPub5 = mqttClient.publish(MQTT_PUB_ALTI, 1, true, String(altitude).c_str());

    Serial.printf("Publishing on topic %s at QoS 1, packetId %i: ", MQTT_PUB_ALTI, packetIdPub5);

    Serial.printf("Message: %.2f \n", altitude);

        

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

    lastTime = millis();

  }

}


/*

#include <Wire.h>

#include <SPI.h>

#include <Adafruit_Sensor.h>

#include "Adafruit_BME680.h"

  

#define SEALEVELPRESSURE_HPA (1013.25)

 

Adafruit_BME680 bme; // I2C

 

void setup() {

  Serial.begin(115200);

  while (!Serial);

  Serial.println(F("BME680 test"));

 

  if (!bme.begin(0x76)) 

  {

    Serial.println("Could not find a valid BME680 sensor, check wiring!");

    while (1);

  }

 

  // Set up oversampling and filter initialization

  bme.setTemperatureOversampling(BME680_OS_8X);

  bme.setHumidityOversampling(BME680_OS_2X);

  bme.setPressureOversampling(BME680_OS_4X);

  bme.setIIRFilterSize(BME680_FILTER_SIZE_3);

  bme.setGasHeater(320, 150); // 320*C for 150 ms

}

 

void loop() 

{

  if (! bme.performReading()) 

  {

    Serial.println("Failed to perform reading :(");

    return;

  }

  Serial.print("Temperature = ");

  Serial.print(bme.temperature);

  Serial.println(" *C");

 

  Serial.print("Pressure = ");

  Serial.print(bme.pressure / 100.0);

  Serial.println(" hPa");

 

  Serial.print("Humidity = ");

  Serial.print(bme.humidity);

  Serial.println(" %");

 

  Serial.print("Gas = ");

  Serial.print(bme.gas_resistance / 1000.0);

  Serial.println(" KOhms");

 

  Serial.print("Approx. Altitude = ");

  Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));

  Serial.println(" m");

 

  Serial.println();

  delay(3000);

}

*/



[{"id":"71090ecf26767fbb","type":"mqtt in","z":"4d138bc4c9b20629","name":"","topic":"alex9ufo/esp32/bme680/temperature","qos":"1","datatype":"auto","broker":"2db287b.addf978","nl":false,"rap":false,"x":160,"y":160,"wires":[["8e88e1a0f7b6fce7","f7586566332578a6","6b5bac781938b316"]]},{"id":"8e88e1a0f7b6fce7","type":"ui_gauge","z":"4d138bc4c9b20629","name":"","group":"c2445c80711cbc8d","order":2,"width":"6","height":"4","gtype":"gage","title":"攝氏溫度","label":"ºC","format":"{{value}}ºC ","min":0,"max":"60","colors":["#00b500","#f7df09","#ca3838"],"seg1":"","seg2":"","className":"","x":420,"y":160,"wires":[]},{"id":"c33110c2f256c455","type":"mqtt in","z":"4d138bc4c9b20629","name":"","topic":"alex9ufo/esp32/bme680/pressure","qos":"1","datatype":"auto","broker":"2db287b.addf978","nl":false,"rap":false,"x":150,"y":440,"wires":[["b11847908c3d13b7","0ec5b5746266f612"]]},{"id":"b11847908c3d13b7","type":"ui_gauge","z":"4d138bc4c9b20629","name":"","group":"c2445c80711cbc8d","order":2,"width":"6","height":"4","gtype":"gage","title":"大氣壓力百帕(hPa)","label":"%","format":"{{value}} hPa","min":"30","max":"2000","colors":["#53a4e6","#1d78a9","#4e38c9"],"seg1":"","seg2":"","className":"","x":390,"y":440,"wires":[]},{"id":"06223fb0edd7653d","type":"mqtt in","z":"4d138bc4c9b20629","name":"","topic":"alex9ufo/esp32/bme680/altitude","qos":"1","datatype":"auto","broker":"2db287b.addf978","nl":false,"rap":false,"x":150,"y":560,"wires":[["10526cef3a9de330","a1fdf4b9ded83893"]]},{"id":"10526cef3a9de330","type":"ui_gauge","z":"4d138bc4c9b20629","name":"","group":"c2445c80711cbc8d","order":3,"width":"6","height":"4","gtype":"gage","title":"大概海拔高度","label":"units","format":"{{value}} 米","min":"-500","max":"500","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","className":"","x":400,"y":560,"wires":[]},{"id":"0355a0781c0f0793","type":"comment","z":"4d138bc4c9b20629","name":"BME680 多功能環境感測器 ","info":"BME680 多功能環境感測器 博世 Bosch Sensortec MEMS 多功能 VOC(揮發性有機物)、溫度、濕度、氣壓","x":130,"y":100,"wires":[]},{"id":"f7586566332578a6","type":"function","z":"4d138bc4c9b20629","name":"傳送信息","func":"//CHANNEL_ACCESS_TOKEN = 'Messaging API Token';\nCHANNEL_ACCESS_TOKEN = 'UwdpPeFsI2wuLNy+2pMf+KKl64ATWBaqmJCHs8u3yHWl28YfeN2B3Ghklw2zeJ7FS8oD8J4DOoB5exbVwEU8XDyFQ1REpYqOxpKmOJ9ZRn4fiEeki9QTtiUtJ0fV9aW4w+ixGoOIvKh+/QWXba5dmQdB04t89/1O/w1cDnyilFU=';\nUSER_ID = 'U1bc09946aebc28d0fba29ec62d84a4d8'; //'使用者ID(不是Line ID)';\nmessage = {\n    type:'text',\n    text:'目前BME680溫度:'+msg.payload + '°C'\n};\nheaders = {\n    'Content-Type': 'application/json; charset=UTF-8',\n    'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN,\n};\npayload = {\n    'to':  USER_ID,\n    'messages': [message]\n};\nmsg.headers = headers;\nmsg.payload = payload;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":420,"y":200,"wires":[["6fdc6878747bc17d","1890d2eb6ab02d6d"]]},{"id":"6fdc6878747bc17d","type":"http request","z":"4d138bc4c9b20629","name":"Messaging API 傳送","method":"POST","ret":"txt","paytoqs":"ignore","url":"https://api.line.me/v2/bot/message/push","tls":"","persist":false,"proxy":"","authType":"","x":780,"y":420,"wires":[["78ba2326c550f4f2"]]},{"id":"98c9909f6ac3fbb9","type":"comment","z":"4d138bc4c9b20629","name":"developers.line.biz","info":"https://developers.line.biz/zh-hant/\n\n\nNews - LINE Developershttps://developers.line.biz › zh-hant\nThe LINE Developers site is a portal site for developers. It contains documents and tools that will help you use our various developer products.\n‎產品 · ‎LINE Login · ‎Messaging API · ‎文件\n\nhttps://developers.line.biz/console/channel/1656701433/basics\n\nhttps://developers.line.biz/console/channel/1656701433/messaging-api","x":770,"y":360,"wires":[]},{"id":"6b5bac781938b316","type":"debug","z":"4d138bc4c9b20629","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":440,"y":120,"wires":[]},{"id":"1890d2eb6ab02d6d","type":"debug","z":"4d138bc4c9b20629","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":610,"y":200,"wires":[]},{"id":"e9ac240b3a259033","type":"mqtt in","z":"4d138bc4c9b20629","name":"","topic":"alex9ufo/esp32/bme680/gasResistance","qos":"1","datatype":"auto","broker":"2db287b.addf978","nl":false,"rap":false,"x":170,"y":340,"wires":[["ba4ff62e890cebcb","8107f2e25d097f5f"]]},{"id":"d65fca67986e5bcf","type":"mqtt in","z":"4d138bc4c9b20629","name":"","topic":"alex9ufo/esp32/bme680/humidity","qos":"1","datatype":"auto","broker":"2db287b.addf978","nl":false,"rap":false,"x":150,"y":260,"wires":[["2d5bf260b60e4e2e","1cc8b59ec77a420f"]]},{"id":"2d5bf260b60e4e2e","type":"ui_gauge","z":"4d138bc4c9b20629","name":"","group":"c2445c80711cbc8d","order":2,"width":"6","height":"4","gtype":"gage","title":"濕度","label":"ºC","format":"{{value}}%","min":0,"max":"100","colors":["#00b500","#f7df09","#ca3838"],"seg1":"","seg2":"","className":"","x":410,"y":260,"wires":[]},{"id":"ba4ff62e890cebcb","type":"ui_gauge","z":"4d138bc4c9b20629","name":"","group":"c2445c80711cbc8d","order":2,"width":"6","height":"4","gtype":"gage","title":"空氣","label":"ºC","format":"{{value}}KΩ","min":0,"max":"500","colors":["#00b500","#f7df09","#ca3838"],"seg1":"","seg2":"","className":"","x":410,"y":340,"wires":[]},{"id":"1cc8b59ec77a420f","type":"delay","z":"4d138bc4c9b20629","name":"","pauseType":"delay","timeout":"1","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"x":420,"y":300,"wires":[["9a1132d1fe9b1649"]]},{"id":"8107f2e25d097f5f","type":"delay","z":"4d138bc4c9b20629","name":"","pauseType":"delay","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"x":420,"y":380,"wires":[["d2d9a4ed764af954"]]},{"id":"0ec5b5746266f612","type":"delay","z":"4d138bc4c9b20629","name":"","pauseType":"delay","timeout":"3","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"x":420,"y":480,"wires":[["0d1a2590c2680909"]]},{"id":"a1fdf4b9ded83893","type":"delay","z":"4d138bc4c9b20629","name":"","pauseType":"delay","timeout":"4","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"x":420,"y":600,"wires":[["cb3ec3dda98f610e"]]},{"id":"78ba2326c550f4f2","type":"debug","z":"4d138bc4c9b20629","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":810,"y":480,"wires":[]},{"id":"9a1132d1fe9b1649","type":"function","z":"4d138bc4c9b20629","name":"傳送信息","func":"//CHANNEL_ACCESS_TOKEN = 'Messaging API Token';\nCHANNEL_ACCESS_TOKEN = 'UwdpPeFsI2wuLNy+2pMf+KKl64ATWBaqmJCHs8u3yHWl28YfeN2B3Ghklw2zeJ7FS8oD8J4DOoB5exbVwEU8XDyFQ1REpYqOxpKmOJ9ZRn4fiEeki9QTtiUtJ0fV9aW4w+ixGoOIvKh+/QWXba5dmQdB04t89/1O/w1cDnyilFU=';\nUSER_ID = 'U1bc09946aebc28d0fba29ec62d84a4d8'; //'使用者ID(不是Line ID)';\nmessage = {\n    type:'text',\n    text:'目前BME680濕度:'+msg.payload + '%'\n};\nheaders = {\n    'Content-Type': 'application/json; charset=UTF-8',\n    'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN,\n};\npayload = {\n    'to':  USER_ID,\n    'messages': [message]\n};\nmsg.headers = headers;\nmsg.payload = payload;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":560,"y":300,"wires":[["6fdc6878747bc17d"]]},{"id":"d2d9a4ed764af954","type":"function","z":"4d138bc4c9b20629","name":"傳送信息","func":"//CHANNEL_ACCESS_TOKEN = 'Messaging API Token';\nCHANNEL_ACCESS_TOKEN = 'UwdpPeFsI21wuLNy+2pMf+KKl64ATWBaqmJCHs8u3yHWl28YfeN2B3Ghklw2zeJ7FS8oD8J4DOoB5exbVwEU8XDyFQ1REpYqOxpKmOJ9ZRn4fiEeki9QTtiUtJ0fV9aW4w+ixGoOIvKh+/QWXba5dmQdB04t89/1O/w1cDnyilFU=';\nUSER_ID = 'U1bc09946aebc28d0fba29ec62d84a4d8'; //'使用者ID(不是Line ID)';\nmessage = {\n    type:'text',\n    text:'目前BME680VOC(揮發性有機物):'+msg.payload + 'KΩ'\n};\nheaders = {\n    'Content-Type': 'application/json; charset=UTF-8',\n    'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN,\n};\npayload = {\n    'to':  USER_ID,\n    'messages': [message]\n};\nmsg.headers = headers;\nmsg.payload = payload;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":560,"y":380,"wires":[["6fdc6878747bc17d"]]},{"id":"0d1a2590c2680909","type":"function","z":"4d138bc4c9b20629","name":"傳送信息","func":"//CHANNEL_ACCESS_TOKEN = 'Messaging API Token';\nCHANNEL_ACCESS_TOKEN = 'UwdpPeFsI2wuLNy+2pMf+KKl64ATWBaqmJCHs8u3yHWl28YfeN2B3Ghklw2zeJ7F1S8oD8J4DOoB5exbVwEU8XDyFQ1REpYqOxpKmOJ9ZRn4fiEeki9QTtiUtJ0fV9aW4w+ixGoOIvKh+/QWXba5dmQdB04t89/1O/w1cDnyilFU=';\nUSER_ID = 'U1bc099416aebc28d0fba29ec62d84a4d8'; //'使用者ID(不是Line ID)';\nmessage = {\n    type:'text',\n    text:'目前BME680大氣壓力百帕:'+msg.payload + 'hPa'\n};\nheaders = {\n    'Content-Type': 'application/json; charset=UTF-8',\n    'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN,\n};\npayload = {\n    'to':  USER_ID,\n    'messages': [message]\n};\nmsg.headers = headers;\nmsg.payload = payload;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":560,"y":480,"wires":[["6fdc6878747bc17d"]]},{"id":"cb3ec3dda98f610e","type":"function","z":"4d138bc4c9b20629","name":"傳送信息","func":"//CHANNEL_ACCESS_TOKEN = 'Messaging API Token';\nCHANNEL_ACCESS_TOKEN = 'UwdpPeFsI2wuLNy+2pMf+KKl64ATWBaqmJCHs8u3yHWl28YfeN2B3Ghklw2zeJ7FS8oD8J4DOoB5exbVwEU8XDyFQ1REpYqOxpKmOJ9ZRn4fiEeki9QTtiUtJ0fV9aW4w+ixGoOIvKh+/QWXba5dmQdB04t89/1O/w1cDnyilFU=';\nUSER_ID = 'U1bc09946aebc28d0fba29ec62d84a4d8'; //'使用者ID(不是Line ID)';\nmessage = {\n    type:'text',\n    text:'目前BME680大概海拔高度:'+msg.payload + '公尺'\n};\nheaders = {\n    'Content-Type': 'application/json; charset=UTF-8',\n    'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN,\n};\npayload = {\n    'to':  USER_ID,\n    'messages': [message]\n};\nmsg.headers = headers;\nmsg.payload = payload;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":560,"y":600,"wires":[["6fdc6878747bc17d"]]},{"id":"2db287b.addf978","type":"mqtt-broker","name":"","broker":"broker.mqtt-dashboard.com","port":"1883","clientid":"","usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"/vm/mqtt/birth","birthQos":"0","birthPayload":"birth","birthMsg":{},"closeTopic":"","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"sessionExpiry":""},{"id":"c2445c80711cbc8d","type":"ui_group","name":"BME680","tab":"2711d5a2.d68132","order":4,"disp":true,"width":"12","collapse":false,"className":""},{"id":"2711d5a2.d68132","type":"ui_tab","name":"Sensor","icon":"dashboard","disabled":false,"hidden":false}]

沒有留言:

張貼留言

Messaging API作為替代方案

  LINE超好用功能要沒了!LINE Notify明年3月底終止服務,有什麼替代方案? LINE Notify將於2025年3月31日結束服務,官方建議改用Messaging API作為替代方案。 //CHANNEL_ACCESS_TOKEN = 'Messaging ...