What’s Node-RED?

Node-RED is an open-source programming tool that allows visual coding using nodes. Nodes are code blocks that perform a specific function such as input, output, or processing. Furthermore, these nodes can be wired together to do more advanced stuff like visualizing data or receiving data with different protocols like MQTT.

In Node-RED, these connected nodes are called flows.

Installing Node-RED

The official Node-RED website provides a short script to install Node-RED and all its dependencies namely Node.js and npm. You can copy the code below into your terminal.

bash <(curl -sL https://raw.githubusercontent.com/node-red/linux-installers/master/deb/update-nodejs-and-nodered)

After entering the command, you should see a screen like this:

After the installation, a prompt will show:

Note that Node-RED is included in the Raspberry Pi repository so you can also install it using sudo apt-get install nodered. The difference is in the dependencies. Doing apt install won’t include npm to the installation so it’s better to use the script provided by the Node-RED website.

Running Node-RED

After installing, Node-RED will be available in your Raspberry Pi menu.

Alternatively, you can start the service in the terminal with:

node-red

Press CTRL+ALT+C or close the terminal to stop Node-RED.

Due to the limited memory of the Raspberry Pi, you will need to start Node-RED with an additional argument to tell the underlying Node.js process to free up unused memory sooner than it would otherwise.

To do this, you should use the alternative node-red-pi command and pass in the max-old-space-size argument.

node-red-pi --max-old-space-size=256

Running as a Service

If you intend to make the Raspberry Pi an autonomous home automation hub, meaning Node-RED runs in the background automatically on boot, we need to set it up as a service.

The following commands are provided to work with the service:

  • node-red-start – this starts the Node-RED service and displays its log output. Pressing Ctrl-C or closing the window does not stop the service; it keeps running in the background
  • node-red-stop – this stops the Node-RED service
  • node-red-restart – this stops and restarts the Node-RED service
  • node-red-log – this displays the log output of the service

To enable Node-RED to automatically start on boot. Enter the following into your terminal.

sudo systemctl enable nodered.service

To disable it, simply enter :

sudo systemctl disable nodered.service

Opening the Editor

You can access the Node-RED editor with any device connected to your network using a web browser. The address of the editor is http://localhost:1880. Basically, your Raspberry Pi’s address plus the port number is 1880.

To know your Pi’s IP address enter hostname -I or ifconfig into the terminal. The address is somewhere inside the WLAN section.

Installing Node-RED Dashboard

Node-RED Dashboard is a module that provides a set of nodes in Node-RED to quickly create a live data dashboard. This will serve as the GUI of your home automation hub.

To install the Node-RED Dashboard, enter:

node-red-stop
cd ~/.node-red
npm install node-red-dashboard

Then, restart your Pi.

sudo reboot

To open the dashboard, type your Pi’s address in a web browser followed by :1880/ui as shown below:

http://Your_RPi_IP_address:1880/ui

The dashboard is still empty because we haven’t worked with the editor yet.

MQTT

MQTT stands for MQ Telemetry Transport. It is a nice lightweight publish and subscribe system where you can publish and receive messages as a client. It is a simple messaging protocol, designed for constrained devices and with low bandwidth. So, it’s the perfect solution for Internet of Things applications.

Installing Mosquitto Broker

In MQTT, the broker is what’s responsible for receiving and filtering messages, deciding who is interested in them and then publishing the message to all subscribed clients.

There are several brokers you can use. In this tutorial, we’re going to use Mosquitto Broker.

First, enter these commands into the terminal:

sudo apt update
sudo apt install -y mosquitto mosquitto-clients

Press Y to proceed with the installation then wait for it to finish. Enter the command below to autostart Mosquitto on boot. Lastly, restart the Pi.

sudo systemctl enable mosquitto.service

Run the following command to test if the program is successfully installed.

mosquitto -v

This returns the version of Mosquitto you have in your system. It also tries to reinitialize the program so if it is already running, it will return an error message. If you see it, don’t worry as the program is already installed properly.

Getting Started With Your Home Automation Hub

Our goal is to have a Raspberry Pi control three ESP8266 12-E Arduino Wifi Shields or NodeMCUs using Node-RED. The boards will be connected to a PIR Sensor, DHT Temperature and Humidity Sensor, and a 5V Relay.

Preparing the Hardware

I used a NodeMCU to describe the connections but you can also apply it to an Arduino ESP8266 Wifi board or an Arduino with an ESP8266 Wifi shield on it.

What you need:

  • Raspberry Pi
  • Raspberry Pi power supply
  • 3 NodeMCU or 3 Arduino with Arduino ESP8266 Wifi Shield
  • Relay
  • DHT sensor
  • PIR sensor
  • Breadboard
  • Jumper Wires

Connect the components as shown below:

Creating the Layout

Open Node-RED editor. On the top right corner, open the dashboard tab and select layout. Create a tab called Home and inside the tab, create three groups: Relay, DHT Sensor, and PIR Sensor as shown in the figure below:

Making the Flow

Drag the following nodes to the workspace. You can find all available nodes in the left side of your editor.

The switch node will determine the message Node-RED will send. Then, the MQTT output node will publish the message according to the switch’s state, turning the LED on or off.

On the other hand, the three MQTT input nodes are subscribed to the air, temperature, and humidity topics. These nodes will fetch the data and send it to the text and gauge node to display the text alert and values.

Connecting Node-RED to Mosquitto

To establish the wireless connection between the Raspberry Pi and NodeMCU, we need to connect Node-RED and the MQTT broker, Mosquitto. Double click the MQTT output node:

Click the Add new mqtt-broker option.

Type localhost in the server field

This will add the broker to the other nodes as well.

Configuring the Nodes

Everything is pretty straightforward in this section. Configuring the nodes means changing labels, units, topics, etc. Just copy the changes in the following images to your editor.

  • Switch
  • MQTT Output Node
  • MQTT Input Node (PIR Sensor)
  • Text
  • MQTT Input Node (Temperature)
  • Gauge (Temperature)
  • MQTT Input Node (Humidity)
  • Gauge (Humidity)

Drag the end of the first node to the next to connect them.

Now, to apply the changes and display them into your dashboard, click the Deploy button on the top right corner. Visit the Node-RED dashboard to view the actual switch and gauges. It is still blank since the NodeMCU isn’t set up yet.

Preparing Your Arduino IDE

In this tutorial, we will use the Arduino IDE to program the NodeMCU.

First, install the required libraries: PubSubClient by Nick O’Leary and DHT Sensor by Adafruit.

The PubSubClient library provides the client with easy publish/subscribe messaging with a server that supports MQTT. On the other hand, the DHT sensor library allows the user to interface any DHT sensor to read temperature and humidity with an Arduino compatible board.

To install libraries in the IDE, open the Library Manager under Tools. You can also use the shortcut CTRL+SHIFT+I. Search for the name of the library in the manager and click install.

After installing the libraries, restart the program. Then, go to Tools. Inside boards, select NodeMCU 1.0 (ESP-12E Module). After that, choose the port number of your device in Tools > Port > COM7 (in my case).

Uploading the Codes

The first code will read the PIR sensor every quarter of a second or 250ms. If the value is 0, the loop will continue, but if the value is 1, it will send a string message to your NodeRED dashboard that a motion has been detected.

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

const char* ssid = "HUAWEI-6HxE";
const char* password = "K4H9khUh";
const char* mqtt_server = "192.168.100.23";

WiFiClient espClient;
PubSubClient client(espClient);

const int PIR = D0;

long now = millis();
long lastMeasure = 0;

void setup() {
  pinMode(PIR, INPUT);
  Serial.begin(115200);
  delay(10);
  
  Serial.println();
  
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  Serial.println("");
  Serial.print("WiFi connected - ESP IP address: ");
  Serial.println(WiFi.localIP());
  client.setServer(mqtt_server, 1883);
}

void loop() {

  if (!client.connected()) {
    while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");

    if (client.connect("ESP8266Client")) {
      Serial.println("connected");  
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
   }
 }
  if(!client.loop())
    client.connect("ESP8266Client");

  now = millis();
  
  if (now - lastMeasure > 250) {
    
    lastMeasure = now;
    
    int pirstate = digitalRead(PIR);
    
    if (pirstate == 1) {
      String alertmessage = "Motion Detected!";
      client.publish("home/pir", alertmessage);
    }        
    Serial.print("PIR State: ");
    Serial.println(PIR);
  }
} 

The next code reads the temperature and humidity readings from the DHT sensor everytwo seconds. Then, it publishes the values into the home/temperature and home/humidity topics via MQTT.

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include "DHT.h"

#define DHTTYPE DHT11   

const char* ssid = "HUAWEI-6HxE";
const char* password = "K4H9khUh";
const char* mqtt_server = "192.168.100.23";

WiFiClient espClient;
PubSubClient client(espClient);

const int DHTPin = D1;

DHT dht(DHTPin, DHTTYPE);

long now = millis();
long lastMeasure = 0;

void setup() {
  dht.begin();
  Serial.begin(115200);
  
  delay(10);

  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  Serial.println("");
  Serial.print("WiFi connected - ESP IP address: ");
  Serial.println(WiFi.localIP());
  client.setServer(mqtt_server, 1883);
}

void loop() {

  if (!client.connected()) {
    while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");

    if (client.connect("ESP8266Client")) {
      Serial.println("connected");  
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
   }
 }
  if(!client.loop())
    client.connect("ESP8266Client");

  now = millis();
  if (now - lastMeasure > 2000) {
    lastMeasure = now;
    float h = dht.readHumidity();
    float t = dht.readTemperature();

    if (isnan(h) || isnan(t)) {
      Serial.println("Failed to read from DHT sensor!");
      return;
    }
    
    static char temperatureTemp[7];
    dtostrf(t, 6, 2, temperatureTemp);
    static char humidityTemp[7];
    dtostrf(h, 6, 2, humidityTemp);

    client.publish("home/temperature", temperatureTemp);
    client.publish("home/humidity", humidityTemp);
    
    Serial.print("Humidity: ");
    Serial.println(h);
    Serial.print(" %\t Temperature: ");
    Serial.println(t);
  }
} 

Finally, the last code subscribes your Arduino or NodeMCU to the home/relay topic. If the switch on your NodeRED dashboard is toggled to HIGH or ON, the relay will be activated. Similarly, if it is toggled to LOW or OFF, the relay will shut down.

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

const char* ssid = "HUAWEI-6HxE";
const char* password = "K4H9khUh";
const char* mqtt_server = "192.168.100.23";

WiFiClient espClient;
PubSubClient client(espClient);

const int relay = D2;

void callback(String topic, byte* message, unsigned int length) {
  Serial.print("Message arrived on topic: ");
  Serial.print(topic);
  Serial.print(". Message: ");
  String messageTemp;
  
  for (int i = 0; i < length; i++) {
    Serial.print((char)message[i]);
    messageTemp += (char)message[i];
  }
  Serial.println();

  if(topic=="home/relay"){
      Serial.print("Changing relay to ");
      if(messageTemp == "on"){
        digitalWrite(relay, HIGH);
        Serial.print("On");
      }
      else if(messageTemp == "off"){
        digitalWrite(relay, LOW);
        Serial.print("Off");
      }
  }
  Serial.println();
}

void setup() {
  pinMode(relay, OUTPUT);
  Serial.begin(115200);
  
  delay(10);

  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  Serial.println("");
  Serial.print("WiFi connected - ESP IP address: ");
  Serial.println(WiFi.localIP());
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);

}

void loop() {

  if (!client.connected()) {
    while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");

    if (client.connect("ESP8266Client")) {
      Serial.println("connected");  
      client.subscribe("home/relay");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
   }
 }
  if(!client.loop())
    client.connect("ESP8266Client");
}

Be sure to update your Wifi name, password, and Raspberry Pi address. I won’t change mine so you can see where to put them. Lastly, you can change the indicated DHT sensor if you are using a different kind.