By IoT Engineering Team

MQTT IoT Digital Twin - Node-RED Flow & Dashboard

Intermediate 7 min
IoTMQTTNode-RED

Step 5: Node-RED Flow & Dashboard

Now let’s build the Node-RED flow that subscribes to MQTT, processes data, and shows it on a dashboard.

Access Node-RED

Node-RED should be running from Docker Compose. Open your browser:

http://localhost:1880

You should see the Node-RED editor.

Install Dashboard Nodes

First, install the dashboard nodes:

  1. Click the menu (☰) → Manage palette
  2. Go to Install tab
  3. Search for node-red-dashboard
  4. Click Install

This adds dashboard nodes for gauges, charts, and UI elements.

Build the Flow

Here’s the complete flow structure:

JSON Temp Hum Bat Data MQTT In Function Gauge Temp Gauge Hum Gauge Bat Chart

Step-by-Step Flow Creation

1. Add MQTT In Node

  • Drag mqtt in node to canvas
  • Double-click to configure:
    • Server: Add new → localhost:1883 (or use mosquitto if in Docker network)
    • Topic: iot/devices/+/telemetry
    • QoS: 1
  • Click Done

2. Add Function Node (Validation)

  • Drag function node to canvas
  • Connect it after MQTT In
  • Double-click and paste this code:
// Validate and parse message
const msg = JSON.parse(msg.payload);

// Validate required fields
if (!msg.deviceId || !msg.ts || !msg.metrics || !msg.seq) {
    node.warn("Missing required fields");
    return null; // Drop invalid message
}

// Validate value ranges
const temp = msg.metrics.temperatureC;
const hum = msg.metrics.humidityPct;
const bat = msg.metrics.batteryPct;

if (temp < -50 || temp > 100 || hum < 0 || hum > 100 || bat < 0 || bat > 100) {
    node.warn("Values out of range");
    return null;
}

// Add derived metric (Fahrenheit)
msg.metrics.temperatureF = (temp * 9/5) + 32;

// Store device ID for routing
msg.deviceId = msg.deviceId;

// Output validated message
return msg;

3. Add Dashboard Nodes

Temperature Gauge:

  • Drag gauge node to canvas
  • Connect from Function
  • Configure:
    • Group: Add new → IoT Dashboard
    • Tab: Add new → Digital Twin
    • Label: Temperature
    • Units: °C
    • Min: 0, Max: 40
    • Value: {{metrics.temperatureC}}

Humidity Gauge:

  • Another gauge node
  • Same group/tab
  • Label: Humidity
  • Units: %
  • Min: 0, Max: 100
  • Value: {{metrics.humidityPct}}

Battery Gauge:

  • Another gauge node
  • Same group/tab
  • Label: Battery
  • Units: %
  • Min: 0, Max: 100
  • Value: {{metrics.batteryPct}}

Chart:

  • Drag chart node
  • Same group/tab
  • Label: Temperature Over Time
  • Chart Type: Line
  • X-axis: Time
  • Y-axis: {{metrics.temperatureC}}

4. Deploy

Click the Deploy button (top right). The flow is now active.

View the Dashboard

Open the dashboard:

http://localhost:1880/ui

You should see:

  • Three gauges showing current values
  • A line chart showing temperature history
  • Values updating in real-time as messages arrive

Add Debug Node (Optional)

To see raw messages in Node-RED sidebar:

  • Add debug node
  • Connect from Function
  • Configure: Output: complete message object
  • Deploy

Messages will appear in the Debug tab on the right.

Flow JSON Export

Here’s the complete flow as JSON (you can import this):


              [
{
  "id": "mqtt-in-1",
  "type": "mqtt in",
  "name": "Subscribe Telemetry",
  "topic": "iot/devices/+/telemetry",
  "qos": "1",
  "broker": "broker-config",
  "x": 100,
  "y": 100,
  "wires": [["function-1"]]
},
{
  "id": "function-1",
  "type": "function",
  "name": "Validate & Transform",
  "func": "const msg = JSON.parse(msg.payload);\nif (!msg.deviceId || !msg.ts || !msg.metrics || !msg.seq) {\n    return null;\n}\nconst temp = msg.metrics.temperatureC;\nconst hum = msg.metrics.humidityPct;\nconst bat = msg.metrics.batteryPct;\nif (temp < -50 || temp > 100 || hum < 0 || hum > 100 || bat < 0 || bat > 100) {\n    return null;\n}\nmsg.metrics.temperatureF = (temp * 9/5) + 32;\nreturn msg;",
  "outputs": 1,
  "x": 300,
  "y": 100,
  "wires": [["gauge-temp", "gauge-hum", "gauge-bat", "chart-1"]]
},
{
  "id": "gauge-temp",
  "type": "ui_gauge",
  "name": "Temperature",
  "group": "dashboard-group",
  "order": 1,
  "width": 0,
  "height": 0,
  "gtype": "gauge",
  "title": "Temperature",
  "label": "units",
  "format": "{{value}}°C",
  "min": 0,
  "max": 40,
  "x": 500,
  "y": 80,
  "wires": []
},
{
  "id": "gauge-hum",
  "type": "ui_gauge",
  "name": "Humidity",
  "group": "dashboard-group",
  "order": 2,
  "width": 0,
  "height": 0,
  "gtype": "gauge",
  "title": "Humidity",
  "label": "units",
  "format": "{{value}}%",
  "min": 0,
  "max": 100,
  "x": 500,
  "y": 150,
  "wires": []
},
{
  "id": "gauge-bat",
  "type": "ui_gauge",
  "name": "Battery",
  "group": "dashboard-group",
  "order": 3,
  "width": 0,
  "height": 0,
  "gtype": "gauge",
  "title": "Battery",
  "label": "units",
  "format": "{{value}}%",
  "min": 0,
  "max": 100,
  "x": 500,
  "y": 220,
  "wires": []
},
{
  "id": "chart-1",
  "type": "ui_chart",
  "name": "Temperature Chart",
  "group": "dashboard-group",
  "order": 4,
  "width": 0,
  "height": 0,
  "label": "Temperature Over Time",
  "chartType": "line",
  "legend": "false",
  "xformat": "HH:mm:ss",
  "interpolate": "linear",
  "nodata": "",
  "dot": false,
  "ymin": "",
  "ymax": "",
  "removeOlder": 1,
  "removeOlderPoints": "",
  "removeOlderUnit": "3600",
  "cutout": 0,
  "x": 500,
  "y": 290,
  "wires": [[], []]
},
{
  "id": "broker-config",
  "type": "mqtt-broker",
  "name": "Local Mosquitto",
  "broker": "mosquitto",
  "port": "1883",
  "clientid": "node-red",
  "autoConnect": true
},
{
  "id": "dashboard-group",
  "type": "ui_group",
  "name": "IoT Dashboard",
  "tab": "dashboard-tab",
  "order": 1,
  "disp": true,
  "width": "6"
},
{
  "id": "dashboard-tab",
  "type": "ui_tab",
  "name": "Digital Twin",
  "icon": "dashboard",
  "order": 1
}
]
            

To import:

  1. In Node-RED, click menu → Import
  2. Paste the JSON
  3. Click Import
  4. Configure the MQTT broker connection
  5. Click Deploy

Checkpoint ✅

You should have:

  • ✅ Node-RED flow deployed and running
  • ✅ Dashboard showing real-time values
  • ✅ Gauges updating as messages arrive
  • ✅ Chart showing temperature history
  • ✅ Messages being validated

If something’s wrong:

  • Check Node-RED logs: docker-compose logs node-red
  • Check MQTT connection in Node-RED (red dot = disconnected)
  • Verify simulator is running and publishing
  • Check topic matches: iot/devices/+/telemetry

What’s Next?

In the final page, you’ll add alert rules (battery low, temperature high) and learn about production considerations. This completes your digital twin system!

Discussion

Join the conversation and share your thoughts

Discussion

0 / 5000