数采卡

02 数采卡

1. 目的

数采卡是整个数采系统的现场执行端,负责把 PLC、机器人等设备里的原始数据按配置采集出来,映射成统一的业务字段,再上传到数据目的地。
数采卡是基于 C++ 开发的常驻服务,核心能力包括:

  1. 解析配置文件并初始化采集任务。
  2. 通过协议适配器访问 PLC 或机器人。
  3. 把读取到的原始数据按 mem_map 映射成业务字段。
  4. 按周期打包并上送到 InfluxDB / MQ 等目标。
  5. 支持 HTTP 下发配置、备份、回滚与重启采集。

2. 总体架构

可以把数采卡理解为“配置驱动的协议采集引擎”,其内部大致分为 5 层。

配置加载层
读取 JSON
校验参数
生成任务对象
设备调度层
按周期触发
维护连接状态
控制重连与超时
协议适配层
PLC / Socket / XML
统一通讯接口
屏蔽协议差异
数据映射层
按 offset/type 解包
位域与字符串转换
生成业务字段
数据上送层
InfluxDB / MQ
可扩展目的地
统一写出

数采卡的数据流向可以进一步理解为:

配置文件
加载器
设备调度器
协议适配器
数据解包器
数据上送器

2.1 配置加载层

启动时读取 config.json 或下发后的 card.json,完成以下初始化:

  • 读取系统参数:edge_ipedge_maskedge_gatewayntp_server_ipicare_ip
  • 读取数据目的地配置:数据库、MQ 账号、端口等。
  • 读取设备清单 machines
  • 读取配方清单 recipes,建立设备与配方的绑定关系。

2.2 设备调度层

每个 machine 对应一个采集对象,至少包含:

  • name:设备编号或产线名称。
  • protocal:协议类型,如 S7MODBUSABPLCRAW_SOCKETXML
  • opts:协议参数,如 IP、端口、rack/slot、slave_id、interval 等。
  • recipe_id:关联的配方 ID。

调度层负责:

  • interval 周期触发采集。
  • 按设备维度维护连接状态。
  • 设备失败时重连、超时、降级或跳过。

2.3 协议适配层

协议层是数采卡最关键的部分,建议采用统一接口抽象不同协议:

  • PLC 类协议:通过地址读写采集。
  • 机器人类协议:通过 socket 发送/接收 XML。

适配层屏蔽协议细节,对上层统一暴露“读块数据”“写块数据”“连接”“断开”“健康检查”等能力。

2.4 数据映射层

配方里的 tag_list 负责定义“从设备哪里读”,mem_map 负责定义“读回来后怎么拆”。

  • tag_list:采集块定义,指定 areaDB_numaddresscount
  • mem_map:字段映射定义,指定 nameoffsettypebitlengthsendway

这意味着数采卡不是直接把原始块上送,而是先按配方解析,再生成业务字段集合。

2.5 数据上送层

默认上送目标包含:

  • InfluxDB:时序数据存储。
  • MQ:异步消息分发。
  • 未来还可能扩展更多目的地。

因此上送层应该是可插拔的 Writer/Publisher 结构,而不是和协议代码耦合在一起。

3. 配置模型

3.1 系统级配置

这部分是数采卡运行环境和基础服务参数,典型字段有:

  • 网卡地址、掩码、网关。
  • NTP 服务器。
  • iCare 平台地址。
  • 采集包数量 packet_num
  • 默认节点 ID default_nodeID
  • 是否拼包/合包标记 nojoiner
网络参数组
edge_ip / edge_mask / edge_gateway
保证数采卡接入现场网络并访问 PLC、机器人和平台服务。
时间同步组
ntp_server_ip
用于统一时间戳,确保时序数据对齐。
平台对接组
icare_ip
用于对接上层系统、告警或配置中心。
采集与拼包组
packet_num / default_nodeID / nojoiner
控制单次上送的数据量、默认节点和拼包策略。

3.2 设备配置

设备配置体现“一个设备绑定一个配方,或者一台设备绑定多个配方”的关系。
从样例看,recipe_id 用来引用 recipes 中的某一个配方。

不同协议的 opts 不同:

  • S7ipintervaltyperackslot
  • MODBUSipmodbus_portslave_idinterval
  • RAW_SOCKETipsocket_port
  • XMLipxml_port

这说明数采卡在初始化时,会按协议类型构造不同的通讯对象。

3.3 配方配置

配方是数采卡的核心抽象,建议理解为“协议采集模板”。
一个配方至少包括:

  • protocal:协议类型。
  • tag_list:原始地址段。
  • mem_map:字段映射。

从设计图可以推断,tag_list 只对主动轮询类协议有意义,例如:

  • ABPLC
  • MODBUS
  • S7

而对于机器人 socket/XML 类协议,tag_list 可能为空,数据更偏向主动推送或固定请求响应。

protocal
协议选择入口
tag_list
定义读取块,决定“读什么”
mem_map
定义字段拆包规则,决定“怎么解释”
作用链路
1. 选择协议适配器
2. 读取原始块数据
3. 按 mem_map 生成业务字段
4. 交给上送层
实现建议
tag_list 负责“块读取”
mem_map 负责“字段解释”
两者分层更利于扩展

4. 协议实现

4.1 PLC 协议

PLC 采集的基本模式应当是:

  1. 建立 TCP/专用协议连接。
  2. tag_list 指定的地址块读取一段连续内存。
  3. mem_mapoffsettype 拆分字段。
  4. 将字段写入统一数据结构并上送。

S7 配置包含 rackslot,说明底层应对接西门子 S7 协议栈。
MODBUS 配置则包含 slave_id 和端口,说明底层会按 Modbus TCP 做寄存器/线圈读取。
ABPLC 看起来像一类面向工厂内部的地址模型,仍然是“按地址块读、按偏移拆字段”的方式。

S7
连接方式:TCP + rack/slot
处理重点:块读取、字节序转换、位拆分
MODBUS
连接方式:TCP + slave_id
处理重点:寄存器地址计算、类型转换
ABPLC
连接方式:TCP
处理重点:统一按地址映射到 mem_map
说明:该图仅表示 PLC 类协议的采集结构,不包含 Raw Socket 和 XML 方式;后两者属于机器人通讯小节中的独立流程。

4.2 机器人 socket/XML

机器人通信原理是通过 socket 连接设备,再通过 XML 进行请求/应答。
实现方式如下:

  1. 通过 TCP socket 连接机器人控制器。
  2. 发送 XML 格式的请求报文。
  3. 接收 XML 响应报文。
  4. 从 XML 节点中提取字段值。
  5. 统一映射到 mem_map 指定字段。
TCP 连接
建立 socket
发送 XML
请求报文
接收 XML
响应报文
节点解析
字段提取
字段映射
进入 mem_map

这种方式更像“应用层协议”,因此相比 PLC 的地址读写,更依赖报文结构解析和字段匹配。

5. 数据映射与字段拆包

mem_map 的设计已经很像一个通用解包表:

  • name:业务字段名,如 AA001RB12_AA002
  • offset:在原始缓冲区中的偏移。
  • type:字段类型,如 INT16INT32FLOATBITSTRING_MAP
  • bit:当类型为 BIT 时,指出位号。
  • length:当类型为字符串映射时,定义长度。
  • sendway:推断为发送方向或采集方向标识,样例中多为 0

从截图可以看到:

  • count 定义的是“读取长度”,不是字段个数。
  • 一个读取块内可以拆出多个字段。
  • 同一偏移可以派生多个 BIT 字段。
  • STRING_MAP 这类字段属于结构化映射,适合固定长度字符串或枚举码表。
tag_list
读取块定义
原始字节流
PLC / XML / Socket 返回
mem_map
按 offset/type/bit 拆包
业务字段集
标准化输出

因此,数采卡内部很可能有一套统一的字节解析器,负责处理大小端、整数、浮点、位域和字符串转换。

6. 运行流程

6.1 启动流程

  1. 读取本地配置文件。
  2. 校验 JSON 结构和协议参数。
  3. 初始化日志、网络、数据库、MQ、定时器。
  4. 为每台设备创建采集任务。
  5. 根据配方建立地址块与字段映射。
  6. 周期性开始采集与上送。
1 读取配置
加载 JSON
2 校验参数
检查协议与字段
3 初始化基础服务
日志 / 网络 / DB / MQ
4 创建设备任务
按 machine 建任务
5 绑定配方
建立地址与字段映射
6 开始周期采集
进入运行态

6.2 周期采集流程

  1. 到达设备采集周期。
  2. 调用协议适配器读取原始数据。
  3. 协议结果进入解包器。
  4. mem_map 生成业务字段。
  5. 打包成统一数据格式。
  6. 写入目的地或消息队列。
触发采集
定时器 / 调度器
协议读取
读取原始字节流 / XML
字段拆包
按 mem_map 解析
数据组包
附加时间戳、设备名、配方信息
数据上送
InfluxDB / MQ

6.3 配置更新流程

设计文档明确提到:配置由配置系统通过 HTTP 下发到数采卡。
因此数采卡应实现如下机制:

  1. 接收 HTTP 配置更新请求。
  2. 备份当前配置。
  3. 写入新配置文件。
  4. 重启采集服务或重新加载配置。
  5. 若失败则回滚旧配置。
  6. 返回成功/失败给配置系统,并标记配置有效性。

这一点很重要,因为它说明数采卡不是静态程序,而是“可远程维护的边缘采集节点”。

HTTP 下发
接收更新请求
备份旧配置
保留回滚点
写入新配置
替换当前文件
重载或重启
使配置生效
返回结果
标记有效或回滚

7. C++ 模块划分

如果按工程实现拆分,比较合理的 C++ 模块如下:

  • ConfigLoader:解析和校验配置。
  • DeviceManager:管理设备实例、连接状态、采集周期。
  • RecipeManager:管理配方、字段映射、地址块。
  • IProtocolAdapter:协议抽象接口。
  • S7Adapter / ModbusAdapter / AbPlcAdapter / SocketXmlAdapter:具体协议实现。
  • DataParser:原始数据解包。
  • PacketBuilder:组包、补时间戳、补设备信息。
  • DataPublisher:写 InfluxDB、发 MQ。
  • ConfigUpdater:HTTP 配置更新、备份与回滚。
  • Logger:采集日志、告警日志、通信日志。

8. 关键实现要点

  1. 协议与配置要解耦,协议代码不能直接依赖具体业务字段名。
  2. tag_listmem_map 要分层,前者解决“读什么”,后者解决“怎么解释”。
  3. 设备和配方是弱绑定关系,支持一台设备挂多个配方。
  4. 配置更新必须有备份和回滚,避免配置下发失败导致整卡不可用。
  5. 机器人 socket/XML 与 PLC 轮询属于不同通讯模型,但最终都要汇聚到统一数据结构。
  6. 上送层最好做成可扩展架构,以支持 InfluxDB 之外的数据目的地。

9. 结论

综合样例配置和设计说明来看,数采卡的本质是一个“配置驱动的多协议采集代理”:

  • 底层用 C++ 实现高可靠通信与周期调度。
  • 中间层用配方统一抽象地址块和字段拆包。
  • 上层通过 HTTP 接收配置下发。
  • 末端将采集数据上送到数据库或消息系统。

也就是说,这套系统的核心不是单纯的“读 PLC”,而是“把不同设备的通讯差异收敛到一套可配置的采集模型里”。


数采卡
https://luischen.github.io/2026/06/18/manulism-work/20_Domain_Knowledge/21 工业数据接入/02 数采卡/
作者
Luis Chen
发布于
2026年6月18日
许可协议