3#include "../platform/tims_wrapper.hpp"
4#include "../messages.hpp"
5#include "../messaging/message_registry.hpp"
6#include "../messaging/message_id.hpp"
7#include "../platform/threading.hpp"
49 return "Unknown error";
59 std::optional<T> value_;
60 std::optional<MailboxError> error_;
70 explicit operator bool()
const {
return value_.has_value(); }
71 bool has_value()
const {
return value_.has_value(); }
81 T&
value() & {
return *value_; }
82 const T&
value() const & {
return *value_; }
83 T&&
value() && {
return std::move(*value_); }
93 std::optional<MailboxError> error_;
107 explicit operator bool()
const {
return !error_.has_value(); }
176template<
typename... MessageDefs>
184 struct is_message_definition : std::false_type {};
186 template<
typename PayloadT, MessagePrefix Prefix, auto SubPrefix, u
int16_t ID>
187 struct is_message_definition<
MessageDefinition<PayloadT, Prefix, SubPrefix, ID>> : std::true_type {};
190 static_assert((is_message_definition<MessageDefs>::value && ...),
191 "All template parameters must be MessageDefinition types");
204 , tims_(create_tims_config(config))
221 : config_(std::move(other.config_))
222 , tims_(std::move(other.tims_))
223 , running_(other.running_.load()) {
224 other.running_ =
false;
228 if (
this != &other) {
230 config_ = std::move(other.config_);
231 tims_ = std::move(other.tims_);
232 running_ = other.running_.load();
233 other.running_ =
false;
289 if constexpr (
requires {
typename T::payload_type; }) {
290 return Registry::template is_registered<typename T::payload_type>;
292 return Registry::template is_registered<T>;
300 return sizeof...(MessageDefs);
316 requires is_registered<T>
322 if (dest_mailbox == 0) {
330 auto tims_result = tims_.
send(message, dest_mailbox);
333 std::cerr <<
"[Mailbox] TiMS send failed with code: " <<
static_cast<int>(tims_result) << std::endl;
351 requires is_registered<T>
359 typename sertial::Message<TimsMessage<T>>::buffer_type buffer;
368 std::span<const std::byte>(buffer.data(), bytes)
375 return std::move(*result);
385 requires is_registered<T>
389 auto result = receive_for<T>(std::chrono::milliseconds(-1));
404 requires is_registered<T>
412 typename sertial::Message<TimsMessage<T>>::buffer_type buffer;
425 std::span<const std::byte>(buffer.data(), bytes)
432 return std::move(*result);
444 auto receive_any_raw(std::chrono::milliseconds timeout = std::chrono::milliseconds{-1})
452 std::array<std::byte, buffer_size> buffer;
456 if (timeout.count() == -1 || timeout == std::chrono::milliseconds{0}) {
464 if (
static_cast<size_t>(bytes) <
sizeof(TimsHeader)) {
469 std::memcpy(&header, buffer.data(),
sizeof(TimsHeader));
472 uint32_t sender_id = 0;
475 RawReceivedMessage raw;
476 raw.buffer = std::vector<std::byte>(buffer.begin(), buffer.begin() + bytes);
477 raw.type =
static_cast<int32_t
>(header.msg_type);
478 raw.sender_id = sender_id;
480 raw.timestamp = header.timestamp;
481 raw.header.msg_type = header.msg_type;
505 template<
typename Visitor>
514 std::array<std::byte, buffer_size> buffer;
522 if (
static_cast<size_t>(bytes) <
sizeof(
TimsHeader)) {
527 std::memcpy(&header, buffer.data(),
sizeof(
TimsHeader));
532 std::span<const std::byte>(buffer.data(), bytes),
533 [&visitor](
auto&& tims_msg) {
535 std::forward<Visitor>(visitor)(std::forward<decltype(tims_msg)>(tims_msg));
561 std::array<std::byte, buffer_size> buffer;
596 ? (
"mailbox_" + std::to_string(config.
mailbox_id))
597 : config.mailbox_name;
604 MailboxConfig config_;
606 std::atomic<bool> running_;
628template<
typename... CustomTypes>
MailboxResult(MailboxError error)
static MailboxResult< void > error(MailboxError err)
static MailboxResult< void > ok()
MailboxError get_error() const
MailboxResult(MailboxError error)
const T & operator*() const &
const T & value() const &
const T * operator->() const
MailboxError error() const
Strongly-typed mailbox for message-based communication.
auto receive_any(Visitor &&visitor) -> MailboxResult< void >
Receive any registered message type using a visitor.
static constexpr bool is_registered
Check if a type is registered with this mailbox at compile time For TimsMessage<PayloadT>,...
auto receive() -> MailboxResult< TimsMessage< T > >
Receive a message of specific type (blocking)
bool is_running() const
Check if mailbox is running.
uint64_t messages_received() const
Get number of messages received.
uint32_t mailbox_id() const
Get the mailbox ID.
Mailbox(Mailbox &&other) noexcept
auto send(T &message, uint32_t dest_mailbox) -> MailboxResult< void >
Send a message to a destination mailbox.
Mailbox & operator=(Mailbox &&other) noexcept
~Mailbox()
Destructor - automatically stops and cleans up.
Mailbox(const MailboxConfig &config)
Construct a mailbox with the given configuration.
void stop()
Stop the mailbox.
Mailbox & operator=(const Mailbox &)=delete
auto receive_any_raw(std::chrono::milliseconds timeout=std::chrono::milliseconds{-1}) -> MailboxResult< RawReceivedMessage >
Receive any message without knowing its type.
auto start() -> MailboxResult< void >
Start the mailbox (initialize TiMS connection)
Mailbox(const Mailbox &)=delete
auto clean() -> MailboxResult< void >
Clear all pending messages from the mailbox.
static constexpr size_t num_message_types()
Get number of registered message types.
auto try_receive() -> std::optional< TimsMessage< T > >
Try to receive a message without blocking.
uint64_t messages_sent() const
Get number of messages sent.
auto receive_for(std::chrono::milliseconds timeout) -> MailboxResult< TimsMessage< T > >
Receive a message with timeout.
static auto serialize(T &message)
Serialize a message with automatic type registration check.
static constexpr size_t max_message_size
static bool visit(uint32_t msg_id, std::span< const std::byte > data, Visitor &&visitor)
Visit a message by its message ID using a visitor.
uint64_t get_messages_sent() const
uint64_t get_messages_received() const
ssize_t receive_raw_bytes(std::span< std::byte > buffer, Milliseconds timeout)
TimsResult send(T &message, uint32_t dest_mailbox_id)
CommRaT - Modern C++ Real-Time Communication Framework.
TimsMessage< SensorPayload > SensorMessage
TimsMessage< ErrorPayload > ErrorMessage
constexpr const char * to_string(MailboxError error)
TimsMessage< AckPayload > AckMessage
TimsMessage< StatusPayload > StatusMessage
auto deserialize(std::span< const std::byte > data) -> sertial::DeserializeResult< T >
TimsMessage< CommandPayload > CommandMessage
Message definition with compile-time ID assignment.
Raw received message with type info.
std::vector< std::byte > buffer
struct commrat::RawReceivedMessage::@0 header