IIoT edge development – Using Modbus
Editor's Note: The Industrial Internet of Things (IIoT) promises to provide deep insight into industrial operations and enhance efficiency of connected machines and systems. Large-scale IIoT applications rely on layered architectures to collect data from a broad range of sensors, move data reliably and securely to the cloud, and perform analysis required to deliver that insight and efficiency. In Industrial Internet Application Development, the authors provide a detailed examination of the IIoT architecture and discuss approaches for meeting the broad requirements associated with these systems.
Adapted from Industrial Internet Application Development, by Alena Traukina, Jayant Thomas, Prashant Tyagi, Kishore Reddipalli.
Chapter 3. IIoT Edge Development (Continued)
By Alena Traukina, Jayant Thomas, Prashant Tyagi, Kishore Reddipalli
Industrial M2M protocols – Modbus
In this section, we will try to build a simple IoT application for sending data from a sensor simulator module to a receiver device (a PC or a cloud), using a Raspberry Pi hub and the Modbus protocol:
Data flow from a sensor simulator to a receiver device
For devices with limited hardware resources, it makes sense to use the Modbus protocol for serial communication. While simple, it has several open and proprietary implementations that vary in functionality.
Note that this protocol can be used on the transport layer, but, in our example, we are going to use Modbus TCP, working on the application level.
In the following table, you can find a more detailed description of the protocol to understand whether it is suitable for your needs:
Key | Value |
Open source | Yes* |
The OSI layer | Transport or an application |
Data types | Integer, float, string, Boolean |
Limitations | • No support for large binary objects
• The master node regularly polls each device for data modifications* • Maximum 254 devices addressed on a single data link* • Only contiguous transmissions are allowed |
Possible operations | Read and write registers and coils, diagnostics |
Latency | High |
Usage | SMS, GPRS, wireline, wireless, mesh communication |
Security | No |
Compression | No |
Table 4: The Modbus protocol specifications
![]() |
The values marked with * are not applicable to all implementations of the Modbus protocol. |
For building the application, we will need the following:
-
Required software:
-
The Cloud Foundry CLI (https://github.com/cloudfoundry/cli#downloads )
-
Required hardware:
-
Raspberry Pi 3 (model B)
-
A power adapter (2A/5V)
-
A microSD card (8 GB+) and an SD adapter
-
An Ethernet cable for a wired network connection
-
Preparing an SD card
To prepare an SD card, follow the sequence of actions as described:
-
Download the latest Raspbian LITE image (available at https://raspberrypi.org/downloads/raspbian/ ).
-
Connect your SD card to a computer and use Etcher (https://io/ ) to flash the Raspbian .img file to the SD card.
-
Enable SSH:
cd /Volumes/boot
touch ssh
-
To enable Wi-Fi, create conf with the following content:
network={
ssid=”YOUR_SSID”
psk=”YOUR_WIFI_PASSWORD”
}
![]() |
To create a file in a Linux console, you can use the GNU nano editor. It is pre-installed in most Linux distributives. All you need is to run the nano FILE_NAME command and follow the displayed instructions. |
-
Create the /home/pi/hub
-
Create the /home/pi/hub/package.json file with the following content:
{
“name”: “hub”,
“version”: “1.0.0”,
“description”: “”,
“main”: “index.js”, “scripts”: {
“start”: “node index.js”,
“test”: “echo “Error: no test specified” && exit 1″
},
“author”: “”,
“license”: “ISC”, “dependencies”: {
“modbus”: “0.0.16”,
“request”: “^2.81.0”
}
}
-
Create the /home/pi/hub/index.js file with the following content, replacing REMOTE-SERVER-ADDRESS.com and REMOTE-SENSOR-ADDRESS with real values:
-
Create a /home/pi/hub/Dockerfile file with the following content:
FROM hypriot/rpi-node:boron-onbuild
RUN apt-get update && apt-get install -y libmodbus5
-
Create the /home/pi/sensor
-
Create the /home/pi/sensor/package.json file with the following content:
{
“name”: “sensor”,
“version”: “1.0.0”,
“description”: “”,
“main”: “index.js”, “scripts”: {
“start”: “node index.js”,
“test”: “echo “Error: no test specified” && exit 1″
},
“author”: “”,
“license”: “ISC”, “dependencies”: {
“modbus”: “0.0.16”
}
}
-
Create the /home/pi/sensor/index.js file with the following content, replacing REMOTE-HUB-ADDRESS.com with a real value:
-
Create the /home/pi/sensor/Dockerfile file with the following content:
FROM hypriot/rpi-node:boron-onbuild
RUN apt-get update && apt-get install -y libmodbus5
Running a hub application on an RPi
To run a hub application on an RPi, proceed as the following steps suggest:
-
Insert an SD card into the
-
Connect an Ethernet cable and open an SSH connection.
-
Navigate to /home/pi/hub .
-
Build an image and run a Docker container:
# Build an image from a Dockerfiledocker build -t modbus-hub .## Run container in foregrounddocker run --privileged -it --rm --name modbus-hub-container modbus-hub## Run container in background# docker run --privileged -d --rm --name modbus-hub-container modbus-hub## Fetch the logs of a container# docker logs -f modbus-hub-container## Stop running container# docker stop modbus-hub-container
Console output when a hub app is running
Running a simulator application on an RPi
To run a simulator application, follow the sequence of actions as described here:
-
Open an SSH
-
Navigate to /home/pi/sensor .
-
Build an image and run a Docker container:
# Build an image from a Dockerfiledocker build -t modbus-sensor .## Run container in foregrounddocker run -p 1502:1502 --privileged -it --rm --name modbus-sensor- container modbus-sensor## Run container in background# docker run -p 1502:1502 --privileged -d --rm --name modbus- sensor-container modbus-sensor## Fetch the logs of a container# docker logs -f modbus-sensor-container## Stop running container# docker stop modbus-sensor-container
Console output when a simulator app is running
Running a receiver application on a PC
To run a receiver application on your PC, proceed as follows:
-
Install and launch a PostgreSQL container:
docker run –rm –name postgres-container -e
POSTGRES_PASSWORD=password -it -p 5433:5432 postgres
docker exec -it postgres-container createdb -U postgres iot-book
-
Create the receiver
-
Create the ./receiver/package.json file with the following content:
{
“name”: “receiver”,
“version”: “1.0.0”,
“description”: “”,
“main”: “index.js”, “scripts”: {
“start”: “node index.js”,
“test”: “echo “Error: no test specified” && exit 1″
},
“author”: “”,
“license”: “ISC”, “dependencies”: {
“pg”: “^6.2.3”
}
}
-
Create the ./receiver/index.js file with the following content, replacing the database credentials with the correct values:
var http = require('http');var querystring = require('querystring');
var Pool = require('pg').Pool;var pool = new Pool({
user: 'user',
database: 'database',
password: 'password',
host: 'host', port: 5432});
//ensure table exists in dbpool.query('CREATE TABLE IF NOT EXISTS "sensor-logs" (id serial NOT
NULL PRIMARY KEY, data json NOT NULL)', function (err, result) {
if (err) console.log(err);});
http.createServer(function (req, res) {
req.on('data', function (chunk) { var data = querystring.parse(chunk.toString());
console.log(data);
//save in db pool.query('INSERT INTO "sensor-logs" (data) VALUES ($1)',
[data], function (err, result) { if (err) console.log(err); });});req.on('end', function () { res.writeHead(200, 'OK', {'Content-Type': 'text/html'});
res.end('ok')});}).listen(process.env.PORT || 8080);
-
Create the ./receiver/Dockerfile file with the following content:
FROM node:boron-onbuild
EXPOSE 8080
-
Navigate to ./receiver .
-
Build an image and run a Docker container:
# Build an image from a Dockerfiledocker build -t modbus-receiver . # Run container in foregrounddocker run -p 8080:8080 -it --rm --name modbus-receiver-container modbus-receiver # Run container in background# docker run -p 8080:8080 -d --rm --name modbus-receiver-container modbus-receiver # Fetch the logs of a container# docker logs -f modbus-sensor-container # Stop running container# docker stop modbus-receiver-container
Console output when a receiver app is running
Running a receiver application in Predix
To run a receiver app in Predix, follow the sequence shown here:
-
Install and connect the Cloud Foundry CLI to your Predix
-
Create a PostgreSQL service and obtain the
-
Create the ./receiver/manifest.yml file with the following content:
applications:
–
name: receiver
memory: 128M
random-route: true
-
Replace the database credentials in ./receiver/index.js .
-
Deploy to the cloud:
cf push
-
Change the REMOTE-SERVER-ADDRESS in the hub application on the RPi to the newly deployed
Reprinted with permission from Packt Publishing. Copyright © 2018 Packt Publishing
About the authors
Alena Traukina is IoT practice Lead at Altoros. She has over 12 years of experience in delivery and support of business-critical software applications and is one of the first GE's Predix Influencers.
Jayant Thomas (JT) is the director of software engineering for the IoT apps for GE Digital. He is responsible for building IoT SaaS applications using the Predix platform, and specializes in building microservices-based architecture, reactive, event-driven systems.
Prashant Tyagi is responsible for enabling the big data strategy at GE Digital for the Industrial Internet that leverages IT and Operational data for predictive analytics. He works with all the P&L verticals (such as oil and gas, power generation, aviation, healthcare, and so on) to enable their IoT use cases on the data and analytics platform.
Kishore Reddipalli is a software technical director and expert in building IIoT big data and cloud computing platform and products at ultra scale. He is passionate in building software for analytics and machine learning to make it simplified for authoring the algorithms from inception to production at scale.