这是我目前正在开发的主力项目,解决工业现场「数据在设备里,人看不到」的问题。目标是做一个轻量、可自部署的工业数据平台,不依赖昂贵的商业 SCADA 系统。
问题背景
工厂里有大量 PLC、传感器、仪表,数据都锁在设备内部或者只有本地面板能看。运维人员想知道「3 号产线昨天的平均温度是多少」,往往需要翻纸质记录或者去现场看。
这个平台要解决的核心问题:
- 数据接入:自动采集多协议设备数据(OPC-UA / MQTT)
- 历史存储:按时序高效存储,支持长达数年的历史查询
- 实时可视化:Web 端仪表盘,支持多设备、多测点配置
- 告警管理:阈值告警 + 通知推送
系统架构
┌──────────────────────────────────────────────────┐
│ 前端(Next.js) │
│ 实时仪表盘 │ 历史查询 │ 设备管理 │ 告警中心 │
└──────────────────┬───────────────────────────────┘
│ REST + WebSocket
┌──────────────────┴───────────────────────────────┐
│ 后端(Node.js) │
│ 设备服务 │ 数据服务 │ 告警服务 │ 用户认证 │
└──────┬─────────────────────────┬─────────────────┘
│ │
┌──────┴──────┐ ┌──────┴──────┐
│ InfluxDB │ │ PostgreSQL │
│ (时序数据) │ │ (配置/用户) │
└─────────────┘ └─────────────┘
↑
┌──────┴──────────────────────┐
│ 协议接入层 │
│ OPC-UA Client │ MQTT Sub │
└─────────────────────────────┘
↑ ↑
PLC/SCADA 传感器节点
前端设计
仪表盘支持拖拽布局(基于 react-grid-layout),每个 Widget 可以配置:
- 数据源(设备 + 测点)
- 图表类型(折线、仪表盘、数值卡片、状态灯)
- 时间范围
- 刷新频率
实时数据通过 WebSocket 推送,避免频繁轮询:
// 前端订阅实时数据
const ws = new WebSocket('ws://api/realtime')
ws.onmessage = (event) => {
const { deviceId, metric, value, timestamp } = JSON.parse(event.data)
updateDashboardWidget(deviceId, metric, value)
}时序数据存储
InfluxDB 存储所有采集数据,schema 设计:
measurement: device_metrics
tags:
- site (工厂)
- device_id
- metric
fields:
- value (float)
timestamp: nanosecond precision
历史查询支持降采样(Flux 查询语言):
from(bucket: "iot-data")
|> range(start: -7d)
|> filter(fn: (r) => r.device_id == "plc-001" and r.metric == "temperature")
|> aggregateWindow(every: 1h, fn: mean) // 按小时平均
|> yield()告警引擎
告警规则存储在 PostgreSQL,后端每隔 30s 对最新数据批量评估:
interface AlertRule {
deviceId: string
metric: string
condition: 'gt' | 'lt' | 'eq'
threshold: number
severity: 'info' | 'warning' | 'critical'
notifyChannels: ('webhook' | 'email')[]
}连续 N 个采样点触发才算告警(避免毛刺误报),恢复正常后自动 resolve。
当前进度
- 协议接入层(OPC-UA + MQTT)
- InfluxDB 写入与查询
- PostgreSQL schema(设备、用户、告警规则)
- REST API 基础框架
- 前端仪表盘(进行中)
- 告警引擎
- Docker Compose 一键部署
- 文档与 Demo 录屏