基于MQTTnet的SparkPlug B指标别名查询与REBIRTH实现问询
关于SparkPlug B指标别名映射与REBIRTH指令实现的问题解答
1. 如何获取指标别名对应的名称
SparkPlug B协议设计中,DDATA/NDATA消息仅携带指标别名(Alias)是为了降低带宽消耗,完整的指标元数据(包括别名、名称、数据类型等)仅在节点/设备的BIRTH消息(NBIRTH/DBIRTH)中传输。
要获取别名对应的名称,你需要:
- 监听目标节点的
NBIRTH主题(格式:spBv1.0/<Group>/NBIRTH/<Node ID>)和目标设备的DBIRTH主题(格式:spBv1.0/<Group>/DBIRTH/<Node ID>/<Device ID>) - 收到
NBIRTH/DBIRTH消息后,解析其Protobuf格式的Payload,提取所有指标的alias和name字段,建立并缓存别名->名称的映射字典 - 后续收到
DDATA/NDATA时,直接通过缓存的字典将别名转换为对应名称
2. 是否需要发送REBIRTH指令?如何在MQTTnet中实现?
是的,当你首次连接Broker、未缓存过目标节点/设备的元数据,或者怀疑元数据有更新时,需要发送REBIRTH指令触发节点/设备重新发送NBIRTH/DBIRTH消息,以此获取最新的指标详情。
MQTTnet中发送REBIRTH指令的实现步骤
步骤1:构造REBIRTH指令的Payload
SparkPlug B的NCMD/DCMD指令Payload为固定JSON格式:
{"command":"REBIRTH"}
步骤2:构造正确的指令主题
- 节点级指令主题(NCMD):
spBv1.0/<Group>/NCMD/<Node ID> - 设备级指令主题(DCMD):
spBv1.0/<Group>/DCMD/<Node ID>/<Device ID>
步骤3:使用MQTTnet客户端发送指令
以下是完整的C#代码示例:
using MQTTnet; using MQTTnet.Client; using System.Text; // 初始化MQTT客户端 var mqttFactory = new MqttFactory(); using var mqttClient = mqttFactory.CreateMqttClient(); // 假设已完成客户端连接(此处省略连接逻辑) // await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None); // 配置SparkPlug B参数 string groupId = "ClientEU1"; string nodeId = "27352352"; string deviceId = "HART0"; string rebirthPayload = "{\"command\":\"REBIRTH\"}"; // 发送节点级REBIRTH指令 var nodeRebirthMsg = new MqttApplicationMessageBuilder() .WithTopic($"spBv1.0/{groupId}/NCMD/{nodeId}") .WithPayload(Encoding.UTF8.GetBytes(rebirthPayload)) .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) .WithRetainFlag(false) .Build(); await mqttClient.PublishAsync(nodeRebirthMsg, CancellationToken.None); // 发送设备级REBIRTH指令(针对HART0设备) var deviceRebirthMsg = new MqttApplicationMessageBuilder() .WithTopic($"spBv1.0/{groupId}/DCMD/{nodeId}/{deviceId}") .WithPayload(Encoding.UTF8.GetBytes(rebirthPayload)) .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) .WithRetainFlag(false) .Build(); await mqttClient.PublishAsync(deviceRebirthMsg, CancellationToken.None);
步骤4:解析NBIRTH/DBIRTH消息获取映射
SparkPlug B的BIRTH消息Payload采用Protobuf编码,你需要根据官方的SparkPlug B Protobuf定义生成C#类(可通过protoc工具或NuGet包处理),然后解析Payload建立映射:
// 监听NBIRTH/DBIRTH消息 mqttClient.ApplicationMessageReceivedAsync += async e => { var topic = e.ApplicationMessage.Topic; if (topic.StartsWith($"spBv1.0/{groupId}/NBIRTH/") || topic.StartsWith($"spBv1.0/{groupId}/DBIRTH/")) { // 假设已生成Protobuf类MetricList var metricList = MetricList.Parser.ParseFrom(e.ApplicationMessage.Payload); var aliasToNameMap = new Dictionary<string, string>(); foreach (var metric in metricList.Metrics) { if (!string.IsNullOrEmpty(metric.Alias) && !string.IsNullOrEmpty(metric.Name)) { aliasToNameMap[metric.Alias] = metric.Name; } } // 将映射字典缓存到全局或持久化存储,供后续DDATA/NDATA解析使用 } await Task.CompletedTask; };
内容的提问来源于stack exchange,提问作者user3426603
相关产品推荐
相关产品推荐

