跳转至

Node-RED Dashboard 可视化数据看板实现

简介

本教程利用Node-RED Dashboard 搭建一个具备实时数据展示、历史趋势追踪、交互控制的完整物联网看板。

1. 安装 Dashboard 可视化插件

Node-RED 默认不包含仪表盘控件,需要先安装官方插件,在 节点管理搜索 node-red-dashboard 进行安装

2. 核心基础:Dashboard 三层 UI 结构

Node-RED Dashboard 页面严格遵循三级层级,从上到下依次嵌套,所有可视化控件必须放在对应层级内才能显示。
层级关系:Tab 标签页 → Group 分组 → Widget 控件

  • Tab (标签页):看板最外层页面,一个 Tab 对应一个独立看板页面
  • Group (分组):页面内的模块区块,用于归类同类功能控件,方便排版布局
  • Widget (控件):最基础的可视化 / 交互组件(仪表盘、曲线、按钮、文字)
    Tab 和 Group 在控件里面进行配置

3. 常用可视化控件快速认知

本项目用到 4 个常用核心控件:

宣传图

Gauge 仪表盘:

  • Group:绑定所属分组,决定控件在看板哪个区块显示
  • Size:控件宽高网格尺寸
  • Type:仪表盘样式(半圆 / 环形 / 罗盘)
  • Label:仪表盘顶部标题
  • Value format:数值渲染模板, {{value}} 接收数据
  • Units:数值后缀单位(℃ /% )
  • Range min/max:仪表盘刻度量程上下限
  • Colour gradient:正常 / 预警 / 超限三色
  • Sectors:两段阈值,划分三色区间
  • Name:编辑器节点备注名称

宣传图

Chart 趋势图:

  • Type:图表类型, Line chart 折线图; enlarge points 放大数据点
  • X-axis:横轴数据留存时长 / 点数,自动清理过期数据
  • X-axis Label:横轴时间格式, as UTC 切换时区
  • Y-axis min/ max:纵轴数值量程, 留空自动适配
  • Legend:是否显示曲线图例
  • Interpolate:曲线插值平滑方式
  • Series Colours:多条曲线自动分配的配色
  • Blank label:无数据时展示的提示文字

宣传图

Text 文本控件:

  • Value format:数据渲染模板, {{msg.payload}}读取消息负载显示内容
  • Layout:标题与数值的排版布局(左右并排/上下堆叠/居中)
  • Style:Apply Style 开启后可自定义文字颜色、字号等样式
  • Class:自定义 CSS样式类,进阶美化控件

宣传图

Button 按钮控件:

  • Icon:按钮前置图标,填写图标名称即可显示
  • Tooltip:鼠标悬浮按钮时弹出的提示文字
  • Color/ Background:分别设置按钮文字图标颜色、按钮背景色
  • Payload:点击按钮时向下游输出的消息负载内容
  • Topic:点击按钮时输出消息的 topic 主题标识
  • If msg arrives on input, emulate a button click:勾选后上游收到消息将自动模拟点击按钮
  • Class:自定义 CSS样式类,用于进阶美化

4. 项目实战:搭建车间温湿度监控看板

4.1 架构流程

宣传图

4.3 节点分步配置讲解

4.3.1 模拟传感器 (Inject节点)

宣传图

自动触发数据采集,模拟传感器 10 秒上报一次数据,无需手动触发。真实项目中可直接替换为 MQTT/Modbus 传感器采集节点。

4.3.2 生成并拆分数据 (Function节点)

自动生成 20~35℃车间温度、40%~80%车间湿度的随机模拟数据。同时拆分三路数据输出,分别供仪表盘、趋势图使用。

//1.模拟生成温湿度数据
const temp=parseFloat((Math.random()*15+20).toFixed(1));
//20~35℃
const humi= parseFloat((Math.random()*40+40).toFixed(1));
//40~80%
var msg_temp= {payload: temp, topic:"温度"};
var msg_humi= {payload: humi, topic:"湿度"};
return[msg_temp, msg_humi,[msg_temp, msg_humi]];

4.3.3 温湿度仪表盘 (Gauge)

  • 温度表盘: 量程0~50℃, ≤25℃绿色正常、25~35℃黄色预警、>35℃红色超限
  • 湿度表盘: 量程0~100%, ≤40%绿色正常、40~70%黄色预警、>70%红色超限

4.3.4 温湿度趋势图 (Chart)

宣传图

自动记录近 10分钟温湿度数据,生成双曲线折线图,时间轴精确到时分秒,自动清理过期数据,界面直观展示数据波动趋势。

4.3.5 告警灯开关(Button)

宣传图

每次点击按钮,会向下游告警逻辑 Function节点发送一条完整消息:

4.3.6 告警逻辑处理 (Function)

通过流程变量缓存告警状态,点击按钮自动翻转状态,分别输出红色警报、绿色正常状态信息。

let isAlarmOn = flow.get('isAlarmOn') || false;
isAlarmOn = !isAlarmOn;
flow.set('isAlarmOn', isAlarmOn);
if(isAlarmOn) {
    msg.payload = "警报";
    msg.color = "red";
} else {
    msg.payload = "正常";
    msg.color = "green";
}
return msg;

4.3.7 告警状态展示 (Text)

实时渲染告警状态文字,居中展示,直观查看车间告警状态。

效果展示

宣传图

宣传图

4.4 页面布局结构

宣传图

  • 主标签页:车间温湿度监控
  • 分组1 (实时数据与告警):温度表盘、湿度表盘、告警按钮、状态文本
  • 分组2 (历史趋势曲线):温湿度历史折线图

5. 看板访问与多终端适配

5.1 访问地址

部署成功后,浏览器打开地址:
http://设备IP:1880/ui
示例:设备局域网 IP 为 192.168.1.100 ,则访问: http://192.168.1.100/ui

5.2 自适应特性

看板自带响应式布局,无需额外开发,自动适配 电脑、平板、手机 所有终端设备。

[
    {
        "id": "f32f05f12df272db",
        "type": "inject",
        "z": "7e8973429d00dbe0",
        "name": " 模拟传感器 ",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "10",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 120,
        "y": 120,
        "wires": [
            [
                "6363e9e60ba7eef4"
            ]
        ]
    },
    {
        "id": "6363e9e60ba7eef4",
        "type": "function",
        "z": "7e8973429d00dbe0",
        "name": " 生成温湿度数据 ",
        "func": "//1.模拟生成温湿度数据\nconst temp=parseFloat((Math.random()*15+20).toFixed(1));\n//20~35℃\nconst humi= parseFloat((Math.random()*40+40).toFixed(1));\n//40~80%\nvar msg_temp= {payload: temp, topic:\"温度\"};\nvar msg_humi= {payload: humi, topic:\"湿度\"};\nreturn[msg_temp, msg_humi,[msg_temp, msg_humi]];",
        "outputs": 3,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 340,
        "y": 120,
        "wires": [
            [
                "a3d5b5e8c7f1a2b3"
            ],
            [
                "b4e6c7d8e9f0a1b2"
            ],
            [
                "d61637279ce20149"
            ]
        ]
    },
    {
        "id": "a3d5b5e8c7f1a2b3",
        "type": "ui_gauge",
        "z": "7e8973429d00dbe0",
        "name": " 温度表 ",
        "group": "84282b608648b0b0",
        "order": 1,
        "width": "3",
        "height": "3",
        "gtype": "gage",
        "title": " 车间温度 ",
        "label": "°C",
        "format": "{{value}}",
        "min": 0,
        "max": "50",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "25",
        "seg2": "35",
        "diff": false,
        "className": "",
        "x": 560,
        "y": 80,
        "wires": []
    },
    {
        "id": "b4e6c7d8e9f0a1b2",
        "type": "ui_gauge",
        "z": "7e8973429d00dbe0",
        "name": " 湿度表 ",
        "group": "84282b608648b0b0",
        "order": 2,
        "width": "3",
        "height": "3",
        "gtype": "gage",
        "title": " 车间湿度 ",
        "label": "%",
        "format": "{{value}}",
        "min": 0,
        "max": "100",
        "colors": [
            "#00b500",
            "#e6e600",
            "#ca3838"
        ],
        "seg1": "40",
        "seg2": "70",
        "x": 550,
        "y": 120,
        "wires": []
    },
    {
        "id": "d61637279ce20149",
        "type": "ui_chart",
        "z": "7e8973429d00dbe0",
        "name": " 温湿度趋势 ",
        "group": "84d42c8c2cc3e7cf",
        "order": 1,
        "width": "12",
        "height": "6",
        "label": " 近 10 分钟温湿度变化 ",
        "chartType": "line",
        "legend": "true",
        "xformat": "HH:mm:ss",
        "interpolate": "linear",
        "nodata": " 等待数据 ...",
        "dot": false,
        "ymin": "",
        "ymax": "",
        "removeOlder": "10",
        "removeOlderPoints": "",
        "removeOlderUnit": "60",
        "cutout": 0,
        "useOneColor": false,
        "useUTC": false,
        "colors": [
            "#1f77b4",
            "#ff7f0e",
            "#2ca02c",
            "#000000",
            "#000000",
            "#000000",
            "#000000",
            "#000000",
            "#000000"
        ],
        "outputs": 1,
        "useDifferentColor": false,
        "className": "",
        "x": 570,
        "y": 160,
        "wires": [
            []
        ]
    },
    {
        "id": "7b218a136044af6c",
        "type": "ui_button",
        "z": "7e8973429d00dbe0",
        "name": " 告警灯开关 ",
        "group": "84282b608648b0b0",
        "order": 3,
        "width": "3",
        "height": "1",
        "passthru": false,
        "label": " 切换告警灯 ",
        "tooltip": "",
        "color": "",
        "bgcolor": "",
        "className": "",
        "icon": "warning",
        "payload": "toggle",
        "payloadType": "str",
        "topic": "alarm_toggle",
        "topicType": "str",
        "x": 130,
        "y": 260,
        "wires": [
            [
                "e8f9a0b1c2d3e4f5"
            ]
        ]
    },
    {
        "id": "e8f9a0b1c2d3e4f5",
        "type": "function",
        "z": "7e8973429d00dbe0",
        "name": " 告警逻辑处理 ",
        "func": "let isAlarmOn = flow.get('isAlarmOn') || false;\nisAlarmOn = !isAlarmOn;\nflow.set('isAlarmOn', isAlarmOn);\nif(isAlarmOn) {\n    msg.payload = \"警报\";\n    msg.color = \"red\";\n} else {\n    msg.payload = \"正常\";\n    msg.color = \"green\";\n}\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 350,
        "y": 260,
        "wires": [
            [
                "f0a1b2c3d4e5f6g7"
            ]
        ]
    },
    {
        "id": "f0a1b2c3d4e5f6g7",
        "type": "ui_text",
        "z": "7e8973429d00dbe0",
        "group": "84282b608648b0b0",
        "order": 4,
        "width": "3",
        "height": "1",
        "name": " 告警状态展示 ",
        "label": "",
        "format": "{{msg.payload}}",
        "layout": "row-center",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": "",
        "color": "#000000",
        "x": 530,
        "y": 260,
        "wires": []
    },
    {
        "id": "84282b608648b0b0",
        "type": "ui_group",
        "name": " 实时数据与告警 ",
        "tab": "9a361410c48a48a3",
        "order": 1,
        "disp": true,
        "width": "6",
        "collapse": false
    },
    {
        "id": "84d42c8c2cc3e7cf",
        "type": "ui_group",
        "name": " 历史趋势曲线 ",
        "tab": "9a361410c48a48a3",
        "order": 2,
        "disp": true,
        "width": "12",
        "collapse": false
    },
    {
        "id": "9a361410c48a48a3",
        "type": "ui_tab",
        "name": " 车间温湿度监控 ",
        "icon": "dashboard",
        "disabled": false,
        "hidden": false
    }
]

售后支持:0755-29451836