3#include "detail/compat.hpp"
5#include "mqtt_handle.hpp"
6#include "payload_builder.hpp"
7#include "sparkplug_b.pb.h"
16#include <unordered_map>
29using CommandCallback =
30 std::function<void(
const Topic&,
const org::eclipse::tahu::protobuf::Payload&)>;
126 std::optional<TlsOptions>
128 std::optional<std::string>
130 std::optional<std::string>
132 std::optional<CommandCallback> command_callback{};
133 std::optional<std::string> primary_host_id{};
134 std::optional<LogCallback> log_callback{};
166 std::optional<std::
string> password);
178 void set_log_callback(std::optional<LogCallback> callback);
192 [[nodiscard]] stdx::expected<
void, std::
string>
connect();
203 [[nodiscard]] stdx::expected<
void, std::
string>
disconnect();
277 [[nodiscard]] stdx::expected<
void, std::
string>
rebirth();
287 std::scoped_lock lock(mutex_);
299 std::scoped_lock lock(mutex_);
313 std::scoped_lock lock(mutex_);
314 return primary_host_online_;
335 [[nodiscard]] stdx::expected<void, std::string>
357 [[nodiscard]] stdx::expected<void, std::string>
371 [[nodiscard]] stdx::expected<void, std::string>
399 [[nodiscard]] stdx::expected<void, std::string>
420 [[nodiscard]] stdx::expected<void, std::string>
422 std::string_view target_device_id,
425 void log(LogLevel level, std::string_view message)
const noexcept;
432 std::vector<uint8_t> last_birth_payload;
433 bool is_online{
false};
437 MQTTAsyncHandle client_;
438 uint64_t seq_num_{0};
439 uint64_t bd_seq_num_{0};
442 std::vector<uint8_t> death_payload_data_;
443 std::string death_topic_str_;
444 MQTTAsync_willOptions will_opts_;
445 MQTTAsync_SSLOptions ssl_opts_{};
448 std::vector<uint8_t> last_birth_payload_;
452 using is_transparent = void;
453 [[nodiscard]]
size_t operator()(std::string_view sv)
const noexcept {
454 return std::hash<std::string_view>{}(sv);
459 using is_transparent = void;
460 [[nodiscard]]
bool operator()(std::string_view lhs,
461 std::string_view rhs)
const noexcept {
467 std::unordered_map<std::string, DeviceState, StringHash, StringEqual> device_states_;
469 bool is_connected_{
false};
470 bool primary_host_online_{
474 mutable std::mutex mutex_;
476 [[nodiscard]]
static stdx::expected<void, std::string>
477 publish_message(MQTTAsync client,
478 const std::string& topic_str,
479 std::span<const uint8_t> payload_data,
484 static int on_message_arrived(
void* context,
487 MQTTAsync_message* message);
490 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.
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)
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)