Zum Hauptinhalt springen

Sparkplug B Driver — Technische Referenz

Der Sparkplug B-Treiber von PlantPulse Edge ist eine native Java-Implementierung eines MQTT 3.1.1-Clients + Sparkplug B Payload-Protobuf-Decoders. Es bestehen keine Abhängigkeiten zu externen paho/tahu-Jars, sodass er bei Auslieferung als Single-Jar ohne zusätzliche Konfiguration funktioniert.

Quelle: plantpulse.driver.protocol.sparkplug.*

KlasseVerantwortung
SparkplugBDriverProtocolDriver-Implementierung — connect/read/write/close, Alias- und Metric-Cache
SparkplugMqttClientMQTT 3.1.1 self-contained Client (CONNECT / SUBSCRIBE / PUBLISH / PINGREQ)
SparkplugBPayloadSparkplug B Payload Protobuf Wire-Encoder/-Decoder (varint / fixed32 / fixed64 / length-delim)

Ablauf

broker ──PUBLISH──> SparkplugMqttClient ──onMessage(topic, payload)──> SparkplugBDriver

├─ topic 파싱 (spBv1.0/G/<msgType>/edge[/dev])
├─ Payload 디코드 → metric list
├─ NBIRTH/DBIRTH 시 alias→name 등록
└─ metricCache[edge[/dev]/name] = formatValue()

PlantPulse 폴러 ──read(addr)──> metricCache[addr] (in-memory hit, 외부 RTT 없음)
write(addr, value) ──encode──> NCMD/DCMD publish → broker

Optionen

SchlüsselStandardwertBeschreibung
group-iddefaultSparkplug Group ID. Wird beim Subscribe als Teil des Wildcards verwendet. Nachrichten mit abweichender Group werden vom Treiber verworfen.
edge-node-id+Edge-Node-Filter. Bei + alle Nodes innerhalb der Group.
keep-alive60MQTT-Keep-Alive in Sekunden. Bei 0 ist Ping deaktiviert.
connect-timeout5000TCP-Verbindungs-Timeout in ms.

Das Subscribe-Topic wird nach dem Muster spBv1.0/<group-id>/+/<edge-node-id>/# aufgebaut (+ ist message_type, # das Wildcard für den Device-Teil).


Sparkplug-Datatype-Zuordnung

SparkplugBPayload.Metric.formatValue() konvertiert je nach Wire-Datatype in einen passenden String.

Sparkplug datatypeSpeicherfeldformat-Ergebnis
Int8 / Int16 / Int32intValue (varint)signed int (Integer.toString)
UInt8 / UInt16 / UInt32intValueunsigned (& 0xFFFFFFFFL)
Int64 / DateTimelongValuesigned long
UInt64longValueLong.toUnsignedString
FloatfloatValue (fixed32)Float.toString
DoubledoubleValue (fixed64)Double.toString
BooleanbooleanValue (varint)"true" / "false"
String / Text / UUIDstringValueUTF-8 unverändert
Bytes / FilebytesValueHex-String

is_null=true-Metriken werden als leerer String ausgewertet.


Alias-Lernen über NBIRTH / DBIRTH

Kern der Sparkplug-Effizienz: BIRTH überträgt Paare aus Metric-Name und Alias → anschließend senden NDATA/DDATA nur noch den Alias.

1) edge1 의 NBIRTH:
metric { name="Temperature" alias=7 datatype=Float float_value=23.5 }
→ driver: aliasByPrefix.put("edge1", {7 → "Temperature"})
metricCache.put("edge1/Temperature", "23.5")

2) edge1 의 NDATA (이름 생략):
metric { alias=7 datatype=Float float_value=24.1 }
→ driver: name 없음 → alias=7 → "Temperature"
metricCache.put("edge1/Temperature", "24.1")

Trifft NDATA ein, ohne dass zuvor NBIRTH empfangen wurde, schlägt das Alias-Lookup fehl und die Nachricht wird verworfen (keine Cache-Aktualisierung). Es wird gewartet, bis der Publisher nach einem Broker-Neustart NBIRTH erneut veröffentlicht.


NDEATH / DDEATH

Wird ein Edge Node oder ein Device beendet, veröffentlicht der Broker NDEATH/DDEATH über LWT (Last Will and Testament). Der Treiber leert lediglich die Alias-Map, der Cache bleibt erhalten — der letzte bekannte Wert wird damit als Polling-Ergebnis bewahrt (der Monitor von PlantPulse zeigt die lastValue-UI unverändert an).


NCMD / DCMD senden

write(ProtocolAddress) verzweigt automatisch anhand der Anzahl der Address-Segmente.

addresspublish topicHinweis
edge1/SetPointspBv1.0/<group>/NCMD/edge1Befehl auf Node-Ebene
edge1/dev1/SetPointspBv1.0/<group>/DCMD/edge1/dev1Befehl auf Device-Ebene

Phase 1 veröffentlicht alle Befehle mit dem Sparkplug-Datatype String — die Empfängerseite (Tahu / Ignition) konvertiert sie in den für die Metric definierten Datatype und verarbeitet sie entsprechend.


Einschränkungen und geplante Arbeiten

  • TLS / Authentifizierung — derzeit nur Klartext + anonym. Optionen für username/password bzw. mTLS folgen.
  • QoS — alle publish/subscribe mit QoS 0. Sparkplug empfiehlt QoS 1 nur für NBIRTH, NDATA/DDATA mit QoS 0.
  • DataSet-/Template-Metriken — auf dem Wire als Raw Bytes erhalten (datasetRaw/templateRaw), decode/format jedoch nicht implementiert.
  • Properties / Metadata — nur Erhalt als Raw Bytes, decode nicht implementiert.
  • bdSeq — bdSeq-Abgleich aus NBIRTH / NDEATH-Prüfung nicht implementiert.

Speicherort der Tests

test/java/plantpulse/driver/protocol/sparkplug/SparkplugBDriverTest.java — 27 Tests.

  • Initialzustand / Options-Parsing
  • Sicheres read/write im nicht verbundenen Zustand
  • BIRTH-Alias-Registrierung, Alias-only-Auflösung bei NDATA, Blockieren bei abweichender Group, Alias-Bereinigung bei DEATH
  • Korrektheit von formatValue je Datatype (Int32 / Float / Double / Boolean / String / UInt32 / UInt64 / is_null)
  • Payload encode→decode Round-Trip
  • MQTT Remaining Length / utf8-Wire-Utility
  • safeId clientId-Sanitization