3#include "detail/compat.hpp"
4#include "detail/secure_buffer.hpp"
6#include "mqtt_handle.hpp"
7#include "payload_builder.hpp"
8#include "sparkplug_b.pb.h"
17#include <unordered_map>
30using CommandCallback =
31 std::function<void(
const Topic&,
const org::eclipse::tahu::protobuf::Payload&)>;
128 std::optional<TlsOptions>
130 std::optional<std::string>
132 std::optional<std::string>
134 std::optional<CommandCallback> command_callback{};
135 std::optional<std::string> primary_host_id{};
136 std::optional<LogCallback> log_callback{};
169 std::optional<std::
string> password);
181 void set_log_callback(std::optional<LogCallback> callback);
195 [[nodiscard]] stdx::expected<
void, std::
string>
connect();
206 [[nodiscard]] stdx::expected<
void, std::
string>
disconnect();
280 [[nodiscard]] stdx::expected<
void, std::
string>
rebirth();
290 std::scoped_lock lock(mutex_);
302 std::scoped_lock lock(mutex_);
316 std::scoped_lock lock(mutex_);
317 return primary_host_online_;
338 [[nodiscard]] stdx::expected<void, std::string>
360 [[nodiscard]] stdx::expected<void, std::string>
374 [[nodiscard]] stdx::expected<void, std::string>
402 [[nodiscard]] stdx::expected<void, std::string>
423 [[nodiscard]] stdx::expected<void, std::string>
425 std::string_view target_device_id,
428 void log(LogLevel level, std::string_view message)
const noexcept;
435 std::vector<uint8_t> last_birth_payload;
436 bool is_online{
false};
440 MQTTAsyncHandle client_;
441 uint64_t seq_num_{0};
442 uint64_t bd_seq_num_{0};
445 std::vector<uint8_t> death_payload_data_;
446 std::string death_topic_str_;
447 MQTTAsync_willOptions will_opts_;
448 MQTTAsync_SSLOptions ssl_opts_{};
452 detail::SecureBuffer password_;
453 detail::SecureBuffer tls_key_password_;
456 std::vector<uint8_t> last_birth_payload_;
460 using is_transparent = void;
461 [[nodiscard]]
size_t operator()(std::string_view sv)
const noexcept {
462 return std::hash<std::string_view>{}(sv);
467 using is_transparent = void;
468 [[nodiscard]]
bool operator()(std::string_view lhs,
469 std::string_view rhs)
const noexcept {
475 std::unordered_map<std::string, DeviceState, StringHash, StringEqual> device_states_;
477 std::atomic<bool> is_connected_{
false};
478 std::atomic<bool> primary_host_online_{
482 mutable std::mutex mutex_;
486 void adopt_secrets();
488 [[nodiscard]]
static stdx::expected<void, std::string>
489 publish_message(MQTTAsync client,
490 const std::string& topic_str,
491 std::span<const uint8_t> payload_data,
496 static int on_message_arrived(
void* context,
499 MQTTAsync_message* message);
502 static void on_connection_lost(
void* context,
char* cause);
Sparkplug B Edge Node implementing the complete message lifecycle.
stdx::expected< void, std::string > connect()
Connects to the MQTT broker and establishes a Sparkplug B session.
~EdgeNode()
Destroys the EdgeNode and cleans up MQTT resources.
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.
stdx::expected< void, std::string > publish_node_command(std::string_view target_edge_node_id, PayloadBuilder &payload)
Publishes an NCMD (Node Command) message to another edge node.
stdx::expected< void, std::string > publish_death()
Publishes an NDEATH (Node Death) message.
stdx::expected< void, std::string > publish_device_death(std::string_view device_id)
Publishes a DDEATH (Device Death) message.
bool is_primary_host_online() const
Checks if the primary host application is online.
stdx::expected< void, std::string > publish_data(PayloadBuilder &payload)
Publishes an NDATA (Node Data) message.
uint64_t get_seq() const
Gets the current message sequence number.
stdx::expected< void, std::string > publish_device_data(std::string_view device_id, PayloadBuilder &payload)
Publishes a DDATA (Device Data) message.
stdx::expected< void, std::string > disconnect()
Gracefully disconnects from the MQTT broker.
stdx::expected< void, std::string > rebirth()
Triggers a rebirth by publishing a new NBIRTH with incremented bdSeq.
stdx::expected< void, std::string > publish_device_command(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 another edge node.
uint64_t get_bd_seq() const
Gets the current birth/death sequence number.
stdx::expected< void, std::string > publish_birth(PayloadBuilder &payload)
Publishes an NBIRTH (Node Birth) message.
EdgeNode(Config config)
Constructs an EdgeNode with the given configuration.
stdx::expected< void, std::string > publish_device_birth(std::string_view device_id, PayloadBuilder &payload)
Publishes a DBIRTH (Device Birth) message.
Type-safe builder for Sparkplug B payloads with automatic type detection.
Configuration parameters for the Sparkplug B Edge Node.
std::string client_id
Unique MQTT client identifier.
int keep_alive_interval
MQTT keep-alive interval in seconds (Sparkplug recommends 60)
bool clean_session
MQTT clean session flag.
int death_qos
MQTT QoS for NDEATH Will Message. Sparkplug requires 1.
std::string group_id
Sparkplug group ID (topic namespace)
std::optional< TlsOptions > tls
TLS/SSL options (required if broker_url uses ssl://)
int data_qos
MQTT QoS for data messages (NBIRTH/NDATA/DBIRTH/DDATA).
std::optional< std::string > password
MQTT password for authentication (optional)
std::optional< std::string > username
MQTT username for authentication (optional)
std::string broker_url
MQTT broker URL (e.g., "tcp://localhost:1883" or "ssl://localhost:8883")
std::string edge_node_id
Edge node identifier within the group.
size_t max_payload_bytes
Max accepted inbound payload size; larger messages are dropped (default 1 MiB, CWE-400)
TLS/SSL configuration options for secure MQTT connections.
std::string private_key_password
Password for encrypted private key (optional)
std::string private_key
Path to client private key file (PEM format, optional)
std::string trust_store
Path to CA certificate file (PEM format)
bool verify_hostname
Verify certificate identity matches broker_url host (default: true)
std::string key_store
Path to client certificate file (PEM format, optional)
bool enable_server_cert_auth
Verify server certificate (default: true)
std::string enabled_cipher_suites
Colon-separated list of cipher suites (optional)