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?name=output_count&time_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、数据库直出三套通道,并不是为了堆功能,而是因为真实工业场景里,业务侧的接入能力、网络环境、数据要求差异实在太大,一套方案根本打不了天下。如果你正在做类似的数据开放,可以先从小流量、单场景试起,把映射和权限体系跑顺,再逐步放开订阅和数据库直出通道。尤其建议把“变化上报策略”和“断线补偿”两件事在项目初期就设计进去,后期你会回来感谢这两个设计。