In this tutorial, you’ll learn how to control the ESP32 outputs using time-based events. For that, we’ll set up an automation system on Node-RED with the Big Timer node. This is a powerful and easy-to-use timing node that provides a huge range of timing facilities to create automated flows based on different time conditions: hours, minutes, days of the week, months, include/exclude specific days or months, based on sunset and sunrise time, and much more.
Project Overview
The Big Timer Node was created by Peter Scargill. We recommend taking a look at the Big Timer page on Peter Scargill’s blog: Big Timer page. Consider donating to the author if you think this node will be useful for your projects.
To show you how you can use the Big Timer node in Node-RED to control the ESP32 based on schedules, we’ll set up a system that automatically turns the ESP32 GPIOs on and off at certain times. The Big Timer node allows you to set up complex schedule rules to determine when the GPIOs will be on and off.
To communicate between Node-RED and the ESP32, we’ll use MQTT communication protocol. Learn more about MQTT: What is MQTT and How It Works.
The following diagram shows a high-level overview of the example we’ll build.
- We’ll create a Node-RED flow with the Big Timer node. We’ll set up the timer to send ON and OFF messages at specific times. You can create any schedule conditions easily with the Big Timer node. We’ll send a 0 at the OFF time and a 1 at the ON time.
- The output of the Big Timer node will be published on a topic that contains the GPIO number we want to control. In our example, we’ll use the following topic: esp32/digital/<gpio>, in which <gpio> represents the GPIO number you want to control. For example, if you want to control GPIO 2, you would publish on the following topic esp32/digital/2.
- The ESP32 is subscribed to the multi-level topic esp32/digital/#, so it receives all messages of any topic that begins with esp32/digital. This means it receives all messages, regardless of the GPIO you want to control.
- The ESP32 will receive a different message at the ON and OFF times (1 and 0) on a topic that contains the GPIO to be controlled. This way, we can easily control the ESP32 GPIOs automatically accordingly to the schedule set up on the Big Timer node.
This project is divided into two parts:
Prerequisites
Before continuing, make sure you follow all the next pre-requisites:
- Install Node-RED and the Big Timer node;
- Set up Mosquitto broker on your Raspberry Pi or set up any other MQTT broker;
1) Program the ESP32 – Subscribe to MQTT Topic (Receive Big Timer messages)
In this section, we’ll program the ESP32 ton to subscribe to the same topic that the Big Timer node is publishing. Then, we’ll automatically set the corresponding ESP32 output states to on or off depending on the message received via MQTT.
Installing the AsyncMQTT Library
There are several MQTT libraries that you can use to set the ESP32 or ESP8266 as an MQTT client. We’ll use the AsyncMQTT library. Click on the following link to download the library ZIP file:
You also need to install the AsyncTCP library. Click on the following link to download the library:
Now that you’ve downloaded all the required library files, let’s install them.
Open your Arduino IDE, go to Sketch > Include Library > Add .ZIP library, and select the ZIP file for the AsyncMQTT library. Repeat the same process for the AsyncTCP library. After installing the libraries, restart your Arduino IDE and proceed to the next unit.
Programming the ESP32 – Subscribe to MQTT Topic
After installing the required libraries, you can finally program the ESP32 to subscribe to an MQTT topic and turn the GPIOs on and off automatically.
Upload the following code to your board—before uploading you need to insert your network credentials (SSID and password), MQTT broker IP address or URL, MQTT username and password, if applicable.
/*********
Rui Santos & Sara Santos - Random Nerd Tutorials
Complete project details: https://randomnerdtutorials.com/esp32-big-timer-node-red/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*********/
#include <Arduino.h>
#include <WiFi.h>
extern "C" {
#include "freertos/FreeRTOS.h"
#include "freertos/timers.h"
}
#include <AsyncMqttClient.h>
#define WIFI_SSID "REPLACE_WITH_YOUR_SSID"
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD"
// BROKER
#define MQTT_HOST IPAddress(192, 168, 1, XXX) //MQTT BROKER IP ADDRESS
/*for example:
#define MQTT_HOST IPAddress(192, 168, 1, 106)*/
#define MQTT_PORT 1883
#define BROKER_USER "REPLACE_WITH_BROKER_USERNAME"
#define BROKER_PASS "REPLACE_WITH_BROKER_PASSWORD"
//MQTT Subscribe Topics
#define MQTT_SUB_DIGITAL "esp32/digital/#"
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 ARDUINO_EVENT_WIFI_STA_GOT_IP:
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
connectToMqtt();
break;
case ARDUINO_EVENT_WIFI_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("digital") > 0) {
//Set the specified GPIO as output
pinMode(gpio.toInt(), OUTPUT);
//Control the GPIO
if (receivedMessage == "1"){
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() {
}
How the Code Works
Continue reading to learn how the code works or skip to the Demonstration section.
Include Libraries
First, we need to include the required libraries. To set the board as an MQTT client, we’re using the AsyncMQTTClient library as we’ve mentioned previously.
#include <Arduino.h>
#include <WiFi.h>
extern "C" {
#include "freertos/FreeRTOS.h"
#include "freertos/timers.h"
}
#include <AsyncMqttClient.h>
Wi-Fi Credentials and Broker Details
You need to include your network credentials on the following lines (SSID and password) so that your board can establish a Wi-Fi connection with your router.
#define WIFI_SSID "REPLACE_WITH_YOUR_SSID"
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD"
You need to insert your MQTT broker IP address. It corresponds to the Raspberry Pi IP address:
#define MQTT_HOST IPAddress(192, 168, 1, 106) //MQTT BROKER IP ADDRESS
/*for example:
#define MQTT_HOST IPAddress(192, 168, 1, XXX)*/
The MQTT broker port is 1883.
#define MQTT_PORT 1883
Insert your MQTT broker username and password on the following lines.
#define BROKER_USER "REPLACE_WITH_BROKER_USERNAME"
#define BROKER_PASS "REPLACE_WITH_BROKER_PASSWORD"
Subscribe to MQTT Topic
Define the MQTT topic you want your board to subscribe to. We’ll subscribe to multiple topics at once by using the multi-level wildcard (#).
//MQTT Subscribe Topics
#define MQTT_SUB_DIGITAL "esp32/digital/#"
AsyncMQTTClient
The following line creates an AsyncMQTTClient object called mqttClient.
AsyncMqttClient mqttClient;
Timers for Wi-Fi Events
Then, we create timers for the Wi-Fi events. This section is needed so that we can detect Wi‑Fi and MQTT events like connecting and disconnecting and automatically call functions (asynchronously) when those events happen. The following lines are creating the time handlers.
TimerHandle_t mqttReconnectTimer;
TimerHandle_t wifiReconnectTimer;
Connect to Wi-Fi
The connectToWiFi() function will be called later to connect your ESP board to Wi‑Fi.
void connectToWifi() {
Serial.println("Connecting to Wi-Fi...");
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
}
Connect to MQTT
As the name suggests, the connectToMqtt() function connects the MQTT client (your board) to the broker.
void connectToMqtt() {
Serial.println("Connecting to MQTT...");
mqttClient.connect();
}
Wi-Fi Events
There is a Wi-Fi event for the ESP32 of type ARDUINO_EVENT_WIFI_STA_GOT_IP (which means that the ESP connected successfully to the router and was assigned an IP address on the network). When that event happens, we connect to the MQTT broker by calling the connectToMQTT() function.
When it detects Wi-Fi is disconnected (ARDUINO_EVENT_WIFI_STA_DISCONNECTED event), we stop reconnecting to the MQTT broker and start the timer to try to reconnect to Wi-Fi.
void WiFiEvent(WiFiEvent_t event) {
Serial.printf("[WiFi-event] event: %d\n", event);
switch(event) {
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
connectToMqtt();
break;
case ARDUINO_EVENT_WIFI_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;
}
}
You can learn more about the ESP32 Wi-Fi events on the following tutorial: ESP32 Useful Wi-Fi Library Functions
onMQTTConnect()
The onMQTTConnect() function will be called when the board is connected successfully to the MQTT broker. In this example, we print a debugging message about the current MQTT session.
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);
}
Subscribe to Topics
To subscribe to an MQTT topic, it’s a good idea to do that right after the ESP connects to the broker, so we do that inside the onMQTTConnect() function.
To subscribe to topics, simply call the subscribe() method on the mqttClient object. It accepts as arguments the topic you want to subscribe to and the QoS (quality of service—it can be 0, 1 or 2). This function outputs the packet Id (which is simply a number to identify the packet).
uint16_t packetIdSub1 = mqttClient.subscribe(MQTT_SUB_DIGITAL, 2);
onMQTTDisconnect()
The onMQTTDisconnect() function will be called when the broker suddenly disconnects. When that happens, we try to reconnect.
void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
Serial.println("Disconnected from MQTT.");
if (WiFi.isConnected()) {
xTimerStart(mqttReconnectTimer, 0);
}
}
onMqttSubscribe()
The onMQTTSubscribe() function will run when you subscribe to a topic. In this example, it just prints messages about the packet ID and QoS, but you can add other tasks.
void onMqttSubscribe(uint16_t packetId, uint8_t qos) {
Serial.println("Subscribe acknowledged.");
Serial.print(" packetId: ");
Serial.println(packetId);
Serial.print(" qos: ");
Serial.println(qos);
}
Receive Messages and Control Outputs
Whenever a message is received on a subscribed topic, the onMqttMessage() runs.
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
So, we must add what we want the ESP to do when it receives a message. We need to get the GPIO we want to control (it’s the last topic level), and the state (it’s the payload message).
First, we save the message on the receivedMessage variable.
// Save the message in a variable
String receivedMessage;
for (int i = 0; i < len; i++) {
Serial.println((char)payload[i]);
receivedMessage += (char)payload[i];
}
Then, we convert the topic to a String variable (receivedTopic) so it’s easier to manipulate later.
// Save topic in a String variable
String receivedTopic = String(topic);
Serial.print("Received Topic: ");
Serial.println(receivedTopic);
The GPIO we want to control comes in the topic, and it is the last level of the topic. For example: esp/digital/2. We can split the string in the last slash /, and we’ll have the GPIO number.
First, we get the length of the topic.
// Check which GPIO we want to control
int stringLen = receivedTopic.length();
Then, we can use the lastIndexOf() function to discover the position of the last slash. The lastIndexOf() method locates a string within another String. It starts searching from the end of the String.
// Get the index of the last slash
int lastSlash = receivedTopic.lastIndexOf("/");
Once we know the position of the last slash, we can split the string using the substring() method. The substring() method gets a substring of a string starting and ending at determined positions. Learn more about the substring() method.
// 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);
Then, we control the LED on or off accordingly to the message content using the digitalWrite() function:
// Check if it is DIGITAL
if (receivedTopic.indexOf("digital") > 0) {
//Set the specified GPIO as output
pinMode(gpio.toInt(), OUTPUT);
//Control the GPIO
if (receivedMessage == "1"){
digitalWrite(gpio.toInt(), HIGH);
}
else{
digitalWrite(gpio.toInt(), LOW);
}
As you can see, we don’t need to hardcode any GPIO numbers, because we declare them and control them accordingly to the topics received.
onMqttPublish()
The onMqttPublish() message runs when we publish a message on a topic. In this case, it simply prints the packet id in the Serial Monitor. You can add other tasks that may make sense for your project.
void onMqttPublish(uint16_t packetId) {
Serial.println("Publish acknowledged.");
Serial.print(" packetId: ");
Serial.println(packetId);
}
setup()
In the setup(), we initialize the Serial Monitor at a baud rate of 115200.
Serial.begin(115200);
Serial.println();
Serial.println();
The following lines create the mqttReconnectTimer and the wifiReconnecTimer tasks that will run when the MQTT or Wi-F disconnects, respectively.
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));
Finally, add the WiFiEvent function to the onEvent Wi-Fi handler. This means that whenever a Wi-Fi event happens, the WiFiEvent() function will run.
WiFi.onEvent(WiFiEvent);
Assigning callback functions
The AsyncMQTT is an asynchronous library. This means that it works with events and callback functions. You create the callback functions and then, assign them to a certain event. When that event happens, the board will automatically run the corresponding callback function. This means that you can be running other tasks on the loop() and whenever one of the events happens, the corresponding callback functions will run.
Important: one thing you need to keep in mind when creating the callback functions (all those functions we have taken a look at previously) is to never use blocking functions inside them like delay() or yield() or methods that use delay() or yield().
On the following lines, we assign the callback functions to their corresponding events.
mqttClient.onConnect(onMqttConnect);
mqttClient.onDisconnect(onMqttDisconnect);
mqttClient.onSubscribe(onMqttSubscribe);
mqttClient.onMessage(onMqttMessage);
mqttClient.onPublish(onMqttPublish);
Set the MQTT Server and Credentials
The next two lines set the MQTT host and port, and set the credentials.
mqttClient.setServer(MQTT_HOST, MQTT_PORT);
mqttClient.setCredentials(BROKER_USER, BROKER_PASS);
Connect to Wi-Fi
Finally, we connect to Wi-Fi by calling the connectToWiFi() function.
connectToWifi();
loop()
In this example, the loop() is empty, but you can add any tasks that you need your ESP32 to do. For example, publishing messages on MQTT topics.
void loop() {
}
That’s pretty much how the code works.
Uploading the Code
After inserting your network credentials and MQTT broker details, you can upload the code to your board.
First, go to Tools > Board and select the board you’re using. Then, select the COM port in Tools > Port. Finally, press the Upload button.
After successfully uploading the code to the board, open the Serial Monitor at a baud rate of 115200.
Press the board RST button to restart it and start running the code.
You should see the ESP32 board successfully subscribing to the topic we defined on the code.
Let the Serial Monitor open and let’s build the Node-RED flow.
2) Set up the Node-RED Flow with Big Timer
In this section, we’ll build a Node-RED flow with the Big Timer node to create a schedule to send ON and OFF commands via MQTT to control the ESP32 GPIOs.
You should have already installed the Big Timer node on Node-RED. If not, check this tutorial.
Creating the Node-RED Flow
Drag a Big Timer node to the flow. Add an MQTT out node, and a debug node. Wire the nodes as shown in the picture below.
The first output of the Big Timer node sends a payload message of the current state at the specified times. The second output sends a status message of 1 or 0 every minute, so it is ideal to wire to an output debug node.
MQTT Node
Double-click on the MQTT node.
Click on the pencil icon next to the Server field if you haven’t set the MQTT broker yet.
If you’re running Mosquitto MQTT broker and Node-RED on the Raspberry Pi or on the same machine, set the server to localhost and port 1883. If you’re using another MQTT broker, insert the broker URL on the server field.
Don’t forget to go to the Security tab and insert your broker username and password. After filling in all the details, click Update.
Now, you can set to which topic we want to publish the message. We’ve seen previously that the ESP32 will be subscribed to all messages on the topic esp32/digital/#. So, we can publish on topics like esp32/digital/4, or esp32/digital/2 to control the GPIOs 4 and 2 respectively. For testing purposes, we’ll publish on the esp32/digital/2 topic to control the ESP32 GPIO 2, the built-in LED.
You can also set the QoS value and if you want to retain the messages or not.
What are retained messages in MQTT? retain (true or false) what does it mean?
A retained message is a normal MQTT message with the retained flag set to true. The broker stores the last retained message and the corresponding QoS for that topic. Each client that subscribes to a topic pattern that matches the topic of the retained message receives the retained message immediately after they subscribe. The broker stores only one retained message per topic.
Why is it useful? Retained messages help newly-subscribed clients get a status update immediately after they subscribe to a topic. This is particularly useful to get the status of a device. For example, GPIO 2 is currently HIGH, and the ESP32 suddenly resets. It doesn’t know what the last state of GPIO 2 was. However, if the state is a retained message, it will receive it right after subscribing to the topic and can update the state of GPIO 2 immediately.
Big Timer Node
Double-click on the Big Timer node to edit its properties.
Fill the On Time and Off Time fields with the time you want to turn an ESP32 GPIO on and off. For demonstration purposes, we recommend selecting something close to the current time so that you can easily see if it is working as expected. Use the offset times if needed. You can then, try the other options to create more complex schedules.
The on message payload and off message payload should be filled on the On Msg and OFF Msg fields. We’re setting the On Msg to 1 and the Off Msg to 0. This means that it will output a 1 when it reaches the On Time and a 0 at Off time.
If you scroll down on the Big Timer node properties, you’ll find some more options. I would like to call your attention to the Repeat output and Output at startup options.
If you have enabled the Repeat Output option, it means that it will output a message with the current On or Off message every minute. This means, in our example, that it will publish an MQTT message every minute—this might be an interesting feature depending on your project application.
The Output at startup option means that it will output the current On or Off message right after we deploy the Node-RED flow.
Debug Node
Optionally, you can also edit the debug node properties so that it shows the complete output message.
Deploying the Node-RED Flow
When you’re done deploy your application.
Demonstration
After deploying you’ll see a timer below the Big Timer node showing how long it will be on or off.
You can open the Node-RED debugging window to see the output of the Big Timer node every minute.
Right after deploying the node, the ESP32 should have received an MQTT message with the current state (this happens because we have enabled the option Output at startup). Additionally, because we’ve set the Repeat Output message to true, the ESP32 will receive MQTT messages with the GPIO state every minute.
If everything is working as expected GPIO 2 should turn on and off automatically at the times you designated.
Note: some ESP32 board models don’t have a controllable built-in LED. If that’s your case, you’ll need to wire an LED to GPIO 2 to actually see the changes.
Because we’ve set the retain flag of the MQTT message to true, even if the ESP32 resets, it will get the last GPIO state and update it accordingly right after connecting to the broker.
You can easily control any other GPIOs on the ESP32 by simply changing the MQTT topic that the Big Timer node is publishing in. This is only possible because the ESP32 is subscribed to a multi-level MQTT topic.
Wrapping Up
In this tutorial, you learned how to create schedules to automatically control the ESP32 GPIOs using Node-RED and the Big Timer node. As an example, we’ve controlled the ESP32 GPIOs, but you can also use this method to trigger any other task on the ESP32, like for example activating or deactivating a motion sensor, trigger notifications, and much more.
The advantage of using Node-RED is that once you have set up a generic code on the ESP32, you just need to make changes to the Node-RED flow to automate tasks.
We hope you found this tutorial useful. If you like home automation and would like to learn more about Node-RED, definitely check out our eBook:
- SMART HOME with Raspberry Pi, ESP32, and ESP8266: Learn Node-RED and InfluxDB on a Raspberry Pi to build a Home Automation System with the ESP32 and ESP8266.
Learn more about the ESP32 with our resources:
- Learn ESP32 with Arduino IDE
- Build Web Servers with ESP32 and ESP8266
- Firebase Web App with ESP32 and ESP8266
- Free ESP32 Projects and Tutorials
Thanks for reading.
Hi
I am getting an error on the last part of the program prior to uploading.
When I run Arduino IDE verify before uploading this message appears
error message:
exit status 1
‘onMqttUnsubscribe’ was not declared in this scope
Although you don’t say verify, prior to uploading, is this still an error.
thanks,
Martin
Hi.
It was our mistake.
Simply remove that line as it is not needed.
I’ll update the code.
Thanks.
Regards,
Sara