数采卡
02 数采卡
1. 目的
数采卡是整个数采系统的现场执行端,负责把 PLC、机器人等设备里的原始数据按配置采集出来,映射成统一的业务字段,再上传到数据目的地。
数采卡是基于 C++ 开发的常驻服务,核心能力包括:
- 解析配置文件并初始化采集任务。
- 通过协议适配器访问 PLC 或机器人。
- 把读取到的原始数据按
mem_map映射成业务字段。 - 按周期打包并上送到 InfluxDB / MQ 等目标。
- 支持 HTTP 下发配置、备份、回滚与重启采集。
2. 总体架构
可以把数采卡理解为“配置驱动的协议采集引擎”,其内部大致分为 5 层。
校验参数
生成任务对象
维护连接状态
控制重连与超时
统一通讯接口
屏蔽协议差异
位域与字符串转换
生成业务字段
可扩展目的地
统一写出
数采卡的数据流向可以进一步理解为:
2.1 配置加载层
启动时读取 config.json 或下发后的 card.json,完成以下初始化:
- 读取系统参数:
edge_ip、edge_mask、edge_gateway、ntp_server_ip、icare_ip。 - 读取数据目的地配置:数据库、MQ 账号、端口等。
- 读取设备清单
machines。 - 读取配方清单
recipes,建立设备与配方的绑定关系。
2.2 设备调度层
每个 machine 对应一个采集对象,至少包含:
name:设备编号或产线名称。protocal:协议类型,如S7、MODBUS、ABPLC、RAW_SOCKET、XML。opts:协议参数,如 IP、端口、rack/slot、slave_id、interval 等。recipe_id:关联的配方 ID。
调度层负责:
- 按
interval周期触发采集。 - 按设备维度维护连接状态。
- 设备失败时重连、超时、降级或跳过。
2.3 协议适配层
协议层是数采卡最关键的部分,建议采用统一接口抽象不同协议:
- PLC 类协议:通过地址读写采集。
- 机器人类协议:通过 socket 发送/接收 XML。
适配层屏蔽协议细节,对上层统一暴露“读块数据”“写块数据”“连接”“断开”“健康检查”等能力。
2.4 数据映射层
配方里的 tag_list 负责定义“从设备哪里读”,mem_map 负责定义“读回来后怎么拆”。
tag_list:采集块定义,指定area、DB_num、address、count。mem_map:字段映射定义,指定name、offset、type、bit、length、sendway。
这意味着数采卡不是直接把原始块上送,而是先按配方解析,再生成业务字段集合。
2.5 数据上送层
默认上送目标包含:
- InfluxDB:时序数据存储。
- MQ:异步消息分发。
- 未来还可能扩展更多目的地。
因此上送层应该是可插拔的 Writer/Publisher 结构,而不是和协议代码耦合在一起。
3. 配置模型
3.1 系统级配置
这部分是数采卡运行环境和基础服务参数,典型字段有:
- 网卡地址、掩码、网关。
- NTP 服务器。
- iCare 平台地址。
- 采集包数量
packet_num。 - 默认节点 ID
default_nodeID。 - 是否拼包/合包标记
nojoiner。
3.2 设备配置
设备配置体现“一个设备绑定一个配方,或者一台设备绑定多个配方”的关系。
从样例看,recipe_id 用来引用 recipes 中的某一个配方。
不同协议的 opts 不同:
S7:ip、interval、type、rack、slotMODBUS:ip、modbus_port、slave_id、intervalRAW_SOCKET:ip、socket_portXML:ip、xml_port
这说明数采卡在初始化时,会按协议类型构造不同的通讯对象。
3.3 配方配置
配方是数采卡的核心抽象,建议理解为“协议采集模板”。
一个配方至少包括:
protocal:协议类型。tag_list:原始地址段。mem_map:字段映射。
从设计图可以推断,tag_list 只对主动轮询类协议有意义,例如:
ABPLCMODBUSS7
而对于机器人 socket/XML 类协议,tag_list 可能为空,数据更偏向主动推送或固定请求响应。
2. 读取原始块数据
3. 按 mem_map 生成业务字段
4. 交给上送层
mem_map 负责“字段解释”
两者分层更利于扩展
4. 协议实现
4.1 PLC 协议
PLC 采集的基本模式应当是:
- 建立 TCP/专用协议连接。
- 按
tag_list指定的地址块读取一段连续内存。 - 按
mem_map的offset和type拆分字段。 - 将字段写入统一数据结构并上送。
S7 配置包含 rack、slot,说明底层应对接西门子 S7 协议栈。MODBUS 配置则包含 slave_id 和端口,说明底层会按 Modbus TCP 做寄存器/线圈读取。ABPLC 看起来像一类面向工厂内部的地址模型,仍然是“按地址块读、按偏移拆字段”的方式。
4.2 机器人 socket/XML
机器人通信原理是通过 socket 连接设备,再通过 XML 进行请求/应答。
实现方式如下:
- 通过 TCP socket 连接机器人控制器。
- 发送 XML 格式的请求报文。
- 接收 XML 响应报文。
- 从 XML 节点中提取字段值。
- 统一映射到
mem_map指定字段。
这种方式更像“应用层协议”,因此相比 PLC 的地址读写,更依赖报文结构解析和字段匹配。
5. 数据映射与字段拆包
mem_map 的设计已经很像一个通用解包表:
name:业务字段名,如AA001、RB12_AA002。offset:在原始缓冲区中的偏移。type:字段类型,如INT16、INT32、FLOAT、BIT、STRING_MAP。bit:当类型为BIT时,指出位号。length:当类型为字符串映射时,定义长度。sendway:推断为发送方向或采集方向标识,样例中多为0。
从截图可以看到:
count定义的是“读取长度”,不是字段个数。- 一个读取块内可以拆出多个字段。
- 同一偏移可以派生多个
BIT字段。 STRING_MAP这类字段属于结构化映射,适合固定长度字符串或枚举码表。
因此,数采卡内部很可能有一套统一的字节解析器,负责处理大小端、整数、浮点、位域和字符串转换。
6. 运行流程
6.1 启动流程
- 读取本地配置文件。
- 校验 JSON 结构和协议参数。
- 初始化日志、网络、数据库、MQ、定时器。
- 为每台设备创建采集任务。
- 根据配方建立地址块与字段映射。
- 周期性开始采集与上送。
6.2 周期采集流程
- 到达设备采集周期。
- 调用协议适配器读取原始数据。
- 协议结果进入解包器。
- 按
mem_map生成业务字段。 - 打包成统一数据格式。
- 写入目的地或消息队列。
6.3 配置更新流程
设计文档明确提到:配置由配置系统通过 HTTP 下发到数采卡。
因此数采卡应实现如下机制:
- 接收 HTTP 配置更新请求。
- 备份当前配置。
- 写入新配置文件。
- 重启采集服务或重新加载配置。
- 若失败则回滚旧配置。
- 返回成功/失败给配置系统,并标记配置有效性。
这一点很重要,因为它说明数采卡不是静态程序,而是“可远程维护的边缘采集节点”。
7. C++ 模块划分
如果按工程实现拆分,比较合理的 C++ 模块如下:
ConfigLoader:解析和校验配置。DeviceManager:管理设备实例、连接状态、采集周期。RecipeManager:管理配方、字段映射、地址块。IProtocolAdapter:协议抽象接口。S7Adapter/ModbusAdapter/AbPlcAdapter/SocketXmlAdapter:具体协议实现。DataParser:原始数据解包。PacketBuilder:组包、补时间戳、补设备信息。DataPublisher:写 InfluxDB、发 MQ。ConfigUpdater:HTTP 配置更新、备份与回滚。Logger:采集日志、告警日志、通信日志。
8. 关键实现要点
- 协议与配置要解耦,协议代码不能直接依赖具体业务字段名。
tag_list和mem_map要分层,前者解决“读什么”,后者解决“怎么解释”。- 设备和配方是弱绑定关系,支持一台设备挂多个配方。
- 配置更新必须有备份和回滚,避免配置下发失败导致整卡不可用。
- 机器人 socket/XML 与 PLC 轮询属于不同通讯模型,但最终都要汇聚到统一数据结构。
- 上送层最好做成可扩展架构,以支持 InfluxDB 之外的数据目的地。
9. 结论
综合样例配置和设计说明来看,数采卡的本质是一个“配置驱动的多协议采集代理”:
- 底层用 C++ 实现高可靠通信与周期调度。
- 中间层用配方统一抽象地址块和字段拆包。
- 上层通过 HTTP 接收配置下发。
- 末端将采集数据上送到数据库或消息系统。
也就是说,这套系统的核心不是单纯的“读 PLC”,而是“把不同设备的通讯差异收敛到一套可配置的采集模型里”。