Smart Manufacturing

Production Line Monitoring Dashboard with MQTT, Grafana and Node-RED

A step-by-step build of a production line monitoring dashboard: stations publish status and counts over MQTT, Telegraf stores them, and Grafana or Node-RED turns them into a live line view.

Production line monitoring dashboard showing station status tiles, part counters and an OEE gauge fed by MQTT data
Run this on your own MQTT brokerGet a private, managed MQTT broker on the Free plan and start from ready-made code samples.
Try it free Code samples No card required

A production line monitoring dashboard turns raw machine signals into one screen that tells supervisors whether the line is running, how many good parts it has made and where it is losing time. In this tutorial you will publish station data over MQTT, store it with Telegraf and InfluxDB, and build the dashboard in Grafana, with a lighter Node-RED alternative for small lines. Everything runs against a real broker, so you can follow along from a laptop.

What a Good Production Line Dashboard Shows

Before wiring anything, decide what the screen must answer. Most line dashboards fail because they display every tag the PLC exposes instead of the handful of questions people actually ask during a shift.

Question on the floor Signal you need Typical widget
Is each station running right now? state (RUNNING, IDLE, DOWN, SETUP) Colour-coded status tiles
Are we on plan for the shift? Good count, plan count Big number plus progress bar
Where is scrap coming from? Reject count per station Bar chart by station
Which station is the bottleneck? Actual rate vs ideal rate Table sorted by rate gap
How healthy is the line overall? Availability, performance, quality OEE gauge with three sub-bars
What stopped us last hour? State changes with timestamps State timeline

Keep the first version to these six. Supervisors will ask for more once they trust the numbers, and trust comes from the counts matching what they see on the floor.

Architecture: From Station to Screen

The data path is short and every piece is replaceable:

  1. Each station (PLC gateway, edge PC or microcontroller) publishes a small JSON status message to an MQTT broker whenever its state changes and at least every few seconds.
  2. Telegraf subscribes to the line's topics and writes every message into InfluxDB as a time series.
  3. Grafana queries InfluxDB and renders the panels.
  4. Optionally, a Node-RED flow subscribes to the same topics and drives a lightweight dashboard on a TV beside the line.

The broker is the hub that decouples stations from consumers. If you are new to that role, this explainer on what an MQTT broker does covers the basics. Because every consumer subscribes independently, you can add a historian, an andon board or an OEE calculator later without touching the stations.

Step 1: Design the Topic Structure

A predictable topic tree saves hours later. Use an ISA-95 style hierarchy so the dashboard can filter by line and station with wildcards:

connectmq/demo/<your-id>/line1/<station>/status

For example connectmq/demo/a7f3k9/line1/filler/status. The payload is a single JSON object:

{
  "state": "RUNNING",
  "good": 1842,
  "reject": 17,
  "rate": 58.5,
  "ideal_rate": 60,
  "ts": 1792137600
}

Counts are cumulative for the shift, which makes the data robust: if a message is lost, the next one still carries the correct total. Rates are parts per minute. Add an enterprise and site level in front of the line when you roll out to more than one plant.

Step 2: Simulate the Stations

To build the dashboard before the real line is connected, run this Python simulator. It uses paho-mqtt 2.x and the free public MQTT broker at broker.connectmq.com. Replace a7f3k9 with your own random ID, because the public area is readable by everyone.

import json
import random
import time

import paho.mqtt.client as mqtt

PREFIX = "connectmq/demo/a7f3k9/line1"
STATIONS = {"filler": 60, "capper": 62, "labeler": 65, "packer": 58}

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="line1-sim-a7f3k9")
client.connect("broker.connectmq.com", 1883, keepalive=30)
client.loop_start()

counters = {name: {"good": 0, "reject": 0, "state": "RUNNING"} for name in STATIONS}

try:
    while True:
        for name, ideal in STATIONS.items():
            c = counters[name]
            # Occasionally change state to make the dashboard interesting
            roll = random.random()
            if c["state"] == "RUNNING" and roll < 0.03:
                c["state"] = random.choice(["DOWN", "IDLE"])
            elif c["state"] != "RUNNING" and roll < 0.25:
                c["state"] = "RUNNING"

            rate = 0.0
            if c["state"] == "RUNNING":
                rate = round(ideal * random.uniform(0.85, 1.0), 1)
                made = int(rate / 12)  # roughly 5 seconds of production
                rejects = 1 if random.random() < 0.04 else 0
                c["good"] += made - rejects
                c["reject"] += rejects

            payload = {
                "state": c["state"],
                "good": c["good"],
                "reject": c["reject"],
                "rate": rate,
                "ideal_rate": ideal,
                "ts": int(time.time()),
            }
            client.publish(f"{PREFIX}/{name}/status", json.dumps(payload), qos=1, retain=True)
        time.sleep(5)
except KeyboardInterrupt:
    client.loop_stop()
    client.disconnect()

Four stations publishing every five seconds stays well inside the public broker limit of 10 messages per second per client. The retain flag means a dashboard that connects mid-shift immediately receives the last known state of every station. Verify the stream from a terminal:

mosquitto_sub -h broker.connectmq.com -p 1883 -i viewer-a7f3k9 -t "connectmq/demo/a7f3k9/line1/+/status" -v

Step 3: Store the Data with Telegraf and InfluxDB

Telegraf's MQTT consumer turns each message into an InfluxDB point, and topic parsing extracts the line and station as tags. Save this as telegraf.conf:

[agent]
  interval = "5s"
  flush_interval = "5s"

[[inputs.mqtt_consumer]]
  servers = ["tcp://broker.connectmq.com:1883"]
  topics = ["connectmq/demo/a7f3k9/line1/+/status"]
  client_id = "telegraf-a7f3k9"
  qos = 1
  data_format = "json"
  json_string_fields = ["state"]
  json_time_key = "ts"
  json_time_format = "unix"

  [[inputs.mqtt_consumer.topic_parsing]]
    topic = "connectmq/demo/+/+/+/status"
    measurement = "_/_/_/_/_/measurement"
    tags = "_/_/_/line/station/_"

[[outputs.influxdb_v2]]
  urls = ["http://localhost:8086"]
  token = "YOUR_INFLUX_TOKEN"
  organization = "plant"
  bucket = "line"

Each point lands in the status measurement with tags line=line1 and station=filler, plus fields state, good, reject, rate and ideal_rate. For production, switch the server to ssl://broker.connectmq.com:8883 and add username = "YOUR_USERNAME", password = "YOUR_PASSWORD" and your issued client_id. More options are covered in the Telegraf MQTT consumer guide.

Step 4: Build the Production Line Monitoring Dashboard in Grafana

Add InfluxDB as a data source in Grafana (Flux query language) and create these panels.

Station status tiles. Use a Stat panel with value mappings: RUNNING to green, IDLE to yellow, DOWN to red, SETUP to blue.

from(bucket: "line")
  |> range(start: -5m)
  |> filter(fn: (r) => r._measurement == "status" and r._field == "state")
  |> last()
  |> group(columns: ["station"])

Good parts this shift. Because counts are cumulative, the last value is the total:

from(bucket: "line")
  |> range(start: today())
  |> filter(fn: (r) => r._measurement == "status" and r._field == "good" and r.station == "packer")
  |> last()

Use the last station on the line (here the packer) as the line output; counting at every station double-counts.

Rate vs ideal. A Time series panel with rate and ideal_rate per station shows the bottleneck at a glance: the station whose actual rate sits furthest below its ideal while running.

State timeline. Grafana's State timeline panel fed by the state field gives a bar per station coloured by state across the shift, which is the fastest way to see when and where the line stopped.

OEE gauge. For a first version, compute OEE in a separate subscriber and publish the result to line1/oee, then chart that topic. The maths is explained in how to calculate OEE, and the real-time OEE monitoring tutorial contains a ready subscriber. Doing the calculation once, outside Grafana, keeps every screen showing the same number.

Node-RED Alternative for a Single Line

If you only need a TV beside one line and do not want a time-series database, Node-RED is quicker. Configure an mqtt-broker config node with server broker.connectmq.com and port 1883 (or 8883 with TLS and your credentials in production), then add:

  1. An mqtt in node subscribed to connectmq/demo/a7f3k9/line1/+/status, output set to a parsed JSON object.
  2. A function node that extracts the station name from msg.topic.split("/")[4] and routes it to the right widget.
  3. Dashboard 2.0 ui-text widgets for state, ui-gauge widgets for rate and a ui-chart for good counts.

The trade-off is history: Node-RED shows the present well but is not a historian. Many plants run both, with Node-RED on the line display and Grafana for the shift review. The Node-RED OEE dashboard article goes further with this approach.

Common Pitfalls and How to Fix Them

  • Counts reset to zero mid-shift. A PLC or gateway restart clears its counter. Store the shift baseline at the edge, or have the dashboard use difference() with nonNegative: true so resets do not create negative production.
  • Tiles show stale RUNNING. If a station goes offline, its retained message still says RUNNING. Add the ts field to the tile and colour it grey when older than 30 seconds, or use an MQTT Last Will message that publishes OFFLINE.
  • Duplicate client IDs. Two Telegraf instances with the same client ID will keep kicking each other off. Every client needs a unique ID.
  • Too many panels. If the screen needs scrolling on the floor TV, it is too busy. Move detail to a drill-down dashboard.

Moving from Demo to Production

The public broker is perfect for building, but its topics are visible to anyone. For a real line, move to a private broker: a managed MQTT broker removes the job of patching and scaling a server, and a cloud MQTT broker lets remote supervisors and the head office view the same dashboard. With ConnectMQ you create the broker in the portal, get a username, password and client ID, and change only the connection settings in the simulator, Telegraf and Node-RED. The portal's live topic explorer is handy for confirming that every station is publishing before you debug a blank Grafana panel.

The free Serverless plan supports up to 25 connections, which covers a pilot line with its gateway, Telegraf and a couple of dashboards. Larger plants typically move to the paid Serverless plan or a Dedicated cluster as more lines come online. For the wider strategy, see the smart manufacturing guide.

Get Started with ConnectMQ

Create a free broker at app.connectmq.com on the Serverless plan with no credit card, point your stations and Telegraf at it, and have a production line dashboard running on private infrastructure today.

Frequently Asked Questions

Should I use Grafana or Node-RED for a production line dashboard?

Use Grafana when you need history, shift comparisons and many users; use Node-RED for a quick live display on one line. Many teams run both from the same MQTT topics.

How often should stations publish status?

Publish immediately on every state change and send a heartbeat every 5 to 10 seconds. That keeps tiles current without flooding the broker.

Can I connect PLCs directly?

Most PLCs need an edge gateway (Node-RED, a protocol converter or the PLC's own MQTT client) that reads tags and publishes JSON to the broker. Once the data is on MQTT, the dashboard does not care where it came from.

Is the public broker safe for real production data?

No. The public area of broker.connectmq.com is readable by anyone, so use it only for tests and move production data to a private ConnectMQ broker with credentials and TLS.

Related articles

OEE vs TEEP vs OOE: Which Metric Should You Use?

OEE, OOE and TEEP share the same performance and quality factors but measure against different time bases. This comparison works through one example and lists the MQTT signals each metric needs.

7 min read

All articles →

Your private MQTT broker is a few clicks away

Create an account, get your broker credentials and connect your first device — no servers to install, patch or scale.