ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

SCADA北向接口设计与实践:REST API+MQTT双通道数据开放

SCADA北向接口设计与实践:REST API+MQTT双通道数据开放 DataPulse这个系列写到现在设备接入、组态画面、报警推送都已经聊过了这一篇集中讲北向接口。很多朋友做SCADA项目时南向采集一堆PLC、电表、传感器都跑得很顺一到往上层系统送数据就开始挠头到底是让别人来拉还是我主动推用数据库直连还是走接口数据要不要缓存权限怎么做DataPulse在设计北向接口时把这些坑都预先填了一遍这篇文章就把完整思路和数据流向拆给你看。先说清楚一件事北向接口不是简单的“API开放”它是SCADA在工业信息化体系里被认可的关键一步。你现场的数据采得再准只要送不到MES、EMS、大屏或者集团调度中心价值就始终停留在车间层。北向接口就是把这些数据“翻译并递出去”的合规通道。DataPulse默认走的是“REST API MQTT双通道”方案再配合数据库视图直出基本可以覆盖90%以上的对接场景而且每一层都留了可配置的开关不至于一上来就被协议绑死。1. 北向接口到底解决什么问题1.1 从SCADA在工业信息化中的位置说起SCADA在全厂信息化架构里的定位比较特殊。向下它要面对PLC、DCS、RTU、智能仪表向上它面对MES、ERP、安防、能耗平台、调度大屏甚至集团云端。过去的做法是“点对点开发”MES需要一组数据开发一个接口能耗平台需要另一组数据再开发一套。数据格式、采集频率、字段命名完全靠口头约定后期维护极其痛苦。DataPulse处理这件事的思路是先建立统一的内部实时数据模型再通过北向接口对外提供一致的访问入口。也就是说无论你南向接的是Modbus TCP的PLC还是BACnet的楼宇控制器一旦进入DataPulse实时库它们都变成标准的测点对象带uid、名称、值、质量戳、时间戳、采集源ID。北向接口只认这套统一模型不关心底层协议。1.2 北向接口与南向接入的边界很多刚接触SCADA的人容易把“北向接口”和“南向驱动”搞混。我做个简单划分南向是“收”北向是“发”。南向驱动负责跟PLC、仪表等设备通信用的是Modbus、OPC UA、IEC 104这类现场协议北向接口负责跟信息系统通信用的则是HTTP API、MQTT、JDBC这类IT协议。为什么要把边界划得这么清楚原因有两个。第一现场协议和IT协议的生命周期、维护主体完全不同。现场协议可能多年不变而IT系统版本迭代飞快混在一起只会互相拖累。第二安全域不同。南向网络通常是工控网络讲究稳定可控北向往往要跨防火墙、跨网段属于非信任区。DataPulse将北向接口独立为一个数据转发服务与采集核心分离运行就算外部系统频繁调用也不会拖垮采集链路。1.3 典型业务场景我把日常项目里最常见的北向接口需求整理成一张表方便你对照自己手上的项目场景对接对象核心数据方式偏好生产实时监控大屏中控室大屏/组态可视化关键测点快照 报警事件MQTT实时推送生产管理MES/APS系统产量、设备状态、工单进度REST API主动拉取能源管理EMS能源平台电表、水表、气表累计量数据库视图或API集团调度总部数据中台汇总后的KPI、设备健康度MQTT 落库历史分析数据仓库BI长时间段的趋势数据数据库直连/批量导出数据特征差异非常大。大屏要求实时性强秒级延迟可接受但丢不得点MES要求结构化、带上下文比如工单号、批次、产线BI系统喜欢宽表、批量、按时间分区。一个成熟的北向接口不是拿一套代码硬适配所有场景而是应该提供多通道让使用者按需选。2. 数据模型与接口协议选型2.1 先定数据模型测点、设备、事件、快照我在做DataPulse北向接口设计时第一件事不是写接口代码而是把数据模型定死。北向接口对外至少需要四类对象测点Point最细粒度比如1号电机电流、2号阀门开度。包含uid、name、unit、value、quality、timestamp、deviceId。设备Device测点的聚合载体包含设备名、型号、位置、状态、所属线体或车间。事件Event报警、开关变位、操作记录包含eventType、level、message、occurTime、ackTime。快照Snapshot某设备或某区域内多个测点在同一时刻的值的集合用于大屏一次性渲染。数据模型一旦统一底层不管是PLC来的模拟量还是人工录入的台账数据对外都表现为同结构的JSON对象。这样带来的直接好处是可以做“字段级映射”。我见过太多项目因为现场表名词典没统一导致每个接口都要写一个字段翻译的硬代码。DataPulse把“外部字段名”和“内部测点uid”做成配置项两侧各叫各的中间由配置中心做映射动配置不用动代码。2.2 三种主流北向方式API、MQTT、数据库直出先看接口方式。REST API适合拉模式客户端主动请求按需获取。DataPulse对外提供/api/v1/points/{uid}获取单点实时值、/api/v1/devices/{id}/snapshot获取设备快照、/api/v1/events分页查询历史事件。API响应时间控制在20ms左右核心实时库用内存索引支撑不需要每次查历史表。再看推送模式。MQTT几乎成了SCADA北向事实标准之一原因很简单现场测点数量大、变化频率高HTTP轮询要么频繁空转要么丢失实时性。DataPulse北向MQTT网关支持按主题区分数据类型比如datapulse/points/updates发实时值变化、datapulse/events/alarm发报警事件、datapulse/devices/status发设备心跳。订阅方按需订阅带宽浪费降到了最低。还有一种是数据库直出。很多MES系统不擅长调用接口但很擅长写SQL。DataPulse提供只读数据库视图比如view_points_realtime、view_events_history把实时库的数据按关系表结构暴露出来。直出的好处是业务系统能直接用JOIN、WHERE做聚合坏处是一旦数据量太大容易拖拽生产库。所以DataPulse把这套视图放在独立的只读从库上并且强制每条查询必须带时间范围限制。2.3 为什么DataPulse默认推荐MQTT REST双通道单用MQTT会有一个问题离线消息补拉困难。平台挂了重启后推送期间的数据丢失怎么办单用REST会有一个问题高频变化的测点数据靠轮询拿延迟和带宽成本不可控。DataPulse默认将两者组合原则是“实时变化用MQTT按需查询用REST”。具体流程是这样的所有测点变化时北向服务先落一个“变化日志”再往MQTT主题里发增量数据。订阅方收到增量后如果需要推进历史补丁就调用REST接口拉取时间区间内的补数数据。这样既保证了实时性也解决了稳定性问题。对于不需要接收推送、只想定时抓数的系统可以直接使用REST接口不必启动MQTT订阅减少不必要的资源开销。3. DataPulse北向接口设计拆解3.1 配置入口与模型映射DataPulse的北向接口配置都在“系统配置 → 北向接口”页面里完成不需要改代码。第一次配置时你需要按顺序走四步创建对接方应用拿到AppKey和AppSecret。在“数据映射”里选择要对外的测点并定义外部字段名。勾选数据上送方式可以同时选MQTT推送REST开放。配置订阅规则比如哪些测点需要变化推送、哪些测点只允许拉取。举一个实际例子。现场有个测点内部uid是line1.press.01对外MES系统希望它叫pressingPressure。在DataPulse里只需新增一条映射内部字段line1.press.01→ 外部字段pressingPressure同时指定数据类型为float单位MPa。之后MES系统拉到的JSON就是{name:pressingPressure,value:22.5,unit:MPa,ts:2024-06-18 10:00:00.123}。配置过程全程页面化映射关系存数据库而非代码里好处是后续新增测点或者换对接方改配置就能上线省去发版流程。3.2 认证与权限控制北向接口直接暴露在网络上如果认证做不好等于把PLC数据全部裸奔出去。DataPulse这里分了三层控制第一层是身份认证。每个对接方持有独立的AppKey/AppSecret调用API时需要通过Authorization: Bearer token头传递令牌令牌在DataPulse内部有效期默认2小时过期后自动刷新。MQTT连接时则需要同时提供用户名和密码用户名是AppKey密码专门生成不跟Web登录密码混用。第二层是测点级权限。一个对接方只能读取分配给他的测点集合。比如MES系统只能看到产量相关测点能耗平台只能看电表测点不能互相越权。这在项目上非常实用多个供应商同时接一台SCADA时不用再担心数据泄露出圈。第三层是访问频率限制。默认限制单个App每秒最多120次API调用MQTT最大下行速率也可配置。我见过一次事故业务方写的定时器有bug每100毫秒轮询一次接口直接把SCADA网关CPU打到80%。加了限流以后即使对方代码写得再烂也只是被DataPulse拒绝请求不会影响现场采集主链路。3.3 数据刷新策略变化上报与周期上报北向接口一个经常被忽略的细节是“数据怎么上送”。如果每个测点变化都立刻推一条电流从50A跳到50.1A也要推一条消息高频抖动会把MQTT主题塞满。DataPulse的处理方式是提供三种策略死区变化上报只有数值变化超过预设阈值才推送。比如压力测点设0.1MPa死区22.5变到22.6才触发推送22.5变到22.55不会触发。这种策略适合连续量测点。定时周期上报不管值有没有变每个固定周期推送一次快照。适合大屏需要周期性刷新显示的场景比如5秒一次全量数据。开关量变化上报对DI、DO这类开关量不做死区只要变位就立刻推送。开关量变化是离散事件延迟直接影响联动必须实时。这三种策略可以按测点维度分别配置同一设备下压力用死区温度用周期开关量用立即推送。DataPulse内部通过一个异步事件循环处理这些策略变化事件先进入内存队列再根据策略决定是否转发避免IO阻塞。4. 常见对接场景实战4.1 对接中控室大屏与组态系统的关键细节中控室大屏是SCADA北向接口最经典的应用场景。大屏那边需要完整画面、闪烁告警、联动趋势数据来源基本都是SCADA。用DataPulse对接大屏时我的推荐做法是走MQTT订阅datapulse/points/updates和datapulse/events/alarm前端组态引擎自己维护一个内存数据快照服务器推送什么就更新什么。这种模式避免了一个大坑HTTP请求在大屏刷新瞬间爆发。上百个组件同时向API要数据经常把网关打成热点。而MQTT是长连接服务端主动下推每个测点只在下一次变化时发一次网络开销小很多。还要注意大屏组态里的数据粒度。大屏往往只需要车间级汇总比如“总产量”“设备综合效率”。DataPulse支持在北向接口前做一层轻量聚合把多个测点先算出calculated.value再作为新的对外测点推送给大屏。计算逻辑可以配置公式不用写代码。4.2 对接上层业务系统MES/ERP的标准流程大多数MES系统的工作方式是周期拉取或事件驱动。DataPulse对接MES最常见的是这几种模式每生产完成一炉/一件MES需要收到“完工上报”事件。MES定时调用/api/v1/points?nameoutput_counttime_from...拉产量。MES需要知道某台设备当前状态调用/api/v1/devices/{id}/status。我在对接MES时通常会建议业务侧使用“增量拉取 事件补偿”的方式。增量拉取就是每次只查最近时间段内更新的测点通过_updateTime字段做游标事件补偿则是当MES发现某条报警事件疑似缺失时通过/api/v1/events?from...to...重新拉那段时间的数据补齐。这个流程的关键点在于对接前先跟MES团队对齐“主键”。SCADA侧用uid作为测点唯一标识MES侧可能用工位号、设备编码。DataPulse的映射表里有一栏externalId专门用来存储业务系统的主键推送的数据会额外带上这个字段方便MES侧直接关联。4.3 从PLC到北向的数据闭环贴近SCADA如何与PLC连接很多朋友对“SCADA如何与PLC连接”和“北向接口”之间的关系还有点模糊。这里我讲一个完整的数据闭环PLC寄存器 → DataPulse采集驱动 → 实时库 → 北向接口 → MES系统。PLC侧无需多余开发。DataPulse通过Modbus TCP驱动读取PLC的保持寄存器和输入寄存器比如%MW100是产线速度%MW102当前温度。在配置驱动时需要设置PLC的IP、端口默认502、单元ID以及每个测点的寄存器地址和数据格式int16/uint16/float32等。连接建立后驱动会按照设定周期一般500ms轮询一次寄存器值一旦变化就写入DataPulse实时库。之后北向接口就只是从这个实时库里取值。你在API查询到的数据其实已经是PLC---DataPulse---业务系统的链路末端。整个链路中PLC只感知到Modbus报文不会受北向端大流量调用的影响。这就是为什么我在前文强调南北分离PLC采集稳定性是优先级最高的北向再挤也不能回头堵住PLC驱动。有一条经验值得注意PLC的数据类型一定核对清楚。Modbus里16位寄存器存整数和32位浮点的排列方式不一样有的PLC还支持位操作有人把32位float按两个16位int读数值直接错乱。DataPulse驱动里可以配置字节序和格式对接时务必先看PLC模块手册确认寄存器位宽和排列方式。4.4 视频/可视化如何辅助北向数据贴合SCADA视频场景现在很多SCADA项目不再只是“数据 组态”还要求叠加视频画面。DataPulse在北向接口中预留了视频点位的数据类型视频流地址可以作为测点值上送。比如一路摄像头的RTSP地址rtsp://192.168.1.20:554/stream1可以直接配置为字符串测点通过北向接口推送给大屏。这样设计的好处是统一了一张数据大图。在大屏上某个设备的实时电压数值、运行状态开关量、设备正下方的监控画面视频流URL全部来自同一套北向接口数据。上层系统只要解析到type: video的测点就调用流媒体播放组件进行拉流展现不需要再另接一套视频平台。不过要做好视频关联需要在配置测点时额外标记摄像头所属的设备ID。DataPulse的测点配置页支持“关联设备”字段视频流测点可以关联到一个设备上。大屏侧根据设备ID同时取到数据测点和视频测点画面加载时并行渲染体验会顺畅很多。5. 踩坑记录与排查清单5.1 数据延迟到底是哪一段慢做北向接口最容易被问的问题是“SCADA数据到MES要几秒”。实际上延迟来自四段PLC采集轮询周期、DataPulse实时库刷新、北向策略触发、网络传输。我建议按顺序排查。先用DataPulse自带的“点位追溯”功能看某一测点的采集原始时间确认是不是PLC驱动本身的轮询周期太长。再打开北向接口日志看该测点上报的实际时间如果日志显示触发时间正常但业务方收到时间很晚再查网络代理和中间队列。常见的一个隐蔽坑是MQTT QoS设置。如果订阅端用QoS 0消息在网络抖一下就可能丢业务方看起来就是“迟到了”。推送重要的报警事件至少把QoS设到1并在业务侧做去重。5.2 断线缓存与数据乱序的处理北向对接过程中断线再恢复很常见。DataPulse对MQTT推送设计了持久化会话和离线缓存。客户端上线时会尽量补推离线期间变化的数据。但补推会导致乱序可能先推送了刚才的实时值再推送离线期间的历史值。业务侧接收时需要根据时间戳排序不能简单信任到达顺序。建议订阅端维护一个lastAppliedTs只有消息时间戳新于这个值才更新内存否则丢弃或进入待处理队列。对于REST接口查询乱序问题则不用担心因为响应中直接带时间戳业务侧按ts字段升序处理即可。需要留意的反而是分页问题当查询时间跨度过大DataPulse默认按500条一页返回必须循环拉取直到返回条数不足500否则会漏数据。5.3 安全暴露面别只看认证最后提醒一句安全。北向接口一旦开放公网就等于把SCADA系统的一部分门户暴露出去。即使加了AppKey、Token也建议做以下几件事只开放必要的端口默认只允许北向服务端口对外其他SCADA端口一律防火墙隔离。加IP白名单MES或大屏系统的出口IP固定时优先用白名单限制访问来源。启用运维审计日志DataPulse会记录每个App的调用时间、来源IP、请求路径、返回状态码方便出问题时回溯。数据传输走HTTPS / TLS不裸用HTTP传输密码或数据内容。有一次项目里业务方直接引用了HTTP的API地址到公网上我查日志发现每分钟有几次非法请求。后来加上IP白名单并强制HTTPS后再没出现过异常。SCADA数据一旦被外部恶意轮询或篡改后果很严重所以北向接口这一环宁可多配几道限制不要图方便。做北向接口这件事功能开发只是其中一部分真正的功夫都在边界设计上哪些数据能出去、以什么格式出去、丢失了怎么补、谁有权限看这些想清楚对接才会顺。DataPulse把北向能力拆成REST、MQTT、数据库直出三套通道并不是为了堆功能而是因为真实工业场景里业务侧的接入能力、网络环境、数据要求差异实在太大一套方案根本打不了天下。如果你正在做类似的数据开放可以先从小流量、单场景试起把映射和权限体系跑顺再逐步放开订阅和数据库直出通道。尤其建议把“变化上报策略”和“断线补偿”两件事在项目初期就设计进去后期你会回来感谢这两个设计。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进