Previously I installed some sensors around my home, and got them to update their status into an MQTT Message Broker. The Message Broker acts as a central nervous system for the apartment, making the status of sensors available to everything.
Knowing status alone is not enough, we must be able to "do" things with the knowledge. We want to be able to transform the status from one form of information to another, to make decisions by combining inputs from different things, and finally, to act on those decisions.
Today I complement my setup by setting up Node-Red, the "brain" for the central nervous system. Node-Red can be used to design flows and processes, based on inputs, and also communicate information to many kinds of outputs.
To kick things off, I use the sensor status to determine what events have occurred in my house ("front door opened", "front door closed") and have this information formatted and sent to my mobile phone using a Telegram Bot.

Here are my setup notes.


Create Docker Container

I ssh'd into the nas using an admin account, and created a storage folder for use by the nodered container:
mkdir -p /volume1/docker/nodered/data
chmod 777 /volume1/docker/nodered/data
I then created the file /volume1/docker/nodered/docker-compose.yaml with the following contents:
version: '3'
services:
server:
image: nodered/node-red:latest
ports:
- "1880:1880"
env:
- "TZ:Asia/Kuala_Lumpur"
volumes:
- "/volume1/docker/nodered/data:/data"
Now I can execute docker-compose to initialize the container:
cd /volume1/docker/nodered
sudo docker-compose up --no-start
Creating network "nodered_default" with the default driver
Pulling server (nodered/node-red:latest)...
latest: Pulling from nodered/node-red
89d9c30c1d48: Pull complete
69ff64b59cc9: Pull complete
4251edd65978: Pull complete
e9fa308999cb: Pull complete
ccb02946661d: Pull complete
ed3d5c7ba54e: Pull complete
df94ef3d5e33: Pull complete
3aa179958f73: Pull complete
31befd7c32cf: Pull complete
4f14ccbb8258: Pull complete
Digest: sha256:32d957f063d937a1a0e0cb42234814a6d29cfa4846e2d476dd8b922989aa3803
Status: Downloaded newer image for nodered/node-red:latest
Creating nodered_server_1 ... done
sudo docker-compose start
Starting server ... done
And now I have node-red running on port 1880 of my NAS!




Let's Play!

Let's start by getting 433Mhz messages from my Mosquitto MQTT Message Broker into node-red:

  • Drag a mqtt-in node from the pallette to the flow area. Double click on it to set it up
    1. Under Server, select "Add a new mqtt-broker" and click the pen icon
      1. I named it "mosquito@nas1"
      2. Within the "Connection" tab
        1. I set the Server to the IP for my nas, and the port to 1883
      3. In the security tab:
        1. I entered a user name and password for accessing the mosquitto service.
        2. I created a new id "nodered" specifically for this connection.
        3. See my mosquitto setup article on how to create a mosquitto id.
      4. Click "Add"
    2. Set the topic to "tele/rfbridge1/RESULT", which is what the topic my Sonoff RFBridge433 sends messages on.
    3. Set output to "a parsed JSON Object"
    4. Set the name to "433Mhz Codes from RFBridge"
    5. Click Done.

  • Drag a "debug" node to the flow
    • Join the output of the "433Mhz Codes from RFBridge" to the Input of the "debug" node.

  • Drag a "switch" node to the flow.
    1. Join the output of the "433Mhz Codes from RFBridge" to the Input of the "Switch" node.
    2. Double click on the node to set it up
    3. I named it "Check RF Code"
    4. Set the property to "msg.payload.RFReceived.Data"
    5. For every code we want to detect:
      1. Press "add" to create a new rule if there isn't one available.
      2. Set the condition to "=="
      3. Set the value type to "String" (a-z)
      4. Set the value to the code for the RF device we want to detect, e.g. "CD04A1". The code is usually in the "Data" field and can be found by triggering the device and monitoring the Sonoff RFBridge433's console.
      5. Each matched code will be assigned a number, indicated by the arrow on the right of the rule.
    6. Select "stopping after first match"
    7. Click done.

  • For every code we detected in the switch node, drag a "function" node to the flow
    1. Join the output #1 of the "Check RF Code" to the input of this "function" node.
    2. Set the name to describe the RF Code detected, e.g. "Study Room Smoke Detector"
    3. Set the function body to:
msg.topic = "alert";
msg.payload = "Study Room Smoke Detector Triggered";
return msg

  • For each function node we created above
    • Drag a debug node to the flow
    • join the function node's output to the debug nodes input.

  • Hit the Deploy button at the top right.

The end result should be something like this:




Next I got up, opened the front gate, pressed the doorbell, and closed the gate. Here's the debug output in node-red:




  • 1/20/2020, 3:46:59 AM node: 6e3a2f41.29bf3, alert : msg.payload : string[21], "Front Gate Open Event"
  • 1/20/2020, 3:47:07 AM node: 223875c4.77ad7a, alert : msg.payload : string[22], "Doorbell Pressed Event"
  • 1/20/2020, 3:47:14 AM node: adcec9ae.78e268, alert : msg.payload : string[17], "Front Gate Closed"

Telegram Integration

We've got the real world interacting with Node-Red, now let's get Node-Red to interact with the Real World.

  • From the menu in the top right, select "Manage Pallette"
  • Click on the "Install" tab
  • Install node-red-contrib-telegrambot
  • Drag a "telegram sender" node into the flow
    • Under Bot: Click the "pen" to define a new bot
      • Enter the bot name
      • Enter the Bot token
      • Under Users: write your user name. This is an easy way to protect your bot from interacting with anybody else.
      • Update Mode: Polling
      • Poll Interval: 300
      • Verbose logging: ticked
      • Save
    • Make sure the bot is selected
    • Under Name: give a label for the node
    • Press "Done"
  • The telegram sender node expects a msg formatted a particular way. Drag a function node to translate our detector outputs into a telegram message format.
    • Name : Format Telegram Msg
    • Function:
msgtext = msg.topic + ": " + msg.payload;
msg.payload = {
content : msgtext,
type : 'message',
chatId: '{your chat id}'
};
return msg;
    • Press "Done"
  • Link the output of all the detector nodes into the "Format Telegram Msg Node"
  • Link the output of the "Format Telegram Msg" node with the Telegram Sender Node.



And now when I go out and ring my doorbell: