本文提出一种SparkplugB到Avro的数据桥接方案,用于工业物联网统一命名空间(UNS)系统中实时设备数据与上层分析系统的格式转换。方案通过MQTT Broker接收生产线设备发布的SparkplugB格式数据(如温度、电流等),经桥接器解析后转换为Avro格式,并注册到Schema Registry以实现数据模型管理,最终输出至Kafka或数据湖。文章详细展示了Python实现的伪代码流程,对比了两种格式在实时性、结构化等方面的特性差异,适用于需要将边缘设备数据标准化并支持大规模分析的场景。
一、背景场景
在一个基于 MQTT Broker(例如 EMQX) 的 UNS 系统中:
-
生产线设备 通过 Sparkplug B 协议发布实时数据(例如电机温度、电流、运行状态等)。
-
上层系统(如 Data Lake、Kafka 或 AI 分析服务)希望这些数据以 Avro + Schema Registry 格式管理,以保证模型演进、数据验证和跨系统兼容。
因此,我们需要一个桥接器(Bridge):
Sparkplug B → Avro Schema + Serialized Avro Record → Schema Registry / Kafka / Data Lake
二、架构示例
[PLC/Edge Device]
↓
Sparkplug B Encoder (MQTT Payload)
↓
[MQTT Broker / UNS Topic Tree]
↓
Sparkplug B x Avro Bridge
├── 解包 Sparkplug B Payload
├── 按设备类型匹配 Avro Schema
├── 转换为 Avro 格式
├── 向 Schema Registry 注册 Schema(若更新)
└── 发布至 Kafka / REST / Data Lake
三、桥接器实现示例
假设设备通过 Sparkplug B 发布如下数据:
Topic: spBv1.0/Factory/Line1/MachineA/NDATA
Payload:
{
"metrics": [
{"name": "Temp", "value": 78.6, "type": "float"},
{"name": "Current", "value": 12.3, "type": "float"},
{"name": "Status", "value": "RUN", "type": "string"}
],
"timestamp": 1731050100000
}
桥接器主要逻辑(Python伪代码):
import avro.schema
from avro.io import DatumWriter, BinaryEncoder
import io
import paho.mqtt.client as mqtt
# 1. 加载 Avro Schema(或从 Schema Registry 拉取)
schema_str = """
{
"namespace": "factory.line1",
"type": "record",
"name": "MachineAData",
"fields": [
{"name": "timestamp", "type": "long"},
{"name": "Temp", "type": "float"},
{"name": "Current", "type": "float"},
{"name": "Status", "type": "string"}
]
}
"""
schema = avro.schema.parse(schema_str)
# 2. MQTT 回调函数
def on_message(client, userdata, msg):
data = decode_sparkplug_b(msg.payload) # 解包Sparkplug B
avro_record = {
"timestamp": data["timestamp"],
"Temp": get_metric(data, "Temp"),
"Current": get_metric(data, "Current"),
"Status": get_metric(data, "Status")
}
# 3. 序列化为Avro二进制
buf = io.BytesIO()
encoder = BinaryEncoder(buf)
writer = DatumWriter(schema)
writer.write(avro_record, encoder)
# 4. 发布到Kafka / Schema Registry
send_to_kafka("factory.line1.machineA", buf.getvalue())
client = mqtt.Client()
client.connect("mqtt-broker.local", 1883)
client.subscribe("spBv1.0/Factory/Line1/MachineA/NDATA")
client.on_message = on_message
client.loop_forever()
四、两者的特点对比
| 特点 | Sparkplug B | Avro |
|---|---|---|
| 定位 | IIoT 设备通信协议 | 数据序列化与Schema管理格式 |
| 使用层级 | 边缘到UNS(L1--L3) | 数据湖 / 流处理 / BI(L3--L4) |
| 数据结构 | MQTT Payload 包含 metrics 列表、模板、Birth/Death 机制 | 基于 Schema 定义的二进制序列化格式 |
| 语义建模 | 与 UNS 紧密结合,通过Topic结构表达 ISA-95 语义 | 通过 Schema Registry 管理语义演进与版本控制 |
| 优点 | 轻量、实时、低延迟、适合边缘设备 | 强类型、安全、可演进、适合大规模数据分析 |
| 缺点 | 不保证 Schema 一致性,易因版本变化导致冲突 | 需事先注册Schema、序列化开销略大 |
| 结合点 | 由桥接器解析Sparkplug B Payload并映射Avro Schema | Schema Registry 统一管理工业数据模型版本 |
五、典型应用
在 UNS 架构中,Sparkplug B × Avro 桥接器可以:
-
作为 边缘网关 的一部分,将工业实时数据标准化;
-
将 MQTT 流式数据 转化为 可持久化、可演进的 Avro 格式;
-
支撑 Kafka 流分析 、AI训练数据集 、BI可视化 等上层业务。