DEV Community

Cover image for How to Build a Robust IoT Prototype In Less Than a Day - Part 1
Luca Cipriani
Luca Cipriani

Posted on • Edited on

How to Build a Robust IoT Prototype In Less Than a Day - Part 1

The IoT world is powerful, but also quite complex. There are many protocols and vendors and the landscape is fragmented. [As Matt Turck has already shown in 2018.]

image5

Creating stable and effective prototypes is becoming essential for every web or embedded developer. However, to create a prototype, you have to deal with:

  • the hardware
  • the connectivity
  • the embedded software
  • the IoT vendor API
  • the security and deployment of your custom application.

Even for a basic prototype, this process could take weeks. In this article, I’ll show you how to build a robust IoT prototype in only a few hours by leveraging the power of Arduino, Heroku, and Node-RED.

The Project

Many IoT projects focus only on reading data from sensors. However, for real prototypes, you need bi-directionality of the data, from the IoT sensor node to the cloud and back from the cloud to the actuators. For all of you with more knowledge in web development and a little less in embedded systems, here are the definitions of sensor and actuator.

  • A sensor is an input device, reading some physical dimension and converting it to either a digital or analog value. This value is then read by a microcontroller. If you want to measure temperature, you would use a temperature sensor.
  • An actuator is an output device, acting on the physical world and changing the status of something physical. A switch or an LED are both actuators—you can turn them ON or OFF.

If you want to know more, read this article about the difference between sensors and actuators.

The overall architecture of most IoT projects might look something like this:

image2

So let’s create a sample app that will allow you to quickly create prototypes. We’ll use the following components:

  • Arduino boards as the IoT Node.
  • Arduino compatible shields as the sensors and actuators.
  • Arduino IoT Cloud account as the IoT server.
  • Node-RED for business logic (running in Heroku and with source code in GitHub)
  • A JavaScript custom application for the UI and mobile use case.

In our sample app, we’ll create a scenario where one Arduino board sends data from a sensor. (We will use luminosity, temperature, and humidity sensors.) The other device will show some information on the LED matrix as soon as it gets the information.

image3

What you need:

Let’s Get Started

As a first step, while we wait for the hardware to arrive, we can set up Node-RED. Node-RED is an incredibly powerful low-code programming tool for event-driven applications based on Node.js. It allows you to easily and graphically wire together flows between hardware devices, then deploy those flows with just one click. Node-RED is built on Node.js. (I will assume you are already familiar with Node.js. If not, then you can learn about and install it at https://nodejs.org/.)

Installing Node-RED

TL;DR: If you want to quickly test the application you can skip this part and jump to the section Wrapping It Up which has a link to a quick-start version of this project.

However, if you want to understand how to build this yourself and eventually update your work to the latest version of Node-RED, please follow the detailed instructions below.

It’s a little bit of work to install Node-RED and get it set up, secured, and working, so let’s walk through the steps. To start, be sure you have the latest stable version. For our purpose, we are going to use git.

git clone git@github.com:node-red/node-red.git node-red-private
cd node-red-private
## Let's move the latest stable version as of 2020-07-01
git checkout 1.1.0
## And create our branch for experimenting
git checkout -b iot-proto
## Install deps and build the app
npm install
npm run build
## Start the app
npm start
Enter fullscreen mode Exit fullscreen mode

Now Node-RED should be up and running, usually at http://localhost:1880. Open it, and you should see an interface similar to the following:

image4

This is a good start, but there's no security, and everything is running locally. This setup is not suitable for serious prototyping, and we do not want to behave like this comic.

image9
https://donthitsave.com/comic/2016/07/15/it-works-on-my-computer

Adding Credentials to Node-RED

To add security to Node-RED it’s best to protect the interface (static assets), the visual editor, and the Admin API. To do this, follow the official guide about Securing Node-RED. To add the credentials, we need a way to create a password and to obtain a hash for it. Node-RED has a simple tool for this called node-red-admin. It can be installed via:

$ npm install --save-dev node-red-admin
## Here is the dir where we will put our configurations
$ mkdir data
Enter fullscreen mode Exit fullscreen mode

Let’s also install the Arduino plugin in the same directory.

$ cd data
$ npm install @arduino/node-red-contrib-arduino-iot-cloud
Enter fullscreen mode Exit fullscreen mode

Now let’s create a password. The script will ask for a password interactively.

# ./node_modules/node-red-admin/node-red-admin.js hash-pw
Password: 
$2b$08$xGtfBswU4BF53FymNK9oae/Oz56d35W4/xxxxxxxxxxxx9cbC
Enter fullscreen mode Exit fullscreen mode

The string given back is the hash we can use in the settings.js file. A proper settings file can be found on the Github repo of Node-RED. Let's start with that file and adapt it to our needs. First, we have to uncomment the part about adminAuth and change it to something like this:

adminAuth: {
       type: "credentials",
       users: [{
           username: process.env.NODERED_USERNAME || "admin",
           password: process.env.NODERED_PASSWORD_HASH,
           permissions: "*"
    }]
},
Enter fullscreen mode Exit fullscreen mode

This allows us to use environment variables to set the hash of the password. (we just created it with the hash-pw command of node-red-admin), and a username (with fallback to “admin”).

The same will apply to another section of the file:


httpStaticAuth: {
        user: process.env.NODERED_USERNAME,
        pass: process.env.NODERED_PASSWORD_HASH
    },
Enter fullscreen mode Exit fullscreen mode

And

credentialSecret: process.env.NODERED_CREDENTIAL_SECRET,
Enter fullscreen mode Exit fullscreen mode

My complete settings file is available at [[ xxxxx ]]

The final important step is to set the port.

    uiPort: process.env.PORT || 1880,
Enter fullscreen mode Exit fullscreen mode

Be sure to save your work in a proper directory. Usually, Node-RED saves the data into $HOME/.node-red, but this will not work well with our setup in Heroku, nor is useful to have the source code revisions for our work. So I added...

     flowFile: 'data/flows.json',
Enter fullscreen mode Exit fullscreen mode

And

     userDir: 'data/',
Enter fullscreen mode Exit fullscreen mode

The full file settings.js without comments is less than 40 lines.

module.exports = {
    // the tcp port that the Node-RED web server is listening on
    uiPort: process.env.PORT || 1880,
    mqttReconnectTime: 15000,
    serialReconnectTime: 15000,
    debugMaxLength: 1000,
    flowFile: 'data/flows.json',
    credentialSecret: process.env.NODERED_CREDENTIAL_SECRET,
    userDir: 'data/',
    adminAuth: {
       type: "credentials",
       users: [{
           username: process.env.NODERED_USERNAME || "admin",
           password: process.env.NODERED_PASSWORD_HASH,
           permissions: "*"
    }]
    },
    httpStaticAuth: {
        user: process.env.NODERED_USERNAME || "admin",
        pass: process.env.NODERED_PASSWORD_HASH
    },
    functionGlobalContext: {
    },
    exportGlobalContextKeys: false,
    logging: {
        console: {
            level: "info",
            metrics: false,
            audit: false
        }
    },
    editorTheme: {
        projects: {
            enabled: false
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Setting Up Environment Variables

To declare the needed variables, you can create a local .env file like this one:

NODERED_PASSWORD_HASH='yourpassword-hash-from-the-node-red-admin-output'
NODERED_USERNAME='admin'
NODERED_CREDENTIAL_SECRET='averylongsecretofyourchoice'
Enter fullscreen mode Exit fullscreen mode

Now let’s load those variables and start Node-RED again.

$ export $(cat .env | xargs)
$ npm run build
$ npm start
Enter fullscreen mode Exit fullscreen mode

As soon as we see the Node-RED interface again, we will be prompted with a password.

image8

Our server is now secure, but still running locally. And after the login, we should be able to see the new Arduino plugin available in the left palette.

image7
image6

The Arduino IoT Cloud plugin for Node-RED allows Node-RED to read data from the sensors, send a payload back to the board, inject a value in one of our Arduino IoT Cloud properties, and access the historical values of a property. A property is the logical web representation of either a sensor or an actuator.

Now it’s time to make everything simpler and use Heroku to deploy Node-RED to our staging environment.

Installing Heroku CLI

Heroku is a PaaS vendor that makes it easy and fast to deploy apps to the cloud. We’ll use the Heroku CLI to set up and deploy to Heroku from our local machine. (The best way to install and understand how this works is by following the official tutorial on how to install Heroku CLI.) Once installed, in the same directory of our Node-RED instance, run

$ heroku login -i
heroku: Enter your login credentials
Email [l.cipriani@hey.com]:             
Password: **************
Two-factor code: ******
Logged in as l.cipriani@hey.com
Enter fullscreen mode Exit fullscreen mode

Then create a new app.

$ heroku create
Creating app... done, ⬢ arcane-castle-06470
https://arcane-castle-06470.herokuapp.com/ | https://git.heroku.com/arcane-castle-06470.git
Enter fullscreen mode Exit fullscreen mode

And finally give it a better, memorizable name:

    $ heroku apps:rename node-red-arduino
    Renaming arcane-castle-06470 to node-red-arduino... done
    https://node-red-arduino.herokuapp.com/ | https://git.heroku.com/node-red-arduino.git
    Git remote heroku updated
     ▸    Don't forget to update git remotes for all other local checkouts of the app.
Enter fullscreen mode Exit fullscreen mode

From now on, we’ll let Heroku handle the heavy work with deploying and running the app, as it supports Node.js and grunt out of the box.

To run Node-RED locally with Heroku, mimicking 100% what will happen in production, you can run...

    $ heroku local
Enter fullscreen mode Exit fullscreen mode

This will open the app at http://localhost:5000. However, we want to run and deploy our app on Heroku. This is just a matter of setting our vars and then pushing to the Heroku git endpoint.

    ## This will set the proper variables in Heroku. You can skip this if you want to use the Heroku Web UI to set your variables
    $ cat .env | xargs heroku config:set
    ## Now deploy our app!
    $ git push heroku iot-proto:master
Enter fullscreen mode Exit fullscreen mode

And see it online!

image1

Wrapping It Up

We now have a secure Node-RED instance running on Heroku and ready to hook up to our Arduino boards.

I’ve also built a quick way to reproduce the steps I’ve shown in detail. Full instructions are available at my node-red-iot repo on Github.

Here’s a recap of what we learned today:

  • The most common IoT Architectures
  • Setting up Node-RED locally
  • Adding security to Node-RED
  • Add environment variables and manage settings
  • Install Heroku CLI
  • Deploy our Node-RED instance to Heroku

Next Steps

In the next article, I’ll show you how to create our embedded system on the Arduino boards, connect them to our Node-RED instance, then create and save a flow to our Heroku instance that is resilient to restarts. Finally, I’ll show you how to create a custom application on top of this setup using JavaScript.

Top comments (0)