边缘网关 / 数据上云
一、设备简介
边缘网关是现场 PLC/设备和上层 MES/ERP/云平台之间的关键枢纽。它承担:
- 向下: 说工业协议 (Modbus TCP / S7 / MC / FINS / EtherCAT / Modbus RTU / BACnet / IEC61850 等 20+ 种), 并发接入 64 台 PLC 和 10 万点;
- 向上: 说物联网协议 (MQTT / OPC UA / REST / Webhook), 对接阿里云 / 华为云 / 腾讯云 / AWS / 自建 EMQX;
- 中间: 协议转换 + 数据清洗 + 断网缓存 (72 小时) + 证书轮换;
- 横向: DarraIPC 对第三方应用开放 SDK (C# / Python / Java / C++ / Rust / Node.js), DarraSync 让多 PLC 变量双向同步 (< 100ms)。
Darra 方案把 "独立网关 + SCADA + 多 PLC 同步软件 + OPC UA Server" 四件套打包到 一台研华无风扇工控机 上, 软件模块全内置, 硬件 ¥1.5~2 万, 部署 1 天上线 500 点。
二、项目模块组成
| 模块 | 职责 | 载体 |
|---|---|---|
| 协议采集引擎 | 20+ 协议并发采集, 支持 10ms~60s 任意周期 | Runtime 内置 |
| DarraIPC Server | 对外 SDK 入口, 多语言客户端直接读写 PLC 变量 | Runtime 内置 |
| DarraSync Engine | 多 PLC 变量同步组, 双向广播 + 冲突解决 | Runtime 内置 |
| MQTT Client | TLS + 客户端证书, QoS 0/1/2, 自动重连 | Runtime 内置 |
| OPC UA Server/Client | 标准建模 + 证书管理 + 订阅 | Runtime 内置 |
| REST / Webhook | 主动推送到 HTTP, JSON 格式 | Runtime 内置 |
| 断网缓存 | SQLite / RocksDB 本地缓存 + 补传限速 | Cache Service |
| 证书管理 | Let's Encrypt 自动续签 + 设备级证书 | Cert Service |
| 网关自监控 | CPU / 内存 / 磁盘 / 网络上报, 异常推送钉钉/企微 | SelfMon |
| 配置 IDE | 设备向导 + 点表 Excel 导入 + 映射配置 | Darra IDE |
三、机械装配架构 (网络拓扑)
布局要点:
- 边缘网关 放在车间机柜, DIN 导轨安装, 无风扇工控机 IP40;
- PLC 网段 与 办公网 物理隔离, 网关双网口跨网 (LAN 1 接 PLC, LAN 2 接上行);
- 4G / 5G DTU 有线断网时自动切换, 不丢数据;
- UPS 保证断电 30 分钟不丢数据 (缓存安全落盘);
- 串口服务器 (或内置 RS485 口) 接 Modbus RTU 电表 / 流量计。
四、程序架构
网关接口 FB 清单
| FB 名 | 输入 | 输出 | 说明 |
|---|---|---|---|
FB_ProtocolCollect | DeviceList / ProtoCfg | DataSet / Status | 多协议采集 |
FB_DarraIPC_Read | VarName | Value / Quality | 对外 SDK 读 |
FB_DarraIPC_Write | VarName / Value / ACL | Done / Err | 对外 SDK 写 |
FB_DarraSync_Register | GroupName / VarList | Done | 定义同步组 |
FB_DarraSync_Update | GroupName / VarName / Value | Broadcasted | 变量更新广播 |
FB_MQTTPublish | Topic / Payload / QoS | Done / Cached | MQTT 上行 |
FB_MQTTSubscribe | Topic / Callback | Message | MQTT 下行 |
FB_OPCUAExpose | NodeId / VarRef | Done | 暴露到 OPC UA |
FB_CacheWrite / CacheFlush | Record / BatchSize | Remaining | 断网缓存 |
FB_CertRenew | CertName | Expires | 证书续签 |
FB_HJ212Report | Pollutant / Value | Done | 环保 HJ212 上报 |
五、硬件 BOM (国产优先)
| 类别 | 设备 | 型号 / 规格 | 数量 | 单价 (¥) | 小计 (¥) |
|---|---|---|---|---|---|
| 边缘网关主机 | 无风扇工控机 | 研华 UNO-2272G / J6412 / 8GB / 256GB SSD / 双网口 | 1 | 6,800 | 6,800 |
| 信创替代 (可选) | 国产 ARM 边缘盒 | 飞腾 D2000 / 8GB / 64GB eMMC | 1 | 4,500 | 4,500 |
| 4G / 5G DTU | 工业级 | 移远 EC200N 4G | 1 | 800 | 800 |
| 工业交换机 | 千兆 8 口 | 华为 S5735-L8T4S | 1 | 2,800 | 2,800 |
| 串口服务器 | RS485 转以太网 | 宇泰 UT-6604 | 1 | 800 | 800 |
| Modbus RTU 隔离 | USB 转 RS485 | 胜为 | 2 | 150 | 300 |
| 电表 | 多回路 | 威胜 DTSD341 | 4 | 600 | 2,400 |
| UPS | 一体式 | 山特 500VA | 1 | 1,500 | 1,500 |
| 网关机柜 | 壁挂 15U IP54 | 图腾 | 1 | 2,500 | 2,500 |
| SIM 卡 | 物联网定向流量 10GB/月 | 三大运营商 | 1 | 180/年 | 180 |
| 证书 U-Key | 加密存储 (可选) | 天喻 / 龙脉 | 1 | 600 | 600 |
| 软件授权 | Darra Runtime 网关版 | 永久 + 1 年升级 | 1 | 9,800 | 9,800 |
| 合计 (主方案) | ¥27,880 |
对比传统 "独立网关 ¥3 万 + SCADA ¥10 万 + OPC UA Server ¥3 万 + 同步软件 ¥5 万 = ¥21 万", Darra 节省 80%+。
六、IO 模块配置
6.1 协议接入清单
| 设备 | 协议 | 数量 | 采集点数 | 周期 |
|---|---|---|---|---|
| 汇川 AM600 | Modbus TCP | 3 | 300 | 500ms |
| 信捷 XD | Modbus TCP | 2 | 150 | 500ms |
| 西门子 S7-1500 | S7 | 2 | 400 | 200ms |
| 三菱 FX5U | MC 3E | 1 | 120 | 500ms |
| 欧姆龙 NX | FINS | 1 | 80 | 500ms |
| 电表 (威胜) | Modbus RTU | 4 | 40 | 1min |
| 流量计 | Modbus RTU | 2 | 20 | 5s |
| 机器人 (Darra) | Runtime 内部 | 2 | 60 | 100ms |
| 环境传感器 | MQTT (南向) | 10 | 30 | 10s |
合计: 1200 采集点 / 20 设备, 单网关上限 10 万点 / 64 设备。
6.2 点表配置 (Excel 模板示例)
| DeviceId | PointName | Protocol | Address | DataType | ScanRate | Unit | Direction | Expose_IPC | Expose_MQTT | Expose_OPCUA |
|---|---|---|---|---|---|---|---|---|---|---|
| PLC1 | Line_Speed | modbus_tcp | 40001 | REAL | 500ms | m/min | RW | YES | YES | YES |
| PLC1 | Line_Status | modbus_tcp | 40010 | INT | 500ms | 枚举 | R | YES | YES | YES |
| PLC3 | Machine_Temp | s7 | DB1.DBD4 | REAL | 200ms | ℃ | R | YES | YES | NO |
| METER_1 | Power_Total | modbus_rtu | 40100 | REAL | 60s | kW | R | NO | YES | YES |
| ROBOT | Robot1_Pose | runtime | internal | UDT | 100ms | mm/deg | R | YES | NO | YES |
6.3 绑定操作流程 (IDE 内)
- IDE → 边缘网关工程: 新建 Gateway 工程;
- 设备向导: Excel 导入点表 → 批量生成 1200 个点位 + 20 个设备对象;
- 协议测试: 每设备点击 "测试连接" → 显示连接状态 + 采样实例;
- DarraIPC 开放: 按
Expose_IPC列筛选 → 勾选 "暴露" → 生成对外变量列表 (带 ACL); - DarraSync 组: 新建同步组
Shift_Recipe→ 把多条产线的Line_Speed/Current_Recipe加入 → 设置传播方向; - MQTT 映射: Topic 模板
factory/line/{lineId}/{pointName}, Payload 模板 JSON{value, ts, quality}; - OPC UA 建模: 自动按 "车间→产线→设备" 生成节点树, 授权用户读写;
- 云端接入: 阿里云 IoT Hub → 录入产品密钥 + 设备证书 → 测试上云;
- 断网测试: 拔云端网线 5 分钟 → 本地缓存 → 插回 → 补传日志查看;
- 第三方集成: Python 测试脚本
from ipc import Client; c.read('Line_Speed'), 确认 SDK 可用。
七、核心数据结构
7.1 点位 UDT
TYPE UDT_Point :
STRUCT
sId : STRING[64];
sDevice : STRING[32];
eProto : E_Protocol;
sAddress : STRING[64];
eDataType : E_DataType;
rValue : REAL;
sStringValue : STRING[128]; // 非数值类型
nQuality : INT; // 0=Good 1=Bad 2=Uncertain
tTimestamp : LTIME;
rUpperLim : REAL;
rLowerLim : REAL;
bExpose_IPC : BOOL;
bExpose_MQTT : BOOL;
bExpose_OPCUA : BOOL;
END_STRUCT
END_TYPE
7.2 同步组 UDT
TYPE UDT_SyncGroup :
STRUCT
sName : STRING[32];
aVarIds : ARRAY[0..31] OF STRING[64];
eDirection : E_SyncDirection; // OneWay / TwoWay
aNodes : ARRAY[0..15] OF STRING[32]; // 参与的 PLC / 网关
rIntervalMs : REAL; // 同步周期
nConflictCnt: DINT; // 冲突次数
END_STRUCT
END_TYPE
7.3 缓存记录 UDT
TYPE UDT_CacheRecord :
STRUCT
sTopic : STRING[128];
sPayload : STRING[512];
tCreatedAt : LTIME;
nRetries : INT;
bSent : BOOL;
END_STRUCT
END_TYPE
7.4 IPC 请求 UDT
TYPE UDT_IPCRequest :
STRUCT
sClientId : STRING[32];
sClientIP : STRING[16];
sMethod : STRING[16]; // Read/Write/Subscribe
sVar : STRING[64];
sValue : STRING[128];
nReqId : DINT;
END_STRUCT
END_TYPE
7.5 全局变量
VAR_GLOBAL
G_Points : ARRAY[0..9999] OF UDT_Point;
G_SyncGroups : ARRAY[0..15] OF UDT_SyncGroup;
G_Cache : ARRAY[0..99999] OF UDT_CacheRecord; // 磁盘落盘
G_MQTT_OK : BOOL;
G_CloudRTT : REAL; // ms
G_SelfStatus : UDT_SelfStatus;
END_VAR
八、核心程序代码
8.1 FB_ProtocolCollect (20+ 协议并发)
FUNCTION_BLOCK FB_ProtocolCollect
VAR
fbModbus : ARRAY[0..15] OF FB_ModbusClient;
fbS7 : ARRAY[0..7] OF FB_S7Client;
fbMC : ARRAY[0..3] OF FB_MCClient;
fbFINS : ARRAY[0..3] OF FB_FINSClient;
fbRTU : ARRAY[0..15] OF FB_ModbusRTUClient;
i : INT;
END_VAR
// 各协议并发采集, 异步完成
FOR i := 0 TO N_MODBUS_TCP - 1 DO
fbModbus[i](
Host := G_DevCfg[i].sHost,
Port := 502,
AddrList := G_DevCfg[i].aAddr,
Execute := TRUE
);
IF fbModbus[i].Done THEN
MapToPoints(fbModbus[i].Result, G_Points);
END_IF;
END_FOR;
// S7 / MC / FINS / RTU 同理, 每个采集器独立运行
8.2 FB_DarraIPC_Server (对外 SDK 入口)
FUNCTION_BLOCK FB_DarraIPC_Server
VAR
fbListener : FB_IPC_Listener;
stReq : UDT_IPCRequest;
sReply : STRING[512];
END_VAR
fbListener(Port := 8841, Execute := TRUE);
IF fbListener.NewRequest THEN
stReq := fbListener.Request;
// ACL 检查
IF NOT ACL_CheckClient(stReq.sClientIP, stReq.sVar, stReq.sMethod) THEN
sReply := '{"err":"ACL denied"}';
ELSE
CASE stReq.sMethod OF
'Read':
sReply := JSON_PointValue(G_Points[IndexOfVar(stReq.sVar)]);
'Write':
WritePointFromClient(stReq.sVar, stReq.sValue);
sReply := '{"ok":true}';
'Subscribe':
Subscribe_AddClient(stReq.sClientId, stReq.sVar);
sReply := '{"ok":true,"sub":"'+stReq.sVar+'"}';
END_CASE;
END_IF;
fbListener.Reply(stReq.nReqId, sReply);
END_IF;
// 周期推送订阅数据
Subscribe_PushUpdates(G_Points);
8.3 FB_DarraSync (多 PLC 变量同步组)
FUNCTION_BLOCK FB_DarraSync
VAR
i, j : INT;
stGrp : UDT_SyncGroup;
END_VAR
// 定期广播同步组变量
FOR i := 0 TO N_SYNC_GROUPS - 1 DO
stGrp := G_SyncGroups[i];
FOR j := 0 TO ArraySize(stGrp.aVarIds) - 1 DO
IF VarChanged(stGrp.aVarIds[j]) THEN
// 向所有参与节点广播
Broadcast_ToNodes(
Nodes := stGrp.aNodes,
VarId := stGrp.aVarIds[j],
Value := GetValue(stGrp.aVarIds[j])
);
END_IF;
END_FOR;
END_FOR;
// 处理收到的同步消息 (双向模式)
IF Sync_Inbox.Count > 0 THEN
ResolveConflict_LastWriteWins(Sync_Inbox);
ApplyUpdates(Sync_Inbox);
END_IF;
8.4 FB_MQTTPublish (断网缓存 + 补传)
FUNCTION_BLOCK FB_MQTTPublish
VAR_INPUT
Topic : STRING[128];
Payload : STRING[512];
QoS : INT := 1;
END_VAR
VAR
fbPub : FB_MQTTClient_Publish;
stRec : UDT_CacheRecord;
END_VAR
IF G_MQTT_OK THEN
fbPub(Topic := Topic, Payload := Payload, QoS := QoS, Execute := TRUE);
IF fbPub.Error THEN
// 入缓存
stRec.sTopic := Topic;
stRec.sPayload := Payload;
stRec.tCreatedAt := LTIME();
FB_CacheWrite(Record := stRec);
END_IF;
ELSE
// 断网直接入缓存
stRec.sTopic := Topic;
stRec.sPayload := Payload;
stRec.tCreatedAt := LTIME();
FB_CacheWrite(Record := stRec);
END_IF;
8.5 FB_CacheFlush (恢复后补传)
FUNCTION_BLOCK FB_CacheFlush
VAR
stRec : UDT_CacheRecord;
nBatchMax : INT := 1000; // 限速
i : INT;
END_VAR
IF G_MQTT_OK AND G_Cache_Pending > 0 THEN
FOR i := 1 TO nBatchMax DO
stRec := FB_CacheReadNext();
IF NOT stRec.bSent THEN
fbPub(Topic := stRec.sTopic,
Payload := stRec.sPayload,
QoS := 1, Execute := TRUE);
IF fbPub.Done THEN
stRec.bSent := TRUE;
FB_CacheMarkSent(stRec);
END_IF;
END_IF;
IF G_Cache_Pending = 0 THEN EXIT; END_IF;
END_FOR;
END_IF;
8.6 FB_CloudCmdDown (云端下发指令 + 写回 PLC)
FUNCTION_BLOCK FB_CloudCmdDown
VAR
fbSub : FB_MQTTClient_Subscribe;
stCmd : UDT_CloudCmd;
END_VAR
fbSub(
Topic := 'factory/cmd/#',
QoS := 1,
Execute := TRUE
);
IF fbSub.NewMessage THEN
stCmd := JSON_Parse(fbSub.Payload);
// 签名校验
IF VerifySignature(stCmd) THEN
CASE stCmd.sAction OF
'WriteVar':
WritePoint(stCmd.sVar, stCmd.sValue);
'LoadRecipe':
LoadRecipeToAllPLCs(stCmd.sRecipe);
'ShutdownLine':
SendStopToPLC(stCmd.sLine);
END_CASE;
END_IF;
// 回执
FB_MQTTPublish(
Topic := 'factory/cmd/ack/'+stCmd.sCmdId,
Payload := '{"ok":true}',
QoS := 1
);
END_IF;
九、运行与调试
9.1 首次部署流程
- 硬件上架: 研华工控机 + 交换机 + UPS + 4G DTU 进机柜;
- 网络规划: LAN1 接 PLC 网段 (192.168.1.x), LAN2 接办公 (10.10.x.x), WAN 经 4G 备用;
- Runtime 安装: 激活 Darra Runtime 网关授权;
- Excel 点表: 按模板填 1200 点 → 导入 IDE → 自动建模;
- 协议测试: 设备向导 "测试" 按钮逐台连, 确保 20 台全绿;
- DarraIPC 自测: Python 一行
c.read("Line_Speed")验证; - DarraSync 自测: 两台 PLC 同一变量, 在 PLC1 改值, 观察 PLC2 秒级跟随;
- MQTT 上云: 阿里云控制台查看消息到达, payload 格式正确;
- OPC UA 自测: 用 UaExpert 客户端浏览节点树, 订阅变量;
- 断网演练: 拔网线 10 分钟 → 缓存积压 → 恢复 → 自动补传;
- 安全配置: 打开 TLS, Let's Encrypt 续签脚本;
- 灰度发布: 1 条线先上, 观察 48 小时无误再全厂推开。
9.2 常见故障排查
| 现象 | 排查点 |
|---|---|
| 某协议始终采不到 | IP / 端口 / 站号 / 固件版本兼容性 |
| 点位值跳变 | ScanRate 太快 / 网络 CRC 错误 |
| MQTT 频繁重连 | Keepalive / 证书过期 / 阿里云 IoT 流控 |
| DarraSync 冲突 | 检查 eDirection 是否与实际相反 / 时钟偏差 |
| DarraIPC 无响应 | 端口 8841 防火墙 / ACL 白名单 |
| 缓存补传慢 | 补传限速设太低 / 云端 QoS=2 太重 |
| 证书续签失败 | ACME 域名解析 / 80 端口未放行 |
| CPU 占用高 | 采集周期太密 / 点位数过多 / 加更多机器 |
9.3 日常运维
- 每天: 自监控上报的 CPU / 磁盘 / 缓存积压查看;
- 每周: 云端 MQTT 消息到达率统计, 应 > 99.99%;
- 每月: 证书到期日提醒;
- 每季度: 导出缓存压缩归档, 释放 SSD 空间。
十、Darra 功能对照表
| 需求 | Darra 功能 |
|---|---|
| 多品牌 PLC 统一采集 | 20+ 协议内置 |
| 多 PLC 变量同步 | DarraSync 同步组 |
| 对外开放 SDK | DarraIPC (C#/Python/Java/C++/Rust/Node.js) |
| MQTT 上云 | 阿里云 / 华为云 / EMQX / AWS |
| OPC UA 对接 MES | OPC UA Server + Client |
| 断网缓存 72h | SQLite/RocksDB + 自动补传 |
| 云端下发指令 | MQTT 订阅 + 签名校验 + 写回 PLC |
| 环保 HJ212 | 内置协议 |
| TLS + 证书管理 | Let's Encrypt 自动续签 |
| IP 白名单 + ACL | 内置访问控制 |
| 信创兼容 | 飞腾 / 龙芯 ARM 版 |
| 自监控 + 推送报警 | SelfMon + DingTalk/WeCom |
| 多节点拓扑 | 支持网关集群 |
| 配置 IDE | 设备向导 + Excel 点表导入 |
十一、项目总结
成果指标
- 接入容量: 20 设备 / 1200 点 (设计 64 设备 / 10 万点);
- 采集延迟: 200~500ms 稳定, 高优点位 10ms (EtherCAT 内部);
- 上云成功率: ≥ 99.99% (含断网补传);
- DarraIPC 调用延迟: < 20ms (SDK 读写 PLC);
- DarraSync 同步: < 100ms 跨 PLC 变量双向;
- 中间件成本: ¥2.8 万 vs 传统 ¥21 万, 省 86%;
- 部署周期: 3~7 天, 传统 2~4 周。
适配场景延伸
- 工厂整体上云 (多品牌 PLC 汇入阿里云 / 华为云 / 自建 EMQX);
- OEM 设备远程运维 (整机厂把客户现场设备数据上传厂商云);
- MES / ERP 无纸化报工;
- 集团多分厂管控 (配合 DarraSync + 总部大屏);
- 环保 / 能耗监管上报 (CEMS / HJ212);
- 第三方 SaaS 集成 (质量 / 能源 / 设备管理);
- 数据湖 / 数据中台原料接入;
- 工厂内部系统开放 (Java / Python / .NET 应用用 DarraIPC 直接读 PLC)。
扩展方向
- 边缘 AI 推理: 网关本地做异常检测 / 预测性维护, 不走云端;
- FMEA 自动关联: 采集到异常值时自动关联 FMEA 知识库给出处理建议;
- 区块链存证: 关键工艺参数 / 批次数据上链, 满足医药 / 食品可追溯;
- 5G + TSN 下行: 网关作 TSN 桥接, 实现工厂 5G 控制下沉;
- 网关集群: 多网关互为热备, 故障切换 < 1 秒;
- 联邦学习接入: 多厂数据协同训练模型, 不泄露原始数据;
- OPC UA PubSub: 替代传统 OPC UA Session, 千节点秒级刷新。
Darra 让 "边缘网关 + SCADA + 同步 + OPC UA + SDK" 四件套软件变成一份工程, 一台工控机, 是企业数字化从现场到云端最短的落地路径。