InfluxDB for Modbus Observability

InfluxDB for Modbus Observability
Photo by Alberto Rodríguez / Unsplash

Introduction

In this previous blog post, I demonstrated a small application I made to retrieve Modbus metrics from a Teltonika Wi-Fi router which would collect metrics and send them via REST, this system works fine if you are happy with a lag in your metrics of up to a second or 2 depending on network conditions, due to:

  1. The modbus-http-exporter waiting for the metrics that are sent via REST.
  2. Prometheus pulling metrics from the exporter.

So, what can we do if we want to have millisecond delays instead?

Pull vs Push model

Firstly, we need to understand the differences between push and pull models for metric collection.

Pull model:

The Pull model does exactly as the name implies, it is a monitoring methodology which actively retrieves metrics from a list of targets. Each target for the pull method requires to expose the necessary metrics in a standardised format.

Pros of pulling metrics:

  • You can create extra monitoring resources when needed.
  • You can easily tell when a target resource is down.
  • Health of a target can be manually checked via a web browser.
  • Centralised configuration.

Cons of pulling metrics:

  • You require a service discovery method, e.g. you have to be able to provide each location of the targets.
  • Each target must be reachable from the monitoring system.
  • HTTP can timeout, especially on larger metric exporters.
  • You introduce more of a delay to the actual metrics, as you must wait for the monitoring system to tick over to pull the metrics on schedule.

Push model:

The Push model, works by immediately sending metrics once they have been gathered, eliminating the delay of waiting for the monitoring system to scrape the application for metrics.

Pros of pushing metrics:

  • No delay of waiting on pulling scrape cycles.
  • Updates are real-time.
  • Flexible configuration for network settings like NAT or firewalls.

Cons of pushing metrics:

  • No knowledge of targets, there is no way for the monitoring system to know whether a target is supposed to be sending metrics or not.
  • Potential for bottlenecks if the monitoring system cannot handle the number of pushes
  • If a network partition occurs between monitoring and application/devices, there's no built-in way to know.

How can we use push metrics for Modbus?

Assuming we want very low latency metrics coming from our modbus devices, and also assuming that your network has been configured to allow for very low latency traffic, what can we do?

As mentioned in the pros for the push model, we can get updates in real-time by utilising the push model, therefore we need to look into what monitoring systems support the push model, some of the options are below:

There are many options for push-based monitoring systems however for this blog post I will be taking a look at InfluxDB.

InfluxDB

InfluxDB is a time-series database, which can be used to collect data up to nanosecond precision. InfluxDB has been rated #1 time series database by DB-Engines (source: db-engines)

Why InfluxDB for Modbus?

I have chosen InfluxDB for this example for a few main reasons:

  1. Speed (as mentioned earlier, InfluxDB can be used with upto nanosecond precision)
  2. InfluxDB can handle high throughput data ingestion.
  3. Open source, InfluxDB's source code is available on Github here: link

This works for Modbus because it allows us to receive and alert on changes within our Modbus connected devices within milliseconds.

modbus-influxdb demo

For this post, I have created an example application which scans each connected devices holding register, and immediately pushes the retrieved data to InfluxDB.

Here's a link to the GitHub repo: https://github.com/azaurus1/modbus-influx

Explanation

The modbus-influxdb demo expects an instance of InfluxDB running on the host machine and an instance of a mock Modbus server, both of these are defined in the docker-compose.yml file and can be started with: docker compose up being run in the root directory of the demo.

Detailed steps:

  1. Run docker compose up in the root directory
  2. Go to http://localhost:8086 and set up InfluxDB
  3. Set up for a Go application and get your token
  4. Export your token to the environment with export INFLUXDB_TOKEN=[Your Token from InfluxDB]
  5. In another terminal run go run ./cmd in the root folder of the demo

What you will see in the docker compose terminal after running go run ./cmd will be debug logs from the mock modbus server displaying each read call of each holding register every millisecond.

Visualisation in InfluxDB:

To visualise the data which is being generated from the mock modbus server within InfluxDB, you can open the data explorer in InfluxDB and enter the following query script:

from(bucket: "modbus")
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|> filter(fn: (r) => r["_measurement"] =~ /^holding_register_\d+$/)
|> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)
|> yield(name: "mean")

This should show something like this:

Each register is configured in the server.json file to return its index as its value, e.g. Register 10 returns 10 for its value.

Future posts

This post is a part of a series around creating sub-second observability systems for IoT devices using Modbus, in future posts I will be going over how to utilise the InfluxDB Collector, Telegraf with Modbus to provide real-time metrics, as well as showing how we can use Redpanda to provide realtime insights from Modbus devices.

Don't forget to subscribe for more tips and tutorials on improving your observability systems.

Thanks for reading!