2023年9月10日 星期日

ESP32 Time-Based Events using Node-RED and Big Timer

 ESP32 Time-Based Events using Node-RED and Big Timer

參考來源 https://randomnerdtutorials.com/esp32-big-timer-node-red/









[{"id":"d0f9e1c4b169bdcf","type":"bigtimer","z":"972e6260e6a3d8bd","outtopic":"","outpayload1":"on","outpayload2":"off","name":"Big Timer","comment":"","lat":0,"lon":0,"starttime":"1200","endtime":"1215","starttime2":0,"endtime2":0,"startoff":0,"endoff":0,"startoff2":0,"endoff2":0,"offs":0,"outtext1":"","outtext2":"","timeout":1440,"sun":true,"mon":true,"tue":true,"wed":true,"thu":true,"fri":true,"sat":true,"jan":true,"feb":true,"mar":true,"apr":true,"may":true,"jun":true,"jul":true,"aug":true,"sep":true,"oct":true,"nov":true,"dec":true,"day1":0,"month1":0,"day2":0,"month2":0,"day3":0,"month3":0,"day4":0,"month4":0,"day5":0,"month5":0,"day6":0,"month6":0,"day7":0,"month7":0,"day8":0,"month8":0,"day9":0,"month9":0,"day10":0,"month10":0,"day11":0,"month11":0,"day12":0,"month12":0,"d1":0,"w1":0,"d2":0,"w2":0,"d3":0,"w3":0,"d4":0,"w4":0,"d5":0,"w5":0,"d6":0,"w6":0,"xday1":0,"xmonth1":0,"xday2":0,"xmonth2":0,"xday3":0,"xmonth3":0,"xday4":0,"xmonth4":0,"xday5":0,"xmonth5":0,"xday6":0,"xmonth6":0,"xday7":0,"xmonth7":0,"xday8":0,"xmonth8":0,"xday9":0,"xmonth9":0,"xday10":0,"xmonth10":0,"xday11":0,"xmonth11":0,"xday12":0,"xmonth12":0,"xd1":0,"xw1":0,"xd2":0,"xw2":0,"xd3":0,"xw3":0,"xd4":0,"xw4":0,"xd5":0,"xw5":0,"xd6":0,"xw6":0,"suspend":false,"random":false,"randon1":false,"randoff1":false,"randon2":false,"randoff2":false,"repeat":true,"atstart":true,"odd":false,"even":false,"x":300,"y":140,"wires":[["3271672feff60197","f838b38ddb9547b9","b3d8b0744a70ab8c","14e7f5105d96fa53"],[],[]]},{"id":"3271672feff60197","type":"mqtt out","z":"972e6260e6a3d8bd","name":"","topic":"esp32/alex9ufo/pin/2","qos":"2","retain":"true","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"841df58d.ee5e98","x":560,"y":160,"wires":[]},{"id":"f838b38ddb9547b9","type":"debug","z":"972e6260e6a3d8bd","name":"debug ","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":510,"y":20,"wires":[]},{"id":"8452623054d94ced","type":"mqtt in","z":"972e6260e6a3d8bd","name":"","topic":"esp32/alex9ufo/pin/2","qos":"2","datatype":"auto-detect","broker":"841df58d.ee5e98","nl":false,"rap":true,"rh":0,"inputs":0,"x":330,"y":220,"wires":[["dba72d6991b76c02"]]},{"id":"dba72d6991b76c02","type":"debug","z":"972e6260e6a3d8bd","name":"debug ","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":510,"y":220,"wires":[]},{"id":"b3d8b0744a70ab8c","type":"function","z":"972e6260e6a3d8bd","name":"function ","func":"var status=msg.payload;\n\nif (status==\"on\")\n    msg.payload=true;\nif (status==\"off\")\n    msg.payload=false;\n    \nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":520,"y":100,"wires":[["69a6b1a3a7c86f94","c42a2fbae6de24e0","af6da0d14b4cda1c"]]},{"id":"69a6b1a3a7c86f94","type":"ui_led","z":"972e6260e6a3d8bd","order":4,"group":"2ac8e3fa.8b8584","width":3,"height":3,"label":"","labelPlacement":"left","labelAlignment":"left","colorForValue":[{"color":"#ff0000","value":"false","valueType":"bool"},{"color":"#008000","value":"true","valueType":"bool"}],"allowColorForValueInMessage":false,"shape":"circle","showGlow":true,"name":"","x":870,"y":100,"wires":[]},{"id":"c42a2fbae6de24e0","type":"debug","z":"972e6260e6a3d8bd","name":"debug ","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":690,"y":60,"wires":[]},{"id":"14e7f5105d96fa53","type":"ui_audio","z":"972e6260e6a3d8bd","name":"","group":"2ac8e3fa.8b8584","voice":"Google US English","always":"","x":520,"y":60,"wires":[]},{"id":"af6da0d14b4cda1c","type":"ui_text","z":"972e6260e6a3d8bd","group":"2ac8e3fa.8b8584","order":13,"width":3,"height":1,"name":"","label":"BigTimer State","format":"{{msg.payload}}","layout":"row-left","className":"","x":720,"y":120,"wires":[]},{"id":"4224bfba72382d8e","type":"inject","z":"972e6260e6a3d8bd","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"auto","payloadType":"str","x":90,"y":100,"wires":[["d0f9e1c4b169bdcf","0f2c3c78b1025c65"]]},{"id":"671cba1c234931a5","type":"inject","z":"972e6260e6a3d8bd","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"manual on","payloadType":"str","x":100,"y":200,"wires":[["d0f9e1c4b169bdcf","0f2c3c78b1025c65"]]},{"id":"981d9c49b7c9cd8f","type":"inject","z":"972e6260e6a3d8bd","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"manual off","payloadType":"str","x":100,"y":280,"wires":[["d0f9e1c4b169bdcf","0f2c3c78b1025c65"]]},{"id":"d289df09806d488f","type":"ui_button","z":"972e6260e6a3d8bd","name":"","group":"2ac8e3fa.8b8584","order":5,"width":3,"height":1,"passthru":false,"label":"AUTO","tooltip":"","color":"","bgcolor":"","className":"","icon":"","payload":"auto","payloadType":"str","topic":"topic","topicType":"msg","x":70,"y":60,"wires":[["d0f9e1c4b169bdcf","0f2c3c78b1025c65"]]},{"id":"571ee06ef4b1ca1a","type":"ui_button","z":"972e6260e6a3d8bd","name":"","group":"2ac8e3fa.8b8584","order":10,"width":3,"height":1,"passthru":false,"label":"manual on","tooltip":"","color":"","bgcolor":"","className":"","icon":"","payload":"manual on","payloadType":"str","topic":"topic","topicType":"msg","x":90,"y":160,"wires":[["d0f9e1c4b169bdcf","0f2c3c78b1025c65"]]},{"id":"956b6d6c2bc2b954","type":"ui_button","z":"972e6260e6a3d8bd","name":"","group":"2ac8e3fa.8b8584","order":8,"width":3,"height":1,"passthru":false,"label":"manual off","tooltip":"","color":"","bgcolor":"","className":"","icon":"","payload":"manual off","payloadType":"str","topic":"topic","topicType":"msg","x":90,"y":240,"wires":[["d0f9e1c4b169bdcf","0f2c3c78b1025c65"]]},{"id":"0f2c3c78b1025c65","type":"ui_text","z":"972e6260e6a3d8bd","group":"2ac8e3fa.8b8584","order":15,"width":0,"height":0,"name":"","label":"button: @","format":"{{msg.payload}}","layout":"row-left","className":"","x":300,"y":60,"wires":[]},{"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":"","closeTopic":"","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"2ac8e3fa.8b8584","type":"ui_group","name":"Default","tab":"ebb1ed1c.5ebe2","order":1,"disp":true,"width":"12","collapse":false},{"id":"ebb1ed1c.5ebe2","type":"ui_tab","name":"Home","icon":"dashboard","disabled":false,"hidden":false}]


/*********
  Rui Santos
  Complete project details: https://randomnerdtutorials.com/esp32-big-timer-node-red/
 
*********/

#include <Arduino.h>

#include <WiFi.h>
extern "C" {
  #include "freertos/FreeRTOS.h"
  #include "freertos/timers.h"
}
#include <AsyncMqttClient.h>

#define WIFI_SSID "alex9ufo" // Enter your Wi-Fi name
#define WIFI_PASSWORD "alex9981"  // Enter Wi-Fi password

// BROKER
const char *MQTT_HOST = "broker.mqtt-dashboard.com";
const char *BROKER_USER = "alex9ufo";
const char *BROKER_PASS = "public";
const int MQTT_PORT = 1883;


//MQTT Subscribe Topics
#define MQTT_SUB_DIGITAL "esp32/alex9ufo/pin/#"


AsyncMqttClient mqttClient;
TimerHandle_t mqttReconnectTimer;
TimerHandle_t wifiReconnectTimer;

//======================================================
void connectToWifi() {
  Serial.println("Connecting to Wi-Fi...");
  WiFi.begin(WIFI_SSID, WIFI_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);
  //Subscribe to topics
  // Subscribe to topic MQTT_SUB_DIGITAL when it connects to the broker
  uint16_t packetIdSub1 = mqttClient.subscribe(MQTT_SUB_DIGITAL, 2);
  Serial.print("Subscribing at QoS 2, packetId: ");
  Serial.println(packetIdSub1);
}
//======================================================
void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
  Serial.println("Disconnected from MQTT.");

  if (WiFi.isConnected()) {
    xTimerStart(mqttReconnectTimer, 0);
  }
}
//======================================================
void onMqttSubscribe(uint16_t packetId, uint8_t qos) {
  Serial.println("Subscribe acknowledged.");
  Serial.print("  packetId: ");
  Serial.println(packetId);
  Serial.print("  qos: ");
  Serial.println(qos);
}
//======================================================
void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {
  // Do whatever you want when you receive a message
 
  // Save the message in a variable
  String receivedMessage;
  for (int i = 0; i < len; i++) {
    Serial.println((char)payload[i]);
    receivedMessage += (char)payload[i];
  }
  // Save topic in a String variable
  String receivedTopic = String(topic);  
  Serial.print("Received Topic: ");
  Serial.println(receivedTopic);

  // Check which GPIO we want to control
  int stringLen = receivedTopic.length();
  // Get the index of the last slash
  int lastSlash = receivedTopic.lastIndexOf("/");
  // Get the GPIO number (it's after the last slash "/")
  // esp/digital/GPIO
  String gpio = receivedTopic.substring(lastSlash+1, stringLen);
  Serial.print("DIGITAL GPIO: ");
  Serial.println(gpio);
  Serial.print("STATE: ");
  Serial.println(receivedMessage);

  // Check if it is DIGITAL
  if (receivedTopic.indexOf("pin") > 0) {
    //Set the specified GPIO as output
    pinMode(gpio.toInt(), OUTPUT);
    //Control the GPIO
    if (receivedMessage == "on"){
      digitalWrite(gpio.toInt(), HIGH);
    }
    else{
      digitalWrite(gpio.toInt(), LOW);
    }
  }
  Serial.println("Publish received.");
  Serial.print("  topic: ");
  Serial.println(topic);
  Serial.print("  qos: ");
  Serial.println(properties.qos);
  Serial.print("  dup: ");
  Serial.println(properties.dup);
  Serial.print("  retain: ");
  Serial.println(properties.retain);
  Serial.print("  len: ");
  Serial.println(len);
  Serial.print("  index: ");
  Serial.println(index);
  Serial.print("  total: ");
  Serial.println(total);
}
//======================================================
void onMqttPublish(uint16_t packetId) {
  Serial.println("Publish acknowledged.");
  Serial.print("  packetId: ");
  Serial.println(packetId);
}
//======================================================
void setup() {
  Serial.begin(115200);
  Serial.println();
  Serial.println();

  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.onMessage(onMqttMessage);
  mqttClient.onPublish(onMqttPublish);
 
  mqttClient.setServer(MQTT_HOST, MQTT_PORT);
  mqttClient.setCredentials(BROKER_USER, BROKER_PASS);

  connectToWifi();
}
//======================================================
void loop() {

}


沒有留言:

張貼留言

Messaging API作為替代方案

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