Sparkplug B C++ Library 1.0.0
Modern C++-23 implementation of Eclipse Sparkplug B 2.2 specification
Loading...
Searching...
No Matches
sparkplug::HostApplication Class Reference

Sparkplug B Host Application for SCADA/Primary Applications. More...

#include <host_application.hpp>

Classes

struct  Config
 Configuration parameters for the Sparkplug B Host Application. More...
 
struct  DeviceState
 Tracks the state of a device attached to an edge node. More...
 
struct  NodeState
 Tracks the state of an individual edge node. More...
 
struct  TlsOptions
 TLS/SSL configuration options for secure MQTT connections. More...
 
struct  TransparentStringHash
 Transparent hash for string keys to enable heterogeneous lookup. More...
 

Public Member Functions

 HostApplication (Config config)
 Constructs a HostApplication with the given configuration.
 
 ~HostApplication ()
 Destroys the HostApplication and cleans up MQTT resources.
 
 HostApplication (const HostApplication &)=delete
 
HostApplicationoperator= (const HostApplication &)=delete
 
 HostApplication (HostApplication &&) noexcept
 
HostApplicationoperator= (HostApplication &&) noexcept
 
void set_credentials (std::optional< std::string > username, std::optional< std::string > password)
 Sets MQTT username and password for authentication.
 
void set_tls (std::optional< TlsOptions > tls)
 Configures TLS/SSL options for secure MQTT connections.
 
void set_message_callback (MessageCallback callback)
 Sets the message callback for receiving Sparkplug messages.
 
void set_log_callback (LogCallback callback)
 Sets the log callback for receiving library diagnostic messages.
 
stdx::expected< void, std::string > connect ()
 Connects to the MQTT broker.
 
stdx::expected< void, std::string > disconnect ()
 Gracefully disconnects from the MQTT broker.
 
stdx::expected< void, std::string > subscribe_all_groups ()
 Subscribes to all Sparkplug B messages across all groups.
 
stdx::expected< void, std::string > subscribe_group (std::string_view group_id)
 Subscribes to messages from a specific group.
 
stdx::expected< void, std::string > subscribe_node (std::string_view group_id, std::string_view edge_node_id)
 Subscribes to messages from a specific edge node in a group.
 
stdx::expected< void, std::string > subscribe_state (std::string_view host_id)
 Subscribes to STATE messages from another primary application.
 
std::optional< std::reference_wrapper< const NodeState > > get_node_state (std::string_view group_id, std::string_view edge_node_id) const
 Gets the current state of a specific edge node.
 
std::optional< std::string_view > get_metric_name (std::string_view group_id, std::string_view edge_node_id, std::string_view device_id, uint64_t alias) const
 Resolves a metric alias to its name for a specific node or device.
 
stdx::expected< void, std::string > publish_state_birth (uint64_t timestamp)
 Publishes a STATE birth message to indicate Host Application is online.
 
stdx::expected< void, std::string > publish_state_death (uint64_t timestamp)
 Publishes a STATE death message to indicate Host Application is offline.
 
stdx::expected< void, std::string > publish_node_command (std::string_view group_id, std::string_view target_edge_node_id, PayloadBuilder &payload)
 Publishes an NCMD (Node Command) message to an Edge Node.
 
stdx::expected< void, std::string > publish_device_command (std::string_view group_id, std::string_view target_edge_node_id, std::string_view target_device_id, PayloadBuilder &payload)
 Publishes a DCMD (Device Command) message to a device on an Edge Node.
 
void log (LogLevel level, std::string_view message) const noexcept
 Internal logging method accessible from C bindings.
 

Detailed Description

Sparkplug B Host Application for SCADA/Primary Applications.

The HostApplication class implements the complete Sparkplug B protocol for Host Applications:

  • Subscribes to spBv1.0/# to receive all Edge Node messages (NBIRTH/NDATA/NDEATH)
  • Validates message sequences and tracks node/device state
  • Publishes STATE messages (JSON format) to indicate online/offline status
  • Publishes NCMD/DCMD commands to control Edge Nodes and Devices
  • Does NOT publish NBIRTH/NDATA/NDEATH (those are for Edge Nodes only)

This is the authoritative consumer and command source in a Sparkplug B topology. A Host Application should use a single MQTT client that both receives data and sends commands.

Thread Safety
This class is fully thread-safe with coarse-grained locking:
  • All public methods use a single internal mutex to protect shared state
  • Methods can be safely called from any thread concurrently
  • Callbacks (message_callback, log_callback) invoked on MQTT thread WITHOUT holding mutex
  • Mutex is released before MQTT publish to prevent callback deadlocks
Rust FFI Compatibility
  • Implements Send: Can transfer between threads safely (all state mutex-protected)
  • Implements Sync: Can access from multiple threads concurrently (mutex-guarded methods) ill *
Example Usage
auto message_callback = [](const sparkplug::Topic& topic, const auto& payload) {
std::cout << "Received: " << topic.to_string() << "\n";
};
.broker_url = "tcp://localhost:1883",
.client_id = "scada_host",
.host_id = "SCADA01",
.message_callback = message_callback
};
sparkplug::HostApplication host_app(std::move(config));
host_app.connect();
// Subscribe to all Sparkplug messages
host_app.subscribe_all_groups();
// Publish STATE birth (Host App is online)
auto timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()).count();
host_app.publish_state_birth(timestamp);
// Send rebirth command to an Edge Node
cmd.add_metric("Node Control/Rebirth", true);
host_app.publish_node_command("Energy", "Gateway01", cmd);
// Publish STATE death before disconnecting
host_app.publish_state_death(timestamp);
host_app.disconnect();
Sparkplug B Host Application for SCADA/Primary Applications.
Type-safe builder for Sparkplug B payloads with automatic type detection.
PayloadBuilder & add_metric(std::string_view name, T &&value)
Adds a metric by name only (for NBIRTH without aliases).
Configuration parameters for the Sparkplug B Host Application.
std::string broker_url
MQTT broker URL (e.g., "tcp://localhost:1883" or "ssl://localhost:8883")
Represents a parsed Sparkplug B MQTT topic.
Definition topic.hpp:47
std::string to_string() const
Converts the topic back to a string.
See also
EdgeNode for Edge Node implementation

Definition at line 95 of file host_application.hpp.

Constructor & Destructor Documentation

◆ HostApplication()

sparkplug::HostApplication::HostApplication ( Config  config)

Constructs a HostApplication with the given configuration.

Parameters
configHostApplication configuration (moved)
Note
Unlike Publisher, HostApplication does NOT set up MQTT Last Will Testament. Host Applications should explicitly publish STATE death before disconnecting.

Member Function Documentation

◆ connect()

stdx::expected< void, std::string > sparkplug::HostApplication::connect ( )

Connects to the MQTT broker.

Unlike Publisher::connect(), this does NOT automatically publish any messages. You should call publish_state_birth() after connecting to declare the Host App online.

Returns
void on success, error message on failure
See also
publish_state_birth() to declare Host Application online

◆ disconnect()

stdx::expected< void, std::string > sparkplug::HostApplication::disconnect ( )

Gracefully disconnects from the MQTT broker.

Returns
void on success, error message on failure
Note
You should call publish_state_death() before disconnect() to properly signal that the Host Application is going offline.

◆ get_metric_name()

std::optional< std::string_view > sparkplug::HostApplication::get_metric_name ( std::string_view  group_id,
std::string_view  edge_node_id,
std::string_view  device_id,
uint64_t  alias 
) const

Resolves a metric alias to its name for a specific node or device.

Looks up the metric name that corresponds to the given alias, based on the alias mappings captured from NBIRTH (node metrics) or DBIRTH (device metrics).

Parameters
group_idThe group ID
edge_node_idThe edge node ID
device_idThe device ID (empty string for node-level metrics)
aliasThe metric alias to resolve
Returns
A string_view to the metric name if found, std::nullopt otherwise
Note
Returns std::nullopt if the node/device hasn't sent a birth message yet, or if the alias is not found in the birth message.

◆ get_node_state()

std::optional< std::reference_wrapper< const NodeState > > sparkplug::HostApplication::get_node_state ( std::string_view  group_id,
std::string_view  edge_node_id 
) const

Gets the current state of a specific edge node.

Parameters
group_idThe group ID
edge_node_idThe edge node ID to query
Returns
NodeState if the node has been seen, std::nullopt otherwise
Note
Useful for monitoring node online/offline status and bdSeq.

◆ log()

void sparkplug::HostApplication::log ( LogLevel  level,
std::string_view  message 
) const
noexcept

Internal logging method accessible from C bindings.

Parameters
levelLog severity level
messageLog message content

◆ publish_device_command()

stdx::expected< void, std::string > sparkplug::HostApplication::publish_device_command ( std::string_view  group_id,
std::string_view  target_edge_node_id,
std::string_view  target_device_id,
PayloadBuilder payload 
)

Publishes a DCMD (Device Command) message to a device on an Edge Node.

DCMD messages are commands sent from Host Applications to devices attached to Edge Nodes.

Parameters
group_idThe Sparkplug group ID containing the target Edge Node
target_edge_node_idThe target Edge Node identifier
target_device_idThe target device identifier
payloadPayloadBuilder containing command metrics
Returns
void on success, error message on failure
Example Usage
cmd.add_metric("SetPoint", 75.0);
host_app.publish_device_command("Energy", "Gateway01", "Motor01", cmd);

◆ publish_node_command()

stdx::expected< void, std::string > sparkplug::HostApplication::publish_node_command ( std::string_view  group_id,
std::string_view  target_edge_node_id,
PayloadBuilder payload 
)

Publishes an NCMD (Node Command) message to an Edge Node.

NCMD messages are commands sent from Host Applications to Edge Nodes to request actions like rebirth, reboot, or custom operations.

Parameters
group_idThe Sparkplug group ID containing the target Edge Node
target_edge_node_idThe target Edge Node identifier
payloadPayloadBuilder containing command metrics (e.g., "Node Control/Rebirth")
Returns
void on success, error message on failure
Note
Common Node Control commands:
  • "Node Control/Rebirth" (bool): Request node to republish NBIRTH
  • "Node Control/Reboot" (bool): Request node to reboot
  • "Node Control/Next Server" (bool): Switch to backup server
  • "Node Control/Scan Rate" (int64): Change data acquisition rate
Example Usage
cmd.add_metric("Node Control/Rebirth", true);
host_app.publish_node_command("Energy", "Gateway01", cmd);

◆ publish_state_birth()

stdx::expected< void, std::string > sparkplug::HostApplication::publish_state_birth ( uint64_t  timestamp)

Publishes a STATE birth message to indicate Host Application is online.

STATE messages are used by Host Applications (SCADA/Primary Applications) to declare their online status to Edge Nodes. The birth message indicates the Host Application is online and ready to process data.

Parameters
timestampUTC milliseconds since epoch
Returns
void on success, error message on failure
Note
Topic format: spBv1.0/STATE/<host_id>
Payload format: JSON {"online": true, "timestamp": <timestamp>}
Message is published with QoS=1 and Retain=true (late-joining Edge Nodes see it)
This is NOT a Sparkplug protobuf message - uses raw JSON payload
Example Usage
auto timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()).count();
host_app.publish_state_birth(timestamp);
See also
publish_state_death() for declaring Host Application offline

◆ publish_state_death()

stdx::expected< void, std::string > sparkplug::HostApplication::publish_state_death ( uint64_t  timestamp)

Publishes a STATE death message to indicate Host Application is offline.

STATE messages are used by Host Applications (SCADA/Primary Applications) to declare their online status to Edge Nodes. The death message indicates the Host Application is going offline.

Parameters
timestampUTC milliseconds since epoch (typically matches birth timestamp)
Returns
void on success, error message on failure
Note
Topic format: spBv1.0/STATE/<host_id>
Payload format: JSON {"online": false, "timestamp": <timestamp>}
Message is published with QoS=1 and Retain=true
This is NOT a Sparkplug protobuf message - uses raw JSON payload
Should be called BEFORE disconnect() to ensure proper delivery
Example Usage
auto timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()).count();
host_app.publish_state_death(timestamp);
host_app.disconnect();
See also
publish_state_birth() for declaring Host Application online

◆ set_credentials()

void sparkplug::HostApplication::set_credentials ( std::optional< std::string >  username,
std::optional< std::string >  password 
)

Sets MQTT username and password for authentication.

Parameters
usernameMQTT username (empty string or std::nullopt to unset)
passwordMQTT password (empty string or std::nullopt to unset)
Note
Must be called before connect().

◆ set_log_callback()

void sparkplug::HostApplication::set_log_callback ( LogCallback  callback)

Sets the log callback for receiving library diagnostic messages.

Parameters
callbackCallback function to invoke for log messages
Note
Can be called at any time.

◆ set_message_callback()

void sparkplug::HostApplication::set_message_callback ( MessageCallback  callback)

Sets the message callback for receiving Sparkplug messages.

Parameters
callbackCallback function to invoke for received messages
Note
Must be called before connect().

◆ set_tls()

void sparkplug::HostApplication::set_tls ( std::optional< TlsOptions tls)

Configures TLS/SSL options for secure MQTT connections.

Parameters
tlsTLS configuration options
Note
Must be called before connect().
broker_url must use ssl:// prefix for TLS connections.

◆ subscribe_all_groups()

stdx::expected< void, std::string > sparkplug::HostApplication::subscribe_all_groups ( )

Subscribes to all Sparkplug B messages across all groups.

Subscribes to the wildcard topic: spBv1.0/#

This receives all message types (NBIRTH, NDATA, NDEATH, DBIRTH, DDATA, DDEATH) from all edge nodes in all groups.

Returns
void on success, error message on failure
Note
Must call connect() first.
The message_callback will be invoked for every message received.

◆ subscribe_group()

stdx::expected< void, std::string > sparkplug::HostApplication::subscribe_group ( std::string_view  group_id)

Subscribes to messages from a specific group.

Subscribes to: spBv1.0/{group_id}/#

Parameters
group_idThe group ID to subscribe to
Returns
void on success, error message on failure
Note
Allows subscribing to multiple groups on a single MQTT connection.

◆ subscribe_node()

stdx::expected< void, std::string > sparkplug::HostApplication::subscribe_node ( std::string_view  group_id,
std::string_view  edge_node_id 
)

Subscribes to messages from a specific edge node in a group.

Subscribes to: spBv1.0/{group_id}/+/{edge_node_id}/#

Parameters
group_idThe group ID
edge_node_idThe edge node ID to subscribe to
Returns
void on success, error message on failure
Note
More efficient than subscribe_all_groups() if you only need specific nodes.

◆ subscribe_state()

stdx::expected< void, std::string > sparkplug::HostApplication::subscribe_state ( std::string_view  host_id)

Subscribes to STATE messages from another primary application.

STATE messages indicate whether another SCADA/Primary Application is online. Subscribe to: spBv1.0/STATE/{host_id}

Parameters
host_idThe host application identifier
Returns
void on success, error message on failure
Note
STATE messages are outside the normal Sparkplug topic namespace.
Useful for High Availability (HA) setups with multiple host applications.

The documentation for this class was generated from the following file: