Grafana for Industrial IoT Monitoring: Modbus Dashboard, Alerts, History

· 8 min read
8 min read
Eziwan Team
IoT Infrastructure

Grafana has become the go-to tool for industrial data visualization. Free, open-source, and extensible, it transforms your Modbus, OPC-UA, or MQTT data into operational dashboards. This guide shows you how to design a comprehensive industrial monitoring system with Grafana—or how Eziwan can provide it to you as a turnkey solution.


Why Use Grafana for Industrial Monitoring?

Grafana has established itself in the industry for several reasons:

  • Universal connectors: InfluxDB, TimescaleDB, PostgreSQL, Prometheus, MQTT, REST API — a data source for every stack
  • Rich dashboards: time series, gauge, stat, table, heatmap, flow chart (with plugins)
  • Built-in alerts: SMS, email, Slack, PagerDuty, and webhook notifications
  • Access management: teams, folders, and permissions per dashboard
  • Industry-specific plugins: P&ID (flowcharting), piping diagrams, and schematic diagrams

Compared to a traditional SCADA system:

Grafana (+ IoT stack)Wonderware/Ignition SCADA
License cost0 (open source)5,000–50,000€
Hosting cost50–200€/month (cloud)Dedicated server + maintenance
Unlimited variables❌ (billed per tag)
Native web interface✅ (Ignition) / ❌ (Wonderware)
Mobile-readyPartially
Cloud integrationNativeComplex

Architecture: From Modbus to Grafana

The complete stack for monitoring Modbus PLCs in Grafana:

Alternative for large volumes:

Eziwan Solution (all-in-one):

Eziwan includes the complete stack (Modbus/OPC-UA data collection, cloud time series, preconfigured Grafana dashboards, SMS/email alerts) without requiring you to install and maintain the components individually.


Install Grafana + InfluxDB with Docker

# docker-compose.yml
version: '3.8'

services:
influxdb:
image: influxdb:2.7
ports:
- "8086:8086"
environment:
DOCKER_INFLUXDB_INIT_MODE: setup
DOCKER_INFLUXDB_INIT_USERNAME: admin
DOCKER_INFLUXDB_INIT_PASSWORD: mot_de_passe_securise
DOCKER_INFLUXDB_INIT_ORG: eziwan
DOCKER_INFLUXDB_INIT_BUCKET: industrie
DOCKER_INFLUXDB_INIT_RETENTION: 1825d # 5 ans
volumes:
- influxdb_data:/var/lib/influxdb2

grafana:
image: grafana/grafana:10.4.0
ports:
- "3000:3000"
environment:
GF_SECURITY_ADMIN_PASSWORD: grafana_securise
volumes:
- grafana_data:/var/lib/grafana
depends_on:
- influxdb

telegraf:
image: telegraf:1.29
volumes:
- ./telegraf.conf:/etc/telegraf/telegraf.conf:ro
depends_on:
- influxdb

volumes:
influxdb_data:
grafana_data:

Configuring Telegraf for MQTT

# telegraf.conf
[[inputs.mqtt_consumer]]
servers = ["tcp://localhost:1883"]
topics = ["usine/#"]
qos = 1
data_format = "json"

# Parsing the MQTT topic: factory/site/station/variable
[[inputs.mqtt_consumer.topic_parsing]]
topic = "usine/+/+/+"
tags = "_/_/station/_"
fields = "_/_/_/value"

[[outputs.influxdb_v2]]
urls = ["http://influxdb:8086"]
token = "votre_token_influxdb"
organization = "eziwan"
bucket = "industrie"

Create Your First Industrial Dashboard

Panel 1: Trend Chart (Time Series)

To view the pressure trends for a station over time:

InfluxDB (Flux) Query:

from(bucket: "industrie")
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|> filter(fn: (r) => r["_measurement"] == "mqtt_consumer")
|> filter(fn: (r) => r["station"] == "station1")
|> filter(fn: (r) => r["_field"] == "pression")
|> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)
|> yield(name: "mean")

Panel settings:

  • Type: Time series
  • Y-axis unit: bar (Pressure)
  • Line width: 2
  • Fill opacity: 10
  • Thresholds: green < 8 bar, orange 8–10 bar, red > 10 bar

Panel 2: Gauge (Instantaneous Value)

To display the current value of a variable:

InfluxDB Query:

from(bucket: "industrie")
|> range(start: -1m)
|> filter(fn: (r) => r["station"] == "station1" and r["_field"] == "pression")
|> last()

Panel settings:

  • Type: Gauge
  • Min: 0, Max: 16
  • Unit: bar
  • Thresholds: 0=green, 10=orange, 12=red

Panel 3: Metrics (KPIs)

To view the OEE or a production counter:

InfluxDB Query:

from(bucket: "industrie")
|> range(start: -24h)
|> filter(fn: (r) => r["_field"] == "pieces_produites")
|> sum()

Panel settings:

  • Type: Stat
  • Unit: pcs (custom)
  • Color mode: Background (red if < target)

Panel 4: Multi-site Table

To view the status of all your sites in real time:

from(bucket: "industrie")
|> range(start: -5m)
|> filter(fn: (r) => r["_field"] == "pression" or r["_field"] == "debit" or r["_field"] == "etat")
|> last()
|> pivot(rowKey: ["_time", "station"], columnKey: ["_field"], valueColumn: "_value")

Result: a table with columns for Station, Pressure, Flow Rate, and Status, with one row per site.


Configure Grafana Alerts

Threshold Exceeded Alert

In Grafana 10+ (Unified Alerting):

  1. Open the panel → Edit → Alert
  2. Create a rule:
    Condition: WHEN last() OF query(A, 5m, now) IS ABOVE 10
  3. Configure the notification:
    • Contact Point: Email → maintenance@usine.fr
    • Contact Point: Webhook → SMS via Twilio/OVH SMS
  4. Auto-mute: 15 minutes after acknowledgment

Alert Grouping for Multi-Site Environments

To avoid "alert storms" when multiple sites go down at the same time:

# alertmanager.yml
route:
group_by: ['alertname', 'site']
group_wait: 30s
group_interval: 5m
repeat_interval: 3h
receiver: 'maintenance-team'

receivers:
- name: 'maintenance-team'
email_configs:
- to: 'maintenance@usine.fr'
send_resolved: true
webhook_configs:
- url: 'https://api.sms-provider.fr/send'

Event Annotation

Add automatic annotations to graphs when alarms occur:

// Create an InfluxDB annotation when a failure occurs
from(bucket: "industrie")
|> range(start: v.timeRangeStart)
|> filter(fn: (r) => r["_field"] == "defaut" and r["_value"] == 1)
|> map(fn: (r) => ({r with _value: "Défaut détecté sur ${r.station}"}))

Grafana Templates and Variables for Multi-Site Setups

Template Variables let you create a generic dashboard that can be reused across all your sites.

Create a "site" variable

Dashboard Settings → Variables → New Variable:

  • Name: site
  • Type: Query
  • Data Source: InfluxDB
  • Query:
    import "influxdata/influxdb/schema"
    schema.tagValues(bucket: "industrie", tag: "station")

Using the variable in panels

from(bucket: "industrie")
|> range(start: v.timeRangeStart)
|> filter(fn: (r) => r["station"] == "${site}")
|> filter(fn: (r) => r["_field"] == "pression")

The operator can now select the site from a drop-down menu at the top of the dashboard.


Preconfigured Grafana Dashboards for Industry

Pumping Station Monitoring Dashboard

┌─────────────────────────────────────────────────────────────────┐
│ Station: [dropdown] │ Period: [6h|24h|7d|30d] │
├──────────────┬──────────────┬──────────────┬────────────────────┤
│ Pressure │ Flow Rate │ Level │ Pump Status │
│ [gauge] │ [gauge] │ [gauge] │ [stat 🟢/🔴] │
├──────────────┴──────────────┴──────────────┴────────────────────┤
│ 24-Hour Trends: Pressure / Flow / Level │
│ [time series graph] │
├─────────────────────────────────────────────────────────────────┤
│ Active Alarms │ Latest Actions │
│ [table] │ [table annotations] │
└─────────────────────────────────────────────────────────────────┘

Multi-Site Production Dashboard

┌────────────────────────────────────────────────────────────────────┐
│ Vue globale — 15 sites │
├──────────┬──────────┬──────────┬──────────┬──────────┬────────────┤
│ Site 1 │ Site 2 │ Site 3 │ Site 4 │ Site 5 │ ... │
│ TRS: 87% │ TRS: 91% │ TRS: 73% │ TRS: 94% │ TRS: 82% │ │
│ 🟢 OK │ 🟢 OK │ 🔴 Alrm │ 🟢 OK │ 🟡 Warn │ │
├──────────┴──────────┴──────────┴──────────┴──────────┴────────────┤
│ 24-Hour Cumulative Production: Target vs. Actual [bar chart] │
└────────────────────────────────────────────────────────────────────┘

Eziwan → Grafana Integration

Eziwan offers two ways to integrate with Grafana:

The Eziwan platform natively integrates Grafana. Your Modbus/OPC-UA data is already stored in our time-series database hosted in France. You can access the dashboards directly from your browser, with:

  • Preconfigured dashboards for common use cases (water, energy, production)
  • Managed SMS/email alerts
  • 5 years of data archiving with no configuration required
  • Multi-site, multi-user, and access rights management

Mode 2: Export to Your Existing Grafana Instance

If you already have an internal Grafana instance:

  • Eziwan REST API: Query your data via GET /api/v1/variables/{id}/history
  • MQTT Webhook: Eziwan publishes your data to your existing MQTT broker
  • Eziwan Grafana Plugin (available upon request): plugin data source for direct connection

FAQ — Grafana for Industrial Monitoring

Can Grafana replace a SCADA system in production? For visualization and alerts, yes, in many cases. For real-time control (writing to a PLC, control sequences), a SCADA system or a dedicated HMI system is still recommended. Grafana excels at data archiving, trend analysis, and multi-site monitoring.

Which database should you use to store industrial data in Grafana? InfluxDB is the standard choice for industrial time series (high frequency, native compression, powerful Flux queries). TimescaleDB (a PostgreSQL extension) is a good fit if you already use PostgreSQL. Prometheus is well-suited for infrastructure metrics but less relevant for process data.

How do I secure access to Grafana from the Internet? Place Grafana behind a reverse proxy (Nginx/Traefik) with TLS, enable OIDC/LDAP authentication, disable anonymous access, and configure alerts for failed login attempts. Never expose InfluxDB directly to the Internet.

Can Grafana handle 1,000 sites and 100,000 variables? Yes, with the right architecture. InfluxDB 2.x supports billions of data points. Grafana Enterprise handles clustering. For very large volumes, consider using Apache Kafka upstream for streaming, along with differentiated retention policies (1-second data retained for 30 days, 1-minute data retained for 5 years).

Can I display a P&ID diagram in Grafana? Yes, with the Flowcharting plugin (based on draw.io). You draw your P&ID diagram, attach Grafana variables to each piece of equipment, and the values are displayed in real time on the diagram, with colors changing based on the status.


Further Reading


Want Grafana dashboards without having to manage the infrastructure? Try Eziwan free for 30 days — get your Modbus data into Grafana in less than an hour.


Additional Resources