跳到主要内容

协议桥接总览

概述

工业现场通常存在多种异构协议: 旧设备用 Modbus RTU, 中控用 OPC UA, 云平台用 MQTT, 办公系统走 REST / SQL。DarraRT 的协议网关 (GatewayManager) 运行在 Service 层, 将 PLC 全局变量区 (M/I/Q/DB) 与外部协议双向映射, 实现一次配置、多向互通

网关是一个独立子系统, 与 PLC 扫描周期解耦: PLC 只负责更新变量, 网关在自己的工作线程按订阅 / 轮询 / 事件三种模式向外转发, 既不拖慢扫描周期, 也避免网络阻塞引发 PLC 停机。

适用场景

场景源端目标端模式
旧仪表上云Modbus RTU 电表MQTT Broker采集 → 发布
MES 读写配方PLC DBSQL Server拉取 / 写回
SCADA 集成PLC 全量OPC UA Server订阅
REST 控制面板PLC 状态HTTP 接口查询 / 命令
跨产线联动A 线 PLCB 线 PLCMQTT 桥

架构图

┌─────────────────────────────────────────┐
│ DarraRT Service (永驻) │
│ │
│ ┌─────────────┐ ┌──────────────┐ │
│ │ PLC 变量区 │◄─►│ GatewayMgr │ │
│ │ M/I/Q/DB │ │ (调度/映射) │ │
│ └─────────────┘ └──────┬───────┘ │
│ │ │
│ ┌──────────┬───────┼──────┬────┐ │
│ ▼ ▼ ▼ ▼ ▼ │
│ [MQTT] [OPC UA] [SQL] [REST] [MB]│
└────────┬─────────┬─────────┬──────┬─────┘
│ │ │ │
Broker Client DB Client

前置条件

  • Service 已启动, 版本 ≥ 2.4
  • 目标端口开放 (MQTT 1883/8883, OPC UA 4840, SQL 1433, HTTP 80/443)
  • 证书齐备 (TLS/mTLS 场景)
  • PLC 变量表导出 variables.csv 供自动映射

配置 GatewayManager

网关配置位于 <Service>/config/gateway.yaml。顶层三个数组: sources (来源)、sinks (去向)、routes (路由规则)。

# gateway.yaml
sources:
- id: plc_main
type: plc
scan_interval_ms: 100
variables:
- M100.0
- DB1.temperature
- DB1.pressure

sinks:
- id: cloud_mqtt
type: mqtt
url: ssl://mqtt.example.com:8883
client_id: line1_gw
username: plc_line1
password: ${MQTT_PASS}
keepalive: 30
lwt:
topic: factory/line1/status
payload: "offline"
qos: 1
retain: true

- id: mes_sql
type: mssql
connstr: "Server=sql.lan;Database=MES;User=plc;Password=${SQL_PASS}"
table: t_plc_telemetry
batch_size: 200
flush_interval_ms: 1000

routes:
- from: plc_main.DB1.temperature
to: cloud_mqtt
topic: factory/line1/temp
qos: 1
retain: false
transform: "x * 0.1" # 原始 0.1 精度 → 真实摄氏度
filter: "abs(x - last) > 0.5" # 死区 0.5 度

- from: plc_main.*
to: mes_sql
column_map:
timestamp: $now_utc
var_name: $path
value: $value
quality: $quality

方向 / 过滤 / 变换

字段说明示例
directionpush (PLC→外) / pull (外→PLC) / bi (双向)push
filter布尔表达式, 真才发送x > 0 and x < 100
transform数据变换表达式x * 1.8 + 32 (℃→℉)
deadband死区, 小于此阈值不发0.5
throttle_ms最小发送间隔200

数据规范化

网关统一做 3 件事:

  1. 时间戳: 统一成 UTC 毫秒 (long 类型), 原始不带时间戳的点补当前时间
  2. 单位: 按变量表 unit 字段标注, 上云前强制转换到 SI 单位
  3. 类型映射: BOOL / BYTE / WORD / DWORD / INT / DINT / REAL / LREAL / STRING 映射到 JSON / SQL / OPC UA 原生类型
// Darra.PLC.Service / Gateway / Normalizer.cs
public sealed class Normalizer
{
public GatewayPoint Normalize(RawPoint raw, VarMeta meta)
{
var value = TypeMapper.Convert(raw.Value, meta.PlcType, meta.TargetType);
var ts = raw.Timestamp ?? DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
var unit = UnitConverter.ToSI(value, meta.Unit);
return new GatewayPoint(meta.Path, unit.Value, ts, raw.Quality);
}
}

容错策略

故障处理可配置项
网络断开本地环形缓冲区 (默认 10 万条) 暂存buffer_size / overflow_policy
重连指数退避, 最大间隔 60sreconnect_max_ms
消息重发QoS 1 / 2 自动, REST 需自定义幂等键idempotency_key
去重基于 var_path + timestamp 的布隆过滤器dedup_window_ms
反压上游降采样或丢弃, 不可阻塞 PLC`backpressure: downsample

缓冲区落盘

长时间断线 (>1 小时) 时, 内存缓冲满了会溢出到磁盘:

sinks:
- id: cloud_mqtt
buffer:
mode: memory_then_disk
memory_size: 100000
disk_path: ./data/mqtt_spool
disk_max_mb: 500

监控与排错

指标位置正常值
gw_queue_depth/api/gateway/metrics<1000
gw_send_rate同上取决业务
gw_drop_count同上0
gw_reconnect_count同上偶发
gw_latency_p95_ms同上<200ms
curl http://localhost:8080/api/gateway/metrics | jq .

排错快速表:

现象可能原因措施
云端收不到数据filter 过严 / 证书失效查日志 gateway_*.log, 搜 publish fail
数据延迟大throttle_ms 太大 / 网络慢降低 throttle, 查网络 RTT
SQL 写入慢批量太小 / 索引缺失增大 batch_size, DBA 加索引
反向命令不生效方向配置为 push改为 bi 并设 target_path

高级技巧

  1. 冷热分流: 高频变量 (10Hz+) 发 MQTT, 低频配置类走 SQL 心跳
  2. 边缘聚合: 先走 边缘预处理 压缩 90% 流量再上云
  3. 影子变量: 网关写入不直接落 PLC, 走影子 DB, PLC 扫描周期里决定是否接受
  4. 多租户: 一台 Service 多条产线, 用 tenant_id 作 MQTT topic 前缀隔离
  5. 热更新配置: PATCH /api/gateway/routes 不需重启 Service

相关文档