Intermediate 25 min

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!