From d9d82202ed970ded3833600308ac27123d3866be Mon Sep 17 00:00:00 2001 From: Juan Lopez Fernandez Date: Thu, 9 Jan 2025 09:03:55 +0100 Subject: [PATCH 01/28] DDS data publication implementation Signed-off-by: Juan Lopez Fernandez --- ddsenabler/include/ddsenabler/DDSEnabler.hpp | 42 +- .../include/ddsenabler/dds_enabler_runner.hpp | 16 +- ddsenabler/src/cpp/DDSEnabler.cpp | 23 +- ddsenabler/src/cpp/dds_enabler_runner.cpp | 15 +- .../test/ddsEnablerTests/DdsEnablerTest.cpp | 2 +- .../ddsenabler_participants/CBCallbacks.hpp | 23 +- .../ddsenabler_participants/CBHandler.hpp | 65 ++- .../ddsenabler_participants/CBWriter.hpp | 30 +- .../DdsParticipant.hpp | 46 ++ .../EnablerParticipant.hpp | 83 +++ .../EnablerParticipantConfiguration.hpp | 49 ++ .../ddsenabler_participants/constants.hpp | 33 ++ .../ddsenabler_participants/serialization.hpp | 82 +++ .../DynamicTypesCollection.hpp | 431 ++++++++++++++ .../DynamicTypesCollection.idl | 19 + .../DynamicTypesCollectionPubSubTypes.hpp | 213 +++++++ ...ynamicTypesCollectionTypeObjectSupport.hpp | 78 +++ ddsenabler_participants/src/cpp/CBHandler.cpp | 208 ++++++- ddsenabler_participants/src/cpp/CBWriter.cpp | 155 +++-- .../src/cpp/DdsParticipant.cpp | 53 ++ .../src/cpp/EnablerParticipant.cpp | 161 ++++++ .../src/cpp/serialization.cpp | 529 ++++++++++++++++++ .../DynamicTypesCollectionCdrAux.hpp | 53 ++ .../DynamicTypesCollectionCdrAux.ipp | 234 ++++++++ .../DynamicTypesCollectionPubSubTypes.cxx | 409 ++++++++++++++ ...ynamicTypesCollectionTypeObjectSupport.cxx | 282 ++++++++++ .../ddsenabler_yaml/EnablerConfiguration.hpp | 5 +- .../yaml_configuration_tags.hpp | 1 + .../src/cpp/EnablerConfiguration.cpp | 12 +- docs/context_broker_interface.rst | 2 + 30 files changed, 3203 insertions(+), 151 deletions(-) create mode 100644 ddsenabler_participants/include/ddsenabler_participants/DdsParticipant.hpp create mode 100644 ddsenabler_participants/include/ddsenabler_participants/EnablerParticipant.hpp create mode 100644 ddsenabler_participants/include/ddsenabler_participants/EnablerParticipantConfiguration.hpp create mode 100644 ddsenabler_participants/include/ddsenabler_participants/constants.hpp create mode 100644 ddsenabler_participants/include/ddsenabler_participants/serialization.hpp create mode 100644 ddsenabler_participants/include/ddsenabler_participants/types/dynamic_types_collection/DynamicTypesCollection.hpp create mode 100644 ddsenabler_participants/include/ddsenabler_participants/types/dynamic_types_collection/DynamicTypesCollection.idl create mode 100644 ddsenabler_participants/include/ddsenabler_participants/types/dynamic_types_collection/DynamicTypesCollectionPubSubTypes.hpp create mode 100644 ddsenabler_participants/include/ddsenabler_participants/types/dynamic_types_collection/DynamicTypesCollectionTypeObjectSupport.hpp create mode 100644 ddsenabler_participants/src/cpp/DdsParticipant.cpp create mode 100644 ddsenabler_participants/src/cpp/EnablerParticipant.cpp create mode 100644 ddsenabler_participants/src/cpp/serialization.cpp create mode 100644 ddsenabler_participants/src/cpp/types/dynamic_types_collection/DynamicTypesCollectionCdrAux.hpp create mode 100644 ddsenabler_participants/src/cpp/types/dynamic_types_collection/DynamicTypesCollectionCdrAux.ipp create mode 100644 ddsenabler_participants/src/cpp/types/dynamic_types_collection/DynamicTypesCollectionPubSubTypes.cxx create mode 100644 ddsenabler_participants/src/cpp/types/dynamic_types_collection/DynamicTypesCollectionTypeObjectSupport.cxx diff --git a/ddsenabler/include/ddsenabler/DDSEnabler.hpp b/ddsenabler/include/ddsenabler/DDSEnabler.hpp index 3489c391..de613138 100644 --- a/ddsenabler/include/ddsenabler/DDSEnabler.hpp +++ b/ddsenabler/include/ddsenabler/DDSEnabler.hpp @@ -19,7 +19,6 @@ #pragma once #include -#include #include #include @@ -33,11 +32,11 @@ #include #include -#include -#include - +#include #include #include +#include +#include #include @@ -68,13 +67,31 @@ class DDSEnabler void set_data_callback( participants::DdsNotification callback) { - cb_handler_.get()->set_data_callback(callback); + cb_handler_->set_data_callback(callback); } void set_type_callback( participants::DdsTypeNotification callback) { - cb_handler_.get()->set_type_callback(callback); + cb_handler_->set_type_callback(callback); + } + + void set_topic_callback( + participants::DdsTopicNotification callback) + { + cb_handler_->set_topic_callback(callback); + } + + void set_topic_request_callback( + participants::DdsTopicRequest callback) + { + enabler_participant_->set_topic_request_callback(callback); + } + + void set_type_request_callback( + participants::DdsTypeRequest callback) + { + cb_handler_->set_type_request_callback(callback); } /** @@ -99,6 +116,11 @@ class DDSEnabler utils::ReturnCode reload_configuration( yaml::EnablerConfiguration& new_configuration); + // TODO + bool publish( + const std::string& topic_name, + const std::string& json); + protected: /** @@ -127,11 +149,11 @@ class DDSEnabler //! CB Handler std::shared_ptr cb_handler_; - //! Dynamic Types Participant - std::shared_ptr dyn_participant_; + //! DDS Participant + std::shared_ptr dds_participant_; - //! Schema Participant - std::shared_ptr enabler_participant_; + //! Enabler Participant + std::shared_ptr enabler_participant_; //! DDS Pipe std::unique_ptr pipe_; diff --git a/ddsenabler/include/ddsenabler/dds_enabler_runner.hpp b/ddsenabler/include/ddsenabler/dds_enabler_runner.hpp index e3236031..e0186f9c 100644 --- a/ddsenabler/include/ddsenabler/dds_enabler_runner.hpp +++ b/ddsenabler/include/ddsenabler/dds_enabler_runner.hpp @@ -19,25 +19,25 @@ #pragma once +#include + +#include +#include #include #include #include #include #include #include -#include -#include + +#include #include #include -#include #include "ddsenabler/DDSEnabler.hpp" -using namespace eprosima::ddspipe; -using namespace eprosima::ddsenabler; - namespace eprosima { namespace ddsenabler { @@ -45,9 +45,11 @@ bool create_dds_enabler( const char* ddsEnablerConfigFile, participants::DdsNotification data_callback, participants::DdsTypeNotification type_callback, + participants::DdsTopicNotification topic_callback, + participants::DdsTypeRequest type_req_callback, + participants::DdsTopicRequest topic_req_callback, participants::DdsLogFunc log_callback, std::unique_ptr& enabler); - } /* namespace ddsenabler */ } /* namespace eprosima */ diff --git a/ddsenabler/src/cpp/DDSEnabler.cpp b/ddsenabler/src/cpp/DDSEnabler.cpp index fae299f1..0ed209f7 100644 --- a/ddsenabler/src/cpp/DDSEnabler.cpp +++ b/ddsenabler/src/cpp/DDSEnabler.cpp @@ -12,10 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include -#include - -#include #include #include @@ -53,12 +49,12 @@ DDSEnabler::DDSEnabler( // Create CB Handler configuration participants::CBHandlerConfiguration handler_config; - // Create DynTypes Participant - dyn_participant_ = std::make_shared( + // Create DDS Participant + dds_participant_ = std::make_shared( configuration_.simple_configuration, payload_pool_, discovery_database_); - dyn_participant_->init(); + dds_participant_->init(); // Create CB Handler cb_handler_ = std::make_shared( @@ -66,7 +62,7 @@ DDSEnabler::DDSEnabler( payload_pool_); // Create Enabler Participant - enabler_participant_ = std::make_shared( + enabler_participant_ = std::make_shared( configuration_.enabler_configuration, payload_pool_, discovery_database_, @@ -77,8 +73,8 @@ DDSEnabler::DDSEnabler( // Populate Participant Database participants_database_->add_participant( - dyn_participant_->id(), - dyn_participant_); + dds_participant_->id(), + dds_participant_); participants_database_->add_participant( enabler_participant_->id(), @@ -176,5 +172,12 @@ void DDSEnabler::load_internal_topics_( } } +bool DDSEnabler::publish( + const std::string& topic_name, + const std::string& json) +{ + return enabler_participant_->publish(topic_name, json); +} + } /* namespace ddsenabler */ } /* namespace eprosima */ diff --git a/ddsenabler/src/cpp/dds_enabler_runner.cpp b/ddsenabler/src/cpp/dds_enabler_runner.cpp index 551b30c0..f1380616 100644 --- a/ddsenabler/src/cpp/dds_enabler_runner.cpp +++ b/ddsenabler/src/cpp/dds_enabler_runner.cpp @@ -17,14 +17,15 @@ * */ -#include #include -#include "fastdds/dds/log/FileConsumer.hpp" +#include +#include -#include "ddsenabler/dds_enabler_runner.hpp" +#include +#include -#include +#include "ddsenabler/dds_enabler_runner.hpp" using namespace eprosima::ddspipe; @@ -35,6 +36,9 @@ bool create_dds_enabler( const char* ddsEnablerConfigFile, participants::DdsNotification data_callback, participants::DdsTypeNotification type_callback, + participants::DdsTopicNotification topic_callback, + participants::DdsTypeRequest type_req_callback, + participants::DdsTopicRequest topic_req_callback, participants::DdsLogFunc log_callback, std::unique_ptr& enabler) { @@ -103,6 +107,9 @@ bool create_dds_enabler( // TODO: avoid setting callback after having created "enabled" enabler (e.g. pass and set in construction) enabler->set_data_callback(data_callback); enabler->set_type_callback(type_callback); + enabler->set_topic_callback(topic_callback); + enabler->set_type_request_callback(type_req_callback); + enabler->set_topic_request_callback(topic_req_callback); // Set the file watcher to reload the configuration if the file changes if (!enabler->set_file_watcher(dds_enabler_config_file)) diff --git a/ddsenabler/test/ddsEnablerTests/DdsEnablerTest.cpp b/ddsenabler/test/ddsEnablerTests/DdsEnablerTest.cpp index 1eab3927..9ce08a83 100644 --- a/ddsenabler/test/ddsEnablerTests/DdsEnablerTest.cpp +++ b/ddsenabler/test/ddsEnablerTests/DdsEnablerTest.cpp @@ -44,7 +44,7 @@ TEST_F(DDSEnablerTest, ddsenabler_reload_configuration) eprosima::utils::Formatter error_msg; ASSERT_TRUE(configuration.is_valid(error_msg)); - ASSERT_NO_THROW(enabler.get()->reload_configuration(configuration)); + ASSERT_NO_THROW(enabler->reload_configuration(configuration)); } TEST_F(DDSEnablerTest, send_type1) diff --git a/ddsenabler_participants/include/ddsenabler_participants/CBCallbacks.hpp b/ddsenabler_participants/include/ddsenabler_participants/CBCallbacks.hpp index 8e88c4f6..48992c1b 100644 --- a/ddsenabler_participants/include/ddsenabler_participants/CBCallbacks.hpp +++ b/ddsenabler_participants/include/ddsenabler_participants/CBCallbacks.hpp @@ -39,18 +39,37 @@ typedef void (*DdsLogFunc)( */ typedef void (*DdsTypeNotification)( const char* typeName, + const char* serializedType, + const unsigned char* serializedTypeInternal, + uint32_t serializedTypeInternalSize, + const char* dataPlaceholder); + +/** + * DdsTopicNotification - callback for reception of DDS topics + */ +typedef void (*DdsTopicNotification)( const char* topicName, - const char* serializedType); + const char* typeName, + const char* serializedQos); /** * DdsNotification - callback for reception of DDS data */ typedef void (*DdsNotification)( - const char* typeName, const char* topicName, const char* json, int64_t publishTime); +// TODO: return a boolean in request callbacks? should nevertheless handle malformed strings passed by user +typedef void (*DdsTopicRequest)( + const char* topicName, + char*& typeName, // TODO: better pass unique_ptr by ref? Then the user would allocate resources but will always have its ownership + char*& serializedQos); + +typedef void (*DdsTypeRequest)( + const char* typeName, + unsigned char*& serializedTypeInternal, + uint32_t& serializedTypeInternalSize); } /* namespace participants */ } /* namespace ddsenabler */ diff --git a/ddsenabler_participants/include/ddsenabler_participants/CBHandler.hpp b/ddsenabler_participants/include/ddsenabler_participants/CBHandler.hpp index 317708cb..af552d13 100644 --- a/ddsenabler_participants/include/ddsenabler_participants/CBHandler.hpp +++ b/ddsenabler_participants/include/ddsenabler_participants/CBHandler.hpp @@ -18,13 +18,11 @@ #pragma once -#include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include #include #include @@ -33,6 +31,7 @@ #include +#include #include #include #include @@ -60,7 +59,7 @@ namespace ddsenabler { namespace participants { /** - * Class that manages the interaction between DDS Pipe \c (SchemaParticipant) and CB. + * Class that manages the interaction between \c EnablerParticipant and CB. * Payloads are efficiently passed from DDS Pipe to CB without copying data (only references). * * @implements ISchemaHandler @@ -101,6 +100,11 @@ class CBHandler : public ddspipe::participants::ISchemaHandler const fastdds::dds::DynamicType::_ref_type& dyn_type, const fastdds::dds::xtypes::TypeIdentifier& type_id) override; + // TODO + DDSENABLER_PARTICIPANTS_DllAPI + void add_topic( + const ddspipe::core::types::DdsTopic& topic); + /** * @brief Add a data sample, associated to the given \c topic. * @@ -114,33 +118,70 @@ class CBHandler : public ddspipe::participants::ISchemaHandler const ddspipe::core::types::DdsTopic& topic, ddspipe::core::types::RtpsPayloadData& data) override; + DDSENABLER_PARTICIPANTS_DllAPI + bool get_type_identifier( + const std::string& type_name, + fastdds::dds::xtypes::TypeIdentifier& type_identifier); + + DDSENABLER_PARTICIPANTS_DllAPI + bool get_serialized_data( + const std::string& type_name, + const std::string& json, + ddspipe::core::types::Payload& payload); DDSENABLER_PARTICIPANTS_DllAPI void set_data_callback( participants::DdsNotification callback) { - cb_writer_.get()->set_data_callback(callback); + cb_writer_->set_data_callback(callback); + } + + DDSENABLER_PARTICIPANTS_DllAPI + void set_topic_callback( + participants::DdsTopicNotification callback) + { + cb_writer_->set_topic_callback(callback); } DDSENABLER_PARTICIPANTS_DllAPI void set_type_callback( participants::DdsTypeNotification callback) { - cb_writer_.get()->set_type_callback(callback); + cb_writer_->set_type_callback(callback); + } + + DDSENABLER_PARTICIPANTS_DllAPI + void set_type_request_callback( + participants::DdsTypeRequest callback) + { + type_req_callback_ = callback; } protected: + void write_schema_( + const fastdds::dds::DynamicType::_ref_type& dyn_type, + const fastdds::dds::xtypes::TypeIdentifier& type_id); + + void write_topic_( + const ddspipe::core::types::DdsTopic& topic); + /** * @brief Write to CB. * * @param [in] msg CBMessage to be added * @param [in] dyn_type DynamicType containing the type information required. */ - void write_sample( + void write_sample_( const CBMessage& msg, const fastdds::dds::DynamicType::_ref_type& dyn_type); + bool register_type_nts_( + const std::string& type_name, + const unsigned char* serialized_type, + uint32_t serialized_type_size, + fastdds::dds::xtypes::TypeIdentifier& type_identifier); + //! Handler configuration CBHandlerConfiguration configuration_; @@ -151,13 +192,15 @@ class CBHandler : public ddspipe::participants::ISchemaHandler std::unique_ptr cb_writer_; //! Schemas map - std::unordered_map schemas_; + std::unordered_map> schemas_; //! Unique sequence number assigned to received messages. It is incremented with every sample added unsigned int unique_sequence_number_{0}; //! Mutex synchronizing access to object's data structures std::mutex mtx_; + + DdsTypeRequest type_req_callback_; }; } /* namespace participants */ diff --git a/ddsenabler_participants/include/ddsenabler_participants/CBWriter.hpp b/ddsenabler_participants/include/ddsenabler_participants/CBWriter.hpp index cf1e607e..0e9c3b59 100644 --- a/ddsenabler_participants/include/ddsenabler_participants/CBWriter.hpp +++ b/ddsenabler_participants/include/ddsenabler_participants/CBWriter.hpp @@ -18,15 +18,11 @@ #pragma once -#include - #include #include -#include #include -#include #include #include @@ -61,6 +57,19 @@ class CBWriter type_callback_ = callback; } + void set_topic_callback( + DdsTopicNotification callback) + { + topic_callback_ = callback; + } + + void write_schema( + const fastdds::dds::DynamicType::_ref_type& dyn_type, + const fastdds::dds::xtypes::TypeIdentifier& type_id); + + void write_topic( + const ddspipe::core::types::DdsTopic& topic); + /** * @brief Writes data. * @@ -80,8 +89,7 @@ class CBWriter * @param [in] msg Pointer to the data. * @param [in] dyn_type DynamicType containing the type information required. */ - DDSENABLER_PARTICIPANTS_DllAPI - void write_schema( + void write_schema_( const CBMessage& msg, const fastdds::dds::DynamicType::_ref_type& dyn_type); @@ -91,20 +99,14 @@ class CBWriter * @param [in] msg Pointer to the data. * @param [in] dyn_type DynamicType containing the type information required. */ - DDSENABLER_PARTICIPANTS_DllAPI - fastdds::dds::DynamicData::_ref_type get_dynamic_data( + fastdds::dds::DynamicData::_ref_type get_dynamic_data_( const CBMessage& msg, const fastdds::dds::DynamicType::_ref_type& dyn_type) noexcept; - //! Schemas map - std::unordered_map stored_schemas_; - - // The mutex to protect the calls to write - std::mutex mutex_; - // Callbacks to notify the CB DdsNotification data_callback_; DdsTypeNotification type_callback_; + DdsTopicNotification topic_callback_; }; } /* namespace participants */ diff --git a/ddsenabler_participants/include/ddsenabler_participants/DdsParticipant.hpp b/ddsenabler_participants/include/ddsenabler_participants/DdsParticipant.hpp new file mode 100644 index 00000000..a75be37d --- /dev/null +++ b/ddsenabler_participants/include/ddsenabler_participants/DdsParticipant.hpp @@ -0,0 +1,46 @@ +// Copyright 2024 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @file DdsParticipant.hpp + */ + +#pragma once + +#include + +#include + +namespace eprosima { +namespace ddsenabler { +namespace participants { + +class DdsParticipant : public ddspipe::participants::DynTypesParticipant +{ +public: + + DDSENABLER_PARTICIPANTS_DllAPI + DdsParticipant( + std::shared_ptr participant_configuration, + std::shared_ptr payload_pool, + std::shared_ptr discovery_database); + + DDSENABLER_PARTICIPANTS_DllAPI + std::shared_ptr create_writer( + const ddspipe::core::ITopic& topic) override; +}; + +} /* namespace participants */ +} /* namespace ddsenabler */ +} /* namespace eprosima */ diff --git a/ddsenabler_participants/include/ddsenabler_participants/EnablerParticipant.hpp b/ddsenabler_participants/include/ddsenabler_participants/EnablerParticipant.hpp new file mode 100644 index 00000000..fd31d994 --- /dev/null +++ b/ddsenabler_participants/include/ddsenabler_participants/EnablerParticipant.hpp @@ -0,0 +1,83 @@ +// Copyright 2024 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @file EnablerParticipant.hpp + */ + +#pragma once + +#include +#include +#include + +#include +#include + +#include +#include +#include + +namespace eprosima { +namespace ddsenabler { +namespace participants { + +class EnablerParticipant : public ddspipe::participants::SchemaParticipant +{ +public: + + DDSENABLER_PARTICIPANTS_DllAPI + EnablerParticipant( + std::shared_ptr participant_configuration, + std::shared_ptr payload_pool, + std::shared_ptr discovery_database, + std::shared_ptr schema_handler); + + DDSENABLER_PARTICIPANTS_DllAPI + std::shared_ptr create_reader( + const ddspipe::core::ITopic& topic) override; + + DDSENABLER_PARTICIPANTS_DllAPI + bool publish( + const std::string& topic_name, + const std::string& json); + + DDSENABLER_PARTICIPANTS_DllAPI + void set_topic_request_callback( + participants::DdsTopicRequest callback) + { + topic_req_callback_ = callback; + } + +protected: + + std::shared_ptr lookup_reader_nts_( + const std::string& topic_name, + std::string& type_name) const; + + std::shared_ptr lookup_reader_nts_( + const std::string& topic_name) const; + + std::map> readers_; + + std::mutex mtx_; + + std::condition_variable cv_; + + DdsTopicRequest topic_req_callback_; +}; + +} /* namespace participants */ +} /* namespace ddsenabler */ +} /* namespace eprosima */ diff --git a/ddsenabler_participants/include/ddsenabler_participants/EnablerParticipantConfiguration.hpp b/ddsenabler_participants/include/ddsenabler_participants/EnablerParticipantConfiguration.hpp new file mode 100644 index 00000000..9af09074 --- /dev/null +++ b/ddsenabler_participants/include/ddsenabler_participants/EnablerParticipantConfiguration.hpp @@ -0,0 +1,49 @@ +// Copyright 2024 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License\. + +#pragma once + +#include + +#include + +namespace eprosima { +namespace ddsenabler { +namespace participants { + +/** + * This data struct represents a configuration for a EnablerParticipant + */ +struct EnablerParticipantConfiguration : public ddspipe::participants::ParticipantConfiguration +{ +public: + + ///////////////////////// + // CONSTRUCTORS + ///////////////////////// + + DDSENABLER_PARTICIPANTS_DllAPI + EnablerParticipantConfiguration() = default; + + ///////////////////////// + // VARIABLES + ///////////////////////// + + DDSENABLER_PARTICIPANTS_DllAPI + unsigned int initial_publish_wait {0u}; +}; + +} /* namespace participants */ +} /* namespace ddspipe */ +} /* namespace eprosima */ diff --git a/ddsenabler_participants/include/ddsenabler_participants/constants.hpp b/ddsenabler_participants/include/ddsenabler_participants/constants.hpp new file mode 100644 index 00000000..133b9f9d --- /dev/null +++ b/ddsenabler_participants/include/ddsenabler_participants/constants.hpp @@ -0,0 +1,33 @@ +// Copyright 2024 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @file constants.hpp + */ + +#pragma once + +namespace eprosima { +namespace ddsenabler { +namespace participants { + +// QoS serialization +constexpr const char* QOS_SERIALIZATION_RELIABILITY("reliability"); +constexpr const char* QOS_SERIALIZATION_DURABILITY("durability"); +constexpr const char* QOS_SERIALIZATION_OWNERSHIP("ownership"); +constexpr const char* QOS_SERIALIZATION_KEYED("keyed"); + +} /* namespace participants */ +} /* namespace ddsenabler */ +} /* namespace eprosima */ diff --git a/ddsenabler_participants/include/ddsenabler_participants/serialization.hpp b/ddsenabler_participants/include/ddsenabler_participants/serialization.hpp new file mode 100644 index 00000000..7011d9d7 --- /dev/null +++ b/ddsenabler_participants/include/ddsenabler_participants/serialization.hpp @@ -0,0 +1,82 @@ +// Copyright 2024 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @file serialization.hpp + */ + +#pragma once + +#include +#include + +#include +#include + +#include + +#include + +namespace eprosima { +namespace ddsenabler { +namespace participants { +namespace serialization { + +/** + * @brief Serialize a \c TopicQoS struct into a string. + * + * @param [in] qos TopicQoS to be serialized + * @return Serialized TopicQoS string + */ +std::string serialize_qos( + const ddspipe::core::types::TopicQoS& qos); + +/** + * @brief Deserialize a serialized \c TopicQoS string. + * + * @param [in] qos_str Serialized \c TopicQoS string + * @return Deserialized TopicQoS + */ +ddspipe::core::types::TopicQoS deserialize_qos( + const std::string& qos_str); + +bool serialize_dynamic_type( + const std::string& type_name, + const fastdds::dds::xtypes::TypeIdentifier& type_identifier, + DynamicTypesCollection& dynamic_types); + +bool serialize_dynamic_type( + const fastdds::dds::xtypes::TypeIdentifier& type_identifier, + const fastdds::dds::xtypes::TypeObject& type_object, + const std::string& type_name, + DynamicTypesCollection& dynamic_types); + +bool deserialize_dynamic_type( + const DynamicType& dynamic_type, + std::string& type_name, + fastdds::dds::xtypes::TypeIdentifier& type_identifier, + fastdds::dds::xtypes::TypeObject& type_object); + +std::unique_ptr serialize_dynamic_types( + const DynamicTypesCollection& dynamic_types); + +bool deserialize_dynamic_types( + const unsigned char* dynamic_types_payload, + uint32_t dynamic_types_payload_size, + DynamicTypesCollection& dynamic_types); + +} /* namespace serialization */ +} /* namespace participants */ +} /* namespace ddsenabler */ +} /* namespace eprosima */ diff --git a/ddsenabler_participants/include/ddsenabler_participants/types/dynamic_types_collection/DynamicTypesCollection.hpp b/ddsenabler_participants/include/ddsenabler_participants/types/dynamic_types_collection/DynamicTypesCollection.hpp new file mode 100644 index 00000000..ff2c281c --- /dev/null +++ b/ddsenabler_participants/include/ddsenabler_participants/types/dynamic_types_collection/DynamicTypesCollection.hpp @@ -0,0 +1,431 @@ +// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*! + * @file DynamicTypesCollection.hpp + * This header file contains the declaration of the described types in the IDL file. + * + * This file was generated by the tool fastddsgen. + */ + +#ifndef FAST_DDS_GENERATED__EPROSIMA_DDSENABLER_PARTICIPANTS_DYNAMICTYPESCOLLECTION_HPP +#define FAST_DDS_GENERATED__EPROSIMA_DDSENABLER_PARTICIPANTS_DYNAMICTYPESCOLLECTION_HPP + +#include +#include +#include +#include + +#include + +#if defined(_WIN32) +#if defined(EPROSIMA_USER_DLL_EXPORT) +#define eProsima_user_DllExport __declspec( dllexport ) +#else +#define eProsima_user_DllExport +#endif // EPROSIMA_USER_DLL_EXPORT +#else +#define eProsima_user_DllExport +#endif // _WIN32 + +#if defined(_WIN32) +#if defined(EPROSIMA_USER_DLL_EXPORT) +#if defined(DYNAMICTYPESCOLLECTION_SOURCE) +#define DYNAMICTYPESCOLLECTION_DllAPI __declspec( dllexport ) +#else +#define DYNAMICTYPESCOLLECTION_DllAPI __declspec( dllimport ) +#endif // DYNAMICTYPESCOLLECTION_SOURCE +#else +#define DYNAMICTYPESCOLLECTION_DllAPI +#endif // EPROSIMA_USER_DLL_EXPORT +#else +#define DYNAMICTYPESCOLLECTION_DllAPI +#endif // _WIN32 + +namespace eprosima { + +namespace ddsenabler { + +namespace participants { + +/*! + * @brief This class represents the structure DynamicType defined by the user in the IDL file. + * @ingroup DynamicTypesCollection + */ +class DynamicType +{ +public: + + /*! + * @brief Default constructor. + */ + eProsima_user_DllExport DynamicType() + { + } + + /*! + * @brief Default destructor. + */ + eProsima_user_DllExport ~DynamicType() + { + } + + /*! + * @brief Copy constructor. + * @param x Reference to the object DynamicType that will be copied. + */ + eProsima_user_DllExport DynamicType( + const DynamicType& x) + { + m_type_name = x.m_type_name; + + m_type_identifier = x.m_type_identifier; + + m_type_object = x.m_type_object; + + } + + /*! + * @brief Move constructor. + * @param x Reference to the object DynamicType that will be copied. + */ + eProsima_user_DllExport DynamicType( + DynamicType&& x) noexcept + { + m_type_name = std::move(x.m_type_name); + m_type_identifier = std::move(x.m_type_identifier); + m_type_object = std::move(x.m_type_object); + } + + /*! + * @brief Copy assignment. + * @param x Reference to the object DynamicType that will be copied. + */ + eProsima_user_DllExport DynamicType& operator =( + const DynamicType& x) + { + + m_type_name = x.m_type_name; + + m_type_identifier = x.m_type_identifier; + + m_type_object = x.m_type_object; + + return *this; + } + + /*! + * @brief Move assignment. + * @param x Reference to the object DynamicType that will be copied. + */ + eProsima_user_DllExport DynamicType& operator =( + DynamicType&& x) noexcept + { + + m_type_name = std::move(x.m_type_name); + m_type_identifier = std::move(x.m_type_identifier); + m_type_object = std::move(x.m_type_object); + return *this; + } + + /*! + * @brief Comparison operator. + * @param x DynamicType object to compare. + */ + eProsima_user_DllExport bool operator ==( + const DynamicType& x) const + { + return (m_type_name == x.m_type_name && + m_type_identifier == x.m_type_identifier && + m_type_object == x.m_type_object); + } + + /*! + * @brief Comparison operator. + * @param x DynamicType object to compare. + */ + eProsima_user_DllExport bool operator !=( + const DynamicType& x) const + { + return !(*this == x); + } + + /*! + * @brief This function copies the value in member type_name + * @param _type_name New value to be copied in member type_name + */ + eProsima_user_DllExport void type_name( + const std::string& _type_name) + { + m_type_name = _type_name; + } + + /*! + * @brief This function moves the value in member type_name + * @param _type_name New value to be moved in member type_name + */ + eProsima_user_DllExport void type_name( + std::string&& _type_name) + { + m_type_name = std::move(_type_name); + } + + /*! + * @brief This function returns a constant reference to member type_name + * @return Constant reference to member type_name + */ + eProsima_user_DllExport const std::string& type_name() const + { + return m_type_name; + } + + /*! + * @brief This function returns a reference to member type_name + * @return Reference to member type_name + */ + eProsima_user_DllExport std::string& type_name() + { + return m_type_name; + } + + + /*! + * @brief This function copies the value in member type_identifier + * @param _type_identifier New value to be copied in member type_identifier + */ + eProsima_user_DllExport void type_identifier( + const std::string& _type_identifier) + { + m_type_identifier = _type_identifier; + } + + /*! + * @brief This function moves the value in member type_identifier + * @param _type_identifier New value to be moved in member type_identifier + */ + eProsima_user_DllExport void type_identifier( + std::string&& _type_identifier) + { + m_type_identifier = std::move(_type_identifier); + } + + /*! + * @brief This function returns a constant reference to member type_identifier + * @return Constant reference to member type_identifier + */ + eProsima_user_DllExport const std::string& type_identifier() const + { + return m_type_identifier; + } + + /*! + * @brief This function returns a reference to member type_identifier + * @return Reference to member type_identifier + */ + eProsima_user_DllExport std::string& type_identifier() + { + return m_type_identifier; + } + + + /*! + * @brief This function copies the value in member type_object + * @param _type_object New value to be copied in member type_object + */ + eProsima_user_DllExport void type_object( + const std::string& _type_object) + { + m_type_object = _type_object; + } + + /*! + * @brief This function moves the value in member type_object + * @param _type_object New value to be moved in member type_object + */ + eProsima_user_DllExport void type_object( + std::string&& _type_object) + { + m_type_object = std::move(_type_object); + } + + /*! + * @brief This function returns a constant reference to member type_object + * @return Constant reference to member type_object + */ + eProsima_user_DllExport const std::string& type_object() const + { + return m_type_object; + } + + /*! + * @brief This function returns a reference to member type_object + * @return Reference to member type_object + */ + eProsima_user_DllExport std::string& type_object() + { + return m_type_object; + } + + + +private: + + std::string m_type_name; + std::string m_type_identifier; + std::string m_type_object; + +}; +/*! + * @brief This class represents the structure DynamicTypesCollection defined by the user in the IDL file. + * @ingroup DynamicTypesCollection + */ +class DynamicTypesCollection +{ +public: + + /*! + * @brief Default constructor. + */ + eProsima_user_DllExport DynamicTypesCollection() + { + } + + /*! + * @brief Default destructor. + */ + eProsima_user_DllExport ~DynamicTypesCollection() + { + } + + /*! + * @brief Copy constructor. + * @param x Reference to the object DynamicTypesCollection that will be copied. + */ + eProsima_user_DllExport DynamicTypesCollection( + const DynamicTypesCollection& x) + { + m_dynamic_types = x.m_dynamic_types; + + } + + /*! + * @brief Move constructor. + * @param x Reference to the object DynamicTypesCollection that will be copied. + */ + eProsima_user_DllExport DynamicTypesCollection( + DynamicTypesCollection&& x) noexcept + { + m_dynamic_types = std::move(x.m_dynamic_types); + } + + /*! + * @brief Copy assignment. + * @param x Reference to the object DynamicTypesCollection that will be copied. + */ + eProsima_user_DllExport DynamicTypesCollection& operator =( + const DynamicTypesCollection& x) + { + + m_dynamic_types = x.m_dynamic_types; + + return *this; + } + + /*! + * @brief Move assignment. + * @param x Reference to the object DynamicTypesCollection that will be copied. + */ + eProsima_user_DllExport DynamicTypesCollection& operator =( + DynamicTypesCollection&& x) noexcept + { + + m_dynamic_types = std::move(x.m_dynamic_types); + return *this; + } + + /*! + * @brief Comparison operator. + * @param x DynamicTypesCollection object to compare. + */ + eProsima_user_DllExport bool operator ==( + const DynamicTypesCollection& x) const + { + return (m_dynamic_types == x.m_dynamic_types); + } + + /*! + * @brief Comparison operator. + * @param x DynamicTypesCollection object to compare. + */ + eProsima_user_DllExport bool operator !=( + const DynamicTypesCollection& x) const + { + return !(*this == x); + } + + /*! + * @brief This function copies the value in member dynamic_types + * @param _dynamic_types New value to be copied in member dynamic_types + */ + eProsima_user_DllExport void dynamic_types( + const std::vector& _dynamic_types) + { + m_dynamic_types = _dynamic_types; + } + + /*! + * @brief This function moves the value in member dynamic_types + * @param _dynamic_types New value to be moved in member dynamic_types + */ + eProsima_user_DllExport void dynamic_types( + std::vector&& _dynamic_types) + { + m_dynamic_types = std::move(_dynamic_types); + } + + /*! + * @brief This function returns a constant reference to member dynamic_types + * @return Constant reference to member dynamic_types + */ + eProsima_user_DllExport const std::vector& dynamic_types() const + { + return m_dynamic_types; + } + + /*! + * @brief This function returns a reference to member dynamic_types + * @return Reference to member dynamic_types + */ + eProsima_user_DllExport std::vector& dynamic_types() + { + return m_dynamic_types; + } + + + +private: + + std::vector m_dynamic_types; + +}; + +} // namespace participants + +} // namespace ddsenabler + +} // namespace eprosima + +#endif // _FAST_DDS_GENERATED_EPROSIMA_DDSENABLER_PARTICIPANTS_DYNAMICTYPESCOLLECTION_HPP_ + + diff --git a/ddsenabler_participants/include/ddsenabler_participants/types/dynamic_types_collection/DynamicTypesCollection.idl b/ddsenabler_participants/include/ddsenabler_participants/types/dynamic_types_collection/DynamicTypesCollection.idl new file mode 100644 index 00000000..c47ffe33 --- /dev/null +++ b/ddsenabler_participants/include/ddsenabler_participants/types/dynamic_types_collection/DynamicTypesCollection.idl @@ -0,0 +1,19 @@ +module eprosima { +module ddsenabler { +module participants { + +struct DynamicType +{ + string type_name; + string type_identifier; + string type_object; +}; + +struct DynamicTypesCollection +{ + sequence dynamic_types; +}; + +}; +}; +}; diff --git a/ddsenabler_participants/include/ddsenabler_participants/types/dynamic_types_collection/DynamicTypesCollectionPubSubTypes.hpp b/ddsenabler_participants/include/ddsenabler_participants/types/dynamic_types_collection/DynamicTypesCollectionPubSubTypes.hpp new file mode 100644 index 00000000..612a4984 --- /dev/null +++ b/ddsenabler_participants/include/ddsenabler_participants/types/dynamic_types_collection/DynamicTypesCollectionPubSubTypes.hpp @@ -0,0 +1,213 @@ +// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*! + * @file DynamicTypesCollectionPubSubTypes.hpp + * This header file contains the declaration of the serialization functions. + * + * This file was generated by the tool fastddsgen. + */ + + +#ifndef FAST_DDS_GENERATED__EPROSIMA_DDSENABLER_PARTICIPANTS_DYNAMICTYPESCOLLECTION_PUBSUBTYPES_HPP +#define FAST_DDS_GENERATED__EPROSIMA_DDSENABLER_PARTICIPANTS_DYNAMICTYPESCOLLECTION_PUBSUBTYPES_HPP + +#include +#include +#include +#include +#include + +#include "DynamicTypesCollection.hpp" + + +#if !defined(FASTDDS_GEN_API_VER) || (FASTDDS_GEN_API_VER != 3) +#error \ + Generated DynamicTypesCollection is not compatible with current installed Fast DDS. Please, regenerate it with fastddsgen. +#endif // FASTDDS_GEN_API_VER + +namespace eprosima +{ + namespace ddsenabler + { + namespace participants + { + + /*! + * @brief This class represents the TopicDataType of the type DynamicType defined by the user in the IDL file. + * @ingroup DynamicTypesCollection + */ + class DynamicTypePubSubType : public eprosima::fastdds::dds::TopicDataType + { + public: + + typedef DynamicType type; + + eProsima_user_DllExport DynamicTypePubSubType(); + + eProsima_user_DllExport ~DynamicTypePubSubType() override; + + eProsima_user_DllExport bool serialize( + const void* const data, + eprosima::fastdds::rtps::SerializedPayload_t& payload, + eprosima::fastdds::dds::DataRepresentationId_t data_representation) override; + + eProsima_user_DllExport bool deserialize( + eprosima::fastdds::rtps::SerializedPayload_t& payload, + void* data) override; + + eProsima_user_DllExport uint32_t calculate_serialized_size( + const void* const data, + eprosima::fastdds::dds::DataRepresentationId_t data_representation) override; + + eProsima_user_DllExport bool compute_key( + eprosima::fastdds::rtps::SerializedPayload_t& payload, + eprosima::fastdds::rtps::InstanceHandle_t& ihandle, + bool force_md5 = false) override; + + eProsima_user_DllExport bool compute_key( + const void* const data, + eprosima::fastdds::rtps::InstanceHandle_t& ihandle, + bool force_md5 = false) override; + + eProsima_user_DllExport void* create_data() override; + + eProsima_user_DllExport void delete_data( + void* data) override; + + //Register TypeObject representation in Fast DDS TypeObjectRegistry + eProsima_user_DllExport void register_type_object_representation() override; + + #ifdef TOPIC_DATA_TYPE_API_HAS_IS_BOUNDED + eProsima_user_DllExport inline bool is_bounded() const override + { + return false; + } + + #endif // TOPIC_DATA_TYPE_API_HAS_IS_BOUNDED + + #ifdef TOPIC_DATA_TYPE_API_HAS_IS_PLAIN + + eProsima_user_DllExport inline bool is_plain( + eprosima::fastdds::dds::DataRepresentationId_t data_representation) const override + { + static_cast(data_representation); + return false; + } + + #endif // TOPIC_DATA_TYPE_API_HAS_IS_PLAIN + + #ifdef TOPIC_DATA_TYPE_API_HAS_CONSTRUCT_SAMPLE + eProsima_user_DllExport inline bool construct_sample( + void* memory) const override + { + static_cast(memory); + return false; + } + + #endif // TOPIC_DATA_TYPE_API_HAS_CONSTRUCT_SAMPLE + + private: + + eprosima::fastdds::MD5 md5_; + unsigned char* key_buffer_; + + }; + + /*! + * @brief This class represents the TopicDataType of the type DynamicTypesCollection defined by the user in the IDL file. + * @ingroup DynamicTypesCollection + */ + class DynamicTypesCollectionPubSubType : public eprosima::fastdds::dds::TopicDataType + { + public: + + typedef DynamicTypesCollection type; + + eProsima_user_DllExport DynamicTypesCollectionPubSubType(); + + eProsima_user_DllExport ~DynamicTypesCollectionPubSubType() override; + + eProsima_user_DllExport bool serialize( + const void* const data, + eprosima::fastdds::rtps::SerializedPayload_t& payload, + eprosima::fastdds::dds::DataRepresentationId_t data_representation) override; + + eProsima_user_DllExport bool deserialize( + eprosima::fastdds::rtps::SerializedPayload_t& payload, + void* data) override; + + eProsima_user_DllExport uint32_t calculate_serialized_size( + const void* const data, + eprosima::fastdds::dds::DataRepresentationId_t data_representation) override; + + eProsima_user_DllExport bool compute_key( + eprosima::fastdds::rtps::SerializedPayload_t& payload, + eprosima::fastdds::rtps::InstanceHandle_t& ihandle, + bool force_md5 = false) override; + + eProsima_user_DllExport bool compute_key( + const void* const data, + eprosima::fastdds::rtps::InstanceHandle_t& ihandle, + bool force_md5 = false) override; + + eProsima_user_DllExport void* create_data() override; + + eProsima_user_DllExport void delete_data( + void* data) override; + + //Register TypeObject representation in Fast DDS TypeObjectRegistry + eProsima_user_DllExport void register_type_object_representation() override; + + #ifdef TOPIC_DATA_TYPE_API_HAS_IS_BOUNDED + eProsima_user_DllExport inline bool is_bounded() const override + { + return false; + } + + #endif // TOPIC_DATA_TYPE_API_HAS_IS_BOUNDED + + #ifdef TOPIC_DATA_TYPE_API_HAS_IS_PLAIN + + eProsima_user_DllExport inline bool is_plain( + eprosima::fastdds::dds::DataRepresentationId_t data_representation) const override + { + static_cast(data_representation); + return false; + } + + #endif // TOPIC_DATA_TYPE_API_HAS_IS_PLAIN + + #ifdef TOPIC_DATA_TYPE_API_HAS_CONSTRUCT_SAMPLE + eProsima_user_DllExport inline bool construct_sample( + void* memory) const override + { + static_cast(memory); + return false; + } + + #endif // TOPIC_DATA_TYPE_API_HAS_CONSTRUCT_SAMPLE + + private: + + eprosima::fastdds::MD5 md5_; + unsigned char* key_buffer_; + + }; + } // namespace participants + } // namespace ddsenabler +} // namespace eprosima + +#endif // FAST_DDS_GENERATED__EPROSIMA_DDSENABLER_PARTICIPANTS_DYNAMICTYPESCOLLECTION_PUBSUBTYPES_HPP + diff --git a/ddsenabler_participants/include/ddsenabler_participants/types/dynamic_types_collection/DynamicTypesCollectionTypeObjectSupport.hpp b/ddsenabler_participants/include/ddsenabler_participants/types/dynamic_types_collection/DynamicTypesCollectionTypeObjectSupport.hpp new file mode 100644 index 00000000..6d6c5471 --- /dev/null +++ b/ddsenabler_participants/include/ddsenabler_participants/types/dynamic_types_collection/DynamicTypesCollectionTypeObjectSupport.hpp @@ -0,0 +1,78 @@ +// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*! + * @file DynamicTypesCollectionTypeObjectSupport.hpp + * Header file containing the API required to register the TypeObject representation of the described types in the IDL file + * + * This file was generated by the tool fastddsgen. + */ + +#ifndef FAST_DDS_GENERATED__EPROSIMA_DDSENABLER_PARTICIPANTS_DYNAMICTYPESCOLLECTION_TYPE_OBJECT_SUPPORT_HPP +#define FAST_DDS_GENERATED__EPROSIMA_DDSENABLER_PARTICIPANTS_DYNAMICTYPESCOLLECTION_TYPE_OBJECT_SUPPORT_HPP + +#include + + +#if defined(_WIN32) +#if defined(EPROSIMA_USER_DLL_EXPORT) +#define eProsima_user_DllExport __declspec( dllexport ) +#else +#define eProsima_user_DllExport +#endif // EPROSIMA_USER_DLL_EXPORT +#else +#define eProsima_user_DllExport +#endif // _WIN32 + +#ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC + +namespace eprosima { +namespace ddsenabler { +namespace participants { +/** + * @brief Register DynamicType related TypeIdentifier. + * Fully-descriptive TypeIdentifiers are directly registered. + * Hash TypeIdentifiers require to fill the TypeObject information and hash it, consequently, the TypeObject is + * indirectly registered as well. + * + * @param[out] TypeIdentifier of the registered type. + * The returned TypeIdentifier corresponds to the complete TypeIdentifier in case of hashed TypeIdentifiers. + * Invalid TypeIdentifier is returned in case of error. + */ +eProsima_user_DllExport void register_DynamicType_type_identifier( + eprosima::fastdds::dds::xtypes::TypeIdentifierPair& type_ids); + +/** + * @brief Register DynamicTypesCollection related TypeIdentifier. + * Fully-descriptive TypeIdentifiers are directly registered. + * Hash TypeIdentifiers require to fill the TypeObject information and hash it, consequently, the TypeObject is + * indirectly registered as well. + * + * @param[out] TypeIdentifier of the registered type. + * The returned TypeIdentifier corresponds to the complete TypeIdentifier in case of hashed TypeIdentifiers. + * Invalid TypeIdentifier is returned in case of error. + */ +eProsima_user_DllExport void register_DynamicTypesCollection_type_identifier( + eprosima::fastdds::dds::xtypes::TypeIdentifierPair& type_ids); + +} // namespace participants + +} // namespace ddsenabler + +} // namespace eprosima + + +#endif // DOXYGEN_SHOULD_SKIP_THIS_PUBLIC + +#endif // FAST_DDS_GENERATED__EPROSIMA_DDSENABLER_PARTICIPANTS_DYNAMICTYPESCOLLECTION_TYPE_OBJECT_SUPPORT_HPP diff --git a/ddsenabler_participants/src/cpp/CBHandler.cpp b/ddsenabler_participants/src/cpp/CBHandler.cpp index 36cc0c3f..c84c4111 100644 --- a/ddsenabler_participants/src/cpp/CBHandler.cpp +++ b/ddsenabler_participants/src/cpp/CBHandler.cpp @@ -16,19 +16,26 @@ * @file CBHandler.cpp */ +<<<<<<< HEAD #include #include #include #include #include +======= +#include +#include +#include +>>>>>>> e025823 (DDS data publication implementation) #include -#include +#include +#include -#include #include -#include -#include + +#include +#include #include @@ -62,33 +69,50 @@ void CBHandler::add_schema( { std::lock_guard lock(mtx_); - auto received_type = dyn_type->get_name().to_string(); - assert(nullptr != dyn_type); + const std::string& type_name = dyn_type->get_name().to_string(); + // Check if it exists already - auto it = schemas_.find(type_id); + auto it = schemas_.find(type_name); if (it != schemas_.end()) { return; } + schemas_[type_name] = {type_id, dyn_type}; // Add to schemas map EPROSIMA_LOG_INFO(DDSENABLER_CB_HANDLER, - "Adding schema with name " << dyn_type->get_name().to_string() << "."); + "Adding schema with name " << type_name << "."); + + write_schema_(dyn_type, type_id); +} - schemas_[type_id] = dyn_type; +void CBHandler::add_topic( + const DdsTopic& topic) +{ + cb_writer_->write_topic(topic); } void CBHandler::add_data( const DdsTopic& topic, RtpsPayloadData& data) { - std::unique_lock lock(mtx_); + std::lock_guard lock(mtx_); EPROSIMA_LOG_INFO(DDSENABLER_CB_HANDLER, "Adding data in topic: " << topic << "."); + fastdds::dds::DynamicType::_ref_type dyn_type; + auto it = schemas_.find(topic.type_name); + if (it == schemas_.end()) + { + EPROSIMA_LOG_WARNING(DDSENABLER_CB_HANDLER, + "Schema for type " << topic.type_name << " not available."); + return; + } + dyn_type = it->second.second; + CBMessage msg; msg.sequence_number = unique_sequence_number_++; msg.publish_time = data.source_timestamp; @@ -116,47 +140,171 @@ void CBHandler::add_data( throw utils::InconsistencyException(STR_ENTRY << "Received sample with no payload."); } - fastdds::dds::DynamicType::_ref_type dyn_type; - fastdds::dds::xtypes::TypeIdentifier type_id; + write_sample_(msg, dyn_type); +} + +bool CBHandler::get_type_identifier( + const std::string& type_name, + fastdds::dds::xtypes::TypeIdentifier& type_identifier) +{ + std::lock_guard lock(mtx_); - if (eprosima::fastdds::dds::xtypes::TK_NONE != topic.type_identifiers.type_identifier1()._d()) + auto it = schemas_.find(type_name); + if (it != schemas_.end()) { - type_id = topic.type_identifiers.type_identifier1(); + type_identifier = it->second.first; + return true; } - else if (eprosima::fastdds::dds::xtypes::TK_NONE != topic.type_identifiers.type_identifier2()._d()) + + if (!type_req_callback_) { - type_id = topic.type_identifiers.type_identifier2(); + EPROSIMA_LOG_ERROR(DDSENABLER_CB_HANDLER, + "Type request callback not set."); + return false; } - else + + unsigned char* serialized_type; + uint32_t serialized_type_size; + type_req_callback_(type_name.c_str(), serialized_type, serialized_type_size); + // TODO: handle fail case + // TODO: free resources allocated by user (serialized_type), or redesign interaction + + return register_type_nts_(type_name, serialized_type, serialized_type_size, type_identifier); +} + +bool CBHandler::get_serialized_data( + const std::string& type_name, + const std::string& json, + Payload& payload) +{ + std::lock_guard lock(mtx_); + + fastdds::dds::DynamicType::_ref_type dyn_type; + auto it = schemas_.find(type_name); + if (it == schemas_.end()) { - // NO TYPE_IDENTIFIERS - EPROSIMA_LOG_WARNING(DDSENABLER_CB_HANDLER, - "Received Schema for type " << topic.type_name << " with no TypeIdentifier."); - return; + EPROSIMA_LOG_ERROR(DDSENABLER_CB_HANDLER, + "Failed to deserialize data for type " << type_name << " : schema not available."); + return false; } + dyn_type = it->second.second; - auto it = schemas_.find(type_id); - if (it != schemas_.end()) + fastdds::dds::DynamicData::_ref_type dyn_data; + if ((fastdds::dds::RETCODE_OK != fastdds::dds::json_deserialize(json, dyn_type, fastdds::dds::DynamicDataJsonFormat::EPROSIMA, dyn_data)) || !dyn_data) { - dyn_type = it->second; - // Schema available -> write - write_sample(msg, dyn_type); + EPROSIMA_LOG_ERROR(DDSENABLER_CB_HANDLER, + "Failed to deserialize data for type " << type_name << " : json deserialization failed."); + return false; } - else + + // TODO: double chekc XCDR2 is the right choice -> only supposed to work against fastdds 3, and appendable only working with XCDR2 + fastdds::dds::DynamicPubSubType pubsub_type(dyn_type); + uint32_t payload_size = pubsub_type.calculate_serialized_size(&dyn_data, fastdds::dds::DataRepresentationId::XCDR2_DATA_REPRESENTATION); + + if (!payload_pool_->get_payload(payload_size, payload)) { - EPROSIMA_LOG_WARNING(DDSENABLER_CB_HANDLER, - "Schema for type " << topic.type_name << " not available."); + EPROSIMA_LOG_ERROR(DDSENABLER_CB_HANDLER, + "Failed to deserialize data for type " << type_name << " : get_payload failed."); + return false; } + if (!pubsub_type.serialize(&dyn_data, payload, fastdds::dds::DataRepresentationId::XCDR2_DATA_REPRESENTATION)) + { + EPROSIMA_LOG_ERROR(DDSENABLER_CB_HANDLER, + "Failed to deserialize data for type " << type_name << " : payload serialization failed."); + return false; + } + + return true; +} + +void CBHandler::write_schema_( + const fastdds::dds::DynamicType::_ref_type& dyn_type, + const fastdds::dds::xtypes::TypeIdentifier& type_id) +{ + cb_writer_->write_schema(dyn_type, type_id); +} + +void CBHandler::write_topic_( + const DdsTopic& topic) +{ + cb_writer_->write_topic(topic); } -void CBHandler::write_sample( +void CBHandler::write_sample_( const CBMessage& msg, const fastdds::dds::DynamicType::_ref_type& dyn_type) { cb_writer_->write_data(msg, dyn_type); } +bool CBHandler::register_type_nts_( + const std::string& type_name, + const unsigned char* serialized_type, + uint32_t serialized_type_size, + fastdds::dds::xtypes::TypeIdentifier& type_identifier) +{ + DynamicTypesCollection dynamic_types; + serialization::deserialize_dynamic_types(serialized_type, serialized_type_size, dynamic_types); // TODO: handle fail case + + std::string _type_name; + fastdds::dds::xtypes::TypeIdentifier _type_identifier; + fastdds::dds::xtypes::TypeObject _type_object; + + // Deserialize and register all dependencies and main type (last one in collection) + for (DynamicType& dynamic_type : dynamic_types.dynamic_types()) + { + if (!serialization::deserialize_dynamic_type(dynamic_type, _type_name, _type_identifier, _type_object)) + { + EPROSIMA_LOG_ERROR(DDSENABLER_CB_HANDLER, + "Failed to deserialize " << dynamic_type.type_name() << " DynamicType."); + return false; + } + + // Create a TypeIdentifierPair to use in register_type_identifier + fastdds::dds::xtypes::TypeIdentifierPair type_identifiers; + type_identifiers.type_identifier1(_type_identifier); + + // Register in factory + if (fastdds::dds::RETCODE_OK != + fastdds::dds::DomainParticipantFactory::get_instance()->type_object_registry().register_type_object( + _type_object, type_identifiers)) + { + EPROSIMA_LOG_ERROR(DDSENABLER_CB_HANDLER, + "Failed to register " << dynamic_type.type_name() << " DynamicType."); + // TODO: check if trying to register a type for the second time would return OK or not + return false; + } + } + + if (_type_name != type_name) + { + EPROSIMA_LOG_ERROR(DDSENABLER_CB_HANDLER, + "Unexpected dynamic types collection format: " << type_name << " expected to be last item, found " << _type_name << " instead."); + return false; + } + + fastdds::dds::DynamicType::_ref_type dyn_type = fastdds::dds::DynamicTypeBuilderFactory::get_instance()->create_type_w_type_object(_type_object)->build(); + if (!dyn_type) + { + EPROSIMA_LOG_ERROR(DDSENABLER_CB_HANDLER, + "Failed to create Dynamic Type " << type_name); + return false; + } + + // Add to schemas map + EPROSIMA_LOG_INFO(DDSENABLER_CB_HANDLER, + "Adding schema with name " << type_name << "."); + schemas_[_type_name] = {_type_identifier, dyn_type}; + + type_identifier = _type_identifier; + return true; + + // TODO: analyze case where dependencies are not added to schemas map, so if afterwards the user tries to publish + // in one of the dependencies type, we will try to register the same type again -> will it fail? if not, will it + // skip registration but still return internal TypeIdentifier? +} + } /* namespace participants */ } /* namespace ddsenabler */ } /* namespace eprosima */ diff --git a/ddsenabler_participants/src/cpp/CBWriter.cpp b/ddsenabler_participants/src/cpp/CBWriter.cpp index 256c3a27..3ae2f569 100644 --- a/ddsenabler_participants/src/cpp/CBWriter.cpp +++ b/ddsenabler_participants/src/cpp/CBWriter.cpp @@ -18,11 +18,14 @@ #include -#include - -#include #include +#include #include +#include +#include + +#include +#include #include @@ -30,20 +33,104 @@ namespace eprosima { namespace ddsenabler { namespace participants { +using namespace eprosima::ddsenabler::participants::serialization; +using namespace eprosima::ddspipe::core::types; + +void CBWriter::write_schema( + const fastdds::dds::DynamicType::_ref_type& dyn_type, + const fastdds::dds::xtypes::TypeIdentifier& type_id) +{ + assert(nullptr != dyn_type); + + const std::string& type_name = dyn_type->get_name().to_string(); + + //Schema has not been registered + EPROSIMA_LOG_INFO(DDSENABLER_CB_WRITER, + "Writing schema: " << type_name << "."); + + std::stringstream ss_idl; + auto ret = fastdds::dds::idl_serialize(dyn_type, ss_idl); + if (ret != fastdds::dds::RETCODE_OK) + { + EPROSIMA_LOG_ERROR(DDSENABLER_CB_WRITER, + "Failed to serialize DynamicType to idl for type with name: " << type_name); + return; + } + + DynamicTypesCollection types_collection; + if (!serialize_dynamic_type(type_name, type_id, types_collection)) + { + EPROSIMA_LOG_ERROR(DDSENABLER_CB_WRITER, + "Failed to serialize dynamic types collection: " << type_name); + return; + } + + std::unique_ptr types_collection_payload = serialize_dynamic_types(types_collection); + if (nullptr == types_collection_payload) + { + EPROSIMA_LOG_ERROR(DDSENABLER_CB_WRITER, + "Failed to serialize dynamic types collection: " << type_name); + return; + } + + std::stringstream ss_data_holder; + ss_data_holder << std::setw(4); + if (fastdds::dds::RETCODE_OK != + fastdds::dds::json_serialize(fastdds::dds::DynamicDataFactory::get_instance()->create_data(dyn_type), fastdds::dds::DynamicDataJsonFormat::EPROSIMA, ss_data_holder)) + { + EPROSIMA_LOG_ERROR(DDSENABLER_CB_WRITER, + "Not able to generate data placeholder for type " << type_name << "."); + return; + } + + //STORE SCHEMA + if (type_callback_) + { + type_callback_( + type_name.c_str(), + ss_idl.str().c_str(), + (unsigned char*)types_collection_payload->data, + types_collection_payload->length, + ss_data_holder.str().c_str() + ); + } +} + +void CBWriter::write_topic( + const DdsTopic& topic) +{ + EPROSIMA_LOG_INFO(DDSENABLER_CB_WRITER, + "Writting topic: " << topic.topic_name() << "."); + + if (topic_callback_) + { + std::string serialized_qos = serialize_qos(topic.topic_qos); + topic_callback_( + topic.topic_name().c_str(), + topic.type_name.c_str(), + serialized_qos.c_str() + ); + } +} void CBWriter::write_data( const CBMessage& msg, const fastdds::dds::DynamicType::_ref_type& dyn_type) { - std::lock_guard lock(mutex_); - - write_schema(msg, dyn_type); + assert(nullptr != dyn_type); EPROSIMA_LOG_INFO(DDSENABLER_CB_WRITER, "Writing message from topic: " << msg.topic.topic_name() << "."); // Get the data as JSON - fastdds::dds::DynamicData::_ref_type dyn_data = get_dynamic_data(msg, dyn_type); + fastdds::dds::DynamicData::_ref_type dyn_data = get_dynamic_data_(msg, dyn_type); + + if (nullptr == dyn_data) + { + EPROSIMA_LOG_ERROR(DDSENABLER_CB_WRITER, + "Not able to get DynamicData from topic " << msg.topic.topic_name() << "."); + return; + } std::stringstream ss_dyn_data; ss_dyn_data << std::setw(4); @@ -56,8 +143,9 @@ void CBWriter::write_data( } // Create the base JSON structure - nlohmann::ordered_json json_output; + nlohmann::json json_output; + // TODO: encapsulate and/or have tags in a constants header?? std::stringstream ss_source_guid_prefix; ss_source_guid_prefix << msg.source_guid.guid_prefix(); json_output["id"] = ss_source_guid_prefix.str(); @@ -69,14 +157,13 @@ void CBWriter::write_data( std::stringstream ss_instanceHandle; ss_instanceHandle << msg.instanceHandle; - nlohmann::ordered_json parsed_dyn_data = nlohmann::json::parse(ss_dyn_data.str()); + nlohmann::json parsed_dyn_data = nlohmann::json::parse(ss_dyn_data.str()); json_output[msg.topic.topic_name()]["data"][ss_instanceHandle.str()] = parsed_dyn_data; //STORE DATA if (data_callback_) { data_callback_( - msg.topic.type_name.c_str(), msg.topic.topic_name().c_str(), json_output.dump(4).c_str(), msg.publish_time.to_ns() @@ -84,52 +171,7 @@ void CBWriter::write_data( } } -void CBWriter::write_schema( - const CBMessage& msg, - const fastdds::dds::DynamicType::_ref_type& dyn_type) -{ - const std::string topic_name = msg.topic.topic_name(); - const std::string type_name = msg.topic.type_name; - const fastdds::dds::xtypes::TypeIdentifier type_id = msg.topic.type_identifiers.type_identifier1(); - - auto it = stored_schemas_.find(topic_name); - if (it == stored_schemas_.end()) - { - //Schema has not been registered - EPROSIMA_LOG_INFO(DDSENABLER_CB_WRITER, - "Writing schema: " << type_name << " on topic: " << topic_name << "."); - - std::stringstream ss_idl; - auto ret = fastdds::dds::idl_serialize(dyn_type, ss_idl); - if (ret != fastdds::dds::RETCODE_OK) - { - EPROSIMA_LOG_ERROR(DDSENABLER_CB_WRITER, - "Failed to serialize DynamicType to idl for type with name: " << type_name); - return; - } - - //Add the schema and topic to stored_schemas_ - stored_schemas_[topic_name] = type_id; - - //STORE SCHEMA - if (type_callback_) - { - type_callback_( - type_name.c_str(), - topic_name.c_str(), - ss_idl.str().c_str() - ); - } - } - else - { - //Schema has been registered - EPROSIMA_LOG_INFO(DDSENABLER_CB_WRITER, - "Schema: " + type_name + " already registered for topic: " + topic_name + "."); - } -} - -fastdds::dds::DynamicData::_ref_type CBWriter::get_dynamic_data( +fastdds::dds::DynamicData::_ref_type CBWriter::get_dynamic_data_( const CBMessage& msg, const fastdds::dds::DynamicType::_ref_type& dyn_type) noexcept { @@ -137,6 +179,7 @@ fastdds::dds::DynamicData::_ref_type CBWriter::get_dynamic_data( auto& data_no_const = const_cast(msg.payload); // Create PubSub Type + // TODO: avoid creating this object each time -> store in a map fastdds::dds::DynamicPubSubType pubsub_type(dyn_type); fastdds::dds::DynamicData::_ref_type dyn_data( fastdds::dds::DynamicDataFactory::get_instance()->create_data(dyn_type)); diff --git a/ddsenabler_participants/src/cpp/DdsParticipant.cpp b/ddsenabler_participants/src/cpp/DdsParticipant.cpp new file mode 100644 index 00000000..3a166c62 --- /dev/null +++ b/ddsenabler_participants/src/cpp/DdsParticipant.cpp @@ -0,0 +1,53 @@ +// Copyright 2024 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @file DdsParticipant.cpp + */ + +#include +#include +#include + +#include + +namespace eprosima { +namespace ddsenabler { +namespace participants { + +using namespace eprosima::ddspipe::core; +using namespace eprosima::ddspipe::core::types; +using namespace eprosima::ddspipe::participants; + +DdsParticipant::DdsParticipant( + std::shared_ptr participant_configuration, + std::shared_ptr payload_pool, + std::shared_ptr discovery_database) + : DynTypesParticipant(participant_configuration, payload_pool, discovery_database) +{ +} + +std::shared_ptr DdsParticipant::create_writer( + const ITopic& topic) +{ + if (is_type_object_topic(topic)) + { + return std::make_shared(); + } + return rtps::SimpleParticipant::create_writer(topic); +} + +} /* namespace participants */ +} /* namespace ddsenabler */ +} /* namespace eprosima */ diff --git a/ddsenabler_participants/src/cpp/EnablerParticipant.cpp b/ddsenabler_participants/src/cpp/EnablerParticipant.cpp new file mode 100644 index 00000000..b9081061 --- /dev/null +++ b/ddsenabler_participants/src/cpp/EnablerParticipant.cpp @@ -0,0 +1,161 @@ +// Copyright 2024 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @file EnablerParticipant.cpp + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include + +namespace eprosima { +namespace ddsenabler { +namespace participants { + +using namespace eprosima::ddspipe::core; +using namespace eprosima::ddspipe::core::types; +using namespace eprosima::ddspipe::participants; + +EnablerParticipant::EnablerParticipant( + std::shared_ptr participant_configuration, + std::shared_ptr payload_pool, + std::shared_ptr discovery_database, + std::shared_ptr schema_handler) + : ddspipe::participants::SchemaParticipant(participant_configuration, payload_pool, discovery_database, schema_handler) +{ +} + +std::shared_ptr EnablerParticipant::create_reader( + const ITopic& topic) +{ + if (is_type_object_topic(topic)) + { + return std::make_shared(); + } + + std::shared_ptr reader; + { + std::lock_guard lck(mtx_); + reader = std::make_shared(id()); + auto dds_topic = dynamic_cast(topic); + readers_[dds_topic] = reader; + std::static_pointer_cast(schema_handler_)->add_topic(dds_topic); + } + cv_.notify_one(); + return reader; +} + +bool EnablerParticipant::publish( + const std::string& topic_name, + const std::string& json) +{ + std::unique_lock lck(mtx_); + + std::string type_name; + auto reader = lookup_reader_nts_(topic_name, type_name); + + if (nullptr == reader) + { + if (!topic_req_callback_) + { + EPROSIMA_LOG_ERROR(DDSENABLER_ENABLER_PARTICIPANT, + "Failed to publish data in topic " << topic_name << " : topic is unknown and topic request callback not set."); + return false; + } + + char* _type_name; + char* serialized_qos_content; + topic_req_callback_(topic_name.c_str(), _type_name, serialized_qos_content); // TODO: allow the user not to provide QoS + handle fail case + type_name = std::string(_type_name); // TODO: free resources allocated by user, or redesign interaction (same for serialized_qos_content) + std::string serialized_qos(serialized_qos_content); + + TopicQoS qos = serialization::deserialize_qos(serialized_qos); // TODO: handle fail case (try-catch?) + + fastdds::dds::xtypes::TypeIdentifier type_identifier; + if (!std::static_pointer_cast(schema_handler_)->get_type_identifier(type_name, type_identifier)) + { + EPROSIMA_LOG_ERROR(DDSENABLER_ENABLER_PARTICIPANT, + "Failed to publish data in topic " << topic_name << " : type identifier not found."); + return false; + } + + DdsTopic topic; + topic.m_topic_name = topic_name; + topic.type_name = type_name; + topic.topic_qos = qos; + topic.type_identifiers.type_identifier1(type_identifier); + this->discovery_database_->add_endpoint(rtps::CommonParticipant::simulate_endpoint(topic, this->id())); + + // Wait for reader to be created from discovery thread + cv_.wait(lck, [&] { return nullptr != (reader = lookup_reader_nts_(topic_name)); }); // TODO: handle case when stopped before processing queue item + + // (Optionally) wait for writer created in DDS participant to match with external readers, to avoid losing this + // message when not using transient durability + std::this_thread::sleep_for(std::chrono::milliseconds(std::static_pointer_cast(configuration_)->initial_publish_wait)); + } + + auto data = std::make_unique(); + + Payload payload; + if (!std::static_pointer_cast(schema_handler_)->get_serialized_data(type_name, json, payload)) + { + EPROSIMA_LOG_ERROR(DDSENABLER_ENABLER_PARTICIPANT, + "Failed to publish data in topic " << topic_name << " : data serialization failed."); + return false; + } + + if (!payload_pool_->get_payload(payload, data->payload)) + { + EPROSIMA_LOG_ERROR(DDSENABLER_ENABLER_PARTICIPANT, + "Failed to publish data in topic " << topic_name << " : get_payload failed."); + return false; + } + + reader->simulate_data_reception(std::move(data)); + return true; +} + +std::shared_ptr EnablerParticipant::lookup_reader_nts_( + const std::string& topic_name, + std::string& type_name) const +{ + for (const auto& reader : readers_) + { + if (reader.first.m_topic_name == topic_name) + { + type_name = reader.first.type_name; + return reader.second; + } + } + return nullptr; +} + +std::shared_ptr EnablerParticipant::lookup_reader_nts_( + const std::string& topic_name) const +{ + std::string _; + return lookup_reader_nts_(topic_name, _); +} + +} /* namespace participants */ +} /* namespace ddsenabler */ +} /* namespace eprosima */ diff --git a/ddsenabler_participants/src/cpp/serialization.cpp b/ddsenabler_participants/src/cpp/serialization.cpp new file mode 100644 index 00000000..564c2bf1 --- /dev/null +++ b/ddsenabler_participants/src/cpp/serialization.cpp @@ -0,0 +1,529 @@ +// Copyright 2024 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @file serialization.cpp + */ + +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +namespace eprosima { +namespace ddsenabler { +namespace participants { +namespace serialization { + +using namespace eprosima::ddspipe::core::types; +using namespace eprosima::fastdds::dds::xtypes; + +/////////////////////// +// QoS serialization // +/////////////////////// + +std::string serialize_qos( + const TopicQoS& qos) +{ + YAML::Node qos_yaml; + + // Reliability tag + YAML::Node reliability_tag = qos_yaml[QOS_SERIALIZATION_RELIABILITY]; + if (qos.is_reliable()) + { + reliability_tag = true; + } + else + { + reliability_tag = false; + } + + // Durability tag + YAML::Node durability_tag = qos_yaml[QOS_SERIALIZATION_DURABILITY]; + if (qos.is_transient_local()) + { + durability_tag = true; + } + else + { + durability_tag = false; + } + + // Ownership tag + YAML::Node ownership_tag = qos_yaml[QOS_SERIALIZATION_OWNERSHIP]; + if (qos.has_ownership()) + { + ownership_tag = true; + } + else + { + ownership_tag = false; + } + + // Keyed tag + YAML::Node keyed_tag = qos_yaml[QOS_SERIALIZATION_KEYED]; + if (qos.keyed) + { + keyed_tag = true; + } + else + { + keyed_tag = false; + } + + return YAML::Dump(qos_yaml); +} + +TopicQoS deserialize_qos( + const std::string& qos_str) +{ + TopicQoS qos{}; + + YAML::Node qos_yaml = YAML::Load(qos_str); + bool reliable = qos_yaml[QOS_SERIALIZATION_RELIABILITY].as(); + bool transient_local = qos_yaml[QOS_SERIALIZATION_DURABILITY].as(); + bool exclusive_ownership = qos_yaml[QOS_SERIALIZATION_OWNERSHIP].as(); + bool keyed = qos_yaml[QOS_SERIALIZATION_KEYED].as(); + + // Parse reliability + if (reliable) + { + qos.reliability_qos = ReliabilityKind::RELIABLE; + } + else + { + qos.reliability_qos = ReliabilityKind::BEST_EFFORT; + } + + // Parse durability + if (transient_local) + { + qos.durability_qos = DurabilityKind::TRANSIENT_LOCAL; + } + else + { + qos.durability_qos = DurabilityKind::VOLATILE; + } + + // Parse ownership + if (exclusive_ownership) + { + qos.ownership_qos = OwnershipQosPolicyKind::EXCLUSIVE_OWNERSHIP_QOS; + } + else + { + qos.ownership_qos = OwnershipQosPolicyKind::SHARED_OWNERSHIP_QOS; + } + + // Parse keyed + qos.keyed = keyed; + + return qos; +} + +////////////////////////// +// XTypes serialization // +////////////////////////// + +template +std::string serialize_type_data( + const DynamicTypeData& type_data); + +template +DynamicTypeData deserialize_type_data( + const std::string& typedata_str); + +std::string serialize_type_identifier( + const TypeIdentifier& type_identifier); + +TypeIdentifier deserialize_type_identifier( + const std::string& typeid_str); + +std::string serialize_type_object( + const TypeObject& type_object); + +TypeObject deserialize_type_object( + const std::string& typeobj_str); + +bool serialize_dynamic_type( + const std::string& type_name, + const TypeIdentifier& type_identifier, + DynamicTypesCollection& dynamic_types) +{ + TypeIdentifierPair type_identifiers; + + // NOTE: type_identifier is assumed to be complete + type_identifiers.type_identifier1(type_identifier); + + TypeInformation type_info; + if (fastdds::dds::RETCODE_OK != + fastdds::dds::DomainParticipantFactory::get_instance()->type_object_registry().get_type_information( + type_identifiers, + type_info, + true)) + { + EPROSIMA_LOG_WARNING(DDSENABLER_SERIALIZATION, + "Error getting TypeInformation for type " << type_name); + return false; + } + + std::string dependency_name; + unsigned int dependency_index = 0; + const auto type_dependencies = type_info.complete().dependent_typeids(); + for (auto dependency : type_dependencies) + { + TypeIdentifier dependency_type_identifier; + dependency_type_identifier = dependency.type_id(); + + TypeObject dependency_type_object; + if (fastdds::dds::RETCODE_OK != + fastdds::dds::DomainParticipantFactory::get_instance()->type_object_registry().get_type_object( + dependency_type_identifier, + dependency_type_object)) + { + EPROSIMA_LOG_WARNING(DDSENABLER_SERIALIZATION, "Error getting TypeObject of dependency " << "for type " << type_name); + return false; + } + + dependency_name = type_name + "_" + std::to_string(dependency_index); + + // Store dependency in dynamic_types collection + serialize_dynamic_type(dependency_type_identifier, dependency_type_object, dependency_name, dynamic_types); + + // Increment suffix counter + dependency_index++; + } + + TypeObject type_object; + if (fastdds::dds::RETCODE_OK != + fastdds::dds::DomainParticipantFactory::get_instance()->type_object_registry().get_type_object( + type_identifier, + type_object)) + { + EPROSIMA_LOG_WARNING(DDSENABLER_SERIALIZATION, "Error getting TypeObject for type " << type_name); + return false; + } + + // Store dynamic type in dynamic_types collection + return serialize_dynamic_type(type_identifier, type_object, type_name, dynamic_types); +} + +bool serialize_dynamic_type( + const TypeIdentifier& type_identifier, + const TypeObject& type_object, + const std::string& type_name, + DynamicTypesCollection& dynamic_types) +{ + DynamicType dynamic_type; + dynamic_type.type_name(type_name); + + try + { + dynamic_type.type_identifier(utils::base64_encode(serialize_type_identifier(type_identifier))); + dynamic_type.type_object(utils::base64_encode(serialize_type_object(type_object))); + } + catch (const utils::InconsistencyException& e) + { + EPROSIMA_LOG_WARNING(DDSENABLER_SERIALIZATION, "Error serializing DynamicType. Error message:\n " << e.what()); + return false; + } + + dynamic_types.dynamic_types().push_back(dynamic_type); + + return true; + +} + +bool deserialize_dynamic_type( + const DynamicType& dynamic_type, + std::string& type_name, + TypeIdentifier& type_identifier, + TypeObject& type_object) +{ + std::string typeid_str = utils::base64_decode(dynamic_type.type_identifier()); + std::string typeobj_str = utils::base64_decode(dynamic_type.type_object()); + + try + { + // Deserialize type identifer and object strings + type_identifier = deserialize_type_identifier(typeid_str); + type_object = deserialize_type_object(typeobj_str); + } + catch (const utils::InconsistencyException& e) + { + EPROSIMA_LOG_WARNING(DDSENABLER_SERIALIZATION, + "Failed to deserialize " << dynamic_type.type_name() << " DynamicType: " << e.what()); + return false; + } + + type_name = dynamic_type.type_name(); + return true; +} + +template +std::string serialize_type_data( + const DynamicTypeData& type_data) +{ + // Reserve payload and create buffer + fastcdr::CdrSizeCalculator calculator(fastcdr::CdrVersion::XCDRv2); + size_t current_alignment {0}; + size_t size = calculator.calculate_serialized_size(type_data, current_alignment) + + fastdds::rtps::SerializedPayload_t::representation_header_size; + + fastdds::rtps::SerializedPayload_t payload(static_cast(size)); + fastcdr::FastBuffer fastbuffer((char*) payload.data, payload.max_size); + + // Create CDR serializer + fastcdr::Cdr ser(fastbuffer, fastcdr::Cdr::DEFAULT_ENDIAN, + fastcdr::CdrVersion::XCDRv2); + + payload.encapsulation = ser.endianness() == fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE; + + // Serialize + fastcdr::serialize(ser, type_data); + payload.length = (uint32_t)ser.get_serialized_data_length(); + size = (ser.get_serialized_data_length() + 3) & ~3; + + // Create CDR message with payload + std::unique_ptr cdr_message = std::make_unique(payload); + + // Add data + if (!(cdr_message && (cdr_message->pos + payload.length <= cdr_message->max_size)) || + (payload.length > 0 && !payload.data)) + { + if (!cdr_message) + { + throw utils::InconsistencyException( + "Error adding data -> cdr_message is null."); + } + else if (cdr_message->pos + payload.length > cdr_message->max_size) + { + throw utils::InconsistencyException( + "Error adding data -> not enough space in cdr_message buffer."); + } + else if (payload.length > 0 && !payload.data) + { + throw utils::InconsistencyException( + "Error adding data -> payload length is greater than 0, but payload data is null."); + } + } + + memcpy(&cdr_message->buffer[cdr_message->pos], payload.data, payload.length); + cdr_message->pos += payload.length; + cdr_message->length += payload.length; + + fastdds::rtps::octet value = 0; + for (uint32_t count = payload.length; count < size; ++count) + { + const uint32_t size_octet = sizeof(value); + if (!(cdr_message && (cdr_message->pos + size_octet <= cdr_message->max_size))) + { + throw utils::InconsistencyException( + "Not enough space in cdr_message buffer."); + } + for (uint32_t i = 0; i < size_octet; i++) + { + cdr_message->buffer[cdr_message->pos + i] = *((fastdds::rtps::octet*)&value + size_octet - 1 - i); + } + cdr_message->pos += size_octet; + cdr_message->length += size_octet; + } + + // Copy buffer to string + std::string typedata_str(reinterpret_cast(cdr_message->buffer), size); + + return typedata_str; +} + +template +DynamicTypeData deserialize_type_data( + const std::string& typedata_str) +{ + // Create CDR message from string + // NOTE: Use 0 length to avoid allocation + fastdds::rtps::CDRMessage_t* cdr_message = new fastdds::rtps::CDRMessage_t(0); + cdr_message->buffer = (unsigned char*)reinterpret_cast(typedata_str.c_str()); + cdr_message->length = typedata_str.length(); +#if __BIG_ENDIAN__ + cdr_message->msg_endian = fastdds::rtps::BIGEND; +#else + cdr_message->msg_endian = fastdds::rtps::LITTLEEND; +#endif // if __BIG_ENDIAN__ + + // Reserve payload and create buffer + const auto parameter_length = cdr_message->length; + fastdds::rtps::SerializedPayload_t payload(parameter_length); + fastcdr::FastBuffer fastbuffer((char*)payload.data, parameter_length); + + // Check cdr message is valid + if (!cdr_message) + { + throw utils::InconsistencyException( + "Error reading data -> cdr_message is null."); + } + + // Check enough space in buffer + if (!(cdr_message->length >= cdr_message->pos + parameter_length)) + { + throw utils::InconsistencyException( + "Error reading data -> not enough space in cdr_message buffer."); + } + + // Check length is consistent + if (!(parameter_length > 0)) + { + throw utils::InconsistencyException( + "Error reading data -> payload length is greater than 0."); + } + + // Check payload is valid + if (!payload.data) + { + throw utils::InconsistencyException( + "Error reading data -> payload data is null."); + } + + // Copy data + memcpy(payload.data, &cdr_message->buffer[cdr_message->pos], parameter_length); + cdr_message->pos += parameter_length; + + // Create CDR deserializer + fastcdr::Cdr deser(fastbuffer, fastcdr::Cdr::DEFAULT_ENDIAN, fastcdr::CdrVersion::XCDRv2); + payload.encapsulation = deser.endianness() == fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE; + + // Deserialize + DynamicTypeData type_data; + fastcdr::deserialize(deser, type_data); + + // Delete CDR message + // NOTE: set wraps attribute to avoid double free (buffer released by string on destruction) + cdr_message->wraps = true; + delete cdr_message; + + return type_data; +} + +std::string serialize_type_identifier( + const TypeIdentifier& type_identifier) +{ + std::string typeid_string; + try + { + typeid_string = serialize_type_data(type_identifier); + } + catch (const utils::InconsistencyException& e) + { + throw utils::InconsistencyException(std::string("Failed to serialize TypeIdentifier: ") + e.what()); + } + + return typeid_string; +} + +TypeIdentifier deserialize_type_identifier( + const std::string& typeid_str) +{ + TypeIdentifier type_id; + try + { + type_id = deserialize_type_data(typeid_str); + } + catch (const utils::InconsistencyException& e) + { + throw utils::InconsistencyException(std::string("Failed to deserialize TypeIdentifier: ") + e.what()); + } + + return type_id; +} + +std::string serialize_type_object( + const TypeObject& type_object) +{ + std::string typeobj_string; + try + { + typeobj_string = serialize_type_data(type_object); + } + catch (const utils::InconsistencyException& e) + { + throw utils::InconsistencyException(std::string("Failed to serialize TypeObject: ") + e.what()); + } + + return typeobj_string; +} + +TypeObject deserialize_type_object( + const std::string& typeobj_str) +{ + TypeObject type_obj; + try + { + type_obj = deserialize_type_data(typeobj_str); + } + catch (const utils::InconsistencyException& e) + { + throw utils::InconsistencyException(std::string("Failed to deserialize TypeObject: ") + e.what()); + } + + return type_obj; +} + +std::unique_ptr serialize_dynamic_types( + const DynamicTypesCollection& dynamic_types) +{ + // Serialize dynamic types collection using CDR + fastdds::dds::TypeSupport type_support(new DynamicTypesCollectionPubSubType()); + auto serialized_payload = std::make_unique( + type_support.calculate_serialized_size(&dynamic_types, fastdds::dds::DEFAULT_DATA_REPRESENTATION)); + type_support.serialize(&dynamic_types, *serialized_payload, fastdds::dds::DEFAULT_DATA_REPRESENTATION); + + return serialized_payload; +} + +bool deserialize_dynamic_types( + const unsigned char* dynamic_types_payload, + uint32_t dynamic_types_payload_size, + DynamicTypesCollection& dynamic_types) +{ + fastdds::dds::TypeSupport type_support(new DynamicTypesCollectionPubSubType()); + fastdds::rtps::SerializedPayload_t serialized_payload = fastdds::rtps::SerializedPayload_t(dynamic_types_payload_size); + serialized_payload.length = dynamic_types_payload_size; + std::memcpy( + serialized_payload.data, + dynamic_types_payload, + dynamic_types_payload_size); + type_support.deserialize(serialized_payload, &dynamic_types); + + // TODO: catch exception and return false + return true; +} + +} /* namespace serialization */ +} /* namespace participants */ +} /* namespace ddsenabler */ +} /* namespace eprosima */ diff --git a/ddsenabler_participants/src/cpp/types/dynamic_types_collection/DynamicTypesCollectionCdrAux.hpp b/ddsenabler_participants/src/cpp/types/dynamic_types_collection/DynamicTypesCollectionCdrAux.hpp new file mode 100644 index 00000000..2310cf91 --- /dev/null +++ b/ddsenabler_participants/src/cpp/types/dynamic_types_collection/DynamicTypesCollectionCdrAux.hpp @@ -0,0 +1,53 @@ +// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*! + * @file DynamicTypesCollectionCdrAux.hpp + * This source file contains some definitions of CDR related functions. + * + * This file was generated by the tool fastddsgen. + */ + +#ifndef FAST_DDS_GENERATED__EPROSIMA_DDSENABLER_PARTICIPANTS_DYNAMICTYPESCOLLECTIONCDRAUX_HPP +#define FAST_DDS_GENERATED__EPROSIMA_DDSENABLER_PARTICIPANTS_DYNAMICTYPESCOLLECTIONCDRAUX_HPP + +#include + +constexpr uint32_t eprosima_ddsenabler_participants_DynamicType_max_cdr_typesize {784UL}; +constexpr uint32_t eprosima_ddsenabler_participants_DynamicType_max_key_cdr_typesize {0UL}; + +constexpr uint32_t eprosima_ddsenabler_participants_DynamicTypesCollection_max_cdr_typesize {12UL}; +constexpr uint32_t eprosima_ddsenabler_participants_DynamicTypesCollection_max_key_cdr_typesize {0UL}; + + +namespace eprosima { +namespace fastcdr { + +class Cdr; +class CdrSizeCalculator; + +eProsima_user_DllExport void serialize_key( + eprosima::fastcdr::Cdr& scdr, + const eprosima::ddsenabler::participants::DynamicType& data); + +eProsima_user_DllExport void serialize_key( + eprosima::fastcdr::Cdr& scdr, + const eprosima::ddsenabler::participants::DynamicTypesCollection& data); + + +} // namespace fastcdr +} // namespace eprosima + +#endif // FAST_DDS_GENERATED__EPROSIMA_DDSENABLER_PARTICIPANTS_DYNAMICTYPESCOLLECTIONCDRAUX_HPP + diff --git a/ddsenabler_participants/src/cpp/types/dynamic_types_collection/DynamicTypesCollectionCdrAux.ipp b/ddsenabler_participants/src/cpp/types/dynamic_types_collection/DynamicTypesCollectionCdrAux.ipp new file mode 100644 index 00000000..e86fbd57 --- /dev/null +++ b/ddsenabler_participants/src/cpp/types/dynamic_types_collection/DynamicTypesCollectionCdrAux.ipp @@ -0,0 +1,234 @@ +// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*! + * @file DynamicTypesCollectionCdrAux.ipp + * This source file contains some declarations of CDR related functions. + * + * This file was generated by the tool fastddsgen. + */ + +#ifndef FAST_DDS_GENERATED__EPROSIMA_DDSENABLER_PARTICIPANTS_DYNAMICTYPESCOLLECTIONCDRAUX_IPP +#define FAST_DDS_GENERATED__EPROSIMA_DDSENABLER_PARTICIPANTS_DYNAMICTYPESCOLLECTIONCDRAUX_IPP + +#include "DynamicTypesCollectionCdrAux.hpp" + +#include +#include + + +#include +using namespace eprosima::fastcdr::exception; + +namespace eprosima { +namespace fastcdr { + +template<> +eProsima_user_DllExport size_t calculate_serialized_size( + eprosima::fastcdr::CdrSizeCalculator& calculator, + const eprosima::ddsenabler::participants::DynamicType& data, + size_t& current_alignment) +{ + using namespace eprosima::ddsenabler::participants; + + static_cast(data); + + eprosima::fastcdr::EncodingAlgorithmFlag previous_encoding = calculator.get_encoding(); + size_t calculated_size {calculator.begin_calculate_type_serialized_size( + eprosima::fastcdr::CdrVersion::XCDRv2 == calculator.get_cdr_version() ? + eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 : + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR, + current_alignment)}; + + + calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(0), + data.type_name(), current_alignment); + + calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(1), + data.type_identifier(), current_alignment); + + calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(2), + data.type_object(), current_alignment); + + + calculated_size += calculator.end_calculate_type_serialized_size(previous_encoding, current_alignment); + + return calculated_size; +} + +template<> +eProsima_user_DllExport void serialize( + eprosima::fastcdr::Cdr& scdr, + const eprosima::ddsenabler::participants::DynamicType& data) +{ + using namespace eprosima::ddsenabler::participants; + + eprosima::fastcdr::Cdr::state current_state(scdr); + scdr.begin_serialize_type(current_state, + eprosima::fastcdr::CdrVersion::XCDRv2 == scdr.get_cdr_version() ? + eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 : + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR); + + scdr + << eprosima::fastcdr::MemberId(0) << data.type_name() + << eprosima::fastcdr::MemberId(1) << data.type_identifier() + << eprosima::fastcdr::MemberId(2) << data.type_object() +; + scdr.end_serialize_type(current_state); +} + +template<> +eProsima_user_DllExport void deserialize( + eprosima::fastcdr::Cdr& cdr, + eprosima::ddsenabler::participants::DynamicType& data) +{ + using namespace eprosima::ddsenabler::participants; + + cdr.deserialize_type(eprosima::fastcdr::CdrVersion::XCDRv2 == cdr.get_cdr_version() ? + eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 : + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR, + [&data](eprosima::fastcdr::Cdr& dcdr, const eprosima::fastcdr::MemberId& mid) -> bool + { + bool ret_value = true; + switch (mid.id) + { + case 0: + dcdr >> data.type_name(); + break; + + case 1: + dcdr >> data.type_identifier(); + break; + + case 2: + dcdr >> data.type_object(); + break; + + default: + ret_value = false; + break; + } + return ret_value; + }); +} + +void serialize_key( + eprosima::fastcdr::Cdr& scdr, + const eprosima::ddsenabler::participants::DynamicType& data) +{ + using namespace eprosima::ddsenabler::participants; + + static_cast(scdr); + static_cast(data); + scdr << data.type_name(); + + scdr << data.type_identifier(); + + scdr << data.type_object(); + +} + + +template<> +eProsima_user_DllExport size_t calculate_serialized_size( + eprosima::fastcdr::CdrSizeCalculator& calculator, + const eprosima::ddsenabler::participants::DynamicTypesCollection& data, + size_t& current_alignment) +{ + using namespace eprosima::ddsenabler::participants; + + static_cast(data); + + eprosima::fastcdr::EncodingAlgorithmFlag previous_encoding = calculator.get_encoding(); + size_t calculated_size {calculator.begin_calculate_type_serialized_size( + eprosima::fastcdr::CdrVersion::XCDRv2 == calculator.get_cdr_version() ? + eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 : + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR, + current_alignment)}; + + + calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(0), + data.dynamic_types(), current_alignment); + + + calculated_size += calculator.end_calculate_type_serialized_size(previous_encoding, current_alignment); + + return calculated_size; +} + +template<> +eProsima_user_DllExport void serialize( + eprosima::fastcdr::Cdr& scdr, + const eprosima::ddsenabler::participants::DynamicTypesCollection& data) +{ + using namespace eprosima::ddsenabler::participants; + + eprosima::fastcdr::Cdr::state current_state(scdr); + scdr.begin_serialize_type(current_state, + eprosima::fastcdr::CdrVersion::XCDRv2 == scdr.get_cdr_version() ? + eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 : + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR); + + scdr + << eprosima::fastcdr::MemberId(0) << data.dynamic_types() +; + scdr.end_serialize_type(current_state); +} + +template<> +eProsima_user_DllExport void deserialize( + eprosima::fastcdr::Cdr& cdr, + eprosima::ddsenabler::participants::DynamicTypesCollection& data) +{ + using namespace eprosima::ddsenabler::participants; + + cdr.deserialize_type(eprosima::fastcdr::CdrVersion::XCDRv2 == cdr.get_cdr_version() ? + eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 : + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR, + [&data](eprosima::fastcdr::Cdr& dcdr, const eprosima::fastcdr::MemberId& mid) -> bool + { + bool ret_value = true; + switch (mid.id) + { + case 0: + dcdr >> data.dynamic_types(); + break; + + default: + ret_value = false; + break; + } + return ret_value; + }); +} + +void serialize_key( + eprosima::fastcdr::Cdr& scdr, + const eprosima::ddsenabler::participants::DynamicTypesCollection& data) +{ + using namespace eprosima::ddsenabler::participants; + + static_cast(scdr); + static_cast(data); + scdr << data.dynamic_types(); + +} + + + +} // namespace fastcdr +} // namespace eprosima + +#endif // FAST_DDS_GENERATED__EPROSIMA_DDSENABLER_PARTICIPANTS_DYNAMICTYPESCOLLECTIONCDRAUX_IPP + diff --git a/ddsenabler_participants/src/cpp/types/dynamic_types_collection/DynamicTypesCollectionPubSubTypes.cxx b/ddsenabler_participants/src/cpp/types/dynamic_types_collection/DynamicTypesCollectionPubSubTypes.cxx new file mode 100644 index 00000000..67b19fdc --- /dev/null +++ b/ddsenabler_participants/src/cpp/types/dynamic_types_collection/DynamicTypesCollectionPubSubTypes.cxx @@ -0,0 +1,409 @@ +// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*! + * @file DynamicTypesCollectionPubSubTypes.cpp + * This header file contains the implementation of the serialization functions. + * + * This file was generated by the tool fastddsgen. + */ + +#include + +#include +#include + +#include "DynamicTypesCollectionCdrAux.hpp" +#include + +using SerializedPayload_t = eprosima::fastdds::rtps::SerializedPayload_t; +using InstanceHandle_t = eprosima::fastdds::rtps::InstanceHandle_t; +using DataRepresentationId_t = eprosima::fastdds::dds::DataRepresentationId_t; + +namespace eprosima { + namespace ddsenabler { + namespace participants { + DynamicTypePubSubType::DynamicTypePubSubType() + { + set_name("eprosima::ddsenabler::participants::DynamicType"); + uint32_t type_size = eprosima_ddsenabler_participants_DynamicType_max_cdr_typesize; + type_size += static_cast(eprosima::fastcdr::Cdr::alignment(type_size, 4)); /* possible submessage alignment */ + max_serialized_type_size = type_size + 4; /*encapsulation*/ + is_compute_key_provided = false; + uint32_t key_length = eprosima_ddsenabler_participants_DynamicType_max_key_cdr_typesize > 16 ? eprosima_ddsenabler_participants_DynamicType_max_key_cdr_typesize : 16; + key_buffer_ = reinterpret_cast(malloc(key_length)); + memset(key_buffer_, 0, key_length); + } + + DynamicTypePubSubType::~DynamicTypePubSubType() + { + if (key_buffer_ != nullptr) + { + free(key_buffer_); + } + } + + bool DynamicTypePubSubType::serialize( + const void* const data, + SerializedPayload_t& payload, + DataRepresentationId_t data_representation) + { + const DynamicType* p_type = static_cast(data); + + // Object that manages the raw buffer. + eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast(payload.data), payload.max_size); + // Object that serializes the data. + eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN, + data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ? + eprosima::fastcdr::CdrVersion::XCDRv1 : eprosima::fastcdr::CdrVersion::XCDRv2); + payload.encapsulation = ser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE; + ser.set_encoding_flag( + data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ? + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR : + eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2); + + try + { + // Serialize encapsulation + ser.serialize_encapsulation(); + // Serialize the object. + ser << *p_type; + ser.set_dds_cdr_options({0,0}); + } + catch (eprosima::fastcdr::exception::Exception& /*exception*/) + { + return false; + } + + // Get the serialized length + payload.length = static_cast(ser.get_serialized_data_length()); + return true; + } + + bool DynamicTypePubSubType::deserialize( + SerializedPayload_t& payload, + void* data) + { + try + { + // Convert DATA to pointer of your type + DynamicType* p_type = static_cast(data); + + // Object that manages the raw buffer. + eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast(payload.data), payload.length); + + // Object that deserializes the data. + eprosima::fastcdr::Cdr deser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN); + + // Deserialize encapsulation. + deser.read_encapsulation(); + payload.encapsulation = deser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE; + + // Deserialize the object. + deser >> *p_type; + } + catch (eprosima::fastcdr::exception::Exception& /*exception*/) + { + return false; + } + + return true; + } + + uint32_t DynamicTypePubSubType::calculate_serialized_size( + const void* const data, + DataRepresentationId_t data_representation) + { + try + { + eprosima::fastcdr::CdrSizeCalculator calculator( + data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ? + eprosima::fastcdr::CdrVersion::XCDRv1 :eprosima::fastcdr::CdrVersion::XCDRv2); + size_t current_alignment {0}; + return static_cast(calculator.calculate_serialized_size( + *static_cast(data), current_alignment)) + + 4u /*encapsulation*/; + } + catch (eprosima::fastcdr::exception::Exception& /*exception*/) + { + return 0; + } + } + + void* DynamicTypePubSubType::create_data() + { + return reinterpret_cast(new DynamicType()); + } + + void DynamicTypePubSubType::delete_data( + void* data) + { + delete(reinterpret_cast(data)); + } + + bool DynamicTypePubSubType::compute_key( + SerializedPayload_t& payload, + InstanceHandle_t& handle, + bool force_md5) + { + if (!is_compute_key_provided) + { + return false; + } + + DynamicType data; + if (deserialize(payload, static_cast(&data))) + { + return compute_key(static_cast(&data), handle, force_md5); + } + + return false; + } + + bool DynamicTypePubSubType::compute_key( + const void* const data, + InstanceHandle_t& handle, + bool force_md5) + { + if (!is_compute_key_provided) + { + return false; + } + + const DynamicType* p_type = static_cast(data); + + // Object that manages the raw buffer. + eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast(key_buffer_), + eprosima_ddsenabler_participants_DynamicType_max_key_cdr_typesize); + + // Object that serializes the data. + eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::BIG_ENDIANNESS, eprosima::fastcdr::CdrVersion::XCDRv2); + ser.set_encoding_flag(eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR2); + eprosima::fastcdr::serialize_key(ser, *p_type); + if (force_md5 || eprosima_ddsenabler_participants_DynamicType_max_key_cdr_typesize > 16) + { + md5_.init(); + md5_.update(key_buffer_, static_cast(ser.get_serialized_data_length())); + md5_.finalize(); + for (uint8_t i = 0; i < 16; ++i) + { + handle.value[i] = md5_.digest[i]; + } + } + else + { + for (uint8_t i = 0; i < 16; ++i) + { + handle.value[i] = key_buffer_[i]; + } + } + return true; + } + + void DynamicTypePubSubType::register_type_object_representation() + { + register_DynamicType_type_identifier(type_identifiers_); + } + + DynamicTypesCollectionPubSubType::DynamicTypesCollectionPubSubType() + { + set_name("eprosima::ddsenabler::participants::DynamicTypesCollection"); + uint32_t type_size = eprosima_ddsenabler_participants_DynamicTypesCollection_max_cdr_typesize; + type_size += static_cast(eprosima::fastcdr::Cdr::alignment(type_size, 4)); /* possible submessage alignment */ + max_serialized_type_size = type_size + 4; /*encapsulation*/ + is_compute_key_provided = false; + uint32_t key_length = eprosima_ddsenabler_participants_DynamicTypesCollection_max_key_cdr_typesize > 16 ? eprosima_ddsenabler_participants_DynamicTypesCollection_max_key_cdr_typesize : 16; + key_buffer_ = reinterpret_cast(malloc(key_length)); + memset(key_buffer_, 0, key_length); + } + + DynamicTypesCollectionPubSubType::~DynamicTypesCollectionPubSubType() + { + if (key_buffer_ != nullptr) + { + free(key_buffer_); + } + } + + bool DynamicTypesCollectionPubSubType::serialize( + const void* const data, + SerializedPayload_t& payload, + DataRepresentationId_t data_representation) + { + const DynamicTypesCollection* p_type = static_cast(data); + + // Object that manages the raw buffer. + eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast(payload.data), payload.max_size); + // Object that serializes the data. + eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN, + data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ? + eprosima::fastcdr::CdrVersion::XCDRv1 : eprosima::fastcdr::CdrVersion::XCDRv2); + payload.encapsulation = ser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE; + ser.set_encoding_flag( + data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ? + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR : + eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2); + + try + { + // Serialize encapsulation + ser.serialize_encapsulation(); + // Serialize the object. + ser << *p_type; + ser.set_dds_cdr_options({0,0}); + } + catch (eprosima::fastcdr::exception::Exception& /*exception*/) + { + return false; + } + + // Get the serialized length + payload.length = static_cast(ser.get_serialized_data_length()); + return true; + } + + bool DynamicTypesCollectionPubSubType::deserialize( + SerializedPayload_t& payload, + void* data) + { + try + { + // Convert DATA to pointer of your type + DynamicTypesCollection* p_type = static_cast(data); + + // Object that manages the raw buffer. + eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast(payload.data), payload.length); + + // Object that deserializes the data. + eprosima::fastcdr::Cdr deser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN); + + // Deserialize encapsulation. + deser.read_encapsulation(); + payload.encapsulation = deser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE; + + // Deserialize the object. + deser >> *p_type; + } + catch (eprosima::fastcdr::exception::Exception& /*exception*/) + { + return false; + } + + return true; + } + + uint32_t DynamicTypesCollectionPubSubType::calculate_serialized_size( + const void* const data, + DataRepresentationId_t data_representation) + { + try + { + eprosima::fastcdr::CdrSizeCalculator calculator( + data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ? + eprosima::fastcdr::CdrVersion::XCDRv1 :eprosima::fastcdr::CdrVersion::XCDRv2); + size_t current_alignment {0}; + return static_cast(calculator.calculate_serialized_size( + *static_cast(data), current_alignment)) + + 4u /*encapsulation*/; + } + catch (eprosima::fastcdr::exception::Exception& /*exception*/) + { + return 0; + } + } + + void* DynamicTypesCollectionPubSubType::create_data() + { + return reinterpret_cast(new DynamicTypesCollection()); + } + + void DynamicTypesCollectionPubSubType::delete_data( + void* data) + { + delete(reinterpret_cast(data)); + } + + bool DynamicTypesCollectionPubSubType::compute_key( + SerializedPayload_t& payload, + InstanceHandle_t& handle, + bool force_md5) + { + if (!is_compute_key_provided) + { + return false; + } + + DynamicTypesCollection data; + if (deserialize(payload, static_cast(&data))) + { + return compute_key(static_cast(&data), handle, force_md5); + } + + return false; + } + + bool DynamicTypesCollectionPubSubType::compute_key( + const void* const data, + InstanceHandle_t& handle, + bool force_md5) + { + if (!is_compute_key_provided) + { + return false; + } + + const DynamicTypesCollection* p_type = static_cast(data); + + // Object that manages the raw buffer. + eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast(key_buffer_), + eprosima_ddsenabler_participants_DynamicTypesCollection_max_key_cdr_typesize); + + // Object that serializes the data. + eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::BIG_ENDIANNESS, eprosima::fastcdr::CdrVersion::XCDRv2); + ser.set_encoding_flag(eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR2); + eprosima::fastcdr::serialize_key(ser, *p_type); + if (force_md5 || eprosima_ddsenabler_participants_DynamicTypesCollection_max_key_cdr_typesize > 16) + { + md5_.init(); + md5_.update(key_buffer_, static_cast(ser.get_serialized_data_length())); + md5_.finalize(); + for (uint8_t i = 0; i < 16; ++i) + { + handle.value[i] = md5_.digest[i]; + } + } + else + { + for (uint8_t i = 0; i < 16; ++i) + { + handle.value[i] = key_buffer_[i]; + } + } + return true; + } + + void DynamicTypesCollectionPubSubType::register_type_object_representation() + { + register_DynamicTypesCollection_type_identifier(type_identifiers_); + } + + } // namespace participants + + } // namespace ddsenabler + +} // namespace eprosima + + +// Include auxiliary functions like for serializing/deserializing. +#include "DynamicTypesCollectionCdrAux.ipp" diff --git a/ddsenabler_participants/src/cpp/types/dynamic_types_collection/DynamicTypesCollectionTypeObjectSupport.cxx b/ddsenabler_participants/src/cpp/types/dynamic_types_collection/DynamicTypesCollectionTypeObjectSupport.cxx new file mode 100644 index 00000000..4fb5c82e --- /dev/null +++ b/ddsenabler_participants/src/cpp/types/dynamic_types_collection/DynamicTypesCollectionTypeObjectSupport.cxx @@ -0,0 +1,282 @@ +// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*! + * @file DynamicTypesCollectionTypeObjectSupport.cxx + * Source file containing the implementation to register the TypeObject representation of the described types in the IDL file + * + * This file was generated by the tool fastddsgen. + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +using namespace eprosima::fastdds::dds::xtypes; + +namespace eprosima { +namespace ddsenabler { +namespace participants { +// TypeIdentifier is returned by reference: dependent structures/unions are registered in this same method +void register_DynamicType_type_identifier( + TypeIdentifierPair& type_ids_DynamicType) +{ + + ReturnCode_t return_code_DynamicType {eprosima::fastdds::dds::RETCODE_OK}; + return_code_DynamicType = + eprosima::fastdds::dds::DomainParticipantFactory::get_instance()->type_object_registry().get_type_identifiers( + "eprosima::ddsenabler::participants::DynamicType", type_ids_DynamicType); + if (eprosima::fastdds::dds::RETCODE_OK != return_code_DynamicType) + { + StructTypeFlag struct_flags_DynamicType = TypeObjectUtils::build_struct_type_flag(eprosima::fastdds::dds::xtypes::ExtensibilityKind::APPENDABLE, + false, false); + QualifiedTypeName type_name_DynamicType = "eprosima::ddsenabler::participants::DynamicType"; + eprosima::fastcdr::optional type_ann_builtin_DynamicType; + eprosima::fastcdr::optional ann_custom_DynamicType; + CompleteTypeDetail detail_DynamicType = TypeObjectUtils::build_complete_type_detail(type_ann_builtin_DynamicType, ann_custom_DynamicType, type_name_DynamicType.to_string()); + CompleteStructHeader header_DynamicType; + header_DynamicType = TypeObjectUtils::build_complete_struct_header(TypeIdentifier(), detail_DynamicType); + CompleteStructMemberSeq member_seq_DynamicType; + { + TypeIdentifierPair type_ids_type_name; + ReturnCode_t return_code_type_name {eprosima::fastdds::dds::RETCODE_OK}; + return_code_type_name = + eprosima::fastdds::dds::DomainParticipantFactory::get_instance()->type_object_registry().get_type_identifiers( + "anonymous_string_unbounded", type_ids_type_name); + + if (eprosima::fastdds::dds::RETCODE_OK != return_code_type_name) + { + { + SBound bound = 0; + StringSTypeDefn string_sdefn = TypeObjectUtils::build_string_s_type_defn(bound); + if (eprosima::fastdds::dds::RETCODE_BAD_PARAMETER == + TypeObjectUtils::build_and_register_s_string_type_identifier(string_sdefn, + "anonymous_string_unbounded", type_ids_type_name)) + { + EPROSIMA_LOG_ERROR(XTYPES_TYPE_REPRESENTATION, + "anonymous_string_unbounded already registered in TypeObjectRegistry for a different type."); + } + } + } + StructMemberFlag member_flags_type_name = TypeObjectUtils::build_struct_member_flag(eprosima::fastdds::dds::xtypes::TryConstructFailAction::DISCARD, + false, false, false, false); + MemberId member_id_type_name = 0x00000000; + bool common_type_name_ec {false}; + CommonStructMember common_type_name {TypeObjectUtils::build_common_struct_member(member_id_type_name, member_flags_type_name, TypeObjectUtils::retrieve_complete_type_identifier(type_ids_type_name, common_type_name_ec))}; + if (!common_type_name_ec) + { + EPROSIMA_LOG_ERROR(XTYPES_TYPE_REPRESENTATION, "Structure type_name member TypeIdentifier inconsistent."); + return; + } + MemberName name_type_name = "type_name"; + eprosima::fastcdr::optional member_ann_builtin_type_name; + ann_custom_DynamicType.reset(); + CompleteMemberDetail detail_type_name = TypeObjectUtils::build_complete_member_detail(name_type_name, member_ann_builtin_type_name, ann_custom_DynamicType); + CompleteStructMember member_type_name = TypeObjectUtils::build_complete_struct_member(common_type_name, detail_type_name); + TypeObjectUtils::add_complete_struct_member(member_seq_DynamicType, member_type_name); + } + { + TypeIdentifierPair type_ids_type_identifier; + ReturnCode_t return_code_type_identifier {eprosima::fastdds::dds::RETCODE_OK}; + return_code_type_identifier = + eprosima::fastdds::dds::DomainParticipantFactory::get_instance()->type_object_registry().get_type_identifiers( + "anonymous_string_unbounded", type_ids_type_identifier); + + if (eprosima::fastdds::dds::RETCODE_OK != return_code_type_identifier) + { + { + SBound bound = 0; + StringSTypeDefn string_sdefn = TypeObjectUtils::build_string_s_type_defn(bound); + if (eprosima::fastdds::dds::RETCODE_BAD_PARAMETER == + TypeObjectUtils::build_and_register_s_string_type_identifier(string_sdefn, + "anonymous_string_unbounded", type_ids_type_identifier)) + { + EPROSIMA_LOG_ERROR(XTYPES_TYPE_REPRESENTATION, + "anonymous_string_unbounded already registered in TypeObjectRegistry for a different type."); + } + } + } + StructMemberFlag member_flags_type_identifier = TypeObjectUtils::build_struct_member_flag(eprosima::fastdds::dds::xtypes::TryConstructFailAction::DISCARD, + false, false, false, false); + MemberId member_id_type_identifier = 0x00000001; + bool common_type_identifier_ec {false}; + CommonStructMember common_type_identifier {TypeObjectUtils::build_common_struct_member(member_id_type_identifier, member_flags_type_identifier, TypeObjectUtils::retrieve_complete_type_identifier(type_ids_type_identifier, common_type_identifier_ec))}; + if (!common_type_identifier_ec) + { + EPROSIMA_LOG_ERROR(XTYPES_TYPE_REPRESENTATION, "Structure type_identifier member TypeIdentifier inconsistent."); + return; + } + MemberName name_type_identifier = "type_identifier"; + eprosima::fastcdr::optional member_ann_builtin_type_identifier; + ann_custom_DynamicType.reset(); + CompleteMemberDetail detail_type_identifier = TypeObjectUtils::build_complete_member_detail(name_type_identifier, member_ann_builtin_type_identifier, ann_custom_DynamicType); + CompleteStructMember member_type_identifier = TypeObjectUtils::build_complete_struct_member(common_type_identifier, detail_type_identifier); + TypeObjectUtils::add_complete_struct_member(member_seq_DynamicType, member_type_identifier); + } + { + TypeIdentifierPair type_ids_type_object; + ReturnCode_t return_code_type_object {eprosima::fastdds::dds::RETCODE_OK}; + return_code_type_object = + eprosima::fastdds::dds::DomainParticipantFactory::get_instance()->type_object_registry().get_type_identifiers( + "anonymous_string_unbounded", type_ids_type_object); + + if (eprosima::fastdds::dds::RETCODE_OK != return_code_type_object) + { + { + SBound bound = 0; + StringSTypeDefn string_sdefn = TypeObjectUtils::build_string_s_type_defn(bound); + if (eprosima::fastdds::dds::RETCODE_BAD_PARAMETER == + TypeObjectUtils::build_and_register_s_string_type_identifier(string_sdefn, + "anonymous_string_unbounded", type_ids_type_object)) + { + EPROSIMA_LOG_ERROR(XTYPES_TYPE_REPRESENTATION, + "anonymous_string_unbounded already registered in TypeObjectRegistry for a different type."); + } + } + } + StructMemberFlag member_flags_type_object = TypeObjectUtils::build_struct_member_flag(eprosima::fastdds::dds::xtypes::TryConstructFailAction::DISCARD, + false, false, false, false); + MemberId member_id_type_object = 0x00000002; + bool common_type_object_ec {false}; + CommonStructMember common_type_object {TypeObjectUtils::build_common_struct_member(member_id_type_object, member_flags_type_object, TypeObjectUtils::retrieve_complete_type_identifier(type_ids_type_object, common_type_object_ec))}; + if (!common_type_object_ec) + { + EPROSIMA_LOG_ERROR(XTYPES_TYPE_REPRESENTATION, "Structure type_object member TypeIdentifier inconsistent."); + return; + } + MemberName name_type_object = "type_object"; + eprosima::fastcdr::optional member_ann_builtin_type_object; + ann_custom_DynamicType.reset(); + CompleteMemberDetail detail_type_object = TypeObjectUtils::build_complete_member_detail(name_type_object, member_ann_builtin_type_object, ann_custom_DynamicType); + CompleteStructMember member_type_object = TypeObjectUtils::build_complete_struct_member(common_type_object, detail_type_object); + TypeObjectUtils::add_complete_struct_member(member_seq_DynamicType, member_type_object); + } + CompleteStructType struct_type_DynamicType = TypeObjectUtils::build_complete_struct_type(struct_flags_DynamicType, header_DynamicType, member_seq_DynamicType); + if (eprosima::fastdds::dds::RETCODE_BAD_PARAMETER == + TypeObjectUtils::build_and_register_struct_type_object(struct_type_DynamicType, type_name_DynamicType.to_string(), type_ids_DynamicType)) + { + EPROSIMA_LOG_ERROR(XTYPES_TYPE_REPRESENTATION, + "eprosima::ddsenabler::participants::DynamicType already registered in TypeObjectRegistry for a different type."); + } + } +} +// TypeIdentifier is returned by reference: dependent structures/unions are registered in this same method +void register_DynamicTypesCollection_type_identifier( + TypeIdentifierPair& type_ids_DynamicTypesCollection) +{ + + ReturnCode_t return_code_DynamicTypesCollection {eprosima::fastdds::dds::RETCODE_OK}; + return_code_DynamicTypesCollection = + eprosima::fastdds::dds::DomainParticipantFactory::get_instance()->type_object_registry().get_type_identifiers( + "eprosima::ddsenabler::participants::DynamicTypesCollection", type_ids_DynamicTypesCollection); + if (eprosima::fastdds::dds::RETCODE_OK != return_code_DynamicTypesCollection) + { + StructTypeFlag struct_flags_DynamicTypesCollection = TypeObjectUtils::build_struct_type_flag(eprosima::fastdds::dds::xtypes::ExtensibilityKind::APPENDABLE, + false, false); + QualifiedTypeName type_name_DynamicTypesCollection = "eprosima::ddsenabler::participants::DynamicTypesCollection"; + eprosima::fastcdr::optional type_ann_builtin_DynamicTypesCollection; + eprosima::fastcdr::optional ann_custom_DynamicTypesCollection; + CompleteTypeDetail detail_DynamicTypesCollection = TypeObjectUtils::build_complete_type_detail(type_ann_builtin_DynamicTypesCollection, ann_custom_DynamicTypesCollection, type_name_DynamicTypesCollection.to_string()); + CompleteStructHeader header_DynamicTypesCollection; + header_DynamicTypesCollection = TypeObjectUtils::build_complete_struct_header(TypeIdentifier(), detail_DynamicTypesCollection); + CompleteStructMemberSeq member_seq_DynamicTypesCollection; + { + TypeIdentifierPair type_ids_dynamic_types; + ReturnCode_t return_code_dynamic_types {eprosima::fastdds::dds::RETCODE_OK}; + return_code_dynamic_types = + eprosima::fastdds::dds::DomainParticipantFactory::get_instance()->type_object_registry().get_type_identifiers( + "anonymous_sequence_eprosima_ddsenabler_participants_DynamicType_unbounded", type_ids_dynamic_types); + + if (eprosima::fastdds::dds::RETCODE_OK != return_code_dynamic_types) + { + return_code_dynamic_types = + eprosima::fastdds::dds::DomainParticipantFactory::get_instance()->type_object_registry().get_type_identifiers( + "eprosima::ddsenabler::participants::DynamicType", type_ids_dynamic_types); + + if (eprosima::fastdds::dds::RETCODE_OK != return_code_dynamic_types) + { + eprosima::ddsenabler::participants::register_DynamicType_type_identifier(type_ids_dynamic_types); + } + bool element_identifier_anonymous_sequence_eprosima_ddsenabler_participants_DynamicType_unbounded_ec {false}; + TypeIdentifier* element_identifier_anonymous_sequence_eprosima_ddsenabler_participants_DynamicType_unbounded {new TypeIdentifier(TypeObjectUtils::retrieve_complete_type_identifier(type_ids_dynamic_types, element_identifier_anonymous_sequence_eprosima_ddsenabler_participants_DynamicType_unbounded_ec))}; + if (!element_identifier_anonymous_sequence_eprosima_ddsenabler_participants_DynamicType_unbounded_ec) + { + EPROSIMA_LOG_ERROR(XTYPES_TYPE_REPRESENTATION, "Sequence element TypeIdentifier inconsistent."); + return; + } + EquivalenceKind equiv_kind_anonymous_sequence_eprosima_ddsenabler_participants_DynamicType_unbounded = EK_COMPLETE; + if (TK_NONE == type_ids_dynamic_types.type_identifier2()._d()) + { + equiv_kind_anonymous_sequence_eprosima_ddsenabler_participants_DynamicType_unbounded = EK_BOTH; + } + CollectionElementFlag element_flags_anonymous_sequence_eprosima_ddsenabler_participants_DynamicType_unbounded = 0; + PlainCollectionHeader header_anonymous_sequence_eprosima_ddsenabler_participants_DynamicType_unbounded = TypeObjectUtils::build_plain_collection_header(equiv_kind_anonymous_sequence_eprosima_ddsenabler_participants_DynamicType_unbounded, element_flags_anonymous_sequence_eprosima_ddsenabler_participants_DynamicType_unbounded); + { + SBound bound = 0; + PlainSequenceSElemDefn seq_sdefn = TypeObjectUtils::build_plain_sequence_s_elem_defn(header_anonymous_sequence_eprosima_ddsenabler_participants_DynamicType_unbounded, bound, + eprosima::fastcdr::external(element_identifier_anonymous_sequence_eprosima_ddsenabler_participants_DynamicType_unbounded)); + if (eprosima::fastdds::dds::RETCODE_BAD_PARAMETER == + TypeObjectUtils::build_and_register_s_sequence_type_identifier(seq_sdefn, "anonymous_sequence_eprosima_ddsenabler_participants_DynamicType_unbounded", type_ids_dynamic_types)) + { + EPROSIMA_LOG_ERROR(XTYPES_TYPE_REPRESENTATION, + "anonymous_sequence_eprosima_ddsenabler_participants_DynamicType_unbounded already registered in TypeObjectRegistry for a different type."); + } + } + } + StructMemberFlag member_flags_dynamic_types = TypeObjectUtils::build_struct_member_flag(eprosima::fastdds::dds::xtypes::TryConstructFailAction::DISCARD, + false, false, false, false); + MemberId member_id_dynamic_types = 0x00000000; + bool common_dynamic_types_ec {false}; + CommonStructMember common_dynamic_types {TypeObjectUtils::build_common_struct_member(member_id_dynamic_types, member_flags_dynamic_types, TypeObjectUtils::retrieve_complete_type_identifier(type_ids_dynamic_types, common_dynamic_types_ec))}; + if (!common_dynamic_types_ec) + { + EPROSIMA_LOG_ERROR(XTYPES_TYPE_REPRESENTATION, "Structure dynamic_types member TypeIdentifier inconsistent."); + return; + } + MemberName name_dynamic_types = "dynamic_types"; + eprosima::fastcdr::optional member_ann_builtin_dynamic_types; + ann_custom_DynamicTypesCollection.reset(); + CompleteMemberDetail detail_dynamic_types = TypeObjectUtils::build_complete_member_detail(name_dynamic_types, member_ann_builtin_dynamic_types, ann_custom_DynamicTypesCollection); + CompleteStructMember member_dynamic_types = TypeObjectUtils::build_complete_struct_member(common_dynamic_types, detail_dynamic_types); + TypeObjectUtils::add_complete_struct_member(member_seq_DynamicTypesCollection, member_dynamic_types); + } + CompleteStructType struct_type_DynamicTypesCollection = TypeObjectUtils::build_complete_struct_type(struct_flags_DynamicTypesCollection, header_DynamicTypesCollection, member_seq_DynamicTypesCollection); + if (eprosima::fastdds::dds::RETCODE_BAD_PARAMETER == + TypeObjectUtils::build_and_register_struct_type_object(struct_type_DynamicTypesCollection, type_name_DynamicTypesCollection.to_string(), type_ids_DynamicTypesCollection)) + { + EPROSIMA_LOG_ERROR(XTYPES_TYPE_REPRESENTATION, + "eprosima::ddsenabler::participants::DynamicTypesCollection already registered in TypeObjectRegistry for a different type."); + } + } +} + +} // namespace participants + +} // namespace ddsenabler + +} // namespace eprosima + diff --git a/ddsenabler_yaml/include/ddsenabler_yaml/EnablerConfiguration.hpp b/ddsenabler_yaml/include/ddsenabler_yaml/EnablerConfiguration.hpp index 000df681..3b97c51b 100644 --- a/ddsenabler_yaml/include/ddsenabler_yaml/EnablerConfiguration.hpp +++ b/ddsenabler_yaml/include/ddsenabler_yaml/EnablerConfiguration.hpp @@ -27,9 +27,10 @@ #include #include -#include #include +#include + #include #include @@ -67,7 +68,7 @@ class EnablerConfiguration // Participants configurations std::shared_ptr simple_configuration; - std::shared_ptr enabler_configuration; + std::shared_ptr enabler_configuration; unsigned int n_threads = DEFAULT_N_THREADS; diff --git a/ddsenabler_yaml/include/ddsenabler_yaml/yaml_configuration_tags.hpp b/ddsenabler_yaml/include/ddsenabler_yaml/yaml_configuration_tags.hpp index b3d43c4c..33cc85ef 100644 --- a/ddsenabler_yaml/include/ddsenabler_yaml/yaml_configuration_tags.hpp +++ b/ddsenabler_yaml/include/ddsenabler_yaml/yaml_configuration_tags.hpp @@ -27,6 +27,7 @@ namespace yaml { constexpr const char* ENABLER_DDS_TAG("dds"); constexpr const char* ENABLER_ENABLER_TAG("ddsenabler"); +constexpr const char* ENABLER_INITIAL_PUBLISH_WAIT_TAG("initial-publish-wait"); } /* namespace yaml */ } /* namespace ddsenabler */ diff --git a/ddsenabler_yaml/src/cpp/EnablerConfiguration.cpp b/ddsenabler_yaml/src/cpp/EnablerConfiguration.cpp index 11daf37a..b9ed397a 100644 --- a/ddsenabler_yaml/src/cpp/EnablerConfiguration.cpp +++ b/ddsenabler_yaml/src/cpp/EnablerConfiguration.cpp @@ -35,6 +35,7 @@ #include #include + #include namespace eprosima { @@ -175,7 +176,7 @@ void EnablerConfiguration::load_ddsenabler_configuration( ///// // Create Enabler Participant Configuration - enabler_configuration = std::make_shared(); + enabler_configuration = std::make_shared(); enabler_configuration->id = "EnablerEnablerParticipant"; enabler_configuration->app_id = "DDS_ENABLER"; // TODO: fill metadata field once its content has been defined. @@ -226,8 +227,7 @@ void EnablerConfiguration::load_ddsenabler_configuration( ddspipe_configuration.init_enabled = true; - // Only trigger the DdsPipe's callbacks when discovering or removing writers - ddspipe_configuration.discovery_trigger = DiscoveryTrigger::WRITER; + ddspipe_configuration.discovery_trigger = DiscoveryTrigger::ANY; } catch (const std::exception& e) { @@ -241,7 +241,11 @@ void EnablerConfiguration::load_enabler_configuration( const Yaml& yml, const YamlReaderVersion& version) { - //Nothing to configure yet + // Get initial publish wait + if (YamlReader::is_tag_present(yml, ENABLER_INITIAL_PUBLISH_WAIT_TAG)) + { + enabler_configuration->initial_publish_wait = YamlReader::get_nonnegative_int(yml, ENABLER_INITIAL_PUBLISH_WAIT_TAG); + } } void EnablerConfiguration::load_specs_configuration( diff --git a/docs/context_broker_interface.rst b/docs/context_broker_interface.rst index d274c2b7..fb9bd256 100644 --- a/docs/context_broker_interface.rst +++ b/docs/context_broker_interface.rst @@ -50,6 +50,8 @@ This callback is invoked by the ``CBHandler`` through the ``CBWriter`` class. const char* topicName, const char* serializedType); +.. TODO: update with topic notification, topic request and type request callbacks + Log callback ============ The Log Callback is responsible for relaying all relevant logging information from the Fast DDS ecosystem to the From a9d2f43bd0f01666945cbb1b5a9f67364c86edfa Mon Sep 17 00:00:00 2001 From: Juan Lopez Fernandez Date: Thu, 9 Jan 2025 12:59:48 +0100 Subject: [PATCH 02/28] Skip null JSON elements Signed-off-by: Juan Lopez Fernandez --- ddsenabler_yaml/src/cpp/EnablerConfiguration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ddsenabler_yaml/src/cpp/EnablerConfiguration.cpp b/ddsenabler_yaml/src/cpp/EnablerConfiguration.cpp index b9ed397a..628ab9d5 100644 --- a/ddsenabler_yaml/src/cpp/EnablerConfiguration.cpp +++ b/ddsenabler_yaml/src/cpp/EnablerConfiguration.cpp @@ -116,7 +116,7 @@ YAML::Node convert_json_to_yaml( else { // Fallback for any other types (like null) - yaml_node[element.key()] = ""; + // Skip element to avoid exception when parsing YAML (YamlReader::is_tag_present expects non-null value) } } } From d363d3da512e4380200e9c46f676a54e20c183a4 Mon Sep 17 00:00:00 2001 From: Eugenio Collado Date: Mon, 27 Jan 2025 16:19:58 +0100 Subject: [PATCH 03/28] Resolve conflicts Signed-off-by: Eugenio Collado --- ddsenabler/test/ddsEnablerTests/DdsEnablerTest.cpp | 1 + ddsenabler_participants/src/cpp/CBHandler.cpp | 14 ++++++++++---- ddsenabler_participants/src/cpp/CBWriter.cpp | 6 ++++-- .../src/cpp/EnablerParticipant.cpp | 14 ++++++++++---- ddsenabler_participants/src/cpp/serialization.cpp | 10 ++++++---- ddsenabler_yaml/test/DdsEnablerYamlTest.cpp | 2 +- 6 files changed, 32 insertions(+), 15 deletions(-) diff --git a/ddsenabler/test/ddsEnablerTests/DdsEnablerTest.cpp b/ddsenabler/test/ddsEnablerTests/DdsEnablerTest.cpp index 9ce08a83..367e8c60 100644 --- a/ddsenabler/test/ddsEnablerTests/DdsEnablerTest.cpp +++ b/ddsenabler/test/ddsEnablerTests/DdsEnablerTest.cpp @@ -72,6 +72,7 @@ TEST_F(DDSEnablerTest, send_type1) TEST_F(DDSEnablerTest, send_many_type1) { ddsenablertester::num_samples_ = 1000; + // ddsenablertester::write_delay_ = 10; auto enabler = create_ddsenabler(); ASSERT_TRUE(enabler != nullptr); diff --git a/ddsenabler_participants/src/cpp/CBHandler.cpp b/ddsenabler_participants/src/cpp/CBHandler.cpp index c84c4111..f07c7ab3 100644 --- a/ddsenabler_participants/src/cpp/CBHandler.cpp +++ b/ddsenabler_participants/src/cpp/CBHandler.cpp @@ -190,7 +190,9 @@ bool CBHandler::get_serialized_data( dyn_type = it->second.second; fastdds::dds::DynamicData::_ref_type dyn_data; - if ((fastdds::dds::RETCODE_OK != fastdds::dds::json_deserialize(json, dyn_type, fastdds::dds::DynamicDataJsonFormat::EPROSIMA, dyn_data)) || !dyn_data) + if ((fastdds::dds::RETCODE_OK != + fastdds::dds::json_deserialize(json, dyn_type, fastdds::dds::DynamicDataJsonFormat::EPROSIMA, + dyn_data)) || !dyn_data) { EPROSIMA_LOG_ERROR(DDSENABLER_CB_HANDLER, "Failed to deserialize data for type " << type_name << " : json deserialization failed."); @@ -199,7 +201,8 @@ bool CBHandler::get_serialized_data( // TODO: double chekc XCDR2 is the right choice -> only supposed to work against fastdds 3, and appendable only working with XCDR2 fastdds::dds::DynamicPubSubType pubsub_type(dyn_type); - uint32_t payload_size = pubsub_type.calculate_serialized_size(&dyn_data, fastdds::dds::DataRepresentationId::XCDR2_DATA_REPRESENTATION); + uint32_t payload_size = pubsub_type.calculate_serialized_size(&dyn_data, + fastdds::dds::DataRepresentationId::XCDR2_DATA_REPRESENTATION); if (!payload_pool_->get_payload(payload_size, payload)) { @@ -280,11 +283,14 @@ bool CBHandler::register_type_nts_( if (_type_name != type_name) { EPROSIMA_LOG_ERROR(DDSENABLER_CB_HANDLER, - "Unexpected dynamic types collection format: " << type_name << " expected to be last item, found " << _type_name << " instead."); + "Unexpected dynamic types collection format: " << type_name << " expected to be last item, found " << _type_name << + " instead."); return false; } - fastdds::dds::DynamicType::_ref_type dyn_type = fastdds::dds::DynamicTypeBuilderFactory::get_instance()->create_type_w_type_object(_type_object)->build(); + fastdds::dds::DynamicType::_ref_type dyn_type = + fastdds::dds::DynamicTypeBuilderFactory::get_instance()->create_type_w_type_object(_type_object) + ->build(); if (!dyn_type) { EPROSIMA_LOG_ERROR(DDSENABLER_CB_HANDLER, diff --git a/ddsenabler_participants/src/cpp/CBWriter.cpp b/ddsenabler_participants/src/cpp/CBWriter.cpp index 3ae2f569..32d98dca 100644 --- a/ddsenabler_participants/src/cpp/CBWriter.cpp +++ b/ddsenabler_participants/src/cpp/CBWriter.cpp @@ -65,7 +65,8 @@ void CBWriter::write_schema( return; } - std::unique_ptr types_collection_payload = serialize_dynamic_types(types_collection); + std::unique_ptr types_collection_payload = serialize_dynamic_types( + types_collection); if (nullptr == types_collection_payload) { EPROSIMA_LOG_ERROR(DDSENABLER_CB_WRITER, @@ -76,7 +77,8 @@ void CBWriter::write_schema( std::stringstream ss_data_holder; ss_data_holder << std::setw(4); if (fastdds::dds::RETCODE_OK != - fastdds::dds::json_serialize(fastdds::dds::DynamicDataFactory::get_instance()->create_data(dyn_type), fastdds::dds::DynamicDataJsonFormat::EPROSIMA, ss_data_holder)) + fastdds::dds::json_serialize(fastdds::dds::DynamicDataFactory::get_instance()->create_data(dyn_type), + fastdds::dds::DynamicDataJsonFormat::EPROSIMA, ss_data_holder)) { EPROSIMA_LOG_ERROR(DDSENABLER_CB_WRITER, "Not able to generate data placeholder for type " << type_name << "."); diff --git a/ddsenabler_participants/src/cpp/EnablerParticipant.cpp b/ddsenabler_participants/src/cpp/EnablerParticipant.cpp index b9081061..ec1f4435 100644 --- a/ddsenabler_participants/src/cpp/EnablerParticipant.cpp +++ b/ddsenabler_participants/src/cpp/EnablerParticipant.cpp @@ -40,7 +40,8 @@ EnablerParticipant::EnablerParticipant( std::shared_ptr payload_pool, std::shared_ptr discovery_database, std::shared_ptr schema_handler) - : ddspipe::participants::SchemaParticipant(participant_configuration, payload_pool, discovery_database, schema_handler) + : ddspipe::participants::SchemaParticipant(participant_configuration, payload_pool, discovery_database, + schema_handler) { } @@ -78,7 +79,8 @@ bool EnablerParticipant::publish( if (!topic_req_callback_) { EPROSIMA_LOG_ERROR(DDSENABLER_ENABLER_PARTICIPANT, - "Failed to publish data in topic " << topic_name << " : topic is unknown and topic request callback not set."); + "Failed to publish data in topic " << topic_name << + " : topic is unknown and topic request callback not set."); return false; } @@ -106,11 +108,15 @@ bool EnablerParticipant::publish( this->discovery_database_->add_endpoint(rtps::CommonParticipant::simulate_endpoint(topic, this->id())); // Wait for reader to be created from discovery thread - cv_.wait(lck, [&] { return nullptr != (reader = lookup_reader_nts_(topic_name)); }); // TODO: handle case when stopped before processing queue item + cv_.wait(lck, [&] + { + return nullptr != (reader = lookup_reader_nts_(topic_name)); + }); // TODO: handle case when stopped before processing queue item // (Optionally) wait for writer created in DDS participant to match with external readers, to avoid losing this // message when not using transient durability - std::this_thread::sleep_for(std::chrono::milliseconds(std::static_pointer_cast(configuration_)->initial_publish_wait)); + std::this_thread::sleep_for(std::chrono::milliseconds(std::static_pointer_cast( + configuration_)->initial_publish_wait)); } auto data = std::make_unique(); diff --git a/ddsenabler_participants/src/cpp/serialization.cpp b/ddsenabler_participants/src/cpp/serialization.cpp index 564c2bf1..d7fe42bd 100644 --- a/ddsenabler_participants/src/cpp/serialization.cpp +++ b/ddsenabler_participants/src/cpp/serialization.cpp @@ -163,13 +163,13 @@ std::string serialize_type_identifier( const TypeIdentifier& type_identifier); TypeIdentifier deserialize_type_identifier( - const std::string& typeid_str); + const std::string& typeid_str); std::string serialize_type_object( const TypeObject& type_object); TypeObject deserialize_type_object( - const std::string& typeobj_str); + const std::string& typeobj_str); bool serialize_dynamic_type( const std::string& type_name, @@ -207,7 +207,8 @@ bool serialize_dynamic_type( dependency_type_identifier, dependency_type_object)) { - EPROSIMA_LOG_WARNING(DDSENABLER_SERIALIZATION, "Error getting TypeObject of dependency " << "for type " << type_name); + EPROSIMA_LOG_WARNING(DDSENABLER_SERIALIZATION, + "Error getting TypeObject of dependency " << "for type " << type_name); return false; } @@ -511,7 +512,8 @@ bool deserialize_dynamic_types( DynamicTypesCollection& dynamic_types) { fastdds::dds::TypeSupport type_support(new DynamicTypesCollectionPubSubType()); - fastdds::rtps::SerializedPayload_t serialized_payload = fastdds::rtps::SerializedPayload_t(dynamic_types_payload_size); + fastdds::rtps::SerializedPayload_t serialized_payload = fastdds::rtps::SerializedPayload_t( + dynamic_types_payload_size); serialized_payload.length = dynamic_types_payload_size; std::memcpy( serialized_payload.data, diff --git a/ddsenabler_yaml/test/DdsEnablerYamlTest.cpp b/ddsenabler_yaml/test/DdsEnablerYamlTest.cpp index bfec170e..6a7cad7c 100644 --- a/ddsenabler_yaml/test/DdsEnablerYamlTest.cpp +++ b/ddsenabler_yaml/test/DdsEnablerYamlTest.cpp @@ -172,7 +172,7 @@ TEST(DdsEnablerYamlTest, get_ddsenabler_incorrect_path_configuration_yaml) { const char* path_str = "incorrect/path/file.yaml"; - EXPECT_THROW({EnablerConfiguration configuration(path_str);}, eprosima::utils::ConfigurationException); + EXPECT_THROW({EnablerConfiguration configuration(path_str, false);}, eprosima::utils::ConfigurationException); } TEST(DdsEnablerYamlTest, get_ddsenabler_full_configuration_json) From 5746d4238a8ece3a9f9f8021311a384ec854fbd9 Mon Sep 17 00:00:00 2001 From: Eugenio Collado Date: Wed, 29 Jan 2025 16:00:30 +0100 Subject: [PATCH 04/28] Overload create_dds_enabler with configuration Signed-off-by: Eugenio Collado --- .../include/ddsenabler/dds_enabler_runner.hpp | 10 ++++ ddsenabler/src/cpp/dds_enabler_runner.cpp | 53 ++++++++++++++----- 2 files changed, 50 insertions(+), 13 deletions(-) diff --git a/ddsenabler/include/ddsenabler/dds_enabler_runner.hpp b/ddsenabler/include/ddsenabler/dds_enabler_runner.hpp index e0186f9c..ec9196eb 100644 --- a/ddsenabler/include/ddsenabler/dds_enabler_runner.hpp +++ b/ddsenabler/include/ddsenabler/dds_enabler_runner.hpp @@ -51,5 +51,15 @@ bool create_dds_enabler( participants::DdsLogFunc log_callback, std::unique_ptr& enabler); +bool create_dds_enabler( + yaml::EnablerConfiguration configuration, + participants::DdsNotification data_callback, + participants::DdsTypeNotification type_callback, + participants::DdsTopicNotification topic_callback, + participants::DdsTypeRequest type_req_callback, + participants::DdsTopicRequest topic_req_callback, + participants::DdsLogFunc log_callback, + std::unique_ptr& enabler); + } /* namespace ddsenabler */ } /* namespace eprosima */ diff --git a/ddsenabler/src/cpp/dds_enabler_runner.cpp b/ddsenabler/src/cpp/dds_enabler_runner.cpp index f1380616..60763fb3 100644 --- a/ddsenabler/src/cpp/dds_enabler_runner.cpp +++ b/ddsenabler/src/cpp/dds_enabler_runner.cpp @@ -47,13 +47,49 @@ bool create_dds_enabler( { dds_enabler_config_file = ddsEnablerConfigFile; } + // Load configuration from file + eprosima::ddsenabler::yaml::EnablerConfiguration configuration(dds_enabler_config_file); + + // Create DDS Enabler instance + if (!create_dds_enabler( + configuration, + data_callback, + type_callback, + topic_callback, + type_req_callback, + topic_req_callback, + log_callback, + enabler)) + { + EPROSIMA_LOG_ERROR(DDSENABLER_EXECUTION, + "Failed to create DDS Enabler from configuration file: " << dds_enabler_config_file); + return false; + } + // Set the file watcher to reload the configuration if the file changes + if (!enabler->set_file_watcher(dds_enabler_config_file)) + { + EPROSIMA_LOG_ERROR(DDSENABLER_EXECUTION, + "Failed to set file watcher."); + return false; + } + + return true; +} + +bool create_dds_enabler( + yaml::EnablerConfiguration configuration, + participants::DdsNotification data_callback, + participants::DdsTypeNotification type_callback, + participants::DdsTopicNotification topic_callback, + participants::DdsTypeRequest type_req_callback, + participants::DdsTopicRequest topic_req_callback, + participants::DdsLogFunc log_callback, + std::unique_ptr& enabler) +{ // Encapsulating execution in block to erase all memory correctly before closing process try { - // Load configuration from file - eprosima::ddsenabler::yaml::EnablerConfiguration configuration(dds_enabler_config_file); - // Verify that the configuration is correct eprosima::utils::Formatter error_msg; if (!configuration.is_valid(error_msg)) @@ -111,22 +147,13 @@ bool create_dds_enabler( enabler->set_type_request_callback(type_req_callback); enabler->set_topic_request_callback(topic_req_callback); - // Set the file watcher to reload the configuration if the file changes - if (!enabler->set_file_watcher(dds_enabler_config_file)) - { - EPROSIMA_LOG_ERROR(DDSENABLER_EXECUTION, - "Failed to set file watcher."); - return false; - } - EPROSIMA_LOG_INFO(DDSENABLER_EXECUTION, "DDS Enabler running."); } catch (const eprosima::utils::ConfigurationException& e) { EPROSIMA_LOG_ERROR(DDSENABLER_EXECUTION, - "Error Loading DDS Enabler Configuration from file " << dds_enabler_config_file << - ". Error message:\n " << e.what()); + "Error Loading DDS Enabler Configuration. Error message:\n " << e.what()); return false; } catch (const eprosima::utils::InitializationException& e) From 057fe21d4fd60131e08ace55d90e6ef91a0d92a5 Mon Sep 17 00:00:00 2001 From: Eugenio Collado Date: Wed, 29 Jan 2025 16:00:45 +0100 Subject: [PATCH 05/28] Fix tests Signed-off-by: Eugenio Collado --- ddsenabler/test/DDSEnablerTester.hpp | 76 +- .../test/ddsEnablerTests/DdsEnablerTest.cpp | 21 +- .../test/ddsEnablerTests/ReloadConfig.cpp | 60 +- .../DdsEnablerTypedTest.cpp | 2 +- ddsenabler_participants/test/CMakeLists.txt | 6 +- .../test/DdsEnablerParticipantsTest.cpp | 463 ++++++----- .../test/types/DDSEnablerTestTypes.hpp | 580 +++++++++++++ .../test/types/DDSEnablerTestTypes.idl | 19 + .../test/types/DDSEnablerTestTypesCdrAux.hpp | 67 ++ .../test/types/DDSEnablerTestTypesCdrAux.ipp | 362 +++++++++ .../types/DDSEnablerTestTypesPubSubTypes.cxx | 760 ++++++++++++++++++ .../types/DDSEnablerTestTypesPubSubTypes.hpp | 366 +++++++++ .../DDSEnablerTestTypesTypeObjectSupport.cxx | 317 ++++++++ .../DDSEnablerTestTypesTypeObjectSupport.hpp | 92 +++ ddsenabler_yaml/test/DdsEnablerYamlTest.cpp | 2 +- 15 files changed, 2941 insertions(+), 252 deletions(-) create mode 100644 ddsenabler_participants/test/types/DDSEnablerTestTypes.hpp create mode 100644 ddsenabler_participants/test/types/DDSEnablerTestTypes.idl create mode 100644 ddsenabler_participants/test/types/DDSEnablerTestTypesCdrAux.hpp create mode 100644 ddsenabler_participants/test/types/DDSEnablerTestTypesCdrAux.ipp create mode 100644 ddsenabler_participants/test/types/DDSEnablerTestTypesPubSubTypes.cxx create mode 100644 ddsenabler_participants/test/types/DDSEnablerTestTypesPubSubTypes.hpp create mode 100644 ddsenabler_participants/test/types/DDSEnablerTestTypesTypeObjectSupport.cxx create mode 100644 ddsenabler_participants/test/types/DDSEnablerTestTypesTypeObjectSupport.hpp diff --git a/ddsenabler/test/DDSEnablerTester.hpp b/ddsenabler/test/DDSEnablerTester.hpp index b80c3ff0..b4a663ec 100644 --- a/ddsenabler/test/DDSEnablerTester.hpp +++ b/ddsenabler/test/DDSEnablerTester.hpp @@ -24,7 +24,7 @@ #include #include -#include "DDSEnabler.hpp" +#include "ddsenabler/dds_enabler_runner.hpp" using namespace eprosima::ddspipe; using namespace eprosima::ddsenabler; @@ -79,13 +79,9 @@ class DDSEnablerTester : public ::testing::Test eprosima::ddsenabler::yaml::EnablerConfiguration configuration(yml); configuration.simple_configuration->domain = DOMAIN_; - auto close_handler = std::make_shared(); - - auto enabler = std::make_unique(configuration, close_handler); - - // Bind the static callbacks (no captures allowed) - enabler->set_data_callback(test_data_callback); - enabler->set_type_callback(test_type_callback); + // Create DDS Enabler + std::unique_ptr enabler; + bool result = create_dds_enabler(configuration, test_data_callback, test_type_callback, test_topic_notification_callback, test_type_request_callback, test_topic_request_callback, test_log_callback, enabler); return enabler; } @@ -249,11 +245,29 @@ class DDSEnablerTester : public ::testing::Test return true; } - // Static type callback + // eprosima::ddsenabler::participants::DdsNotification data_callback; + static void test_data_callback( + const char* topicName, + const char* json, + int64_t publishTime) + { + if (current_test_instance_) + { + std::lock_guard lock(current_test_instance_->data_received_mutex_); + + current_test_instance_->received_data_++; + std::cout << "Data callback received: " << topicName << ", Total data: " << + current_test_instance_->received_data_ << std::endl; + } + } + + // eprosima::ddsenabler::participants::DdsTypeNotification data_callback; static void test_type_callback( const char* typeName, - const char* topicName, - const char* serializedType) + const char* serializedType, + const unsigned char* serializedTypeInternal, + uint32_t serializedTypeInternalSize, + const char* dataPlaceholder) { if (current_test_instance_) { @@ -265,21 +279,39 @@ class DDSEnablerTester : public ::testing::Test } } - // Static data callback - static void test_data_callback( + // eprosima::ddsenabler::participants::DdsTopicNotification topic_callback; + static void test_topic_notification_callback( + const char* topicName, const char* typeName, + const char* serializedQos) + { + } + + // eprosima::ddsenabler::participants::DdsTopicRequest topic_req_callback; + static void test_topic_request_callback( const char* topicName, - const char* json, - int64_t publishTime) + char*& typeName, + char*& serializedQos) { - if (current_test_instance_) - { - std::lock_guard lock(current_test_instance_->data_received_mutex_); + } - current_test_instance_->received_data_++; - std::cout << "Data callback received: " << typeName << ", Total data: " << - current_test_instance_->received_data_ << std::endl; - } + // eprosima::ddsenabler::participants::DdsTypeRequest type_req_callback; + static void test_type_request_callback( + const char* typeName, + unsigned char*& serializedTypeInternal, + uint32_t& serializedTypeInternalSize) + { + } + + + //eprosima::ddsenabler::participants::DdsLogFunc log_callback; + static void test_log_callback( + const char* fileName, + int lineNo, + const char* funcName, + int category, + const char* msg) + { } int get_received_types() diff --git a/ddsenabler/test/ddsEnablerTests/DdsEnablerTest.cpp b/ddsenabler/test/ddsEnablerTests/DdsEnablerTest.cpp index 367e8c60..01c56ea4 100644 --- a/ddsenabler/test/ddsEnablerTests/DdsEnablerTest.cpp +++ b/ddsenabler/test/ddsEnablerTests/DdsEnablerTest.cpp @@ -59,7 +59,7 @@ TEST_F(DDSEnablerTest, send_type1) ASSERT_TRUE(create_publisher(a_type)); - ASSERT_EQ(get_received_types(), 0); + ASSERT_EQ(get_received_types(), 1); ASSERT_EQ(get_received_data(), 0); // Send data @@ -72,7 +72,6 @@ TEST_F(DDSEnablerTest, send_type1) TEST_F(DDSEnablerTest, send_many_type1) { ddsenablertester::num_samples_ = 1000; - // ddsenablertester::write_delay_ = 10; auto enabler = create_ddsenabler(); ASSERT_TRUE(enabler != nullptr); @@ -82,7 +81,7 @@ TEST_F(DDSEnablerTest, send_many_type1) ASSERT_TRUE(create_publisher(a_type)); - ASSERT_EQ(get_received_types(), 0); + ASSERT_EQ(get_received_types(), 1); ASSERT_EQ(get_received_data(), 0); // Send data @@ -104,7 +103,7 @@ TEST_F(DDSEnablerTest, send_type2) ASSERT_TRUE(create_publisher(a_type)); - ASSERT_EQ(get_received_types(), 0); + ASSERT_EQ(get_received_types(), 1); ASSERT_EQ(get_received_data(), 0); // Send data @@ -126,7 +125,7 @@ TEST_F(DDSEnablerTest, send_type3) ASSERT_TRUE(create_publisher(a_type)); - ASSERT_EQ(get_received_types(), 0); + ASSERT_EQ(get_received_types(), 1); ASSERT_EQ(get_received_data(), 0); // Send data @@ -154,7 +153,7 @@ TEST_F(DDSEnablerTest, send_type4) ASSERT_TRUE(create_publisher(a_type)); - ASSERT_EQ(get_received_types(), 0); + ASSERT_EQ(get_received_types(), 1); ASSERT_EQ(get_received_data(), 0); // Send data @@ -176,7 +175,7 @@ TEST_F(DDSEnablerTest, send_multiple_types) ASSERT_TRUE(create_publisher(a_type1)); - ASSERT_EQ(get_received_types(), 0); + ASSERT_EQ(get_received_types(), 1); ASSERT_EQ(get_received_data(), 0); // Send data @@ -190,7 +189,7 @@ TEST_F(DDSEnablerTest, send_multiple_types) ASSERT_TRUE(create_publisher(a_type2)); - ASSERT_EQ(get_received_types(), 1); + ASSERT_EQ(get_received_types(), 2); ASSERT_EQ(get_received_data(), num_samples_); // Send data @@ -204,7 +203,7 @@ TEST_F(DDSEnablerTest, send_multiple_types) ASSERT_TRUE(create_publisher(a_type3)); - ASSERT_EQ(get_received_types(), 2); + ASSERT_EQ(get_received_types(), 3); ASSERT_EQ(get_received_data(), num_samples_ * 2); // Send data @@ -218,7 +217,7 @@ TEST_F(DDSEnablerTest, send_multiple_types) ASSERT_TRUE(create_publisher(a_type4)); - ASSERT_EQ(get_received_types(), 3); + ASSERT_EQ(get_received_types(), 4); ASSERT_EQ(get_received_data(), num_samples_ * 3); // Send data @@ -240,7 +239,7 @@ TEST_F(DDSEnablerTest, send_repeated_type) ASSERT_TRUE(create_publisher(a_type)); - ASSERT_EQ(get_received_types(), 0); + ASSERT_EQ(get_received_types(), 1); ASSERT_EQ(get_received_data(), 0); // Send data diff --git a/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp b/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp index 6fb1ac82..f6780afe 100644 --- a/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp +++ b/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp @@ -22,22 +22,60 @@ #include #include -// Static type callback -void type_callback( - const char* typeName, +static uint32_t data_callback_count = 0; + +// Empty callbacks just to create the enabler being tested + +// eprosima::ddsenabler::participants::DdsNotification data_callback; +void test_data_callback( const char* topicName, - const char* serializedType) + const char* json, + int64_t publishTime) { } -static uint32_t data_callback_count = 0; +// eprosima::ddsenabler::participants::DdsTypeNotification data_callback; +void test_type_callback( + const char* typeName, + const char* serializedType, + const unsigned char* serializedTypeInternal, + uint32_t serializedTypeInternalSize, + const char* dataPlaceholder) +{ +} -// Static data callback -void data_callback( +// eprosima::ddsenabler::participants::DdsTopicNotification topic_callback; +void test_topic_notification_callback( + const char* topicName, const char* typeName, + const char* serializedQos) +{ +} + +// eprosima::ddsenabler::participants::DdsTopicRequest topic_req_callback; +void test_topic_request_callback( const char* topicName, - const char* json, - int64_t publishTime) + char*& typeName, + char*& serializedQos) +{ +} + +// eprosima::ddsenabler::participants::DdsTypeRequest type_req_callback; +void test_type_request_callback( + const char* typeName, + unsigned char*& serializedTypeInternal, + uint32_t& serializedTypeInternalSize) +{ +} + + +//eprosima::ddsenabler::participants::DdsLogFunc log_callback; +void test_log_callback( + const char* fileName, + int lineNo, + const char* funcName, + int category, + const char* msg) { } @@ -137,7 +175,7 @@ TEST(ReloadConfig, json) // Create DDS Enabler std::unique_ptr enabler; - ASSERT_TRUE(create_dds_enabler(configfile, data_callback, type_callback, nullptr, enabler)); + ASSERT_TRUE(create_dds_enabler(configfile, test_data_callback, test_type_callback, test_topic_notification_callback, test_type_request_callback, test_topic_request_callback, test_log_callback, enabler)); // Create DDSEnablerAccessor to access protected configuration auto enabler_accessor = static_cast(enabler.get()); @@ -168,7 +206,7 @@ TEST(ReloadConfig, yaml) // Create DDS Enabler std::unique_ptr enabler; - bool result = create_dds_enabler(configfile, data_callback, type_callback, nullptr, enabler); + bool result = create_dds_enabler(configfile, test_data_callback, test_type_callback, test_topic_notification_callback, test_type_request_callback, test_topic_request_callback, test_log_callback, enabler); ASSERT_TRUE(result); // Create DDSEnablerAccessor to access protected configuration diff --git a/ddsenabler/test/ddsEnablerTypedTests/DdsEnablerTypedTest.cpp b/ddsenabler/test/ddsEnablerTypedTests/DdsEnablerTypedTest.cpp index 5e6a023a..26e4bbc2 100644 --- a/ddsenabler/test/ddsEnablerTypedTests/DdsEnablerTypedTest.cpp +++ b/ddsenabler/test/ddsEnablerTypedTests/DdsEnablerTypedTest.cpp @@ -47,7 +47,7 @@ class DDSEnablerTypedTest : public ddsenablertester::DDSEnablerTester \ ASSERT_TRUE(create_publisher(a_type)); \ \ - ASSERT_EQ(get_received_types(), 0); \ + ASSERT_EQ(get_received_types(), 1); \ ASSERT_EQ(get_received_data(), 0); \ \ /* Send data */ \ diff --git a/ddsenabler_participants/test/CMakeLists.txt b/ddsenabler_participants/test/CMakeLists.txt index c3a720a7..598a9322 100644 --- a/ddsenabler_participants/test/CMakeLists.txt +++ b/ddsenabler_participants/test/CMakeLists.txt @@ -20,14 +20,16 @@ set(TEST_NAME DdsEnablerParticipantsTest) set(TEST_SOURCES ${PROJECT_SOURCE_DIR}/test/DdsEnablerParticipantsTest.cpp + ${PROJECT_SOURCE_DIR}/test/types/DDSEnablerTestTypesPubSubTypes.cxx + ${PROJECT_SOURCE_DIR}/test/types/DDSEnablerTestTypesTypeObjectSupport.cxx ) set(TEST_LIST ddsenabler_participants_cb_handler_creation ddsenabler_participants_add_new_schemas - ddsenabler_participants_add_same_type_id_schema - ddsenabler_participants_add_same_type_name_schema + ddsenabler_participants_add_same_type_schema ddsenabler_participants_add_data_with_schema + ddsenabler_participants_add_data_without_schema ddsenabler_participants_write_schema_first_time ddsenabler_participants_write_schema_repeated ) diff --git a/ddsenabler_participants/test/DdsEnablerParticipantsTest.cpp b/ddsenabler_participants/test/DdsEnablerParticipantsTest.cpp index c6a630b7..96f24c2b 100644 --- a/ddsenabler_participants/test/DdsEnablerParticipantsTest.cpp +++ b/ddsenabler_participants/test/DdsEnablerParticipantsTest.cpp @@ -16,6 +16,9 @@ #include #include +#include +#include +#include #include #include #include @@ -26,6 +29,7 @@ #include #include + #include #include @@ -33,6 +37,10 @@ #include #include +#include + +#include "types/DDSEnablerTestTypesPubSubTypes.hpp" + using namespace eprosima; using namespace eprosima::fastdds::dds; using namespace eprosima::ddsenabler; @@ -60,21 +68,198 @@ class CBWriterTest : public participants::CBWriter // Expose protected methods using CBWriter::write_data; using CBWriter::write_schema; - using CBWriter::stored_schemas_; }; class CBHandlerTest : public participants::CBHandler { public: - // Inherit the constructor from CBHandler - using participants::CBHandler::CBHandler; + CBHandlerTest( + const participants::CBHandlerConfiguration& config, + const std::shared_ptr& payload_pool) + : participants::CBHandler(config, payload_pool) + { + current_test_instance_ = this; + + cb_writer_ = std::make_unique(); + + // Set the callbacks + set_data_callback(test_data_callback); + set_type_callback(test_type_callback); + set_topic_callback(test_topic_notification_callback); + set_type_request_callback(test_type_request_callback); + + + } // Expose protected members using participants::CBHandler::schemas_; using participants::CBHandler::cb_writer_; + using participants::CBHandler::unique_sequence_number_; + + // eprosima::ddsenabler::participants::DdsTypeRequest type_req_callback; + static void test_type_request_callback( + const char* typeName, + unsigned char*& serializedTypeInternal, + uint32_t& serializedTypeInternalSize) + { + if(current_test_instance_ == nullptr) + return; + + current_test_instance_->type_request_called++; + } + + // eprosima::ddsenabler::participants::DdsNotification data_callback; + static void test_data_callback( + const char* topicName, + const char* json, + int64_t publishTime) + { + if(current_test_instance_ == nullptr) + return; + + current_test_instance_->data_called_++; + } + + // eprosima::ddsenabler::participants::DdsTypeNotification data_callback; + static void test_type_callback( + const char* typeName, + const char* serializedType, + const unsigned char* serializedTypeInternal, + uint32_t serializedTypeInternalSize, + const char* dataPlaceholder) + { + if(current_test_instance_ == nullptr) + return; + + current_test_instance_->type_called_++; + } + + // eprosima::ddsenabler::participants::DdsTopicNotification topic_callback; + static void test_topic_notification_callback( + const char* topicName, + const char* typeName, + const char* serializedQos) + { + if(current_test_instance_ == nullptr) + return; + + current_test_instance_->topic_called_++; + } + + uint32_t type_request_called = 0; + uint32_t data_called_ = 0; + uint32_t type_called_ = 0; + uint32_t topic_called_ = 0; + + + // Pointer to the current test instance (for use in the static callback) + static CBHandlerTest* current_test_instance_; }; +CBHandlerTest* CBHandlerTest::current_test_instance_ = nullptr; + +struct KnownType +{ + DynamicType::_ref_type dyn_type_; + TypeSupport type_sup_; + DataWriter* writer_ = nullptr; +}; + +bool test_create_publisher( + KnownType& a_type, + Topic** topic, + std::string topic_name_suffix = "topic_name") +{ + DomainParticipant* participant = DomainParticipantFactory::get_instance() + ->create_participant(0, PARTICIPANT_QOS_DEFAULT); + if (participant == nullptr) + { + std::cout << "ERROR DDSEnablerTester: create_participant" << std::endl; + return false; + } + + if (RETCODE_OK != a_type.type_sup_.register_type(participant)) + { + std::cout << "ERROR DDSEnablerTester: fail to register type: " << + a_type.type_sup_.get_type_name() << std::endl; + return false; + } + + Publisher* publisher = participant->create_publisher(PUBLISHER_QOS_DEFAULT); + if (publisher == nullptr) + { + std::cout << "ERROR DDSEnablerTester: create_publisher: " << + a_type.type_sup_.get_type_name() << std::endl; + return false; + } + + std::ostringstream topic_name; + topic_name << a_type.type_sup_.get_type_name() << topic_name_suffix; + *topic = participant->create_topic(topic_name.str(), a_type.type_sup_.get_type_name(), TOPIC_QOS_DEFAULT); + std::cout << (*topic)->get_name() << std::endl; + if (*topic == nullptr) + { + std::cout << "ERROR DDSEnablerTester: create_topic: " << + a_type.type_sup_.get_type_name() << std::endl; + return false; + } + + DataWriterQos wqos = publisher->get_default_datawriter_qos(); + a_type.writer_ = publisher->create_datawriter(*topic, wqos); + if (a_type.writer_ == nullptr) + { + std::cout << "ERROR DDSEnablerTester: create_datawriter: " << + a_type.type_sup_.get_type_name() << std::endl; + return false; + } + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + return true; +} + +ddspipe::core::types::DdsTopic new_schema( + int num_type, + DynamicType::_ref_type& dynamic_type, + xtypes::TypeIdentifierPair& type_id_pair) +{ + KnownType k_type; + switch(num_type) + { + case 3: + { + k_type.type_sup_.reset(new DDSEnablerTestType3PubSubType()); + break; + } + case 2: + { + k_type.type_sup_.reset(new DDSEnablerTestType2PubSubType()); + break; + } + case 1: + default: + { + k_type.type_sup_.reset(new DDSEnablerTestType1PubSubType()); + break; + } + } + + eprosima::fastdds::dds::Topic* topic = nullptr; + + std::string str_topic_name = "topic_name" + std::to_string(num_type); + test_create_publisher(k_type, &topic, str_topic_name); + + ddspipe::core::types::DdsTopic pipe_topic; + pipe_topic.m_topic_name = topic->get_name(); + pipe_topic.type_name = topic->get_type_name(); + + eprosima::fastdds::dds::DomainParticipantFactory::get_instance()->type_object_registry().get_type_identifiers( + topic->get_type_name(), type_id_pair); + pipe_topic.type_identifiers = type_id_pair; + + dynamic_type = create_schema(pipe_topic); + return pipe_topic; +} + TEST(DdsEnablerParticipantsTest, ddsenabler_participants_cb_handler_creation) { // Create Payload Pool @@ -103,49 +288,32 @@ TEST(DdsEnablerParticipantsTest, ddsenabler_participants_add_new_schemas) auto cb_handler_ = std::make_shared(handler_config, payload_pool_); ASSERT_NE(cb_handler_, nullptr); - // Replace CBWriter with test version - std::unique_ptr cb_writer_test = std::make_unique(); - ASSERT_NE(cb_writer_test, nullptr); - cb_handler_->cb_writer_ = std::move(cb_writer_test); - - ddspipe::core::types::DdsTopic topic; - topic.m_topic_name = "topic1"; - topic.type_name = "type1"; - xtypes::TypeIdentifier type_id; - xtypes::EquivalenceHash hash = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - type_id.equivalence_hash(hash); - topic.type_identifiers.type_identifier1(type_id); - + xtypes::TypeIdentifierPair type_id_pair; DynamicType::_ref_type dynamic_type; - dynamic_type = create_schema(topic); - ASSERT_NE(dynamic_type, nullptr); + new_schema(1, dynamic_type, type_id_pair); ASSERT_TRUE(cb_handler_->schemas_.empty()); ASSERT_EQ(cb_handler_->schemas_.size(), 0); - cb_handler_->add_schema(dynamic_type, type_id); + cb_handler_->add_schema(dynamic_type, type_id_pair.type_identifier1()); ASSERT_FALSE(cb_handler_->schemas_.empty()); ASSERT_EQ(cb_handler_->schemas_.size(), 1); + ASSERT_EQ(cb_handler_->type_called_, 1); + - ddspipe::core::types::DdsTopic topic2; - topic2.m_topic_name = "topic2"; - topic2.type_name = "type2"; - xtypes::TypeIdentifier type_id2; - xtypes::EquivalenceHash hash2 = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; - type_id2.equivalence_hash(hash2); - topic2.type_identifiers.type_identifier1(type_id2); + xtypes::TypeIdentifierPair type_id_pair2; DynamicType::_ref_type dynamic_type2; - dynamic_type2 = create_schema(topic2); - ASSERT_NE(dynamic_type2, nullptr); + new_schema(2, dynamic_type2, type_id_pair2); ASSERT_FALSE(cb_handler_->schemas_.empty()); ASSERT_EQ(cb_handler_->schemas_.size(), 1); - cb_handler_->add_schema(dynamic_type2, type_id2); + cb_handler_->add_schema(dynamic_type2, type_id_pair2.type_identifier1()); ASSERT_FALSE(cb_handler_->schemas_.empty()); ASSERT_EQ(cb_handler_->schemas_.size(), 2); + ASSERT_EQ(cb_handler_->type_called_, 2); } -TEST(DdsEnablerParticipantsTest, ddsenabler_participants_add_same_type_id_schema) +TEST(DdsEnablerParticipantsTest, ddsenabler_participants_add_same_type_schema) { // Create Payload Pool auto payload_pool_ = std::make_shared(); @@ -158,48 +326,32 @@ TEST(DdsEnablerParticipantsTest, ddsenabler_participants_add_same_type_id_schema auto cb_handler_ = std::make_shared(handler_config, payload_pool_); ASSERT_NE(cb_handler_, nullptr); - // Replace CBWriter with test version - std::unique_ptr cb_writer_test = std::make_unique(); - ASSERT_NE(cb_writer_test, nullptr); - cb_handler_->cb_writer_ = std::move(cb_writer_test); - - ddspipe::core::types::DdsTopic topic; - topic.m_topic_name = "topic1"; - topic.type_name = "type1"; - xtypes::TypeIdentifier type_id; - xtypes::EquivalenceHash hash = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - type_id.equivalence_hash(hash); - topic.type_identifiers.type_identifier1(type_id); - + xtypes::TypeIdentifierPair type_id_pair; DynamicType::_ref_type dynamic_type; - dynamic_type = create_schema(topic); - ASSERT_NE(dynamic_type, nullptr); + new_schema(1, dynamic_type, type_id_pair); ASSERT_TRUE(cb_handler_->schemas_.empty()); ASSERT_EQ(cb_handler_->schemas_.size(), 0); - cb_handler_->add_schema(dynamic_type, type_id); + cb_handler_->add_schema(dynamic_type, type_id_pair.type_identifier1()); ASSERT_FALSE(cb_handler_->schemas_.empty()); ASSERT_EQ(cb_handler_->schemas_.size(), 1); + ASSERT_EQ(cb_handler_->type_called_, 1); + - ddspipe::core::types::DdsTopic topic2; - topic2.m_topic_name = "topic2"; - topic2.type_name = "type2"; - xtypes::TypeIdentifier type_id2; - type_id2.equivalence_hash(hash); - topic2.type_identifiers.type_identifier1(type_id2); + xtypes::TypeIdentifierPair type_id_pair2; DynamicType::_ref_type dynamic_type2; - dynamic_type2 = create_schema(topic2); - ASSERT_NE(dynamic_type2, nullptr); + new_schema(1, dynamic_type2, type_id_pair2); ASSERT_FALSE(cb_handler_->schemas_.empty()); ASSERT_EQ(cb_handler_->schemas_.size(), 1); - cb_handler_->add_schema(dynamic_type2, type_id2); + cb_handler_->add_schema(dynamic_type2, type_id_pair2.type_identifier1()); ASSERT_FALSE(cb_handler_->schemas_.empty()); ASSERT_EQ(cb_handler_->schemas_.size(), 1); + ASSERT_EQ(cb_handler_->type_called_, 1); } -TEST(DdsEnablerParticipantsTest, ddsenabler_participants_add_same_type_name_schema) +TEST(DdsEnablerParticipantsTest, ddsenabler_participants_add_data_with_schema) { // Create Payload Pool auto payload_pool_ = std::make_shared(); @@ -212,49 +364,43 @@ TEST(DdsEnablerParticipantsTest, ddsenabler_participants_add_same_type_name_sche auto cb_handler_ = std::make_shared(handler_config, payload_pool_); ASSERT_NE(cb_handler_, nullptr); - // Replace CBWriter with test version - std::unique_ptr cb_writer_test = std::make_unique(); - ASSERT_NE(cb_writer_test, nullptr); - cb_handler_->cb_writer_ = std::move(cb_writer_test); - - ddspipe::core::types::DdsTopic topic; - topic.m_topic_name = "topic1"; - topic.type_name = "type1"; - xtypes::TypeIdentifier type_id; - xtypes::EquivalenceHash hash = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - type_id.equivalence_hash(hash); - topic.type_identifiers.type_identifier1(type_id); - + xtypes::TypeIdentifierPair type_id_pair; DynamicType::_ref_type dynamic_type; - dynamic_type = create_schema(topic); - ASSERT_NE(dynamic_type, nullptr); + ddspipe::core::types::DdsTopic pipe_topic = new_schema(1, dynamic_type, type_id_pair); ASSERT_TRUE(cb_handler_->schemas_.empty()); ASSERT_EQ(cb_handler_->schemas_.size(), 0); - cb_handler_->add_schema(dynamic_type, type_id); + cb_handler_->add_schema(dynamic_type, type_id_pair.type_identifier1()); ASSERT_FALSE(cb_handler_->schemas_.empty()); ASSERT_EQ(cb_handler_->schemas_.size(), 1); + ASSERT_EQ(cb_handler_->type_called_, 1); - ddspipe::core::types::DdsTopic topic2; - topic2.m_topic_name = "topic2"; - topic2.type_name = "type1"; - xtypes::TypeIdentifier type_id2; - xtypes::EquivalenceHash hash2 = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; - type_id2.equivalence_hash(hash2); - topic2.type_identifiers.type_identifier1(type_id2); + auto data = std::make_unique(); + eprosima::ddspipe::core::types::Payload payload; - DynamicType::_ref_type dynamic_type2; - dynamic_type2 = create_schema(topic2); - ASSERT_NE(dynamic_type2, nullptr); + std::string content = + "{\n" + " \"color\": \"RED\",\n" + " \"shapesize\": 30,\n" + " \"x\": 198,\n" + " \"y\": 189\n" + "}"; - ASSERT_FALSE(cb_handler_->schemas_.empty()); - ASSERT_EQ(cb_handler_->schemas_.size(), 1); - cb_handler_->add_schema(dynamic_type2, type_id2); - ASSERT_FALSE(cb_handler_->schemas_.empty()); - ASSERT_EQ(cb_handler_->schemas_.size(), 2); + payload.length = static_cast(content.length()); + payload.max_size = static_cast(content.length()); + payload.data = (unsigned char*)reinterpret_cast(content.data()); + + payload_pool_->get_payload(payload, data->payload); + payload.data = nullptr; // Set to nullptr after copy to avoid free on destruction + data->payload_owner = payload_pool_.get(); + + ASSERT_NO_THROW(cb_handler_->add_data(pipe_topic, *data)); + // If the data has been added, the sequence number should be 1 + ASSERT_TRUE(cb_handler_->unique_sequence_number_ == 1); + ASSERT_EQ(cb_handler_->data_called_, 1); } -TEST(DdsEnablerParticipantsTest, ddsenabler_participants_add_data_with_schema) +TEST(DdsEnablerParticipantsTest, ddsenabler_participants_add_data_without_schema) { // Create Payload Pool auto payload_pool_ = std::make_shared(); @@ -267,28 +413,9 @@ TEST(DdsEnablerParticipantsTest, ddsenabler_participants_add_data_with_schema) auto cb_handler_ = std::make_shared(handler_config, payload_pool_); ASSERT_NE(cb_handler_, nullptr); - // Replace CBWriter with test version - std::unique_ptr cb_writer_test = std::make_unique(); - ASSERT_NE(cb_writer_test, nullptr); - cb_handler_->cb_writer_ = std::move(cb_writer_test); - - ddspipe::core::types::DdsTopic topic; - topic.m_topic_name = "topic1"; - topic.type_name = "type1"; - xtypes::TypeIdentifier type_id; - xtypes::EquivalenceHash hash = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - type_id.equivalence_hash(hash); - topic.type_identifiers.type_identifier1(type_id); - + xtypes::TypeIdentifierPair type_id_pair; DynamicType::_ref_type dynamic_type; - dynamic_type = create_schema(topic); - ASSERT_NE(dynamic_type, nullptr); - - ASSERT_TRUE(cb_handler_->schemas_.empty()); - ASSERT_EQ(cb_handler_->schemas_.size(), 0); - cb_handler_->add_schema(dynamic_type, type_id); - ASSERT_FALSE(cb_handler_->schemas_.empty()); - ASSERT_EQ(cb_handler_->schemas_.size(), 1); + ddspipe::core::types::DdsTopic pipe_topic = new_schema(1, dynamic_type, type_id_pair); auto data = std::make_unique(); eprosima::ddspipe::core::types::Payload payload; @@ -303,13 +430,17 @@ TEST(DdsEnablerParticipantsTest, ddsenabler_participants_add_data_with_schema) payload.length = static_cast(content.length()); payload.max_size = static_cast(content.length()); - payload.data = (unsigned char*)reinterpret_cast(content.data()); + payload.data = new unsigned char[payload.length]; + std::memcpy(payload.data, content.data(), payload.length); payload_pool_->get_payload(payload, data->payload); payload.data = nullptr; // Set to nullptr after copy to avoid free on destruction data->payload_owner = payload_pool_.get(); - ASSERT_NO_THROW(cb_handler_->add_data(topic, *data)); + ASSERT_NO_THROW(cb_handler_->add_data(pipe_topic, *data)); + // As there is no schema associated, the sequence number should still be 0 + ASSERT_TRUE(cb_handler_->unique_sequence_number_ == 0); + ASSERT_EQ(cb_handler_->data_called_, 0); } TEST(DdsEnablerParticipantsTest, ddsenabler_participants_write_schema_first_time) @@ -318,20 +449,16 @@ TEST(DdsEnablerParticipantsTest, ddsenabler_participants_write_schema_first_time auto payload_pool_ = std::make_shared(); ASSERT_NE(payload_pool_, nullptr); - std::unique_ptr cb_writer_test = std::make_unique(); - ASSERT_NE(cb_writer_test, nullptr); + // Create CB Handler configuration + participants::CBHandlerConfiguration handler_config; - ddspipe::core::types::DdsTopic topic; - topic.m_topic_name = "topic1"; - topic.type_name = "type1"; - xtypes::TypeIdentifier type_id; - xtypes::EquivalenceHash hash = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - type_id.equivalence_hash(hash); - topic.type_identifiers.type_identifier1(type_id); + // Create CB Handler + auto cb_handler_ = std::make_shared(handler_config, payload_pool_); + ASSERT_NE(cb_handler_, nullptr); + xtypes::TypeIdentifierPair type_id_pair; DynamicType::_ref_type dynamic_type; - dynamic_type = create_schema(topic); - ASSERT_NE(dynamic_type, nullptr); + ddspipe::core::types::DdsTopic pipe_topic = new_schema(1, dynamic_type, type_id_pair); auto data = std::make_unique(); eprosima::ddspipe::core::types::Payload payload; @@ -355,29 +482,19 @@ TEST(DdsEnablerParticipantsTest, ddsenabler_participants_write_schema_first_time participants::CBMessage msg; msg.sequence_number = 1; msg.publish_time = data->source_timestamp; - msg.topic = topic; + msg.topic = pipe_topic; msg.instanceHandle = data->instanceHandle; msg.source_guid = data->source_guid; payload_pool_->get_payload(data->payload, msg.payload); msg.payload_owner = payload_pool_.get(); - ASSERT_TRUE(cb_writer_test->stored_schemas_.empty()); - ASSERT_EQ(cb_writer_test->stored_schemas_.size(), 0); - cb_writer_test->write_schema(msg, dynamic_type); - ASSERT_FALSE(cb_writer_test->stored_schemas_.empty()); - ASSERT_EQ(cb_writer_test->stored_schemas_.size(), 1); - - ddspipe::core::types::DdsTopic topic2; - topic2.m_topic_name = "topic2"; - topic2.type_name = "type2"; - xtypes::TypeIdentifier type_id2; - xtypes::EquivalenceHash hash2 = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; - type_id2.equivalence_hash(hash2); - topic2.type_identifiers.type_identifier1(type_id2); + cb_handler_->cb_writer_->write_data(msg, dynamic_type); + // The data will be successfully written as the dynamic type exists and we are bypassing the handler schema check + ASSERT_EQ(cb_handler_->data_called_, 1); + xtypes::TypeIdentifierPair type_id_pair2; DynamicType::_ref_type dynamic_type2; - dynamic_type2 = create_schema(topic2); - ASSERT_NE(dynamic_type2, nullptr); + ddspipe::core::types::DdsTopic pipe_topic2 = new_schema(2, dynamic_type2, type_id_pair2); auto data2 = std::make_unique(); eprosima::ddspipe::core::types::Payload payload2; @@ -393,83 +510,21 @@ TEST(DdsEnablerParticipantsTest, ddsenabler_participants_write_schema_first_time participants::CBMessage msg2; msg2.sequence_number = 1; msg2.publish_time = data2->source_timestamp; - msg2.topic = topic2; + msg2.topic = pipe_topic2; msg2.instanceHandle = data2->instanceHandle; msg2.source_guid = data2->source_guid; payload_pool_->get_payload(data2->payload, msg2.payload); msg2.payload_owner = payload_pool_.get(); - ASSERT_FALSE(cb_writer_test->stored_schemas_.empty()); - ASSERT_EQ(cb_writer_test->stored_schemas_.size(), 1); - cb_writer_test->write_schema(msg2, dynamic_type2); - ASSERT_FALSE(cb_writer_test->stored_schemas_.empty()); - ASSERT_EQ(cb_writer_test->stored_schemas_.size(), 2); -} - -TEST(DdsEnablerParticipantsTest, ddsenabler_participants_write_schema_repeated) -{ - // Create Payload Pool - auto payload_pool_ = std::make_shared(); - ASSERT_NE(payload_pool_, nullptr); - - std::unique_ptr cb_writer_test = std::make_unique(); - ASSERT_NE(cb_writer_test, nullptr); - - ddspipe::core::types::DdsTopic topic; - topic.m_topic_name = "topic1"; - topic.type_name = "type1"; - xtypes::TypeIdentifier type_id; - xtypes::EquivalenceHash hash = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - type_id.equivalence_hash(hash); - topic.type_identifiers.type_identifier1(type_id); - - DynamicType::_ref_type dynamic_type; - dynamic_type = create_schema(topic); - ASSERT_NE(dynamic_type, nullptr); - - auto data = std::make_unique(); - eprosima::ddspipe::core::types::Payload payload; - - std::string content = - "{\n" - " \"color\": \"RED\",\n" - " \"shapesize\": 30,\n" - " \"x\": 198,\n" - " \"y\": 189\n" - "}"; - - payload.length = static_cast(content.length()); - payload.max_size = static_cast(content.length()); - payload.data = (unsigned char*)reinterpret_cast(content.data()); - - payload_pool_->get_payload(payload, data->payload); - payload.data = nullptr; // Set to nullptr after copy to avoid free on destruction - data->payload_owner = payload_pool_.get(); - - participants::CBMessage msg; - msg.sequence_number = 1; - msg.publish_time = data->source_timestamp; - msg.topic = topic; - msg.instanceHandle = data->instanceHandle; - msg.source_guid = data->source_guid; - payload_pool_->get_payload(data->payload, msg.payload); - msg.payload_owner = payload_pool_.get(); - - ASSERT_TRUE(cb_writer_test->stored_schemas_.empty()); - ASSERT_EQ(cb_writer_test->stored_schemas_.size(), 0); - cb_writer_test->write_schema(msg, dynamic_type); - ASSERT_FALSE(cb_writer_test->stored_schemas_.empty()); - ASSERT_EQ(cb_writer_test->stored_schemas_.size(), 1); - - cb_writer_test->write_schema(msg, dynamic_type); - ASSERT_FALSE(cb_writer_test->stored_schemas_.empty()); - ASSERT_EQ(cb_writer_test->stored_schemas_.size(), 1); + cb_handler_->cb_writer_->write_data(msg2, dynamic_type2); + ASSERT_EQ(cb_handler_->data_called_, 2); } int main( int argc, char** argv) { + eprosima::fastdds::dds::Log::SetVerbosity(Log::Kind::Warning); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/ddsenabler_participants/test/types/DDSEnablerTestTypes.hpp b/ddsenabler_participants/test/types/DDSEnablerTestTypes.hpp new file mode 100644 index 00000000..840fc12b --- /dev/null +++ b/ddsenabler_participants/test/types/DDSEnablerTestTypes.hpp @@ -0,0 +1,580 @@ +// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*! + * @file DDSEnablerTestTypes.hpp + * This header file contains the declaration of the described types in the IDL file. + * + * This file was generated by the tool fastddsgen. + */ + +#ifndef FAST_DDS_GENERATED__DDSENABLERTESTTYPES_HPP +#define FAST_DDS_GENERATED__DDSENABLERTESTTYPES_HPP + +#include +#include +#include +#include +#include + +#if defined(_WIN32) +#if defined(EPROSIMA_USER_DLL_EXPORT) +#define eProsima_user_DllExport __declspec( dllexport ) +#else +#define eProsima_user_DllExport +#endif // EPROSIMA_USER_DLL_EXPORT +#else +#define eProsima_user_DllExport +#endif // _WIN32 + +#if defined(_WIN32) +#if defined(EPROSIMA_USER_DLL_EXPORT) +#if defined(DDSENABLERTESTTYPES_SOURCE) +#define DDSENABLERTESTTYPES_DllAPI __declspec( dllexport ) +#else +#define DDSENABLERTESTTYPES_DllAPI __declspec( dllimport ) +#endif // DDSENABLERTESTTYPES_SOURCE +#else +#define DDSENABLERTESTTYPES_DllAPI +#endif // EPROSIMA_USER_DLL_EXPORT +#else +#define DDSENABLERTESTTYPES_DllAPI +#endif // _WIN32 + +/*! + * @brief This class represents the structure DDSEnablerTestType1 defined by the user in the IDL file. + * @ingroup DDSEnablerTestTypes + */ +class DDSEnablerTestType1 +{ +public: + + /*! + * @brief Default constructor. + */ + eProsima_user_DllExport DDSEnablerTestType1() + { + } + + /*! + * @brief Default destructor. + */ + eProsima_user_DllExport ~DDSEnablerTestType1() + { + } + + /*! + * @brief Copy constructor. + * @param x Reference to the object DDSEnablerTestType1 that will be copied. + */ + eProsima_user_DllExport DDSEnablerTestType1( + const DDSEnablerTestType1& x) + { + m_value = x.m_value; + + } + + /*! + * @brief Move constructor. + * @param x Reference to the object DDSEnablerTestType1 that will be copied. + */ + eProsima_user_DllExport DDSEnablerTestType1( + DDSEnablerTestType1&& x) noexcept + { + m_value = x.m_value; + } + + /*! + * @brief Copy assignment. + * @param x Reference to the object DDSEnablerTestType1 that will be copied. + */ + eProsima_user_DllExport DDSEnablerTestType1& operator =( + const DDSEnablerTestType1& x) + { + + m_value = x.m_value; + + return *this; + } + + /*! + * @brief Move assignment. + * @param x Reference to the object DDSEnablerTestType1 that will be copied. + */ + eProsima_user_DllExport DDSEnablerTestType1& operator =( + DDSEnablerTestType1&& x) noexcept + { + + m_value = x.m_value; + return *this; + } + + /*! + * @brief Comparison operator. + * @param x DDSEnablerTestType1 object to compare. + */ + eProsima_user_DllExport bool operator ==( + const DDSEnablerTestType1& x) const + { + return (m_value == x.m_value); + } + + /*! + * @brief Comparison operator. + * @param x DDSEnablerTestType1 object to compare. + */ + eProsima_user_DllExport bool operator !=( + const DDSEnablerTestType1& x) const + { + return !(*this == x); + } + + /*! + * @brief This function sets a value in member value + * @param _value New value for member value + */ + eProsima_user_DllExport void value( + int16_t _value) + { + m_value = _value; + } + + /*! + * @brief This function returns the value of member value + * @return Value of member value + */ + eProsima_user_DllExport int16_t value() const + { + return m_value; + } + + /*! + * @brief This function returns a reference to member value + * @return Reference to member value + */ + eProsima_user_DllExport int16_t& value() + { + return m_value; + } + + + +private: + + int16_t m_value{0}; + +}; +/*! + * @brief This class represents the structure DDSEnablerTestType2 defined by the user in the IDL file. + * @ingroup DDSEnablerTestTypes + */ +class DDSEnablerTestType2 +{ +public: + + /*! + * @brief Default constructor. + */ + eProsima_user_DllExport DDSEnablerTestType2() + { + } + + /*! + * @brief Default destructor. + */ + eProsima_user_DllExport ~DDSEnablerTestType2() + { + } + + /*! + * @brief Copy constructor. + * @param x Reference to the object DDSEnablerTestType2 that will be copied. + */ + eProsima_user_DllExport DDSEnablerTestType2( + const DDSEnablerTestType2& x) + { + m_value = x.m_value; + + } + + /*! + * @brief Move constructor. + * @param x Reference to the object DDSEnablerTestType2 that will be copied. + */ + eProsima_user_DllExport DDSEnablerTestType2( + DDSEnablerTestType2&& x) noexcept + { + m_value = std::move(x.m_value); + } + + /*! + * @brief Copy assignment. + * @param x Reference to the object DDSEnablerTestType2 that will be copied. + */ + eProsima_user_DllExport DDSEnablerTestType2& operator =( + const DDSEnablerTestType2& x) + { + + m_value = x.m_value; + + return *this; + } + + /*! + * @brief Move assignment. + * @param x Reference to the object DDSEnablerTestType2 that will be copied. + */ + eProsima_user_DllExport DDSEnablerTestType2& operator =( + DDSEnablerTestType2&& x) noexcept + { + + m_value = std::move(x.m_value); + return *this; + } + + /*! + * @brief Comparison operator. + * @param x DDSEnablerTestType2 object to compare. + */ + eProsima_user_DllExport bool operator ==( + const DDSEnablerTestType2& x) const + { + return (m_value == x.m_value); + } + + /*! + * @brief Comparison operator. + * @param x DDSEnablerTestType2 object to compare. + */ + eProsima_user_DllExport bool operator !=( + const DDSEnablerTestType2& x) const + { + return !(*this == x); + } + + /*! + * @brief This function copies the value in member value + * @param _value New value to be copied in member value + */ + eProsima_user_DllExport void value( + const std::string& _value) + { + m_value = _value; + } + + /*! + * @brief This function moves the value in member value + * @param _value New value to be moved in member value + */ + eProsima_user_DllExport void value( + std::string&& _value) + { + m_value = std::move(_value); + } + + /*! + * @brief This function returns a constant reference to member value + * @return Constant reference to member value + */ + eProsima_user_DllExport const std::string& value() const + { + return m_value; + } + + /*! + * @brief This function returns a reference to member value + * @return Reference to member value + */ + eProsima_user_DllExport std::string& value() + { + return m_value; + } + + + +private: + + std::string m_value; + +}; +/*! + * @brief This class represents the structure DDSEnablerTestType3 defined by the user in the IDL file. + * @ingroup DDSEnablerTestTypes + */ +class DDSEnablerTestType3 +{ +public: + + /*! + * @brief Default constructor. + */ + eProsima_user_DllExport DDSEnablerTestType3() + { + } + + /*! + * @brief Default destructor. + */ + eProsima_user_DllExport ~DDSEnablerTestType3() + { + } + + /*! + * @brief Copy constructor. + * @param x Reference to the object DDSEnablerTestType3 that will be copied. + */ + eProsima_user_DllExport DDSEnablerTestType3( + const DDSEnablerTestType3& x) + { + m_value = x.m_value; + + } + + /*! + * @brief Move constructor. + * @param x Reference to the object DDSEnablerTestType3 that will be copied. + */ + eProsima_user_DllExport DDSEnablerTestType3( + DDSEnablerTestType3&& x) noexcept + { + m_value = std::move(x.m_value); + } + + /*! + * @brief Copy assignment. + * @param x Reference to the object DDSEnablerTestType3 that will be copied. + */ + eProsima_user_DllExport DDSEnablerTestType3& operator =( + const DDSEnablerTestType3& x) + { + + m_value = x.m_value; + + return *this; + } + + /*! + * @brief Move assignment. + * @param x Reference to the object DDSEnablerTestType3 that will be copied. + */ + eProsima_user_DllExport DDSEnablerTestType3& operator =( + DDSEnablerTestType3&& x) noexcept + { + + m_value = std::move(x.m_value); + return *this; + } + + /*! + * @brief Comparison operator. + * @param x DDSEnablerTestType3 object to compare. + */ + eProsima_user_DllExport bool operator ==( + const DDSEnablerTestType3& x) const + { + return (m_value == x.m_value); + } + + /*! + * @brief Comparison operator. + * @param x DDSEnablerTestType3 object to compare. + */ + eProsima_user_DllExport bool operator !=( + const DDSEnablerTestType3& x) const + { + return !(*this == x); + } + + /*! + * @brief This function copies the value in member value + * @param _value New value to be copied in member value + */ + eProsima_user_DllExport void value( + const std::array& _value) + { + m_value = _value; + } + + /*! + * @brief This function moves the value in member value + * @param _value New value to be moved in member value + */ + eProsima_user_DllExport void value( + std::array&& _value) + { + m_value = std::move(_value); + } + + /*! + * @brief This function returns a constant reference to member value + * @return Constant reference to member value + */ + eProsima_user_DllExport const std::array& value() const + { + return m_value; + } + + /*! + * @brief This function returns a reference to member value + * @return Reference to member value + */ + eProsima_user_DllExport std::array& value() + { + return m_value; + } + + + +private: + + std::array m_value{0}; + +}; +/*! + * @brief This class represents the structure DDSEnablerTestType4 defined by the user in the IDL file. + * @ingroup DDSEnablerTestTypes + */ +class DDSEnablerTestType4 +{ +public: + + /*! + * @brief Default constructor. + */ + eProsima_user_DllExport DDSEnablerTestType4() + { + } + + /*! + * @brief Default destructor. + */ + eProsima_user_DllExport ~DDSEnablerTestType4() + { + } + + /*! + * @brief Copy constructor. + * @param x Reference to the object DDSEnablerTestType4 that will be copied. + */ + eProsima_user_DllExport DDSEnablerTestType4( + const DDSEnablerTestType4& x) + { + m_value = x.m_value; + + } + + /*! + * @brief Move constructor. + * @param x Reference to the object DDSEnablerTestType4 that will be copied. + */ + eProsima_user_DllExport DDSEnablerTestType4( + DDSEnablerTestType4&& x) noexcept + { + m_value = std::move(x.m_value); + } + + /*! + * @brief Copy assignment. + * @param x Reference to the object DDSEnablerTestType4 that will be copied. + */ + eProsima_user_DllExport DDSEnablerTestType4& operator =( + const DDSEnablerTestType4& x) + { + + m_value = x.m_value; + + return *this; + } + + /*! + * @brief Move assignment. + * @param x Reference to the object DDSEnablerTestType4 that will be copied. + */ + eProsima_user_DllExport DDSEnablerTestType4& operator =( + DDSEnablerTestType4&& x) noexcept + { + + m_value = std::move(x.m_value); + return *this; + } + + /*! + * @brief Comparison operator. + * @param x DDSEnablerTestType4 object to compare. + */ + eProsima_user_DllExport bool operator ==( + const DDSEnablerTestType4& x) const + { + return (m_value == x.m_value); + } + + /*! + * @brief Comparison operator. + * @param x DDSEnablerTestType4 object to compare. + */ + eProsima_user_DllExport bool operator !=( + const DDSEnablerTestType4& x) const + { + return !(*this == x); + } + + /*! + * @brief This function copies the value in member value + * @param _value New value to be copied in member value + */ + eProsima_user_DllExport void value( + const DDSEnablerTestType1& _value) + { + m_value = _value; + } + + /*! + * @brief This function moves the value in member value + * @param _value New value to be moved in member value + */ + eProsima_user_DllExport void value( + DDSEnablerTestType1&& _value) + { + m_value = std::move(_value); + } + + /*! + * @brief This function returns a constant reference to member value + * @return Constant reference to member value + */ + eProsima_user_DllExport const DDSEnablerTestType1& value() const + { + return m_value; + } + + /*! + * @brief This function returns a reference to member value + * @return Reference to member value + */ + eProsima_user_DllExport DDSEnablerTestType1& value() + { + return m_value; + } + + + +private: + + DDSEnablerTestType1 m_value; + +}; + +#endif // _FAST_DDS_GENERATED_DDSENABLERTESTTYPES_HPP_ + + diff --git a/ddsenabler_participants/test/types/DDSEnablerTestTypes.idl b/ddsenabler_participants/test/types/DDSEnablerTestTypes.idl new file mode 100644 index 00000000..ec4db993 --- /dev/null +++ b/ddsenabler_participants/test/types/DDSEnablerTestTypes.idl @@ -0,0 +1,19 @@ +struct DDSEnablerTestType1 +{ + short value; +}; + +struct DDSEnablerTestType2 +{ + string value; +}; + +struct DDSEnablerTestType3 +{ + long value[10]; +}; + +struct DDSEnablerTestType4 +{ + DDSEnablerTestType1 value; +}; diff --git a/ddsenabler_participants/test/types/DDSEnablerTestTypesCdrAux.hpp b/ddsenabler_participants/test/types/DDSEnablerTestTypesCdrAux.hpp new file mode 100644 index 00000000..e46c7a78 --- /dev/null +++ b/ddsenabler_participants/test/types/DDSEnablerTestTypesCdrAux.hpp @@ -0,0 +1,67 @@ +// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*! + * @file DDSEnablerTestTypesCdrAux.hpp + * This source file contains some definitions of CDR related functions. + * + * This file was generated by the tool fastddsgen. + */ + +#ifndef FAST_DDS_GENERATED__DDSENABLERTESTTYPESCDRAUX_HPP +#define FAST_DDS_GENERATED__DDSENABLERTESTTYPESCDRAUX_HPP + +#include "DDSEnablerTestTypes.hpp" + +constexpr uint32_t DDSEnablerTestType2_max_cdr_typesize {264UL}; +constexpr uint32_t DDSEnablerTestType2_max_key_cdr_typesize {0UL}; + +constexpr uint32_t DDSEnablerTestType3_max_cdr_typesize {44UL}; +constexpr uint32_t DDSEnablerTestType3_max_key_cdr_typesize {0UL}; + +constexpr uint32_t DDSEnablerTestType1_max_cdr_typesize {6UL}; +constexpr uint32_t DDSEnablerTestType1_max_key_cdr_typesize {0UL}; + +constexpr uint32_t DDSEnablerTestType4_max_cdr_typesize {10UL}; +constexpr uint32_t DDSEnablerTestType4_max_key_cdr_typesize {0UL}; + + +namespace eprosima { +namespace fastcdr { + +class Cdr; +class CdrSizeCalculator; + +eProsima_user_DllExport void serialize_key( + eprosima::fastcdr::Cdr& scdr, + const DDSEnablerTestType1& data); + +eProsima_user_DllExport void serialize_key( + eprosima::fastcdr::Cdr& scdr, + const DDSEnablerTestType2& data); + +eProsima_user_DllExport void serialize_key( + eprosima::fastcdr::Cdr& scdr, + const DDSEnablerTestType3& data); + +eProsima_user_DllExport void serialize_key( + eprosima::fastcdr::Cdr& scdr, + const DDSEnablerTestType4& data); + + +} // namespace fastcdr +} // namespace eprosima + +#endif // FAST_DDS_GENERATED__DDSENABLERTESTTYPESCDRAUX_HPP + diff --git a/ddsenabler_participants/test/types/DDSEnablerTestTypesCdrAux.ipp b/ddsenabler_participants/test/types/DDSEnablerTestTypesCdrAux.ipp new file mode 100644 index 00000000..848c0afe --- /dev/null +++ b/ddsenabler_participants/test/types/DDSEnablerTestTypesCdrAux.ipp @@ -0,0 +1,362 @@ +// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*! + * @file DDSEnablerTestTypesCdrAux.ipp + * This source file contains some declarations of CDR related functions. + * + * This file was generated by the tool fastddsgen. + */ + +#ifndef FAST_DDS_GENERATED__DDSENABLERTESTTYPESCDRAUX_IPP +#define FAST_DDS_GENERATED__DDSENABLERTESTTYPESCDRAUX_IPP + +#include "DDSEnablerTestTypesCdrAux.hpp" + +#include +#include + + +#include +using namespace eprosima::fastcdr::exception; + +namespace eprosima { +namespace fastcdr { + +template<> +eProsima_user_DllExport size_t calculate_serialized_size( + eprosima::fastcdr::CdrSizeCalculator& calculator, + const DDSEnablerTestType1& data, + size_t& current_alignment) +{ + static_cast(data); + + eprosima::fastcdr::EncodingAlgorithmFlag previous_encoding = calculator.get_encoding(); + size_t calculated_size {calculator.begin_calculate_type_serialized_size( + eprosima::fastcdr::CdrVersion::XCDRv2 == calculator.get_cdr_version() ? + eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 : + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR, + current_alignment)}; + + + calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(0), + data.value(), current_alignment); + + + calculated_size += calculator.end_calculate_type_serialized_size(previous_encoding, current_alignment); + + return calculated_size; +} + +template<> +eProsima_user_DllExport void serialize( + eprosima::fastcdr::Cdr& scdr, + const DDSEnablerTestType1& data) +{ + eprosima::fastcdr::Cdr::state current_state(scdr); + scdr.begin_serialize_type(current_state, + eprosima::fastcdr::CdrVersion::XCDRv2 == scdr.get_cdr_version() ? + eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 : + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR); + + scdr + << eprosima::fastcdr::MemberId(0) << data.value() +; + scdr.end_serialize_type(current_state); +} + +template<> +eProsima_user_DllExport void deserialize( + eprosima::fastcdr::Cdr& cdr, + DDSEnablerTestType1& data) +{ + cdr.deserialize_type(eprosima::fastcdr::CdrVersion::XCDRv2 == cdr.get_cdr_version() ? + eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 : + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR, + [&data](eprosima::fastcdr::Cdr& dcdr, const eprosima::fastcdr::MemberId& mid) -> bool + { + bool ret_value = true; + switch (mid.id) + { + case 0: + dcdr >> data.value(); + break; + + default: + ret_value = false; + break; + } + return ret_value; + }); +} + +void serialize_key( + eprosima::fastcdr::Cdr& scdr, + const DDSEnablerTestType1& data) +{ + + static_cast(scdr); + static_cast(data); + scdr << data.value(); + +} + + +template<> +eProsima_user_DllExport size_t calculate_serialized_size( + eprosima::fastcdr::CdrSizeCalculator& calculator, + const DDSEnablerTestType2& data, + size_t& current_alignment) +{ + static_cast(data); + + eprosima::fastcdr::EncodingAlgorithmFlag previous_encoding = calculator.get_encoding(); + size_t calculated_size {calculator.begin_calculate_type_serialized_size( + eprosima::fastcdr::CdrVersion::XCDRv2 == calculator.get_cdr_version() ? + eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 : + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR, + current_alignment)}; + + + calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(0), + data.value(), current_alignment); + + + calculated_size += calculator.end_calculate_type_serialized_size(previous_encoding, current_alignment); + + return calculated_size; +} + +template<> +eProsima_user_DllExport void serialize( + eprosima::fastcdr::Cdr& scdr, + const DDSEnablerTestType2& data) +{ + eprosima::fastcdr::Cdr::state current_state(scdr); + scdr.begin_serialize_type(current_state, + eprosima::fastcdr::CdrVersion::XCDRv2 == scdr.get_cdr_version() ? + eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 : + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR); + + scdr + << eprosima::fastcdr::MemberId(0) << data.value() +; + scdr.end_serialize_type(current_state); +} + +template<> +eProsima_user_DllExport void deserialize( + eprosima::fastcdr::Cdr& cdr, + DDSEnablerTestType2& data) +{ + cdr.deserialize_type(eprosima::fastcdr::CdrVersion::XCDRv2 == cdr.get_cdr_version() ? + eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 : + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR, + [&data](eprosima::fastcdr::Cdr& dcdr, const eprosima::fastcdr::MemberId& mid) -> bool + { + bool ret_value = true; + switch (mid.id) + { + case 0: + dcdr >> data.value(); + break; + + default: + ret_value = false; + break; + } + return ret_value; + }); +} + +void serialize_key( + eprosima::fastcdr::Cdr& scdr, + const DDSEnablerTestType2& data) +{ + + static_cast(scdr); + static_cast(data); + scdr << data.value(); + +} + + +template<> +eProsima_user_DllExport size_t calculate_serialized_size( + eprosima::fastcdr::CdrSizeCalculator& calculator, + const DDSEnablerTestType3& data, + size_t& current_alignment) +{ + static_cast(data); + + eprosima::fastcdr::EncodingAlgorithmFlag previous_encoding = calculator.get_encoding(); + size_t calculated_size {calculator.begin_calculate_type_serialized_size( + eprosima::fastcdr::CdrVersion::XCDRv2 == calculator.get_cdr_version() ? + eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 : + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR, + current_alignment)}; + + + calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(0), + data.value(), current_alignment); + + + calculated_size += calculator.end_calculate_type_serialized_size(previous_encoding, current_alignment); + + return calculated_size; +} + +template<> +eProsima_user_DllExport void serialize( + eprosima::fastcdr::Cdr& scdr, + const DDSEnablerTestType3& data) +{ + eprosima::fastcdr::Cdr::state current_state(scdr); + scdr.begin_serialize_type(current_state, + eprosima::fastcdr::CdrVersion::XCDRv2 == scdr.get_cdr_version() ? + eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 : + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR); + + scdr + << eprosima::fastcdr::MemberId(0) << data.value() +; + scdr.end_serialize_type(current_state); +} + +template<> +eProsima_user_DllExport void deserialize( + eprosima::fastcdr::Cdr& cdr, + DDSEnablerTestType3& data) +{ + cdr.deserialize_type(eprosima::fastcdr::CdrVersion::XCDRv2 == cdr.get_cdr_version() ? + eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 : + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR, + [&data](eprosima::fastcdr::Cdr& dcdr, const eprosima::fastcdr::MemberId& mid) -> bool + { + bool ret_value = true; + switch (mid.id) + { + case 0: + dcdr >> data.value(); + break; + + default: + ret_value = false; + break; + } + return ret_value; + }); +} + +void serialize_key( + eprosima::fastcdr::Cdr& scdr, + const DDSEnablerTestType3& data) +{ + + static_cast(scdr); + static_cast(data); + scdr << data.value(); + +} + + +template<> +eProsima_user_DllExport size_t calculate_serialized_size( + eprosima::fastcdr::CdrSizeCalculator& calculator, + const DDSEnablerTestType4& data, + size_t& current_alignment) +{ + static_cast(data); + + eprosima::fastcdr::EncodingAlgorithmFlag previous_encoding = calculator.get_encoding(); + size_t calculated_size {calculator.begin_calculate_type_serialized_size( + eprosima::fastcdr::CdrVersion::XCDRv2 == calculator.get_cdr_version() ? + eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 : + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR, + current_alignment)}; + + + calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(0), + data.value(), current_alignment); + + + calculated_size += calculator.end_calculate_type_serialized_size(previous_encoding, current_alignment); + + return calculated_size; +} + +template<> +eProsima_user_DllExport void serialize( + eprosima::fastcdr::Cdr& scdr, + const DDSEnablerTestType4& data) +{ + eprosima::fastcdr::Cdr::state current_state(scdr); + scdr.begin_serialize_type(current_state, + eprosima::fastcdr::CdrVersion::XCDRv2 == scdr.get_cdr_version() ? + eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 : + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR); + + scdr + << eprosima::fastcdr::MemberId(0) << data.value() +; + scdr.end_serialize_type(current_state); +} + +template<> +eProsima_user_DllExport void deserialize( + eprosima::fastcdr::Cdr& cdr, + DDSEnablerTestType4& data) +{ + cdr.deserialize_type(eprosima::fastcdr::CdrVersion::XCDRv2 == cdr.get_cdr_version() ? + eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 : + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR, + [&data](eprosima::fastcdr::Cdr& dcdr, const eprosima::fastcdr::MemberId& mid) -> bool + { + bool ret_value = true; + switch (mid.id) + { + case 0: + dcdr >> data.value(); + break; + + default: + ret_value = false; + break; + } + return ret_value; + }); +} + +void serialize_key( + eprosima::fastcdr::Cdr& scdr, + const DDSEnablerTestType4& data) +{ + extern void serialize_key( + Cdr& scdr, + const DDSEnablerTestType1& data); + + + static_cast(scdr); + static_cast(data); + serialize_key(scdr, data.value()); + +} + + + +} // namespace fastcdr +} // namespace eprosima + +#endif // FAST_DDS_GENERATED__DDSENABLERTESTTYPESCDRAUX_IPP + diff --git a/ddsenabler_participants/test/types/DDSEnablerTestTypesPubSubTypes.cxx b/ddsenabler_participants/test/types/DDSEnablerTestTypesPubSubTypes.cxx new file mode 100644 index 00000000..047f5f9d --- /dev/null +++ b/ddsenabler_participants/test/types/DDSEnablerTestTypesPubSubTypes.cxx @@ -0,0 +1,760 @@ +// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*! + * @file DDSEnablerTestTypesPubSubTypes.cpp + * This header file contains the implementation of the serialization functions. + * + * This file was generated by the tool fastddsgen. + */ + +#include "DDSEnablerTestTypesPubSubTypes.hpp" + +#include +#include + +#include "DDSEnablerTestTypesCdrAux.hpp" +#include "DDSEnablerTestTypesTypeObjectSupport.hpp" + +using SerializedPayload_t = eprosima::fastdds::rtps::SerializedPayload_t; +using InstanceHandle_t = eprosima::fastdds::rtps::InstanceHandle_t; +using DataRepresentationId_t = eprosima::fastdds::dds::DataRepresentationId_t; + +DDSEnablerTestType1PubSubType::DDSEnablerTestType1PubSubType() +{ + set_name("DDSEnablerTestType1"); + uint32_t type_size = DDSEnablerTestType1_max_cdr_typesize; + type_size += static_cast(eprosima::fastcdr::Cdr::alignment(type_size, 4)); /* possible submessage alignment */ + max_serialized_type_size = type_size + 4; /*encapsulation*/ + is_compute_key_provided = false; + uint32_t key_length = DDSEnablerTestType1_max_key_cdr_typesize > 16 ? DDSEnablerTestType1_max_key_cdr_typesize : 16; + key_buffer_ = reinterpret_cast(malloc(key_length)); + memset(key_buffer_, 0, key_length); +} + +DDSEnablerTestType1PubSubType::~DDSEnablerTestType1PubSubType() +{ + if (key_buffer_ != nullptr) + { + free(key_buffer_); + } +} + +bool DDSEnablerTestType1PubSubType::serialize( + const void* const data, + SerializedPayload_t& payload, + DataRepresentationId_t data_representation) +{ + const DDSEnablerTestType1* p_type = static_cast(data); + + // Object that manages the raw buffer. + eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast(payload.data), payload.max_size); + // Object that serializes the data. + eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN, + data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ? + eprosima::fastcdr::CdrVersion::XCDRv1 : eprosima::fastcdr::CdrVersion::XCDRv2); + payload.encapsulation = ser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE; + ser.set_encoding_flag( + data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ? + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR : + eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2); + + try + { + // Serialize encapsulation + ser.serialize_encapsulation(); + // Serialize the object. + ser << *p_type; + } + catch (eprosima::fastcdr::exception::Exception& /*exception*/) + { + return false; + } + + // Get the serialized length + payload.length = static_cast(ser.get_serialized_data_length()); + return true; +} + +bool DDSEnablerTestType1PubSubType::deserialize( + SerializedPayload_t& payload, + void* data) +{ + try + { + // Convert DATA to pointer of your type + DDSEnablerTestType1* p_type = static_cast(data); + + // Object that manages the raw buffer. + eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast(payload.data), payload.length); + + // Object that deserializes the data. + eprosima::fastcdr::Cdr deser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN); + + // Deserialize encapsulation. + deser.read_encapsulation(); + payload.encapsulation = deser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE; + + // Deserialize the object. + deser >> *p_type; + } + catch (eprosima::fastcdr::exception::Exception& /*exception*/) + { + return false; + } + + return true; +} + +uint32_t DDSEnablerTestType1PubSubType::calculate_serialized_size( + const void* const data, + DataRepresentationId_t data_representation) +{ + try + { + eprosima::fastcdr::CdrSizeCalculator calculator( + data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ? + eprosima::fastcdr::CdrVersion::XCDRv1 :eprosima::fastcdr::CdrVersion::XCDRv2); + size_t current_alignment {0}; + return static_cast(calculator.calculate_serialized_size( + *static_cast(data), current_alignment)) + + 4u /*encapsulation*/; + } + catch (eprosima::fastcdr::exception::Exception& /*exception*/) + { + return 0; + } +} + +void* DDSEnablerTestType1PubSubType::create_data() +{ + return reinterpret_cast(new DDSEnablerTestType1()); +} + +void DDSEnablerTestType1PubSubType::delete_data( + void* data) +{ + delete(reinterpret_cast(data)); +} + +bool DDSEnablerTestType1PubSubType::compute_key( + SerializedPayload_t& payload, + InstanceHandle_t& handle, + bool force_md5) +{ + if (!is_compute_key_provided) + { + return false; + } + + DDSEnablerTestType1 data; + if (deserialize(payload, static_cast(&data))) + { + return compute_key(static_cast(&data), handle, force_md5); + } + + return false; +} + +bool DDSEnablerTestType1PubSubType::compute_key( + const void* const data, + InstanceHandle_t& handle, + bool force_md5) +{ + if (!is_compute_key_provided) + { + return false; + } + + const DDSEnablerTestType1* p_type = static_cast(data); + + // Object that manages the raw buffer. + eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast(key_buffer_), + DDSEnablerTestType1_max_key_cdr_typesize); + + // Object that serializes the data. + eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::BIG_ENDIANNESS, eprosima::fastcdr::CdrVersion::XCDRv2); + ser.set_encoding_flag(eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR2); + eprosima::fastcdr::serialize_key(ser, *p_type); + if (force_md5 || DDSEnablerTestType1_max_key_cdr_typesize > 16) + { + md5_.init(); + md5_.update(key_buffer_, static_cast(ser.get_serialized_data_length())); + md5_.finalize(); + for (uint8_t i = 0; i < 16; ++i) + { + handle.value[i] = md5_.digest[i]; + } + } + else + { + for (uint8_t i = 0; i < 16; ++i) + { + handle.value[i] = key_buffer_[i]; + } + } + return true; +} + +void DDSEnablerTestType1PubSubType::register_type_object_representation() +{ + register_DDSEnablerTestType1_type_identifier(type_identifiers_); +} + +DDSEnablerTestType2PubSubType::DDSEnablerTestType2PubSubType() +{ + set_name("DDSEnablerTestType2"); + uint32_t type_size = DDSEnablerTestType2_max_cdr_typesize; + type_size += static_cast(eprosima::fastcdr::Cdr::alignment(type_size, 4)); /* possible submessage alignment */ + max_serialized_type_size = type_size + 4; /*encapsulation*/ + is_compute_key_provided = false; + uint32_t key_length = DDSEnablerTestType2_max_key_cdr_typesize > 16 ? DDSEnablerTestType2_max_key_cdr_typesize : 16; + key_buffer_ = reinterpret_cast(malloc(key_length)); + memset(key_buffer_, 0, key_length); +} + +DDSEnablerTestType2PubSubType::~DDSEnablerTestType2PubSubType() +{ + if (key_buffer_ != nullptr) + { + free(key_buffer_); + } +} + +bool DDSEnablerTestType2PubSubType::serialize( + const void* const data, + SerializedPayload_t& payload, + DataRepresentationId_t data_representation) +{ + const DDSEnablerTestType2* p_type = static_cast(data); + + // Object that manages the raw buffer. + eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast(payload.data), payload.max_size); + // Object that serializes the data. + eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN, + data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ? + eprosima::fastcdr::CdrVersion::XCDRv1 : eprosima::fastcdr::CdrVersion::XCDRv2); + payload.encapsulation = ser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE; + ser.set_encoding_flag( + data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ? + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR : + eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2); + + try + { + // Serialize encapsulation + ser.serialize_encapsulation(); + // Serialize the object. + ser << *p_type; + } + catch (eprosima::fastcdr::exception::Exception& /*exception*/) + { + return false; + } + + // Get the serialized length + payload.length = static_cast(ser.get_serialized_data_length()); + return true; +} + +bool DDSEnablerTestType2PubSubType::deserialize( + SerializedPayload_t& payload, + void* data) +{ + try + { + // Convert DATA to pointer of your type + DDSEnablerTestType2* p_type = static_cast(data); + + // Object that manages the raw buffer. + eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast(payload.data), payload.length); + + // Object that deserializes the data. + eprosima::fastcdr::Cdr deser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN); + + // Deserialize encapsulation. + deser.read_encapsulation(); + payload.encapsulation = deser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE; + + // Deserialize the object. + deser >> *p_type; + } + catch (eprosima::fastcdr::exception::Exception& /*exception*/) + { + return false; + } + + return true; +} + +uint32_t DDSEnablerTestType2PubSubType::calculate_serialized_size( + const void* const data, + DataRepresentationId_t data_representation) +{ + try + { + eprosima::fastcdr::CdrSizeCalculator calculator( + data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ? + eprosima::fastcdr::CdrVersion::XCDRv1 :eprosima::fastcdr::CdrVersion::XCDRv2); + size_t current_alignment {0}; + return static_cast(calculator.calculate_serialized_size( + *static_cast(data), current_alignment)) + + 4u /*encapsulation*/; + } + catch (eprosima::fastcdr::exception::Exception& /*exception*/) + { + return 0; + } +} + +void* DDSEnablerTestType2PubSubType::create_data() +{ + return reinterpret_cast(new DDSEnablerTestType2()); +} + +void DDSEnablerTestType2PubSubType::delete_data( + void* data) +{ + delete(reinterpret_cast(data)); +} + +bool DDSEnablerTestType2PubSubType::compute_key( + SerializedPayload_t& payload, + InstanceHandle_t& handle, + bool force_md5) +{ + if (!is_compute_key_provided) + { + return false; + } + + DDSEnablerTestType2 data; + if (deserialize(payload, static_cast(&data))) + { + return compute_key(static_cast(&data), handle, force_md5); + } + + return false; +} + +bool DDSEnablerTestType2PubSubType::compute_key( + const void* const data, + InstanceHandle_t& handle, + bool force_md5) +{ + if (!is_compute_key_provided) + { + return false; + } + + const DDSEnablerTestType2* p_type = static_cast(data); + + // Object that manages the raw buffer. + eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast(key_buffer_), + DDSEnablerTestType2_max_key_cdr_typesize); + + // Object that serializes the data. + eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::BIG_ENDIANNESS, eprosima::fastcdr::CdrVersion::XCDRv2); + ser.set_encoding_flag(eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR2); + eprosima::fastcdr::serialize_key(ser, *p_type); + if (force_md5 || DDSEnablerTestType2_max_key_cdr_typesize > 16) + { + md5_.init(); + md5_.update(key_buffer_, static_cast(ser.get_serialized_data_length())); + md5_.finalize(); + for (uint8_t i = 0; i < 16; ++i) + { + handle.value[i] = md5_.digest[i]; + } + } + else + { + for (uint8_t i = 0; i < 16; ++i) + { + handle.value[i] = key_buffer_[i]; + } + } + return true; +} + +void DDSEnablerTestType2PubSubType::register_type_object_representation() +{ + register_DDSEnablerTestType2_type_identifier(type_identifiers_); +} + +DDSEnablerTestType3PubSubType::DDSEnablerTestType3PubSubType() +{ + set_name("DDSEnablerTestType3"); + uint32_t type_size = DDSEnablerTestType3_max_cdr_typesize; + type_size += static_cast(eprosima::fastcdr::Cdr::alignment(type_size, 4)); /* possible submessage alignment */ + max_serialized_type_size = type_size + 4; /*encapsulation*/ + is_compute_key_provided = false; + uint32_t key_length = DDSEnablerTestType3_max_key_cdr_typesize > 16 ? DDSEnablerTestType3_max_key_cdr_typesize : 16; + key_buffer_ = reinterpret_cast(malloc(key_length)); + memset(key_buffer_, 0, key_length); +} + +DDSEnablerTestType3PubSubType::~DDSEnablerTestType3PubSubType() +{ + if (key_buffer_ != nullptr) + { + free(key_buffer_); + } +} + +bool DDSEnablerTestType3PubSubType::serialize( + const void* const data, + SerializedPayload_t& payload, + DataRepresentationId_t data_representation) +{ + const DDSEnablerTestType3* p_type = static_cast(data); + + // Object that manages the raw buffer. + eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast(payload.data), payload.max_size); + // Object that serializes the data. + eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN, + data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ? + eprosima::fastcdr::CdrVersion::XCDRv1 : eprosima::fastcdr::CdrVersion::XCDRv2); + payload.encapsulation = ser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE; + ser.set_encoding_flag( + data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ? + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR : + eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2); + + try + { + // Serialize encapsulation + ser.serialize_encapsulation(); + // Serialize the object. + ser << *p_type; + } + catch (eprosima::fastcdr::exception::Exception& /*exception*/) + { + return false; + } + + // Get the serialized length + payload.length = static_cast(ser.get_serialized_data_length()); + return true; +} + +bool DDSEnablerTestType3PubSubType::deserialize( + SerializedPayload_t& payload, + void* data) +{ + try + { + // Convert DATA to pointer of your type + DDSEnablerTestType3* p_type = static_cast(data); + + // Object that manages the raw buffer. + eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast(payload.data), payload.length); + + // Object that deserializes the data. + eprosima::fastcdr::Cdr deser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN); + + // Deserialize encapsulation. + deser.read_encapsulation(); + payload.encapsulation = deser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE; + + // Deserialize the object. + deser >> *p_type; + } + catch (eprosima::fastcdr::exception::Exception& /*exception*/) + { + return false; + } + + return true; +} + +uint32_t DDSEnablerTestType3PubSubType::calculate_serialized_size( + const void* const data, + DataRepresentationId_t data_representation) +{ + try + { + eprosima::fastcdr::CdrSizeCalculator calculator( + data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ? + eprosima::fastcdr::CdrVersion::XCDRv1 :eprosima::fastcdr::CdrVersion::XCDRv2); + size_t current_alignment {0}; + return static_cast(calculator.calculate_serialized_size( + *static_cast(data), current_alignment)) + + 4u /*encapsulation*/; + } + catch (eprosima::fastcdr::exception::Exception& /*exception*/) + { + return 0; + } +} + +void* DDSEnablerTestType3PubSubType::create_data() +{ + return reinterpret_cast(new DDSEnablerTestType3()); +} + +void DDSEnablerTestType3PubSubType::delete_data( + void* data) +{ + delete(reinterpret_cast(data)); +} + +bool DDSEnablerTestType3PubSubType::compute_key( + SerializedPayload_t& payload, + InstanceHandle_t& handle, + bool force_md5) +{ + if (!is_compute_key_provided) + { + return false; + } + + DDSEnablerTestType3 data; + if (deserialize(payload, static_cast(&data))) + { + return compute_key(static_cast(&data), handle, force_md5); + } + + return false; +} + +bool DDSEnablerTestType3PubSubType::compute_key( + const void* const data, + InstanceHandle_t& handle, + bool force_md5) +{ + if (!is_compute_key_provided) + { + return false; + } + + const DDSEnablerTestType3* p_type = static_cast(data); + + // Object that manages the raw buffer. + eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast(key_buffer_), + DDSEnablerTestType3_max_key_cdr_typesize); + + // Object that serializes the data. + eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::BIG_ENDIANNESS, eprosima::fastcdr::CdrVersion::XCDRv2); + ser.set_encoding_flag(eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR2); + eprosima::fastcdr::serialize_key(ser, *p_type); + if (force_md5 || DDSEnablerTestType3_max_key_cdr_typesize > 16) + { + md5_.init(); + md5_.update(key_buffer_, static_cast(ser.get_serialized_data_length())); + md5_.finalize(); + for (uint8_t i = 0; i < 16; ++i) + { + handle.value[i] = md5_.digest[i]; + } + } + else + { + for (uint8_t i = 0; i < 16; ++i) + { + handle.value[i] = key_buffer_[i]; + } + } + return true; +} + +void DDSEnablerTestType3PubSubType::register_type_object_representation() +{ + register_DDSEnablerTestType3_type_identifier(type_identifiers_); +} + +DDSEnablerTestType4PubSubType::DDSEnablerTestType4PubSubType() +{ + set_name("DDSEnablerTestType4"); + uint32_t type_size = DDSEnablerTestType4_max_cdr_typesize; + type_size += static_cast(eprosima::fastcdr::Cdr::alignment(type_size, 4)); /* possible submessage alignment */ + max_serialized_type_size = type_size + 4; /*encapsulation*/ + is_compute_key_provided = false; + uint32_t key_length = DDSEnablerTestType4_max_key_cdr_typesize > 16 ? DDSEnablerTestType4_max_key_cdr_typesize : 16; + key_buffer_ = reinterpret_cast(malloc(key_length)); + memset(key_buffer_, 0, key_length); +} + +DDSEnablerTestType4PubSubType::~DDSEnablerTestType4PubSubType() +{ + if (key_buffer_ != nullptr) + { + free(key_buffer_); + } +} + +bool DDSEnablerTestType4PubSubType::serialize( + const void* const data, + SerializedPayload_t& payload, + DataRepresentationId_t data_representation) +{ + const DDSEnablerTestType4* p_type = static_cast(data); + + // Object that manages the raw buffer. + eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast(payload.data), payload.max_size); + // Object that serializes the data. + eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN, + data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ? + eprosima::fastcdr::CdrVersion::XCDRv1 : eprosima::fastcdr::CdrVersion::XCDRv2); + payload.encapsulation = ser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE; + ser.set_encoding_flag( + data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ? + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR : + eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2); + + try + { + // Serialize encapsulation + ser.serialize_encapsulation(); + // Serialize the object. + ser << *p_type; + } + catch (eprosima::fastcdr::exception::Exception& /*exception*/) + { + return false; + } + + // Get the serialized length + payload.length = static_cast(ser.get_serialized_data_length()); + return true; +} + +bool DDSEnablerTestType4PubSubType::deserialize( + SerializedPayload_t& payload, + void* data) +{ + try + { + // Convert DATA to pointer of your type + DDSEnablerTestType4* p_type = static_cast(data); + + // Object that manages the raw buffer. + eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast(payload.data), payload.length); + + // Object that deserializes the data. + eprosima::fastcdr::Cdr deser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN); + + // Deserialize encapsulation. + deser.read_encapsulation(); + payload.encapsulation = deser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE; + + // Deserialize the object. + deser >> *p_type; + } + catch (eprosima::fastcdr::exception::Exception& /*exception*/) + { + return false; + } + + return true; +} + +uint32_t DDSEnablerTestType4PubSubType::calculate_serialized_size( + const void* const data, + DataRepresentationId_t data_representation) +{ + try + { + eprosima::fastcdr::CdrSizeCalculator calculator( + data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ? + eprosima::fastcdr::CdrVersion::XCDRv1 :eprosima::fastcdr::CdrVersion::XCDRv2); + size_t current_alignment {0}; + return static_cast(calculator.calculate_serialized_size( + *static_cast(data), current_alignment)) + + 4u /*encapsulation*/; + } + catch (eprosima::fastcdr::exception::Exception& /*exception*/) + { + return 0; + } +} + +void* DDSEnablerTestType4PubSubType::create_data() +{ + return reinterpret_cast(new DDSEnablerTestType4()); +} + +void DDSEnablerTestType4PubSubType::delete_data( + void* data) +{ + delete(reinterpret_cast(data)); +} + +bool DDSEnablerTestType4PubSubType::compute_key( + SerializedPayload_t& payload, + InstanceHandle_t& handle, + bool force_md5) +{ + if (!is_compute_key_provided) + { + return false; + } + + DDSEnablerTestType4 data; + if (deserialize(payload, static_cast(&data))) + { + return compute_key(static_cast(&data), handle, force_md5); + } + + return false; +} + +bool DDSEnablerTestType4PubSubType::compute_key( + const void* const data, + InstanceHandle_t& handle, + bool force_md5) +{ + if (!is_compute_key_provided) + { + return false; + } + + const DDSEnablerTestType4* p_type = static_cast(data); + + // Object that manages the raw buffer. + eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast(key_buffer_), + DDSEnablerTestType4_max_key_cdr_typesize); + + // Object that serializes the data. + eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::BIG_ENDIANNESS, eprosima::fastcdr::CdrVersion::XCDRv2); + ser.set_encoding_flag(eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR2); + eprosima::fastcdr::serialize_key(ser, *p_type); + if (force_md5 || DDSEnablerTestType4_max_key_cdr_typesize > 16) + { + md5_.init(); + md5_.update(key_buffer_, static_cast(ser.get_serialized_data_length())); + md5_.finalize(); + for (uint8_t i = 0; i < 16; ++i) + { + handle.value[i] = md5_.digest[i]; + } + } + else + { + for (uint8_t i = 0; i < 16; ++i) + { + handle.value[i] = key_buffer_[i]; + } + } + return true; +} + +void DDSEnablerTestType4PubSubType::register_type_object_representation() +{ + register_DDSEnablerTestType4_type_identifier(type_identifiers_); +} + + +// Include auxiliary functions like for serializing/deserializing. +#include "DDSEnablerTestTypesCdrAux.ipp" diff --git a/ddsenabler_participants/test/types/DDSEnablerTestTypesPubSubTypes.hpp b/ddsenabler_participants/test/types/DDSEnablerTestTypesPubSubTypes.hpp new file mode 100644 index 00000000..c05373e7 --- /dev/null +++ b/ddsenabler_participants/test/types/DDSEnablerTestTypesPubSubTypes.hpp @@ -0,0 +1,366 @@ +// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*! + * @file DDSEnablerTestTypesPubSubTypes.hpp + * This header file contains the declaration of the serialization functions. + * + * This file was generated by the tool fastddsgen. + */ + + +#ifndef FAST_DDS_GENERATED__DDSENABLERTESTTYPES_PUBSUBTYPES_HPP +#define FAST_DDS_GENERATED__DDSENABLERTESTTYPES_PUBSUBTYPES_HPP + +#include +#include +#include +#include +#include + +#include "DDSEnablerTestTypes.hpp" + + +#if !defined(FASTDDS_GEN_API_VER) || (FASTDDS_GEN_API_VER != 3) +#error \ + Generated DDSEnablerTestTypes is not compatible with current installed Fast DDS. Please, regenerate it with fastddsgen. +#endif // FASTDDS_GEN_API_VER + + +/*! + * @brief This class represents the TopicDataType of the type DDSEnablerTestType1 defined by the user in the IDL file. + * @ingroup DDSEnablerTestTypes + */ +class DDSEnablerTestType1PubSubType : public eprosima::fastdds::dds::TopicDataType +{ +public: + + typedef DDSEnablerTestType1 type; + + eProsima_user_DllExport DDSEnablerTestType1PubSubType(); + + eProsima_user_DllExport ~DDSEnablerTestType1PubSubType() override; + + eProsima_user_DllExport bool serialize( + const void* const data, + eprosima::fastdds::rtps::SerializedPayload_t& payload, + eprosima::fastdds::dds::DataRepresentationId_t data_representation) override; + + eProsima_user_DllExport bool deserialize( + eprosima::fastdds::rtps::SerializedPayload_t& payload, + void* data) override; + + eProsima_user_DllExport uint32_t calculate_serialized_size( + const void* const data, + eprosima::fastdds::dds::DataRepresentationId_t data_representation) override; + + eProsima_user_DllExport bool compute_key( + eprosima::fastdds::rtps::SerializedPayload_t& payload, + eprosima::fastdds::rtps::InstanceHandle_t& ihandle, + bool force_md5 = false) override; + + eProsima_user_DllExport bool compute_key( + const void* const data, + eprosima::fastdds::rtps::InstanceHandle_t& ihandle, + bool force_md5 = false) override; + + eProsima_user_DllExport void* create_data() override; + + eProsima_user_DllExport void delete_data( + void* data) override; + + //Register TypeObject representation in Fast DDS TypeObjectRegistry + eProsima_user_DllExport void register_type_object_representation() override; + +#ifdef TOPIC_DATA_TYPE_API_HAS_IS_BOUNDED + eProsima_user_DllExport inline bool is_bounded() const override + { + return true; + } + +#endif // TOPIC_DATA_TYPE_API_HAS_IS_BOUNDED + +#ifdef TOPIC_DATA_TYPE_API_HAS_IS_PLAIN + + eProsima_user_DllExport inline bool is_plain( + eprosima::fastdds::dds::DataRepresentationId_t data_representation) const override + { + static_cast(data_representation); + return false; + } + +#endif // TOPIC_DATA_TYPE_API_HAS_IS_PLAIN + +#ifdef TOPIC_DATA_TYPE_API_HAS_CONSTRUCT_SAMPLE + eProsima_user_DllExport inline bool construct_sample( + void* memory) const override + { + static_cast(memory); + return false; + } + +#endif // TOPIC_DATA_TYPE_API_HAS_CONSTRUCT_SAMPLE + +private: + + eprosima::fastdds::MD5 md5_; + unsigned char* key_buffer_; + +}; + +/*! + * @brief This class represents the TopicDataType of the type DDSEnablerTestType2 defined by the user in the IDL file. + * @ingroup DDSEnablerTestTypes + */ +class DDSEnablerTestType2PubSubType : public eprosima::fastdds::dds::TopicDataType +{ +public: + + typedef DDSEnablerTestType2 type; + + eProsima_user_DllExport DDSEnablerTestType2PubSubType(); + + eProsima_user_DllExport ~DDSEnablerTestType2PubSubType() override; + + eProsima_user_DllExport bool serialize( + const void* const data, + eprosima::fastdds::rtps::SerializedPayload_t& payload, + eprosima::fastdds::dds::DataRepresentationId_t data_representation) override; + + eProsima_user_DllExport bool deserialize( + eprosima::fastdds::rtps::SerializedPayload_t& payload, + void* data) override; + + eProsima_user_DllExport uint32_t calculate_serialized_size( + const void* const data, + eprosima::fastdds::dds::DataRepresentationId_t data_representation) override; + + eProsima_user_DllExport bool compute_key( + eprosima::fastdds::rtps::SerializedPayload_t& payload, + eprosima::fastdds::rtps::InstanceHandle_t& ihandle, + bool force_md5 = false) override; + + eProsima_user_DllExport bool compute_key( + const void* const data, + eprosima::fastdds::rtps::InstanceHandle_t& ihandle, + bool force_md5 = false) override; + + eProsima_user_DllExport void* create_data() override; + + eProsima_user_DllExport void delete_data( + void* data) override; + + //Register TypeObject representation in Fast DDS TypeObjectRegistry + eProsima_user_DllExport void register_type_object_representation() override; + +#ifdef TOPIC_DATA_TYPE_API_HAS_IS_BOUNDED + eProsima_user_DllExport inline bool is_bounded() const override + { + return false; + } + +#endif // TOPIC_DATA_TYPE_API_HAS_IS_BOUNDED + +#ifdef TOPIC_DATA_TYPE_API_HAS_IS_PLAIN + + eProsima_user_DllExport inline bool is_plain( + eprosima::fastdds::dds::DataRepresentationId_t data_representation) const override + { + static_cast(data_representation); + return false; + } + +#endif // TOPIC_DATA_TYPE_API_HAS_IS_PLAIN + +#ifdef TOPIC_DATA_TYPE_API_HAS_CONSTRUCT_SAMPLE + eProsima_user_DllExport inline bool construct_sample( + void* memory) const override + { + static_cast(memory); + return false; + } + +#endif // TOPIC_DATA_TYPE_API_HAS_CONSTRUCT_SAMPLE + +private: + + eprosima::fastdds::MD5 md5_; + unsigned char* key_buffer_; + +}; + +/*! + * @brief This class represents the TopicDataType of the type DDSEnablerTestType3 defined by the user in the IDL file. + * @ingroup DDSEnablerTestTypes + */ +class DDSEnablerTestType3PubSubType : public eprosima::fastdds::dds::TopicDataType +{ +public: + + typedef DDSEnablerTestType3 type; + + eProsima_user_DllExport DDSEnablerTestType3PubSubType(); + + eProsima_user_DllExport ~DDSEnablerTestType3PubSubType() override; + + eProsima_user_DllExport bool serialize( + const void* const data, + eprosima::fastdds::rtps::SerializedPayload_t& payload, + eprosima::fastdds::dds::DataRepresentationId_t data_representation) override; + + eProsima_user_DllExport bool deserialize( + eprosima::fastdds::rtps::SerializedPayload_t& payload, + void* data) override; + + eProsima_user_DllExport uint32_t calculate_serialized_size( + const void* const data, + eprosima::fastdds::dds::DataRepresentationId_t data_representation) override; + + eProsima_user_DllExport bool compute_key( + eprosima::fastdds::rtps::SerializedPayload_t& payload, + eprosima::fastdds::rtps::InstanceHandle_t& ihandle, + bool force_md5 = false) override; + + eProsima_user_DllExport bool compute_key( + const void* const data, + eprosima::fastdds::rtps::InstanceHandle_t& ihandle, + bool force_md5 = false) override; + + eProsima_user_DllExport void* create_data() override; + + eProsima_user_DllExport void delete_data( + void* data) override; + + //Register TypeObject representation in Fast DDS TypeObjectRegistry + eProsima_user_DllExport void register_type_object_representation() override; + +#ifdef TOPIC_DATA_TYPE_API_HAS_IS_BOUNDED + eProsima_user_DllExport inline bool is_bounded() const override + { + return true; + } + +#endif // TOPIC_DATA_TYPE_API_HAS_IS_BOUNDED + +#ifdef TOPIC_DATA_TYPE_API_HAS_IS_PLAIN + + eProsima_user_DllExport inline bool is_plain( + eprosima::fastdds::dds::DataRepresentationId_t data_representation) const override + { + static_cast(data_representation); + return false; + } + +#endif // TOPIC_DATA_TYPE_API_HAS_IS_PLAIN + +#ifdef TOPIC_DATA_TYPE_API_HAS_CONSTRUCT_SAMPLE + eProsima_user_DllExport inline bool construct_sample( + void* memory) const override + { + static_cast(memory); + return false; + } + +#endif // TOPIC_DATA_TYPE_API_HAS_CONSTRUCT_SAMPLE + +private: + + eprosima::fastdds::MD5 md5_; + unsigned char* key_buffer_; + +}; + +/*! + * @brief This class represents the TopicDataType of the type DDSEnablerTestType4 defined by the user in the IDL file. + * @ingroup DDSEnablerTestTypes + */ +class DDSEnablerTestType4PubSubType : public eprosima::fastdds::dds::TopicDataType +{ +public: + + typedef DDSEnablerTestType4 type; + + eProsima_user_DllExport DDSEnablerTestType4PubSubType(); + + eProsima_user_DllExport ~DDSEnablerTestType4PubSubType() override; + + eProsima_user_DllExport bool serialize( + const void* const data, + eprosima::fastdds::rtps::SerializedPayload_t& payload, + eprosima::fastdds::dds::DataRepresentationId_t data_representation) override; + + eProsima_user_DllExport bool deserialize( + eprosima::fastdds::rtps::SerializedPayload_t& payload, + void* data) override; + + eProsima_user_DllExport uint32_t calculate_serialized_size( + const void* const data, + eprosima::fastdds::dds::DataRepresentationId_t data_representation) override; + + eProsima_user_DllExport bool compute_key( + eprosima::fastdds::rtps::SerializedPayload_t& payload, + eprosima::fastdds::rtps::InstanceHandle_t& ihandle, + bool force_md5 = false) override; + + eProsima_user_DllExport bool compute_key( + const void* const data, + eprosima::fastdds::rtps::InstanceHandle_t& ihandle, + bool force_md5 = false) override; + + eProsima_user_DllExport void* create_data() override; + + eProsima_user_DllExport void delete_data( + void* data) override; + + //Register TypeObject representation in Fast DDS TypeObjectRegistry + eProsima_user_DllExport void register_type_object_representation() override; + +#ifdef TOPIC_DATA_TYPE_API_HAS_IS_BOUNDED + eProsima_user_DllExport inline bool is_bounded() const override + { + return true; + } + +#endif // TOPIC_DATA_TYPE_API_HAS_IS_BOUNDED + +#ifdef TOPIC_DATA_TYPE_API_HAS_IS_PLAIN + + eProsima_user_DllExport inline bool is_plain( + eprosima::fastdds::dds::DataRepresentationId_t data_representation) const override + { + static_cast(data_representation); + return false; + } + +#endif // TOPIC_DATA_TYPE_API_HAS_IS_PLAIN + +#ifdef TOPIC_DATA_TYPE_API_HAS_CONSTRUCT_SAMPLE + eProsima_user_DllExport inline bool construct_sample( + void* memory) const override + { + static_cast(memory); + return false; + } + +#endif // TOPIC_DATA_TYPE_API_HAS_CONSTRUCT_SAMPLE + +private: + + eprosima::fastdds::MD5 md5_; + unsigned char* key_buffer_; + +}; + +#endif // FAST_DDS_GENERATED__DDSENABLERTESTTYPES_PUBSUBTYPES_HPP + diff --git a/ddsenabler_participants/test/types/DDSEnablerTestTypesTypeObjectSupport.cxx b/ddsenabler_participants/test/types/DDSEnablerTestTypesTypeObjectSupport.cxx new file mode 100644 index 00000000..fc805396 --- /dev/null +++ b/ddsenabler_participants/test/types/DDSEnablerTestTypesTypeObjectSupport.cxx @@ -0,0 +1,317 @@ +// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*! + * @file DDSEnablerTestTypesTypeObjectSupport.cxx + * Source file containing the implementation to register the TypeObject representation of the described types in the IDL file + * + * This file was generated by the tool fastddsgen. + */ + +#include "DDSEnablerTestTypesTypeObjectSupport.hpp" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "DDSEnablerTestTypes.hpp" + + +using namespace eprosima::fastdds::dds::xtypes; + +// TypeIdentifier is returned by reference: dependent structures/unions are registered in this same method +void register_DDSEnablerTestType1_type_identifier( + TypeIdentifierPair& type_ids_DDSEnablerTestType1) +{ + + ReturnCode_t return_code_DDSEnablerTestType1 {eprosima::fastdds::dds::RETCODE_OK}; + return_code_DDSEnablerTestType1 = + eprosima::fastdds::dds::DomainParticipantFactory::get_instance()->type_object_registry().get_type_identifiers( + "DDSEnablerTestType1", type_ids_DDSEnablerTestType1); + if (eprosima::fastdds::dds::RETCODE_OK != return_code_DDSEnablerTestType1) + { + StructTypeFlag struct_flags_DDSEnablerTestType1 = TypeObjectUtils::build_struct_type_flag(eprosima::fastdds::dds::xtypes::ExtensibilityKind::APPENDABLE, + false, false); + QualifiedTypeName type_name_DDSEnablerTestType1 = "DDSEnablerTestType1"; + eprosima::fastcdr::optional type_ann_builtin_DDSEnablerTestType1; + eprosima::fastcdr::optional ann_custom_DDSEnablerTestType1; + CompleteTypeDetail detail_DDSEnablerTestType1 = TypeObjectUtils::build_complete_type_detail(type_ann_builtin_DDSEnablerTestType1, ann_custom_DDSEnablerTestType1, type_name_DDSEnablerTestType1.to_string()); + CompleteStructHeader header_DDSEnablerTestType1; + header_DDSEnablerTestType1 = TypeObjectUtils::build_complete_struct_header(TypeIdentifier(), detail_DDSEnablerTestType1); + CompleteStructMemberSeq member_seq_DDSEnablerTestType1; + { + TypeIdentifierPair type_ids_value; + ReturnCode_t return_code_value {eprosima::fastdds::dds::RETCODE_OK}; + return_code_value = + eprosima::fastdds::dds::DomainParticipantFactory::get_instance()->type_object_registry().get_type_identifiers( + "_int16_t", type_ids_value); + + if (eprosima::fastdds::dds::RETCODE_OK != return_code_value) + { + EPROSIMA_LOG_ERROR(XTYPES_TYPE_REPRESENTATION, + "value Structure member TypeIdentifier unknown to TypeObjectRegistry."); + return; + } + StructMemberFlag member_flags_value = TypeObjectUtils::build_struct_member_flag(eprosima::fastdds::dds::xtypes::TryConstructFailAction::DISCARD, + false, false, false, false); + MemberId member_id_value = 0x00000000; + bool common_value_ec {false}; + CommonStructMember common_value {TypeObjectUtils::build_common_struct_member(member_id_value, member_flags_value, TypeObjectUtils::retrieve_complete_type_identifier(type_ids_value, common_value_ec))}; + if (!common_value_ec) + { + EPROSIMA_LOG_ERROR(XTYPES_TYPE_REPRESENTATION, "Structure value member TypeIdentifier inconsistent."); + return; + } + MemberName name_value = "value"; + eprosima::fastcdr::optional member_ann_builtin_value; + ann_custom_DDSEnablerTestType1.reset(); + CompleteMemberDetail detail_value = TypeObjectUtils::build_complete_member_detail(name_value, member_ann_builtin_value, ann_custom_DDSEnablerTestType1); + CompleteStructMember member_value = TypeObjectUtils::build_complete_struct_member(common_value, detail_value); + TypeObjectUtils::add_complete_struct_member(member_seq_DDSEnablerTestType1, member_value); + } + CompleteStructType struct_type_DDSEnablerTestType1 = TypeObjectUtils::build_complete_struct_type(struct_flags_DDSEnablerTestType1, header_DDSEnablerTestType1, member_seq_DDSEnablerTestType1); + if (eprosima::fastdds::dds::RETCODE_BAD_PARAMETER == + TypeObjectUtils::build_and_register_struct_type_object(struct_type_DDSEnablerTestType1, type_name_DDSEnablerTestType1.to_string(), type_ids_DDSEnablerTestType1)) + { + EPROSIMA_LOG_ERROR(XTYPES_TYPE_REPRESENTATION, + "DDSEnablerTestType1 already registered in TypeObjectRegistry for a different type."); + } + } +} +// TypeIdentifier is returned by reference: dependent structures/unions are registered in this same method +void register_DDSEnablerTestType2_type_identifier( + TypeIdentifierPair& type_ids_DDSEnablerTestType2) +{ + + ReturnCode_t return_code_DDSEnablerTestType2 {eprosima::fastdds::dds::RETCODE_OK}; + return_code_DDSEnablerTestType2 = + eprosima::fastdds::dds::DomainParticipantFactory::get_instance()->type_object_registry().get_type_identifiers( + "DDSEnablerTestType2", type_ids_DDSEnablerTestType2); + if (eprosima::fastdds::dds::RETCODE_OK != return_code_DDSEnablerTestType2) + { + StructTypeFlag struct_flags_DDSEnablerTestType2 = TypeObjectUtils::build_struct_type_flag(eprosima::fastdds::dds::xtypes::ExtensibilityKind::APPENDABLE, + false, false); + QualifiedTypeName type_name_DDSEnablerTestType2 = "DDSEnablerTestType2"; + eprosima::fastcdr::optional type_ann_builtin_DDSEnablerTestType2; + eprosima::fastcdr::optional ann_custom_DDSEnablerTestType2; + CompleteTypeDetail detail_DDSEnablerTestType2 = TypeObjectUtils::build_complete_type_detail(type_ann_builtin_DDSEnablerTestType2, ann_custom_DDSEnablerTestType2, type_name_DDSEnablerTestType2.to_string()); + CompleteStructHeader header_DDSEnablerTestType2; + header_DDSEnablerTestType2 = TypeObjectUtils::build_complete_struct_header(TypeIdentifier(), detail_DDSEnablerTestType2); + CompleteStructMemberSeq member_seq_DDSEnablerTestType2; + { + TypeIdentifierPair type_ids_value; + ReturnCode_t return_code_value {eprosima::fastdds::dds::RETCODE_OK}; + return_code_value = + eprosima::fastdds::dds::DomainParticipantFactory::get_instance()->type_object_registry().get_type_identifiers( + "anonymous_string_unbounded", type_ids_value); + + if (eprosima::fastdds::dds::RETCODE_OK != return_code_value) + { + { + SBound bound = 0; + StringSTypeDefn string_sdefn = TypeObjectUtils::build_string_s_type_defn(bound); + if (eprosima::fastdds::dds::RETCODE_BAD_PARAMETER == + TypeObjectUtils::build_and_register_s_string_type_identifier(string_sdefn, + "anonymous_string_unbounded", type_ids_value)) + { + EPROSIMA_LOG_ERROR(XTYPES_TYPE_REPRESENTATION, + "anonymous_string_unbounded already registered in TypeObjectRegistry for a different type."); + } + } + } + StructMemberFlag member_flags_value = TypeObjectUtils::build_struct_member_flag(eprosima::fastdds::dds::xtypes::TryConstructFailAction::DISCARD, + false, false, false, false); + MemberId member_id_value = 0x00000000; + bool common_value_ec {false}; + CommonStructMember common_value {TypeObjectUtils::build_common_struct_member(member_id_value, member_flags_value, TypeObjectUtils::retrieve_complete_type_identifier(type_ids_value, common_value_ec))}; + if (!common_value_ec) + { + EPROSIMA_LOG_ERROR(XTYPES_TYPE_REPRESENTATION, "Structure value member TypeIdentifier inconsistent."); + return; + } + MemberName name_value = "value"; + eprosima::fastcdr::optional member_ann_builtin_value; + ann_custom_DDSEnablerTestType2.reset(); + CompleteMemberDetail detail_value = TypeObjectUtils::build_complete_member_detail(name_value, member_ann_builtin_value, ann_custom_DDSEnablerTestType2); + CompleteStructMember member_value = TypeObjectUtils::build_complete_struct_member(common_value, detail_value); + TypeObjectUtils::add_complete_struct_member(member_seq_DDSEnablerTestType2, member_value); + } + CompleteStructType struct_type_DDSEnablerTestType2 = TypeObjectUtils::build_complete_struct_type(struct_flags_DDSEnablerTestType2, header_DDSEnablerTestType2, member_seq_DDSEnablerTestType2); + if (eprosima::fastdds::dds::RETCODE_BAD_PARAMETER == + TypeObjectUtils::build_and_register_struct_type_object(struct_type_DDSEnablerTestType2, type_name_DDSEnablerTestType2.to_string(), type_ids_DDSEnablerTestType2)) + { + EPROSIMA_LOG_ERROR(XTYPES_TYPE_REPRESENTATION, + "DDSEnablerTestType2 already registered in TypeObjectRegistry for a different type."); + } + } +} +// TypeIdentifier is returned by reference: dependent structures/unions are registered in this same method +void register_DDSEnablerTestType3_type_identifier( + TypeIdentifierPair& type_ids_DDSEnablerTestType3) +{ + + ReturnCode_t return_code_DDSEnablerTestType3 {eprosima::fastdds::dds::RETCODE_OK}; + return_code_DDSEnablerTestType3 = + eprosima::fastdds::dds::DomainParticipantFactory::get_instance()->type_object_registry().get_type_identifiers( + "DDSEnablerTestType3", type_ids_DDSEnablerTestType3); + if (eprosima::fastdds::dds::RETCODE_OK != return_code_DDSEnablerTestType3) + { + StructTypeFlag struct_flags_DDSEnablerTestType3 = TypeObjectUtils::build_struct_type_flag(eprosima::fastdds::dds::xtypes::ExtensibilityKind::APPENDABLE, + false, false); + QualifiedTypeName type_name_DDSEnablerTestType3 = "DDSEnablerTestType3"; + eprosima::fastcdr::optional type_ann_builtin_DDSEnablerTestType3; + eprosima::fastcdr::optional ann_custom_DDSEnablerTestType3; + CompleteTypeDetail detail_DDSEnablerTestType3 = TypeObjectUtils::build_complete_type_detail(type_ann_builtin_DDSEnablerTestType3, ann_custom_DDSEnablerTestType3, type_name_DDSEnablerTestType3.to_string()); + CompleteStructHeader header_DDSEnablerTestType3; + header_DDSEnablerTestType3 = TypeObjectUtils::build_complete_struct_header(TypeIdentifier(), detail_DDSEnablerTestType3); + CompleteStructMemberSeq member_seq_DDSEnablerTestType3; + { + TypeIdentifierPair type_ids_value; + ReturnCode_t return_code_value {eprosima::fastdds::dds::RETCODE_OK}; + return_code_value = + eprosima::fastdds::dds::DomainParticipantFactory::get_instance()->type_object_registry().get_type_identifiers( + "anonymous_array_int32_t_10", type_ids_value); + + if (eprosima::fastdds::dds::RETCODE_OK != return_code_value) + { + return_code_value = + eprosima::fastdds::dds::DomainParticipantFactory::get_instance()->type_object_registry().get_type_identifiers( + "_int32_t", type_ids_value); + + if (eprosima::fastdds::dds::RETCODE_OK != return_code_value) + { + EPROSIMA_LOG_ERROR(XTYPES_TYPE_REPRESENTATION, + "Array element TypeIdentifier unknown to TypeObjectRegistry."); + return; + } + bool element_identifier_anonymous_array_int32_t_10_ec {false}; + TypeIdentifier* element_identifier_anonymous_array_int32_t_10 {new TypeIdentifier(TypeObjectUtils::retrieve_complete_type_identifier(type_ids_value, element_identifier_anonymous_array_int32_t_10_ec))}; + if (!element_identifier_anonymous_array_int32_t_10_ec) + { + EPROSIMA_LOG_ERROR(XTYPES_TYPE_REPRESENTATION, "Array element TypeIdentifier inconsistent."); + return; + } + EquivalenceKind equiv_kind_anonymous_array_int32_t_10 = EK_COMPLETE; + if (TK_NONE == type_ids_value.type_identifier2()._d()) + { + equiv_kind_anonymous_array_int32_t_10 = EK_BOTH; + } + CollectionElementFlag element_flags_anonymous_array_int32_t_10 = 0; + PlainCollectionHeader header_anonymous_array_int32_t_10 = TypeObjectUtils::build_plain_collection_header(equiv_kind_anonymous_array_int32_t_10, element_flags_anonymous_array_int32_t_10); + { + SBoundSeq array_bound_seq; + TypeObjectUtils::add_array_dimension(array_bound_seq, static_cast(10)); + + PlainArraySElemDefn array_sdefn = TypeObjectUtils::build_plain_array_s_elem_defn(header_anonymous_array_int32_t_10, array_bound_seq, + eprosima::fastcdr::external(element_identifier_anonymous_array_int32_t_10)); + if (eprosima::fastdds::dds::RETCODE_BAD_PARAMETER == + TypeObjectUtils::build_and_register_s_array_type_identifier(array_sdefn, "anonymous_array_int32_t_10", type_ids_value)) + { + EPROSIMA_LOG_ERROR(XTYPES_TYPE_REPRESENTATION, + "anonymous_array_int32_t_10 already registered in TypeObjectRegistry for a different type."); + } + } + } + StructMemberFlag member_flags_value = TypeObjectUtils::build_struct_member_flag(eprosima::fastdds::dds::xtypes::TryConstructFailAction::DISCARD, + false, false, false, false); + MemberId member_id_value = 0x00000000; + bool common_value_ec {false}; + CommonStructMember common_value {TypeObjectUtils::build_common_struct_member(member_id_value, member_flags_value, TypeObjectUtils::retrieve_complete_type_identifier(type_ids_value, common_value_ec))}; + if (!common_value_ec) + { + EPROSIMA_LOG_ERROR(XTYPES_TYPE_REPRESENTATION, "Structure value member TypeIdentifier inconsistent."); + return; + } + MemberName name_value = "value"; + eprosima::fastcdr::optional member_ann_builtin_value; + ann_custom_DDSEnablerTestType3.reset(); + CompleteMemberDetail detail_value = TypeObjectUtils::build_complete_member_detail(name_value, member_ann_builtin_value, ann_custom_DDSEnablerTestType3); + CompleteStructMember member_value = TypeObjectUtils::build_complete_struct_member(common_value, detail_value); + TypeObjectUtils::add_complete_struct_member(member_seq_DDSEnablerTestType3, member_value); + } + CompleteStructType struct_type_DDSEnablerTestType3 = TypeObjectUtils::build_complete_struct_type(struct_flags_DDSEnablerTestType3, header_DDSEnablerTestType3, member_seq_DDSEnablerTestType3); + if (eprosima::fastdds::dds::RETCODE_BAD_PARAMETER == + TypeObjectUtils::build_and_register_struct_type_object(struct_type_DDSEnablerTestType3, type_name_DDSEnablerTestType3.to_string(), type_ids_DDSEnablerTestType3)) + { + EPROSIMA_LOG_ERROR(XTYPES_TYPE_REPRESENTATION, + "DDSEnablerTestType3 already registered in TypeObjectRegistry for a different type."); + } + } +} +// TypeIdentifier is returned by reference: dependent structures/unions are registered in this same method +void register_DDSEnablerTestType4_type_identifier( + TypeIdentifierPair& type_ids_DDSEnablerTestType4) +{ + + ReturnCode_t return_code_DDSEnablerTestType4 {eprosima::fastdds::dds::RETCODE_OK}; + return_code_DDSEnablerTestType4 = + eprosima::fastdds::dds::DomainParticipantFactory::get_instance()->type_object_registry().get_type_identifiers( + "DDSEnablerTestType4", type_ids_DDSEnablerTestType4); + if (eprosima::fastdds::dds::RETCODE_OK != return_code_DDSEnablerTestType4) + { + StructTypeFlag struct_flags_DDSEnablerTestType4 = TypeObjectUtils::build_struct_type_flag(eprosima::fastdds::dds::xtypes::ExtensibilityKind::APPENDABLE, + false, false); + QualifiedTypeName type_name_DDSEnablerTestType4 = "DDSEnablerTestType4"; + eprosima::fastcdr::optional type_ann_builtin_DDSEnablerTestType4; + eprosima::fastcdr::optional ann_custom_DDSEnablerTestType4; + CompleteTypeDetail detail_DDSEnablerTestType4 = TypeObjectUtils::build_complete_type_detail(type_ann_builtin_DDSEnablerTestType4, ann_custom_DDSEnablerTestType4, type_name_DDSEnablerTestType4.to_string()); + CompleteStructHeader header_DDSEnablerTestType4; + header_DDSEnablerTestType4 = TypeObjectUtils::build_complete_struct_header(TypeIdentifier(), detail_DDSEnablerTestType4); + CompleteStructMemberSeq member_seq_DDSEnablerTestType4; + { + TypeIdentifierPair type_ids_value; + ReturnCode_t return_code_value {eprosima::fastdds::dds::RETCODE_OK}; + return_code_value = + eprosima::fastdds::dds::DomainParticipantFactory::get_instance()->type_object_registry().get_type_identifiers( + "DDSEnablerTestType1", type_ids_value); + + if (eprosima::fastdds::dds::RETCODE_OK != return_code_value) + { + ::register_DDSEnablerTestType1_type_identifier(type_ids_value); + } + StructMemberFlag member_flags_value = TypeObjectUtils::build_struct_member_flag(eprosima::fastdds::dds::xtypes::TryConstructFailAction::DISCARD, + false, false, false, false); + MemberId member_id_value = 0x00000000; + bool common_value_ec {false}; + CommonStructMember common_value {TypeObjectUtils::build_common_struct_member(member_id_value, member_flags_value, TypeObjectUtils::retrieve_complete_type_identifier(type_ids_value, common_value_ec))}; + if (!common_value_ec) + { + EPROSIMA_LOG_ERROR(XTYPES_TYPE_REPRESENTATION, "Structure value member TypeIdentifier inconsistent."); + return; + } + MemberName name_value = "value"; + eprosima::fastcdr::optional member_ann_builtin_value; + ann_custom_DDSEnablerTestType4.reset(); + CompleteMemberDetail detail_value = TypeObjectUtils::build_complete_member_detail(name_value, member_ann_builtin_value, ann_custom_DDSEnablerTestType4); + CompleteStructMember member_value = TypeObjectUtils::build_complete_struct_member(common_value, detail_value); + TypeObjectUtils::add_complete_struct_member(member_seq_DDSEnablerTestType4, member_value); + } + CompleteStructType struct_type_DDSEnablerTestType4 = TypeObjectUtils::build_complete_struct_type(struct_flags_DDSEnablerTestType4, header_DDSEnablerTestType4, member_seq_DDSEnablerTestType4); + if (eprosima::fastdds::dds::RETCODE_BAD_PARAMETER == + TypeObjectUtils::build_and_register_struct_type_object(struct_type_DDSEnablerTestType4, type_name_DDSEnablerTestType4.to_string(), type_ids_DDSEnablerTestType4)) + { + EPROSIMA_LOG_ERROR(XTYPES_TYPE_REPRESENTATION, + "DDSEnablerTestType4 already registered in TypeObjectRegistry for a different type."); + } + } +} + diff --git a/ddsenabler_participants/test/types/DDSEnablerTestTypesTypeObjectSupport.hpp b/ddsenabler_participants/test/types/DDSEnablerTestTypesTypeObjectSupport.hpp new file mode 100644 index 00000000..e93f69f2 --- /dev/null +++ b/ddsenabler_participants/test/types/DDSEnablerTestTypesTypeObjectSupport.hpp @@ -0,0 +1,92 @@ +// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*! + * @file DDSEnablerTestTypesTypeObjectSupport.hpp + * Header file containing the API required to register the TypeObject representation of the described types in the IDL file + * + * This file was generated by the tool fastddsgen. + */ + +#ifndef FAST_DDS_GENERATED__DDSENABLERTESTTYPES_TYPE_OBJECT_SUPPORT_HPP +#define FAST_DDS_GENERATED__DDSENABLERTESTTYPES_TYPE_OBJECT_SUPPORT_HPP + +#include + + +#if defined(_WIN32) +#if defined(EPROSIMA_USER_DLL_EXPORT) +#define eProsima_user_DllExport __declspec( dllexport ) +#else +#define eProsima_user_DllExport +#endif // EPROSIMA_USER_DLL_EXPORT +#else +#define eProsima_user_DllExport +#endif // _WIN32 + +#ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC + +/** + * @brief Register DDSEnablerTestType1 related TypeIdentifier. + * Fully-descriptive TypeIdentifiers are directly registered. + * Hash TypeIdentifiers require to fill the TypeObject information and hash it, consequently, the TypeObject is + * indirectly registered as well. + * + * @param[out] TypeIdentifier of the registered type. + * The returned TypeIdentifier corresponds to the complete TypeIdentifier in case of hashed TypeIdentifiers. + * Invalid TypeIdentifier is returned in case of error. + */ +eProsima_user_DllExport void register_DDSEnablerTestType1_type_identifier( + eprosima::fastdds::dds::xtypes::TypeIdentifierPair& type_ids); +/** + * @brief Register DDSEnablerTestType2 related TypeIdentifier. + * Fully-descriptive TypeIdentifiers are directly registered. + * Hash TypeIdentifiers require to fill the TypeObject information and hash it, consequently, the TypeObject is + * indirectly registered as well. + * + * @param[out] TypeIdentifier of the registered type. + * The returned TypeIdentifier corresponds to the complete TypeIdentifier in case of hashed TypeIdentifiers. + * Invalid TypeIdentifier is returned in case of error. + */ +eProsima_user_DllExport void register_DDSEnablerTestType2_type_identifier( + eprosima::fastdds::dds::xtypes::TypeIdentifierPair& type_ids); +/** + * @brief Register DDSEnablerTestType3 related TypeIdentifier. + * Fully-descriptive TypeIdentifiers are directly registered. + * Hash TypeIdentifiers require to fill the TypeObject information and hash it, consequently, the TypeObject is + * indirectly registered as well. + * + * @param[out] TypeIdentifier of the registered type. + * The returned TypeIdentifier corresponds to the complete TypeIdentifier in case of hashed TypeIdentifiers. + * Invalid TypeIdentifier is returned in case of error. + */ +eProsima_user_DllExport void register_DDSEnablerTestType3_type_identifier( + eprosima::fastdds::dds::xtypes::TypeIdentifierPair& type_ids); +/** + * @brief Register DDSEnablerTestType4 related TypeIdentifier. + * Fully-descriptive TypeIdentifiers are directly registered. + * Hash TypeIdentifiers require to fill the TypeObject information and hash it, consequently, the TypeObject is + * indirectly registered as well. + * + * @param[out] TypeIdentifier of the registered type. + * The returned TypeIdentifier corresponds to the complete TypeIdentifier in case of hashed TypeIdentifiers. + * Invalid TypeIdentifier is returned in case of error. + */ +eProsima_user_DllExport void register_DDSEnablerTestType4_type_identifier( + eprosima::fastdds::dds::xtypes::TypeIdentifierPair& type_ids); + + +#endif // DOXYGEN_SHOULD_SKIP_THIS_PUBLIC + +#endif // FAST_DDS_GENERATED__DDSENABLERTESTTYPES_TYPE_OBJECT_SUPPORT_HPP diff --git a/ddsenabler_yaml/test/DdsEnablerYamlTest.cpp b/ddsenabler_yaml/test/DdsEnablerYamlTest.cpp index 6a7cad7c..bfec170e 100644 --- a/ddsenabler_yaml/test/DdsEnablerYamlTest.cpp +++ b/ddsenabler_yaml/test/DdsEnablerYamlTest.cpp @@ -172,7 +172,7 @@ TEST(DdsEnablerYamlTest, get_ddsenabler_incorrect_path_configuration_yaml) { const char* path_str = "incorrect/path/file.yaml"; - EXPECT_THROW({EnablerConfiguration configuration(path_str, false);}, eprosima::utils::ConfigurationException); + EXPECT_THROW({EnablerConfiguration configuration(path_str);}, eprosima::utils::ConfigurationException); } TEST(DdsEnablerYamlTest, get_ddsenabler_full_configuration_json) From d2b2fbd288ec8013bc6df45f5002c9e211ad8571 Mon Sep 17 00:00:00 2001 From: Juan Lopez Fernandez Date: Thu, 24 Apr 2025 15:29:54 +0200 Subject: [PATCH 06/28] Use CDRv1 when serializing data to be published Signed-off-by: Juan Lopez Fernandez --- ddsenabler_participants/src/cpp/CBHandler.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ddsenabler_participants/src/cpp/CBHandler.cpp b/ddsenabler_participants/src/cpp/CBHandler.cpp index f07c7ab3..456c1bb2 100644 --- a/ddsenabler_participants/src/cpp/CBHandler.cpp +++ b/ddsenabler_participants/src/cpp/CBHandler.cpp @@ -199,10 +199,10 @@ bool CBHandler::get_serialized_data( return false; } - // TODO: double chekc XCDR2 is the right choice -> only supposed to work against fastdds 3, and appendable only working with XCDR2 + // Use XCDR1 for backwards compatibility (e.g. ROS 2 distributions prior to Kilt) fastdds::dds::DynamicPubSubType pubsub_type(dyn_type); uint32_t payload_size = pubsub_type.calculate_serialized_size(&dyn_data, - fastdds::dds::DataRepresentationId::XCDR2_DATA_REPRESENTATION); + fastdds::dds::DataRepresentationId::XCDR_DATA_REPRESENTATION); if (!payload_pool_->get_payload(payload_size, payload)) { @@ -211,7 +211,7 @@ bool CBHandler::get_serialized_data( return false; } - if (!pubsub_type.serialize(&dyn_data, payload, fastdds::dds::DataRepresentationId::XCDR2_DATA_REPRESENTATION)) + if (!pubsub_type.serialize(&dyn_data, payload, fastdds::dds::DataRepresentationId::XCDR_DATA_REPRESENTATION)) { EPROSIMA_LOG_ERROR(DDSENABLER_CB_HANDLER, "Failed to deserialize data for type " << type_name << " : payload serialization failed."); From 32c6f3bf143644543007f44e951cc4bd719c5cb7 Mon Sep 17 00:00:00 2001 From: Juan Lopez Fernandez Date: Fri, 9 May 2025 12:21:08 +0200 Subject: [PATCH 07/28] Rebase fixes and updates Signed-off-by: Juan Lopez Fernandez --- ddsenabler/examples/CLIParser.hpp | 14 +++++--- ddsenabler/examples/main.cpp | 36 ++++++++++++++++--- .../test/ddsEnablerTests/ReloadConfig.cpp | 3 +- .../ddsenabler_participants/CBWriter.hpp | 2 -- ddsenabler_participants/src/cpp/CBHandler.cpp | 9 ----- .../test_cases/topics_json/compose.yml | 2 +- .../test_cases/topics_yaml/compose.yml | 2 +- 7 files changed, 43 insertions(+), 25 deletions(-) diff --git a/ddsenabler/examples/CLIParser.hpp b/ddsenabler/examples/CLIParser.hpp index 2548d9f3..2bcf1661 100644 --- a/ddsenabler/examples/CLIParser.hpp +++ b/ddsenabler/examples/CLIParser.hpp @@ -29,6 +29,7 @@ class CLIParser struct example_config { uint32_t expected_types_ = 0; + uint32_t expected_topics_ = 0; uint32_t expected_data_ = 0; uint32_t timeout_seconds = 30; std::string config_file_path_ = ""; @@ -44,12 +45,14 @@ class CLIParser static void print_help( uint8_t return_code) { - std::cout << "Usage: ddsenabler_example " << + std::cout << "Usage: ddsenabler_example " << std::endl; std::cout << "" << std::endl; std::cout << "expected_types: number of types to be expected" << std::endl; + std::cout << "expected_topics: number of topics to be expected" << + std::endl; std::cout << "expected_data: number of data to be expected" << std::endl; std::cout << "timeout: time to wait before stopping the program if the data is not received" << @@ -74,7 +77,7 @@ class CLIParser { example_config config; - if (argc < 5) + if (argc < 6) { std::cerr << "Missing entity argument" << std::endl; print_help(EXIT_FAILURE); @@ -83,9 +86,10 @@ class CLIParser try { config.expected_types_ = std::stoi(argv[1]); - config.expected_data_ = std::stoi(argv[2]); - config.timeout_seconds = std::stoi(argv[3]); - config.config_file_path_ = argv[4]; + config.expected_topics_ = std::stoi(argv[2]); + config.expected_data_ = std::stoi(argv[3]); + config.timeout_seconds = std::stoi(argv[4]); + config.config_file_path_ = argv[5]; } catch (const std::exception& e) { diff --git a/ddsenabler/examples/main.cpp b/ddsenabler/examples/main.cpp index 4e4d8a5b..126f244c 100644 --- a/ddsenabler/examples/main.cpp +++ b/ddsenabler/examples/main.cpp @@ -27,16 +27,20 @@ #include "CLIParser.hpp" uint32_t received_types_ = 0; +uint32_t received_topics_ = 0; uint32_t received_data_ = 0; std::mutex type_received_mutex_; +std::mutex topic_received_mutex_; std::mutex data_received_mutex_; bool stop_app_ = false; // Static type callback static void test_type_callback( const char* typeName, - const char* topicName, - const char* serializedType) + const char* serializedType, + const unsigned char* serializedTypeInternal, + uint32_t serializedTypeInternalSize, + const char* dataPlaceholder) { std::lock_guard lock(type_received_mutex_); @@ -45,9 +49,21 @@ static void test_type_callback( received_types_ << std::endl; } +// Static topic callback +static void test_topic_callback( + const char* topicName, + const char* typeName, + const char* serializedQos) +{ + std::lock_guard lock(topic_received_mutex_); + + received_topics_++; + std::cout << "Topic callback received: " << topicName << " of type " << typeName << ", Total topics: " << + received_topics_ << std::endl; +} + // Static data callback static void test_data_callback( - const char* typeName, const char* topicName, const char* json, int64_t publishTime) @@ -55,7 +71,7 @@ static void test_data_callback( std::lock_guard lock(data_received_mutex_); received_data_++; - std::cout << "Data callback received: " << typeName << ", Total data: " << + std::cout << "Data callback received: " << topicName << ", Total data: " << received_data_ << std::endl; } @@ -66,6 +82,13 @@ int get_received_types() return received_types_; } +int get_received_topics() +{ + std::lock_guard lock(topic_received_mutex_); + + return received_topics_; +} + int get_received_data() { std::lock_guard lock(data_received_mutex_); @@ -84,10 +107,12 @@ int main( int argc, char** argv) { + using namespace eprosima::ddsenabler; + CLIParser::example_config config = CLIParser::parse_cli_options(argc, argv); std::unique_ptr enabler; - create_dds_enabler(config.config_file_path_.c_str(), test_data_callback, test_type_callback, nullptr, enabler); + create_dds_enabler(config.config_file_path_.c_str(), test_data_callback, test_type_callback, test_topic_callback, nullptr, nullptr, nullptr, enabler); signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); @@ -106,6 +131,7 @@ int main( return EXIT_SUCCESS; } else if (get_received_types() >= config.expected_types_ && + get_received_topics() >= config.expected_topics_ && get_received_data() >= config.expected_data_) { std::cout << "Received enough data, stopping..." << std::endl; diff --git a/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp b/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp index f6780afe..85cfe855 100644 --- a/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp +++ b/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp @@ -206,8 +206,7 @@ TEST(ReloadConfig, yaml) // Create DDS Enabler std::unique_ptr enabler; - bool result = create_dds_enabler(configfile, test_data_callback, test_type_callback, test_topic_notification_callback, test_type_request_callback, test_topic_request_callback, test_log_callback, enabler); - ASSERT_TRUE(result); + ASSERT_TRUE(create_dds_enabler(configfile, test_data_callback, test_type_callback, test_topic_notification_callback, test_type_request_callback, test_topic_request_callback, test_log_callback, enabler)); // Create DDSEnablerAccessor to access protected configuration auto enabler_accessor = static_cast(enabler.get()); diff --git a/ddsenabler_participants/include/ddsenabler_participants/CBWriter.hpp b/ddsenabler_participants/include/ddsenabler_participants/CBWriter.hpp index 0e9c3b59..f6f2de92 100644 --- a/ddsenabler_participants/include/ddsenabler_participants/CBWriter.hpp +++ b/ddsenabler_participants/include/ddsenabler_participants/CBWriter.hpp @@ -45,7 +45,6 @@ class CBWriter void set_data_callback( DdsNotification callback) { - std::lock_guard lock(mutex_); data_callback_ = callback; } @@ -53,7 +52,6 @@ class CBWriter void set_type_callback( DdsTypeNotification callback) { - std::lock_guard lock(mutex_); type_callback_ = callback; } diff --git a/ddsenabler_participants/src/cpp/CBHandler.cpp b/ddsenabler_participants/src/cpp/CBHandler.cpp index 456c1bb2..c2725c01 100644 --- a/ddsenabler_participants/src/cpp/CBHandler.cpp +++ b/ddsenabler_participants/src/cpp/CBHandler.cpp @@ -16,18 +16,9 @@ * @file CBHandler.cpp */ -<<<<<<< HEAD -#include -#include -#include -#include - -#include -======= #include #include #include ->>>>>>> e025823 (DDS data publication implementation) #include #include #include diff --git a/ddsenabler_test/compose/test_cases/topics_json/compose.yml b/ddsenabler_test/compose/test_cases/topics_json/compose.yml index 0c757ee2..96a0a33e 100644 --- a/ddsenabler_test/compose/test_cases/topics_json/compose.yml +++ b/ddsenabler_test/compose/test_cases/topics_json/compose.yml @@ -16,7 +16,7 @@ services: - std_net volumes: - ./config.json:/config/config.json - command: ./build/ddsenabler/examples/ddsenabler_example 1 1 10 /config/config.json + command: ./build/ddsenabler/examples/ddsenabler_example 1 1 1 10 /config/config.json talker: image: ${DDSENABLER_COMPOSE_TEST_ROS2_DOCKER_IMAGE} diff --git a/ddsenabler_test/compose/test_cases/topics_yaml/compose.yml b/ddsenabler_test/compose/test_cases/topics_yaml/compose.yml index 4db0aeed..f6c4af2a 100644 --- a/ddsenabler_test/compose/test_cases/topics_yaml/compose.yml +++ b/ddsenabler_test/compose/test_cases/topics_yaml/compose.yml @@ -16,7 +16,7 @@ services: - std_net volumes: - ./config.yml:/config/config.yml - command: ./build/ddsenabler/examples/ddsenabler_example 1 1 10 /config/config.yml + command: ./build/ddsenabler/examples/ddsenabler_example 1 1 1 10 /config/config.yml talker: image: ${DDSENABLER_COMPOSE_TEST_ROS2_DOCKER_IMAGE} From 422ab7a724720fcbeefb88488ff56910bd1d19cc Mon Sep 17 00:00:00 2001 From: Juan Lopez Fernandez Date: Fri, 9 May 2025 12:33:31 +0200 Subject: [PATCH 08/28] TMP: use custom artifact in CI Signed-off-by: Juan Lopez Fernandez --- .github/workflows/test.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4124dc36..e3180dab 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -38,7 +38,7 @@ on: dependencies_artifact_postfix: description: 'Postfix name to add to artifact name to download dependencies. This is use to download a specific artifact version from eProsima-CI.' required: true - default: '_nightly' + default: '_ddsenabler' pull_request: push: @@ -51,7 +51,7 @@ jobs: name: reusable_tests uses: ./.github/workflows/reusable-ubuntu-ci.yml with: - dependencies_artifact_postfix: ${{ inputs.dependencies_artifact_postfix || '_nightly' }} + dependencies_artifact_postfix: ${{ inputs.dependencies_artifact_postfix || '_ddsenabler' }} ref: ${{ github.ref }} secrets: inherit @@ -59,7 +59,7 @@ jobs: name: reusable_tests uses: ./.github/workflows/reusable-windows-ci.yml with: - dependencies_artifact_postfix: ${{ inputs.dependencies_artifact_postfix || '_nightly' }} + dependencies_artifact_postfix: ${{ inputs.dependencies_artifact_postfix || '_ddsenabler' }} ref: ${{ github.ref }} secrets: inherit @@ -72,6 +72,6 @@ jobs: devutils_branch: ${{ inputs.devutils_branch || 'main' }} ddspipe_branch: ${{ inputs.ddspipe_branch || 'main' }} ddsenabler_branch: ${{ inputs.ddsenabler_branch || github.head_ref || github.ref_name }} - dependencies_artifact_postfix: ${{ inputs.dependencies_artifact_postfix || '_nightly' }} + dependencies_artifact_postfix: ${{ inputs.dependencies_artifact_postfix || '_ddsenabler' }} ref: ${{ github.ref }} secrets: inherit From cd69e317474984fcabfcecd678e7272966349e10 Mon Sep 17 00:00:00 2001 From: Juan Lopez Fernandez Date: Tue, 20 May 2025 07:57:11 +0200 Subject: [PATCH 09/28] Store DomainParticipantFactory reference in DDSEnabler objects Signed-off-by: Juan Lopez Fernandez --- ddsenabler/include/ddsenabler/DDSEnabler.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ddsenabler/include/ddsenabler/DDSEnabler.hpp b/ddsenabler/include/ddsenabler/DDSEnabler.hpp index de613138..c4752af2 100644 --- a/ddsenabler/include/ddsenabler/DDSEnabler.hpp +++ b/ddsenabler/include/ddsenabler/DDSEnabler.hpp @@ -20,6 +20,8 @@ #include +#include + #include #include #include @@ -131,6 +133,9 @@ class DDSEnabler void load_internal_topics_( yaml::EnablerConfiguration& configuration); + //! Store reference to DomainParticipantFactory to avoid Fast-DDS singletons being destroyed before they should + std::shared_ptr part_factory_ = eprosima::fastdds::dds::DomainParticipantFactory::get_shared_instance(); + //! Configuration of the DDS Enabler yaml::EnablerConfiguration configuration_; From 866195fd8ab1d45803861917671f8b2dd00a6c12 Mon Sep 17 00:00:00 2001 From: Juan Lopez Fernandez Date: Tue, 20 May 2025 07:58:48 +0200 Subject: [PATCH 10/28] Change unique_ptr to shared_ptr in create_dds_enabler Signed-off-by: Juan Lopez Fernandez --- ddsenabler/examples/main.cpp | 2 +- ddsenabler/include/ddsenabler/dds_enabler_runner.hpp | 5 +++-- ddsenabler/src/cpp/dds_enabler_runner.cpp | 5 +++-- ddsenabler/test/DDSEnablerTester.hpp | 8 ++++---- ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp | 4 ++-- 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/ddsenabler/examples/main.cpp b/ddsenabler/examples/main.cpp index 126f244c..fb0f376a 100644 --- a/ddsenabler/examples/main.cpp +++ b/ddsenabler/examples/main.cpp @@ -111,7 +111,7 @@ int main( CLIParser::example_config config = CLIParser::parse_cli_options(argc, argv); - std::unique_ptr enabler; + std::shared_ptr enabler; create_dds_enabler(config.config_file_path_.c_str(), test_data_callback, test_type_callback, test_topic_callback, nullptr, nullptr, nullptr, enabler); signal(SIGINT, signal_handler); diff --git a/ddsenabler/include/ddsenabler/dds_enabler_runner.hpp b/ddsenabler/include/ddsenabler/dds_enabler_runner.hpp index ec9196eb..33759920 100644 --- a/ddsenabler/include/ddsenabler/dds_enabler_runner.hpp +++ b/ddsenabler/include/ddsenabler/dds_enabler_runner.hpp @@ -19,6 +19,7 @@ #pragma once +#include #include #include @@ -49,7 +50,7 @@ bool create_dds_enabler( participants::DdsTypeRequest type_req_callback, participants::DdsTopicRequest topic_req_callback, participants::DdsLogFunc log_callback, - std::unique_ptr& enabler); + std::shared_ptr& enabler); bool create_dds_enabler( yaml::EnablerConfiguration configuration, @@ -59,7 +60,7 @@ bool create_dds_enabler( participants::DdsTypeRequest type_req_callback, participants::DdsTopicRequest topic_req_callback, participants::DdsLogFunc log_callback, - std::unique_ptr& enabler); + std::shared_ptr& enabler); } /* namespace ddsenabler */ } /* namespace eprosima */ diff --git a/ddsenabler/src/cpp/dds_enabler_runner.cpp b/ddsenabler/src/cpp/dds_enabler_runner.cpp index 60763fb3..ee19ca3f 100644 --- a/ddsenabler/src/cpp/dds_enabler_runner.cpp +++ b/ddsenabler/src/cpp/dds_enabler_runner.cpp @@ -40,13 +40,14 @@ bool create_dds_enabler( participants::DdsTypeRequest type_req_callback, participants::DdsTopicRequest topic_req_callback, participants::DdsLogFunc log_callback, - std::unique_ptr& enabler) + std::shared_ptr& enabler) { std::string dds_enabler_config_file = ""; if (ddsEnablerConfigFile != NULL) { dds_enabler_config_file = ddsEnablerConfigFile; } + // Load configuration from file eprosima::ddsenabler::yaml::EnablerConfiguration configuration(dds_enabler_config_file); @@ -85,7 +86,7 @@ bool create_dds_enabler( participants::DdsTypeRequest type_req_callback, participants::DdsTopicRequest topic_req_callback, participants::DdsLogFunc log_callback, - std::unique_ptr& enabler) + std::shared_ptr& enabler) { // Encapsulating execution in block to erase all memory correctly before closing process try diff --git a/ddsenabler/test/DDSEnablerTester.hpp b/ddsenabler/test/DDSEnablerTester.hpp index b4a663ec..2d0a5231 100644 --- a/ddsenabler/test/DDSEnablerTester.hpp +++ b/ddsenabler/test/DDSEnablerTester.hpp @@ -72,7 +72,7 @@ class DDSEnablerTester : public ::testing::Test } // Create the DDSEnabler and bind the static callbacks - std::unique_ptr create_ddsenabler() + std::shared_ptr create_ddsenabler() { YAML::Node yml; @@ -80,14 +80,14 @@ class DDSEnablerTester : public ::testing::Test configuration.simple_configuration->domain = DOMAIN_; // Create DDS Enabler - std::unique_ptr enabler; + std::shared_ptr enabler; bool result = create_dds_enabler(configuration, test_data_callback, test_type_callback, test_topic_notification_callback, test_type_request_callback, test_topic_request_callback, test_log_callback, enabler); return enabler; } // Create the DDSEnabler and bind the static callbacks - std::unique_ptr create_ddsenabler_w_history() + std::shared_ptr create_ddsenabler_w_history() { const char* yml_str = R"( @@ -110,7 +110,7 @@ class DDSEnablerTester : public ::testing::Test auto close_handler = std::make_shared(); - auto enabler = std::make_unique(configuration, close_handler); + auto enabler = std::make_shared(configuration, close_handler); // Bind the static callbacks (no captures allowed) enabler->set_data_callback(test_data_callback); diff --git a/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp b/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp index 85cfe855..d8b59cc8 100644 --- a/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp +++ b/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp @@ -174,7 +174,7 @@ TEST(ReloadConfig, json) write_json_file(configfile, false); // Create DDS Enabler - std::unique_ptr enabler; + std::shared_ptr enabler; ASSERT_TRUE(create_dds_enabler(configfile, test_data_callback, test_type_callback, test_topic_notification_callback, test_type_request_callback, test_topic_request_callback, test_log_callback, enabler)); // Create DDSEnablerAccessor to access protected configuration @@ -205,7 +205,7 @@ TEST(ReloadConfig, yaml) write_yaml_file(configfile, 0); // Create DDS Enabler - std::unique_ptr enabler; + std::shared_ptr enabler; ASSERT_TRUE(create_dds_enabler(configfile, test_data_callback, test_type_callback, test_topic_notification_callback, test_type_request_callback, test_topic_request_callback, test_log_callback, enabler)); // Create DDSEnablerAccessor to access protected configuration From aeabbbfaed97bc1d4e81336eb141d4b824ba3c53 Mon Sep 17 00:00:00 2001 From: Juan Lopez Fernandez Date: Tue, 27 May 2025 12:41:50 +0200 Subject: [PATCH 11/28] Tackle pending TODOs Signed-off-by: Juan Lopez Fernandez --- ddsenabler/DDS_ENABLER_CONFIGURATION.json | 4 +- ddsenabler/DDS_ENABLER_CONFIGURATION.yaml | 1 + ddsenabler/examples/config.yml | 3 + ddsenabler/examples/main.cpp | 52 +++--- ddsenabler/include/ddsenabler/CallbackSet.hpp | 48 +++++ ddsenabler/include/ddsenabler/DDSEnabler.hpp | 58 ++---- .../include/ddsenabler/dds_enabler_runner.hpp | 19 +- ddsenabler/src/cpp/DDSEnabler.cpp | 40 ++++- ddsenabler/src/cpp/dds_enabler_runner.cpp | 42 +---- ddsenabler/test/DDSEnablerTester.hpp | 107 +++++++---- .../test/ddsEnablerTests/DdsEnablerTest.cpp | 28 ++- .../test/ddsEnablerTests/ReloadConfig.cpp | 76 +++++--- .../DdsEnablerTypedTest.cpp | 2 + ddsenabler_participants/README.md | 5 - .../ddsenabler_participants/CBCallbacks.hpp | 61 ++++--- .../ddsenabler_participants/CBHandler.hpp | 120 +++++++++++-- .../ddsenabler_participants/CBWriter.hpp | 66 +++++-- .../DDSEnablerLogConsumer.hpp | 1 + .../ddsenabler_participants/serialization.hpp | 40 +++++ ddsenabler_participants/src/cpp/CBHandler.cpp | 168 ++++++++++++------ ddsenabler_participants/src/cpp/CBWriter.cpp | 95 ++++++---- .../src/cpp/EnablerParticipant.cpp | 48 +++-- .../src/cpp/serialization.cpp | 26 ++- .../test/DdsEnablerParticipantsTest.cpp | 53 +++--- .../test_cases/topics_json/config.json | 4 +- ddsenabler_test/package.xml | 2 +- ddsenabler_yaml/README.md | 43 ----- .../ddsenabler_yaml/EnablerConfiguration.hpp | 12 +- .../src/cpp/EnablerConfiguration.cpp | 37 ++-- .../test/resources/correct_config.json | 4 +- .../test/resources/full_config.json | 4 +- docs/context_broker_interface.rst | 2 +- 32 files changed, 835 insertions(+), 436 deletions(-) create mode 100644 ddsenabler/include/ddsenabler/CallbackSet.hpp delete mode 100644 ddsenabler_participants/README.md delete mode 100644 ddsenabler_yaml/README.md diff --git a/ddsenabler/DDS_ENABLER_CONFIGURATION.json b/ddsenabler/DDS_ENABLER_CONFIGURATION.json index 3be31cdc..4bdfa292 100644 --- a/ddsenabler/DDS_ENABLER_CONFIGURATION.json +++ b/ddsenabler/DDS_ENABLER_CONFIGURATION.json @@ -23,7 +23,9 @@ } ] }, - "ddsenabler": null, + "ddsenabler": { + "initial-publish-wait": 500 + }, "specs": { "threads": 12, "logging": { diff --git a/ddsenabler/DDS_ENABLER_CONFIGURATION.yaml b/ddsenabler/DDS_ENABLER_CONFIGURATION.yaml index d06934f0..4702da85 100644 --- a/ddsenabler/DDS_ENABLER_CONFIGURATION.yaml +++ b/ddsenabler/DDS_ENABLER_CONFIGURATION.yaml @@ -13,6 +13,7 @@ dds: # DDS Enabler configuration ddsenabler: + initial-publish-wait: 500 #Specs configuration specs: diff --git a/ddsenabler/examples/config.yml b/ddsenabler/examples/config.yml index 7fc78ef3..5cc4050d 100644 --- a/ddsenabler/examples/config.yml +++ b/ddsenabler/examples/config.yml @@ -21,3 +21,6 @@ dds: transport: shm whitelist-interfaces: - "127.0.0.1" + +ddsenabler: + initial-publish-wait: 500 diff --git a/ddsenabler/examples/main.cpp b/ddsenabler/examples/main.cpp index fb0f376a..6a20d9fc 100644 --- a/ddsenabler/examples/main.cpp +++ b/ddsenabler/examples/main.cpp @@ -18,13 +18,13 @@ */ #include +#include #include #include -#include +#include "CLIParser.hpp" #include "ddsenabler/dds_enabler_runner.hpp" #include "ddsenabler/DDSEnabler.hpp" -#include "CLIParser.hpp" uint32_t received_types_ = 0; uint32_t received_topics_ = 0; @@ -34,45 +34,45 @@ std::mutex topic_received_mutex_; std::mutex data_received_mutex_; bool stop_app_ = false; -// Static type callback -static void test_type_callback( - const char* typeName, - const char* serializedType, - const unsigned char* serializedTypeInternal, - uint32_t serializedTypeInternalSize, - const char* dataPlaceholder) +// Static type notification callback +static void test_type_notification_callback( + const char* type_name, + const char* serialized_type, + const unsigned char* serialized_type_internal, + uint32_t serialized_type_internal_size, + const char* data_placeholder) { std::lock_guard lock(type_received_mutex_); received_types_++; - std::cout << "Type callback received: " << typeName << ", Total types: " << + std::cout << "Type callback received: " << type_name << ", Total types: " << received_types_ << std::endl; } -// Static topic callback -static void test_topic_callback( - const char* topicName, - const char* typeName, +// Static topic notification callback +static void test_topic_notification_callback( + const char* topic_name, + const char* type_name, const char* serializedQos) { std::lock_guard lock(topic_received_mutex_); received_topics_++; - std::cout << "Topic callback received: " << topicName << " of type " << typeName << ", Total topics: " << + std::cout << "Topic callback received: " << topic_name << " of type " << type_name << ", Total topics: " << received_topics_ << std::endl; } -// Static data callback -static void test_data_callback( - const char* topicName, +// Static data notification callback +static void test_data_notification_callback( + const char* topic_name, const char* json, - int64_t publishTime) + int64_t publish_time) { std::lock_guard lock(data_received_mutex_); received_data_++; - std::cout << "Data callback received: " << topicName << ", Total data: " << - received_data_ << std::endl; + std::cout << "Data callback received: " << topic_name << ", Total data: " << + received_data_ << ", data: " << json << std::endl; } int get_received_types() @@ -111,8 +111,16 @@ int main( CLIParser::example_config config = CLIParser::parse_cli_options(argc, argv); + CallbackSet callbacks{ + .dds = { + .type_notification = test_type_notification_callback, + .topic_notification = test_topic_notification_callback, + .data_notification = test_data_notification_callback + } + }; + std::shared_ptr enabler; - create_dds_enabler(config.config_file_path_.c_str(), test_data_callback, test_type_callback, test_topic_callback, nullptr, nullptr, nullptr, enabler); + create_dds_enabler(config.config_file_path_.c_str(), callbacks, enabler); signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); diff --git a/ddsenabler/include/ddsenabler/CallbackSet.hpp b/ddsenabler/include/ddsenabler/CallbackSet.hpp new file mode 100644 index 00000000..4d04ce7b --- /dev/null +++ b/ddsenabler/include/ddsenabler/CallbackSet.hpp @@ -0,0 +1,48 @@ +// Copyright 2025 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @file CallbackSet.hpp + */ + +#pragma once + +#include + +namespace eprosima { +namespace ddsenabler { + +/** + * @brief Struct that encapsulates all the DDS related callbacks used by the DDS Enabler. + */ +struct DdsCallbacks +{ + participants::DdsTypeNotification type_notification{nullptr}; + participants::DdsTopicNotification topic_notification{nullptr}; + participants::DdsDataNotification data_notification{nullptr}; + participants::DdsTypeRequest type_request{nullptr}; + participants::DdsTopicRequest topic_request{nullptr}; +}; + +/** + * @brief Struct that encapsulates all the callbacks used by the DDS Enabler. + */ +struct CallbackSet +{ + participants::DdsLogFunc log{nullptr}; + DdsCallbacks dds; +}; + +} /* namespace ddsenabler */ +} /* namespace eprosima */ diff --git a/ddsenabler/include/ddsenabler/DDSEnabler.hpp b/ddsenabler/include/ddsenabler/DDSEnabler.hpp index c4752af2..c9acd520 100644 --- a/ddsenabler/include/ddsenabler/DDSEnabler.hpp +++ b/ddsenabler/include/ddsenabler/DDSEnabler.hpp @@ -23,7 +23,6 @@ #include #include -#include #include #include @@ -42,6 +41,7 @@ #include +#include namespace eprosima { namespace ddsenabler { @@ -54,47 +54,16 @@ class DDSEnabler public: /** - * DDSEnabler constructor by required values and event handler reference. + * DDSEnabler constructor by required values. * * Creates DDSEnabler instance with given configuration. * * @param configuration: Structure encapsulating all enabler configuration options. - * @param event_handler: Reference to event handler used for thread synchronization in main application. + * @param callbacks: Set of callbacks to be used by the enabler. */ DDSEnabler( const yaml::EnablerConfiguration& configuration, - std::shared_ptr event_handler); - - - void set_data_callback( - participants::DdsNotification callback) - { - cb_handler_->set_data_callback(callback); - } - - void set_type_callback( - participants::DdsTypeNotification callback) - { - cb_handler_->set_type_callback(callback); - } - - void set_topic_callback( - participants::DdsTopicNotification callback) - { - cb_handler_->set_topic_callback(callback); - } - - void set_topic_request_callback( - participants::DdsTopicRequest callback) - { - enabler_participant_->set_topic_request_callback(callback); - } - - void set_type_request_callback( - participants::DdsTypeRequest callback) - { - cb_handler_->set_type_request_callback(callback); - } + const CallbackSet& callbacks); /** * Associate the file watcher to the configuration file and establish the callback to reload the configuration. @@ -118,7 +87,13 @@ class DDSEnabler utils::ReturnCode reload_configuration( yaml::EnablerConfiguration& new_configuration); - // TODO + /** + * Publish a JSON message to the specified topic. + * + * @param topic_name: The name of the topic to publish to. + * @param json: The JSON message to publish. + * @return \c true if the message was published successfully, \c false otherwise. + */ bool publish( const std::string& topic_name, const std::string& json); @@ -133,6 +108,14 @@ class DDSEnabler void load_internal_topics_( yaml::EnablerConfiguration& configuration); + /** + * Set the internal callbacks used by the enabler. + * + * @param callbacks: The set of callbacks to be used by the enabler. + */ + void set_internal_callbacks_( + const CallbackSet& callbacks); + //! Store reference to DomainParticipantFactory to avoid Fast-DDS singletons being destroyed before they should std::shared_ptr part_factory_ = eprosima::fastdds::dds::DomainParticipantFactory::get_shared_instance(); @@ -163,9 +146,6 @@ class DDSEnabler //! DDS Pipe std::unique_ptr pipe_; - //! Reference to event handler used for thread synchronization in main application - std::shared_ptr event_handler_; - //! Config File watcher handler std::unique_ptr file_watcher_handler_; diff --git a/ddsenabler/include/ddsenabler/dds_enabler_runner.hpp b/ddsenabler/include/ddsenabler/dds_enabler_runner.hpp index 33759920..44821575 100644 --- a/ddsenabler/include/ddsenabler/dds_enabler_runner.hpp +++ b/ddsenabler/include/ddsenabler/dds_enabler_runner.hpp @@ -31,35 +31,24 @@ #include #include -#include - #include #include -#include "ddsenabler/DDSEnabler.hpp" +#include +#include namespace eprosima { namespace ddsenabler { bool create_dds_enabler( const char* ddsEnablerConfigFile, - participants::DdsNotification data_callback, - participants::DdsTypeNotification type_callback, - participants::DdsTopicNotification topic_callback, - participants::DdsTypeRequest type_req_callback, - participants::DdsTopicRequest topic_req_callback, - participants::DdsLogFunc log_callback, + const CallbackSet& callbacks, std::shared_ptr& enabler); bool create_dds_enabler( yaml::EnablerConfiguration configuration, - participants::DdsNotification data_callback, - participants::DdsTypeNotification type_callback, - participants::DdsTopicNotification topic_callback, - participants::DdsTypeRequest type_req_callback, - participants::DdsTopicRequest topic_req_callback, - participants::DdsLogFunc log_callback, + const CallbackSet& callbacks, std::shared_ptr& enabler); } /* namespace ddsenabler */ diff --git a/ddsenabler/src/cpp/DDSEnabler.cpp b/ddsenabler/src/cpp/DDSEnabler.cpp index 0ed209f7..02b61b78 100644 --- a/ddsenabler/src/cpp/DDSEnabler.cpp +++ b/ddsenabler/src/cpp/DDSEnabler.cpp @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include #include #include @@ -30,9 +31,8 @@ using namespace eprosima::utils; DDSEnabler::DDSEnabler( const yaml::EnablerConfiguration& configuration, - std::shared_ptr event_handler) + const CallbackSet& callbacks) : configuration_(configuration) - , event_handler_(event_handler) { // Load the Enabler's internal topics from a configuration object. load_internal_topics_(configuration_); @@ -81,12 +81,23 @@ DDSEnabler::DDSEnabler( enabler_participant_); // Create DDS Pipe + // NOTE: Create disabled, and enable after all callbacks are set to avoid missing notifications pipe_ = std::make_unique( configuration_.ddspipe_configuration, discovery_database_, payload_pool_, participants_database_, thread_pool_); + + // Set user defined callbacks in all internal entities requiring it + set_internal_callbacks_(callbacks); + + // Enable DDS Pipe after having set all callbacks + if (pipe_->enable() != utils::ReturnCode::RETCODE_OK) + { + throw utils::InitializationException( + utils::Formatter() << "Failed to enable DDS Pipe."); + } } bool DDSEnabler::set_file_watcher( @@ -172,6 +183,31 @@ void DDSEnabler::load_internal_topics_( } } +void DDSEnabler::set_internal_callbacks_( + const CallbackSet& callbacks) +{ + if (callbacks.dds.type_notification) + { + cb_handler_->set_type_notification_callback(callbacks.dds.type_notification); + } + if (callbacks.dds.topic_notification) + { + cb_handler_->set_topic_notification_callback(callbacks.dds.topic_notification); + } + if (callbacks.dds.data_notification) + { + cb_handler_->set_data_notification_callback(callbacks.dds.data_notification); + } + if (callbacks.dds.type_request) + { + cb_handler_->set_type_request_callback(callbacks.dds.type_request); + } + if (callbacks.dds.topic_request) + { + enabler_participant_->set_topic_request_callback(callbacks.dds.topic_request); + } +} + bool DDSEnabler::publish( const std::string& topic_name, const std::string& json) diff --git a/ddsenabler/src/cpp/dds_enabler_runner.cpp b/ddsenabler/src/cpp/dds_enabler_runner.cpp index ee19ca3f..67b7ace0 100644 --- a/ddsenabler/src/cpp/dds_enabler_runner.cpp +++ b/ddsenabler/src/cpp/dds_enabler_runner.cpp @@ -22,10 +22,9 @@ #include #include -#include #include -#include "ddsenabler/dds_enabler_runner.hpp" +#include using namespace eprosima::ddspipe; @@ -34,12 +33,7 @@ namespace ddsenabler { bool create_dds_enabler( const char* ddsEnablerConfigFile, - participants::DdsNotification data_callback, - participants::DdsTypeNotification type_callback, - participants::DdsTopicNotification topic_callback, - participants::DdsTypeRequest type_req_callback, - participants::DdsTopicRequest topic_req_callback, - participants::DdsLogFunc log_callback, + const CallbackSet& callbacks, std::shared_ptr& enabler) { std::string dds_enabler_config_file = ""; @@ -54,12 +48,7 @@ bool create_dds_enabler( // Create DDS Enabler instance if (!create_dds_enabler( configuration, - data_callback, - type_callback, - topic_callback, - type_req_callback, - topic_req_callback, - log_callback, + callbacks, enabler)) { EPROSIMA_LOG_ERROR(DDSENABLER_EXECUTION, @@ -80,12 +69,7 @@ bool create_dds_enabler( bool create_dds_enabler( yaml::EnablerConfiguration configuration, - participants::DdsNotification data_callback, - participants::DdsTypeNotification type_callback, - participants::DdsTopicNotification topic_callback, - participants::DdsTypeRequest type_req_callback, - participants::DdsTopicRequest topic_req_callback, - participants::DdsLogFunc log_callback, + const CallbackSet& callbacks, std::shared_ptr& enabler) { // Encapsulating execution in block to erase all memory correctly before closing process @@ -106,11 +90,11 @@ bool create_dds_enabler( eprosima::utils::Log::ClearConsumers(); eprosima::utils::Log::SetVerbosity(log_configuration.verbosity); - if (log_callback) + if (callbacks.log) { // User callback Log Consumer auto* log_consumer = new eprosima::ddsenabler::participants::DDSEnablerLogConsumer(&log_configuration); - log_consumer->set_log_callback(log_callback); + log_consumer->set_log_callback(callbacks.log); eprosima::utils::Log::RegisterConsumer( std::unique_ptr(log_consumer)); @@ -135,18 +119,8 @@ bool create_dds_enabler( EPROSIMA_LOG_INFO(DDSENABLER_EXECUTION, "Starting DDS Enabler execution."); - // Create a multiple event handler that handles all events that make the enabler stop - auto close_handler = std::make_shared(); - - // Create DDSEnabler and set the context broker callbacks - enabler.reset(new DDSEnabler(configuration, close_handler)); - - // TODO: avoid setting callback after having created "enabled" enabler (e.g. pass and set in construction) - enabler->set_data_callback(data_callback); - enabler->set_type_callback(type_callback); - enabler->set_topic_callback(topic_callback); - enabler->set_type_request_callback(type_req_callback); - enabler->set_topic_request_callback(topic_req_callback); + // Create DDSEnabler + enabler.reset(new DDSEnabler(configuration, callbacks)); EPROSIMA_LOG_INFO(DDSENABLER_EXECUTION, "DDS Enabler running."); diff --git a/ddsenabler/test/DDSEnablerTester.hpp b/ddsenabler/test/DDSEnablerTester.hpp index 2d0a5231..71050613 100644 --- a/ddsenabler/test/DDSEnablerTester.hpp +++ b/ddsenabler/test/DDSEnablerTester.hpp @@ -56,6 +56,7 @@ class DDSEnablerTester : public ::testing::Test { std::cout << "Setting up test..." << std::endl; received_types_ = 0; + received_topics_ = 0; received_data_ = 0; current_test_instance_ = this; // Set the current instance for callbacks } @@ -65,8 +66,10 @@ class DDSEnablerTester : public ::testing::Test { std::cout << "Tearing down test..." << std::endl; std::cout << "Received types before reset: " << received_types_ << std::endl; + std::cout << "Received topics before reset: " << received_topics_ << std::endl; std::cout << "Received data before reset: " << received_data_ << std::endl; received_types_ = 0; + received_topics_ = 0; received_data_ = 0; current_test_instance_ = nullptr; } @@ -79,9 +82,20 @@ class DDSEnablerTester : public ::testing::Test eprosima::ddsenabler::yaml::EnablerConfiguration configuration(yml); configuration.simple_configuration->domain = DOMAIN_; + CallbackSet callbacks{ + .log = test_log_callback, + .dds = { + .type_notification = test_type_notification_callback, + .topic_notification = test_topic_notification_callback, + .data_notification = test_data_notification_callback, + .type_request = test_type_request_callback, + .topic_request = test_topic_request_callback + } + }; + // Create DDS Enabler std::shared_ptr enabler; - bool result = create_dds_enabler(configuration, test_data_callback, test_type_callback, test_topic_notification_callback, test_type_request_callback, test_topic_request_callback, test_log_callback, enabler); + bool result = create_dds_enabler(configuration, callbacks, enabler); return enabler; } @@ -108,15 +122,15 @@ class DDSEnablerTester : public ::testing::Test return nullptr; } - auto close_handler = std::make_shared(); - - auto enabler = std::make_shared(configuration, close_handler); - - // Bind the static callbacks (no captures allowed) - enabler->set_data_callback(test_data_callback); - enabler->set_type_callback(test_type_callback); + CallbackSet callbacks{ + .dds = { + .type_notification = test_type_notification_callback, + .topic_notification = test_topic_notification_callback, + .data_notification = test_data_notification_callback + } + }; - return enabler; + return std::make_shared(configuration, callbacks); } bool create_publisher( @@ -245,65 +259,74 @@ class DDSEnablerTester : public ::testing::Test return true; } - // eprosima::ddsenabler::participants::DdsNotification data_callback; - static void test_data_callback( - const char* topicName, + // eprosima::ddsenabler::participants::DdsDataNotification data_callback; + static void test_data_notification_callback( + const char* topic_name, const char* json, - int64_t publishTime) + int64_t publish_time) { if (current_test_instance_) { std::lock_guard lock(current_test_instance_->data_received_mutex_); current_test_instance_->received_data_++; - std::cout << "Data callback received: " << topicName << ", Total data: " << + std::cout << "Data callback received: " << topic_name << ", Total data: " << current_test_instance_->received_data_ << std::endl; } } // eprosima::ddsenabler::participants::DdsTypeNotification data_callback; - static void test_type_callback( - const char* typeName, - const char* serializedType, - const unsigned char* serializedTypeInternal, - uint32_t serializedTypeInternalSize, - const char* dataPlaceholder) + static void test_type_notification_callback( + const char* type_name, + const char* serialized_type, + const unsigned char* serialized_type_internal, + uint32_t serialized_type_internal_size, + const char* data_placeholder) { if (current_test_instance_) { std::lock_guard lock(current_test_instance_->type_received_mutex_); current_test_instance_->received_types_++; - std::cout << "Type callback received: " << typeName << ", Total types: " << + std::cout << "Type callback received: " << type_name << ", Total types: " << current_test_instance_->received_types_ << std::endl; } } // eprosima::ddsenabler::participants::DdsTopicNotification topic_callback; static void test_topic_notification_callback( - const char* topicName, - const char* typeName, - const char* serializedQos) + const char* topic_name, + const char* type_name, + const char* serialized_qos) { + if (current_test_instance_) + { + std::lock_guard lock(current_test_instance_->topic_received_mutex_); + + current_test_instance_->received_topics_++; + std::cout << "Topic callback received: " << topic_name << ", Total topics: " << + current_test_instance_->received_topics_ << std::endl; + } } // eprosima::ddsenabler::participants::DdsTopicRequest topic_req_callback; - static void test_topic_request_callback( - const char* topicName, - char*& typeName, - char*& serializedQos) + static bool test_topic_request_callback( + const char* topic_name, + std::string& type_name, + std::string& serialized_qos) { + return true; } // eprosima::ddsenabler::participants::DdsTypeRequest type_req_callback; - static void test_type_request_callback( - const char* typeName, - unsigned char*& serializedTypeInternal, - uint32_t& serializedTypeInternalSize) + static bool test_type_request_callback( + const char* type_name, + std::unique_ptr& serialized_type_internal, + uint32_t& serialized_type_internal_size) { + return true; } - //eprosima::ddsenabler::participants::DdsLogFunc log_callback; static void test_log_callback( const char* fileName, @@ -328,6 +351,20 @@ class DDSEnablerTester : public ::testing::Test } } + int get_received_topics() + { + if (current_test_instance_) + { + std::lock_guard lock(current_test_instance_->topic_received_mutex_); + + return current_test_instance_->received_topics_; + } + else + { + return 0; + } + } + int get_received_data() { if (current_test_instance_) @@ -347,10 +384,12 @@ class DDSEnablerTester : public ::testing::Test // Test-specific received counters int received_types_ = 0; + int received_topics_ = 0; int received_data_ = 0; - // Mutex for synchronizing access to received_types_ and received_data_ + // Mutex for synchronizing access to received_types_, received_topics_ and received_data_ std::mutex type_received_mutex_; + std::mutex topic_received_mutex_; std::mutex data_received_mutex_; }; diff --git a/ddsenabler/test/ddsEnablerTests/DdsEnablerTest.cpp b/ddsenabler/test/ddsEnablerTests/DdsEnablerTest.cpp index 01c56ea4..85305197 100644 --- a/ddsenabler/test/ddsEnablerTests/DdsEnablerTest.cpp +++ b/ddsenabler/test/ddsEnablerTests/DdsEnablerTest.cpp @@ -60,12 +60,14 @@ TEST_F(DDSEnablerTest, send_type1) ASSERT_TRUE(create_publisher(a_type)); ASSERT_EQ(get_received_types(), 1); + ASSERT_EQ(get_received_topics(), 1); ASSERT_EQ(get_received_data(), 0); // Send data ASSERT_TRUE(send_samples(a_type)); ASSERT_EQ(get_received_types(), 1); + ASSERT_EQ(get_received_topics(), 1); ASSERT_EQ(get_received_data(), num_samples_); } @@ -82,12 +84,14 @@ TEST_F(DDSEnablerTest, send_many_type1) ASSERT_TRUE(create_publisher(a_type)); ASSERT_EQ(get_received_types(), 1); + ASSERT_EQ(get_received_topics(), 1); ASSERT_EQ(get_received_data(), 0); // Send data ASSERT_TRUE(send_samples(a_type)); ASSERT_EQ(get_received_types(), 1); + ASSERT_EQ(get_received_topics(), 1); ASSERT_EQ(get_received_data(), num_samples_); } @@ -104,12 +108,14 @@ TEST_F(DDSEnablerTest, send_type2) ASSERT_TRUE(create_publisher(a_type)); ASSERT_EQ(get_received_types(), 1); + ASSERT_EQ(get_received_topics(), 1); ASSERT_EQ(get_received_data(), 0); // Send data ASSERT_TRUE(send_samples(a_type)); ASSERT_EQ(get_received_types(), 1); + ASSERT_EQ(get_received_topics(), 1); ASSERT_EQ(get_received_data(), num_samples_); } @@ -126,18 +132,21 @@ TEST_F(DDSEnablerTest, send_type3) ASSERT_TRUE(create_publisher(a_type)); ASSERT_EQ(get_received_types(), 1); + ASSERT_EQ(get_received_topics(), 1); ASSERT_EQ(get_received_data(), 0); // Send data ASSERT_TRUE(send_samples(a_type)); ASSERT_EQ(get_received_types(), 1); + ASSERT_EQ(get_received_topics(), 1); ASSERT_EQ(get_received_data(), num_samples_); // Send data ASSERT_TRUE(send_samples(a_type)); ASSERT_EQ(get_received_types(), 1); + ASSERT_EQ(get_received_topics(), 1); ASSERT_EQ(get_received_data(), num_samples_ * 2); } @@ -154,12 +163,14 @@ TEST_F(DDSEnablerTest, send_type4) ASSERT_TRUE(create_publisher(a_type)); ASSERT_EQ(get_received_types(), 1); + ASSERT_EQ(get_received_topics(), 1); ASSERT_EQ(get_received_data(), 0); // Send data ASSERT_TRUE(send_samples(a_type)); ASSERT_EQ(get_received_types(), 1); + ASSERT_EQ(get_received_topics(), 1); ASSERT_EQ(get_received_data(), num_samples_); } @@ -176,12 +187,14 @@ TEST_F(DDSEnablerTest, send_multiple_types) ASSERT_TRUE(create_publisher(a_type1)); ASSERT_EQ(get_received_types(), 1); + ASSERT_EQ(get_received_topics(), 1); ASSERT_EQ(get_received_data(), 0); // Send data ASSERT_TRUE(send_samples(a_type1)); ASSERT_EQ(get_received_types(), 1); + ASSERT_EQ(get_received_topics(), 1); ASSERT_EQ(get_received_data(), num_samples_); KnownType a_type2; @@ -190,12 +203,14 @@ TEST_F(DDSEnablerTest, send_multiple_types) ASSERT_TRUE(create_publisher(a_type2)); ASSERT_EQ(get_received_types(), 2); + ASSERT_EQ(get_received_topics(), 2); ASSERT_EQ(get_received_data(), num_samples_); // Send data ASSERT_TRUE(send_samples(a_type2)); ASSERT_EQ(get_received_types(), 2); + ASSERT_EQ(get_received_topics(), 2); ASSERT_EQ(get_received_data(), num_samples_ * 2); KnownType a_type3; @@ -204,12 +219,14 @@ TEST_F(DDSEnablerTest, send_multiple_types) ASSERT_TRUE(create_publisher(a_type3)); ASSERT_EQ(get_received_types(), 3); + ASSERT_EQ(get_received_topics(), 3); ASSERT_EQ(get_received_data(), num_samples_ * 2); // Send data ASSERT_TRUE(send_samples(a_type3)); ASSERT_EQ(get_received_types(), 3); + ASSERT_EQ(get_received_topics(), 3); ASSERT_EQ(get_received_data(), num_samples_ * 3); KnownType a_type4; @@ -218,12 +235,14 @@ TEST_F(DDSEnablerTest, send_multiple_types) ASSERT_TRUE(create_publisher(a_type4)); ASSERT_EQ(get_received_types(), 4); + ASSERT_EQ(get_received_topics(), 4); ASSERT_EQ(get_received_data(), num_samples_ * 3); // Send data ASSERT_TRUE(send_samples(a_type4)); ASSERT_EQ(get_received_types(), 4); + ASSERT_EQ(get_received_topics(), 4); ASSERT_EQ(get_received_data(), num_samples_ * 4); } @@ -240,12 +259,14 @@ TEST_F(DDSEnablerTest, send_repeated_type) ASSERT_TRUE(create_publisher(a_type)); ASSERT_EQ(get_received_types(), 1); + ASSERT_EQ(get_received_topics(), 1); ASSERT_EQ(get_received_data(), 0); // Send data ASSERT_TRUE(send_samples(a_type)); ASSERT_EQ(get_received_types(), 1); + ASSERT_EQ(get_received_topics(), 1); ASSERT_EQ(get_received_data(), num_samples_); KnownType another_type; @@ -257,20 +278,23 @@ TEST_F(DDSEnablerTest, send_repeated_type) ASSERT_TRUE(send_samples(another_type)); ASSERT_EQ(get_received_types(), 2); + ASSERT_EQ(get_received_topics(), 2); ASSERT_EQ(get_received_data(), num_samples_ * 2); KnownType same_type; same_type.type_sup_.reset(new DDSEnablerTestType1PubSubType()); - ASSERT_TRUE(create_publisher(same_type)); + ASSERT_TRUE(create_publisher(same_type)); // and topic ASSERT_EQ(get_received_types(), 2); + ASSERT_EQ(get_received_topics(), 2); ASSERT_EQ(get_received_data(), num_samples_ * 2); // Send data ASSERT_TRUE(send_samples(same_type)); ASSERT_EQ(get_received_types(), 2); + ASSERT_EQ(get_received_topics(), 2); ASSERT_EQ(get_received_data(), num_samples_ * 3); } @@ -313,6 +337,7 @@ TEST_F(DDSEnablerTest, send_history_smaller_than_writer) std::this_thread::sleep_for(std::chrono::milliseconds(history_depth * 100)); ASSERT_EQ(get_received_types(), 1); + ASSERT_EQ(get_received_topics(), 1); ASSERT_EQ(get_received_data(), history_depth); } @@ -356,6 +381,7 @@ TEST_F(DDSEnablerTest, send_history_multiple_types) std::this_thread::sleep_for(std::chrono::milliseconds(types * history_depth * 100)); ASSERT_EQ(get_received_types(), types); + ASSERT_EQ(get_received_topics(), types); ASSERT_EQ(get_received_data(), types * history_depth); } diff --git a/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp b/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp index d8b59cc8..54262085 100644 --- a/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp +++ b/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp @@ -26,54 +26,56 @@ static uint32_t data_callback_count = 0; // Empty callbacks just to create the enabler being tested -// eprosima::ddsenabler::participants::DdsNotification data_callback; -void test_data_callback( - const char* topicName, +// eprosima::ddsenabler::participants::DdsDataNotification data_callback; +void test_data_notification_callback( + const char* topic_name, const char* json, - int64_t publishTime) + int64_t publish_time) { } // eprosima::ddsenabler::participants::DdsTypeNotification data_callback; -void test_type_callback( - const char* typeName, - const char* serializedType, - const unsigned char* serializedTypeInternal, - uint32_t serializedTypeInternalSize, - const char* dataPlaceholder) +void test_type_notification_callback( + const char* type_name, + const char* serialized_type, + const unsigned char* serialized_type_internal, + uint32_t serialized_type_internal_size, + const char* data_placeholder) { } // eprosima::ddsenabler::participants::DdsTopicNotification topic_callback; void test_topic_notification_callback( - const char* topicName, - const char* typeName, - const char* serializedQos) + const char* topic_name, + const char* type_name, + const char* serialized_qos) { } // eprosima::ddsenabler::participants::DdsTopicRequest topic_req_callback; -void test_topic_request_callback( - const char* topicName, - char*& typeName, - char*& serializedQos) +bool test_topic_request_callback( + const char* topic_name, + std::string& type_name, + std::string& serialized_qos) { + return true; } // eprosima::ddsenabler::participants::DdsTypeRequest type_req_callback; -void test_type_request_callback( - const char* typeName, - unsigned char*& serializedTypeInternal, - uint32_t& serializedTypeInternalSize) +bool test_type_request_callback( + const char* type_name, + std::unique_ptr& serialized_type_internal, + uint32_t& serialized_type_internal_size) { + return true; } //eprosima::ddsenabler::participants::DdsLogFunc log_callback; void test_log_callback( - const char* fileName, - int lineNo, - const char* funcName, + const char* file_name, + int line_no, + const char* func_name, int category, const char* msg) { @@ -173,9 +175,20 @@ TEST(ReloadConfig, json) auto configfile = "./file_watcher_test.json"; write_json_file(configfile, false); + CallbackSet callbacks{ + .log = test_log_callback, + .dds = { + .type_notification = test_type_notification_callback, + .topic_notification = test_topic_notification_callback, + .data_notification = test_data_notification_callback, + .type_request = test_type_request_callback, + .topic_request = test_topic_request_callback + } + }; + // Create DDS Enabler std::shared_ptr enabler; - ASSERT_TRUE(create_dds_enabler(configfile, test_data_callback, test_type_callback, test_topic_notification_callback, test_type_request_callback, test_topic_request_callback, test_log_callback, enabler)); + ASSERT_TRUE(create_dds_enabler(configfile, callbacks, enabler)); // Create DDSEnablerAccessor to access protected configuration auto enabler_accessor = static_cast(enabler.get()); @@ -204,9 +217,20 @@ TEST(ReloadConfig, yaml) auto configfile = "./file_watcher_test.yaml"; write_yaml_file(configfile, 0); + CallbackSet callbacks{ + .log = test_log_callback, + .dds = { + .type_notification = test_type_notification_callback, + .topic_notification = test_topic_notification_callback, + .data_notification = test_data_notification_callback, + .type_request = test_type_request_callback, + .topic_request = test_topic_request_callback + } + }; + // Create DDS Enabler std::shared_ptr enabler; - ASSERT_TRUE(create_dds_enabler(configfile, test_data_callback, test_type_callback, test_topic_notification_callback, test_type_request_callback, test_topic_request_callback, test_log_callback, enabler)); + ASSERT_TRUE(create_dds_enabler(configfile, callbacks, enabler)); // Create DDSEnablerAccessor to access protected configuration auto enabler_accessor = static_cast(enabler.get()); diff --git a/ddsenabler/test/ddsEnablerTypedTests/DdsEnablerTypedTest.cpp b/ddsenabler/test/ddsEnablerTypedTests/DdsEnablerTypedTest.cpp index 26e4bbc2..ee43349a 100644 --- a/ddsenabler/test/ddsEnablerTypedTests/DdsEnablerTypedTest.cpp +++ b/ddsenabler/test/ddsEnablerTypedTests/DdsEnablerTypedTest.cpp @@ -48,6 +48,7 @@ class DDSEnablerTypedTest : public ddsenablertester::DDSEnablerTester ASSERT_TRUE(create_publisher(a_type)); \ \ ASSERT_EQ(get_received_types(), 1); \ + ASSERT_EQ(get_received_topics(), 1); \ ASSERT_EQ(get_received_data(), 0); \ \ /* Send data */ \ @@ -57,6 +58,7 @@ class DDSEnablerTypedTest : public ddsenablertester::DDSEnablerTester std::this_thread::sleep_for(std::chrono::milliseconds(wait_after_publication_ms)); \ \ ASSERT_EQ(get_received_types(), 1); \ + ASSERT_EQ(get_received_topics(), 1); \ ASSERT_EQ(get_received_data(), num_samples_); \ } diff --git a/ddsenabler_participants/README.md b/ddsenabler_participants/README.md deleted file mode 100644 index 749bea32..00000000 --- a/ddsenabler_participants/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# eProsima DDS Enabler Participants - -`ddsenabler_participants` subpackage. - -> :warning: **TODO** diff --git a/ddsenabler_participants/include/ddsenabler_participants/CBCallbacks.hpp b/ddsenabler_participants/include/ddsenabler_participants/CBCallbacks.hpp index 48992c1b..46189ae1 100644 --- a/ddsenabler_participants/include/ddsenabler_participants/CBCallbacks.hpp +++ b/ddsenabler_participants/include/ddsenabler_participants/CBCallbacks.hpp @@ -19,57 +19,64 @@ #pragma once #include +#include +#include namespace eprosima { namespace ddsenabler { namespace participants { /** - * DdsLogFunc - callback for reception of DDS types + * DdsLogFunc - callback executed when consuming log messages */ typedef void (*DdsLogFunc)( - const char* fileName, - int lineNo, - const char* funcName, + const char* file_name, + int line_no, + const char* func_name, int category, const char* msg); /** - * DdsTypeNotification - callback for reception of DDS types + * DdsTypeNotification - callback for notifying the reception of DDS types */ typedef void (*DdsTypeNotification)( - const char* typeName, - const char* serializedType, - const unsigned char* serializedTypeInternal, - uint32_t serializedTypeInternalSize, - const char* dataPlaceholder); + const char* type_name, + const char* serialized_type, + const unsigned char* serialized_type_internal, + uint32_t serialized_type_internal_size, + const char* data_placeholder); /** - * DdsTopicNotification - callback for reception of DDS topics + * DdsTopicNotification - callback for notifying the reception of DDS topics */ typedef void (*DdsTopicNotification)( - const char* topicName, - const char* typeName, - const char* serializedQos); + const char* topic_name, + const char* type_name, + const char* serialized_qos); /** - * DdsNotification - callback for reception of DDS data + * DdsDataNotification - callback for notifying the reception of DDS data */ -typedef void (*DdsNotification)( - const char* topicName, +typedef void (*DdsDataNotification)( + const char* topic_name, const char* json, - int64_t publishTime); + int64_t publish_time); -// TODO: return a boolean in request callbacks? should nevertheless handle malformed strings passed by user -typedef void (*DdsTopicRequest)( - const char* topicName, - char*& typeName, // TODO: better pass unique_ptr by ref? Then the user would allocate resources but will always have its ownership - char*& serializedQos); +/** + * DdsTopicRequest - callback for requesting information (type and QoS) of a DDS topic + */ +typedef bool (*DdsTopicRequest)( + const char* topic_name, + std::string& type_name, + std::string& serialized_qos); -typedef void (*DdsTypeRequest)( - const char* typeName, - unsigned char*& serializedTypeInternal, - uint32_t& serializedTypeInternalSize); +/** + * DdsTypeRequest - callback for requesting information (serialized description and size) of a DDS type + */ +typedef bool (*DdsTypeRequest)( + const char* type_name, + std::unique_ptr& serialized_type_internal, + uint32_t& serialized_type_internal_size); } /* namespace participants */ } /* namespace ddsenabler */ diff --git a/ddsenabler_participants/include/ddsenabler_participants/CBHandler.hpp b/ddsenabler_participants/include/ddsenabler_participants/CBHandler.hpp index af552d13..72b650ad 100644 --- a/ddsenabler_participants/include/ddsenabler_participants/CBHandler.hpp +++ b/ddsenabler_participants/include/ddsenabler_participants/CBHandler.hpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include @@ -89,8 +89,7 @@ class CBHandler : public ddspipe::participants::ISchemaHandler ~CBHandler(); /** - * @brief Create and store in \c schemas_ an OMG IDL (.idl format) schema. - * Any samples following this schema that were received before the schema itself are moved to the memory buffer. + * @brief Add a type schema, associated to the given \c dyn_type and \c type_id. * * @param [in] dyn_type DynamicType containing the type information required to generate the schema. * @param [in] type_id TypeIdentifier of the type. @@ -100,7 +99,11 @@ class CBHandler : public ddspipe::participants::ISchemaHandler const fastdds::dds::DynamicType::_ref_type& dyn_type, const fastdds::dds::xtypes::TypeIdentifier& type_id) override; - // TODO + /** + * @brief Add a topic, associated to the given \c topic. + * + * @param [in] topic DDS topic to be added. + */ DDSENABLER_PARTICIPANTS_DllAPI void add_topic( const ddspipe::core::types::DdsTopic& topic); @@ -108,8 +111,6 @@ class CBHandler : public ddspipe::participants::ISchemaHandler /** * @brief Add a data sample, associated to the given \c topic. * - * The sample is added to buffer without schema. - * * @param [in] topic DDS topic associated to this sample. * @param [in] data payload data to be added. */ @@ -118,38 +119,73 @@ class CBHandler : public ddspipe::participants::ISchemaHandler const ddspipe::core::types::DdsTopic& topic, ddspipe::core::types::RtpsPayloadData& data) override; + /** + * @brief Get the TypeIdentifier associated to the given type name. + * + * @param [in] type_name Name of the type to be retrieved. + * @param [out] type_identifier TypeIdentifier of the type. + * @return \c true if the type was found, \c false otherwise. + */ DDSENABLER_PARTICIPANTS_DllAPI bool get_type_identifier( const std::string& type_name, fastdds::dds::xtypes::TypeIdentifier& type_identifier); + /** + * @brief Get the serialized data (payload) associated to the given type name from a JSON string. + * + * @param [in] type_name Name of the type of the data to be serialized. + * @param [in] json JSON string containing the data to be serialized. + * @param [out] payload Payload reference where the serialized data will be stored. + * @return \c true if the data was successfully serialized, \c false otherwise. + */ DDSENABLER_PARTICIPANTS_DllAPI bool get_serialized_data( const std::string& type_name, const std::string& json, ddspipe::core::types::Payload& payload); + /** + * @brief Set the data notification callback. + * + * @param [in] callback Callback to be set. + */ DDSENABLER_PARTICIPANTS_DllAPI - void set_data_callback( - participants::DdsNotification callback) + void set_data_notification_callback( + participants::DdsDataNotification callback) { - cb_writer_->set_data_callback(callback); + cb_writer_->set_data_notification_callback(callback); } + /** + * @brief Set the topic notification callback. + * + * @param [in] callback Callback to be set. + */ DDSENABLER_PARTICIPANTS_DllAPI - void set_topic_callback( + void set_topic_notification_callback( participants::DdsTopicNotification callback) { - cb_writer_->set_topic_callback(callback); + cb_writer_->set_topic_notification_callback(callback); } + /** + * @brief Set the type notification callback. + * + * @param [in] callback Callback to be set. + */ DDSENABLER_PARTICIPANTS_DllAPI - void set_type_callback( + void set_type_notification_callback( participants::DdsTypeNotification callback) { - cb_writer_->set_type_callback(callback); + cb_writer_->set_type_notification_callback(callback); } + /** + * @brief Set the type request callback. + * + * @param [in] callback Callback to be set. + */ DDSENABLER_PARTICIPANTS_DllAPI void set_type_request_callback( participants::DdsTypeRequest callback) @@ -159,11 +195,47 @@ class CBHandler : public ddspipe::participants::ISchemaHandler protected: - void write_schema_( + /** + * @brief Add a schema, associated to the given \c dyn_type and \c type_id. + * + * @param [in] dyn_type DynamicType containing the type information required to generate the schema. + * @param [in] type_id TypeIdentifier of the type. + * @param [in] write_schema Whether to write the schema to CB or not. + */ + void add_schema_nts_( + const fastdds::dds::DynamicType::_ref_type& dyn_type, + const fastdds::dds::xtypes::TypeIdentifier& type_id, + bool write_schema = true); + + /** + * @brief Add a schema, associated to the given \c type_id and \c type_obj. + * + * @param [in] type_id TypeIdentifier of the type. + * @param [in] type_obj TypeObject of the type. + * @param [in] write_schema Whether to write the schema to CB or not. + * @return \c true if the schema was added successfully, \c false otherwise. + */ + bool add_schema_nts_( + const fastdds::dds::xtypes::TypeIdentifier& type_id, + const fastdds::dds::xtypes::TypeObject& type_obj, + bool write_schema = true); + + /** + * @brief Write the schema to CB. + * + * @param [in] dyn_type DynamicType containing the type information required to generate the schema. + * @param [in] type_id TypeIdentifier of the type. + */ + void write_schema_nts_( const fastdds::dds::DynamicType::_ref_type& dyn_type, const fastdds::dds::xtypes::TypeIdentifier& type_id); - void write_topic_( + /** + * @brief Write the topic to CB. + * + * @param [in] topic DDS topic to be added. + */ + void write_topic_nts_( const ddspipe::core::types::DdsTopic& topic); /** @@ -172,15 +244,26 @@ class CBHandler : public ddspipe::participants::ISchemaHandler * @param [in] msg CBMessage to be added * @param [in] dyn_type DynamicType containing the type information required. */ - void write_sample_( + void write_sample_nts_( const CBMessage& msg, const fastdds::dds::DynamicType::_ref_type& dyn_type); + /** + * @brief Register a type using the given serialized type data. + * + * @param [in] type_name Name of the type to be registered. + * @param [in] serialized_type Pointer to the serialized type data. + * @param [in] serialized_type_size Size of the serialized type data. + * @param [out] type_identifier TypeIdentifier of the registered type. + * @param [out] type_object TypeObject of the registered type. + * @return \c true if the type was registered successfully, \c false otherwise. + */ bool register_type_nts_( const std::string& type_name, const unsigned char* serialized_type, uint32_t serialized_type_size, - fastdds::dds::xtypes::TypeIdentifier& type_identifier); + fastdds::dds::xtypes::TypeIdentifier& type_identifier, + fastdds::dds::xtypes::TypeObject& type_object); //! Handler configuration CBHandlerConfiguration configuration_; @@ -192,7 +275,7 @@ class CBHandler : public ddspipe::participants::ISchemaHandler std::unique_ptr cb_writer_; //! Schemas map - std::unordered_map> schemas_; + std::map> schemas_; //! Unique sequence number assigned to received messages. It is incremented with every sample added unsigned int unique_sequence_number_{0}; @@ -200,6 +283,7 @@ class CBHandler : public ddspipe::participants::ISchemaHandler //! Mutex synchronizing access to object's data structures std::mutex mtx_; + //! Callback to request types from the user DdsTypeRequest type_req_callback_; }; diff --git a/ddsenabler_participants/include/ddsenabler_participants/CBWriter.hpp b/ddsenabler_participants/include/ddsenabler_participants/CBWriter.hpp index f6f2de92..034ee0d7 100644 --- a/ddsenabler_participants/include/ddsenabler_participants/CBWriter.hpp +++ b/ddsenabler_participants/include/ddsenabler_participants/CBWriter.hpp @@ -18,8 +18,13 @@ #pragma once -#include +#include + +#include + #include +#include +#include #include @@ -42,29 +47,43 @@ class CBWriter ~CBWriter() = default; DDSENABLER_PARTICIPANTS_DllAPI - void set_data_callback( - DdsNotification callback) + void set_data_notification_callback( + DdsDataNotification callback) { - data_callback_ = callback; + data_notification_callback_ = callback; } DDSENABLER_PARTICIPANTS_DllAPI - void set_type_callback( + void set_type_notification_callback( DdsTypeNotification callback) { - type_callback_ = callback; + type_notification_callback_ = callback; } - void set_topic_callback( + DDSENABLER_PARTICIPANTS_DllAPI + void set_topic_notification_callback( DdsTopicNotification callback) { - topic_callback_ = callback; + topic_notification_callback_ = callback; } + /** + * @brief Writes the schema of a DynamicType to CB. + * + * @param [in] dyn_type DynamicType containing the type information required. + * @param [in] type_id TypeIdentifier of the DynamicType. + */ + DDSENABLER_PARTICIPANTS_DllAPI void write_schema( const fastdds::dds::DynamicType::_ref_type& dyn_type, const fastdds::dds::xtypes::TypeIdentifier& type_id); + /** + * @brief Writes the topic to CB. + * + * @param [in] topic DDS topic to be added. + */ + DDSENABLER_PARTICIPANTS_DllAPI void write_topic( const ddspipe::core::types::DdsTopic& topic); @@ -101,10 +120,35 @@ class CBWriter const CBMessage& msg, const fastdds::dds::DynamicType::_ref_type& dyn_type) noexcept; + /** + * @brief Returns the pubsub type of a dyn_type. + * + * @param [in] dyn_type DynamicType from which to get the pubsub type. + * @return The pubsub type associated to the given dyn_type. + * @note If the pubsub type is not already created, it will be created and stored in the map. + */ + fastdds::dds::DynamicPubSubType get_pubsub_type_( + const fastdds::dds::DynamicType::_ref_type& dyn_type) noexcept; + + /** + * @brief Fills a JSON object with the data from a CBMessage. + * + * @param [in,out] json JSON object to be filled. + * @param [in] msg CBMessage containing the data used to fill the JSON object. + * @param [in] serialized_data Serialized data to be added to the JSON object. + */ + void fill_json_( + nlohmann::json& json, + const CBMessage& msg, + const std::string& serialized_data) noexcept; + // Callbacks to notify the CB - DdsNotification data_callback_; - DdsTypeNotification type_callback_; - DdsTopicNotification topic_callback_; + DdsDataNotification data_notification_callback_; + DdsTypeNotification type_notification_callback_; + DdsTopicNotification topic_notification_callback_; + + // Map to store the pubsub types associated to dynamic types so they can be reused + std::map dynamic_pubsub_types_; }; } /* namespace participants */ diff --git a/ddsenabler_participants/include/ddsenabler_participants/DDSEnablerLogConsumer.hpp b/ddsenabler_participants/include/ddsenabler_participants/DDSEnablerLogConsumer.hpp index 5da12bb5..d1730fe9 100644 --- a/ddsenabler_participants/include/ddsenabler_participants/DDSEnablerLogConsumer.hpp +++ b/ddsenabler_participants/include/ddsenabler_participants/DDSEnablerLogConsumer.hpp @@ -47,6 +47,7 @@ class DDSEnablerLogConsumer : public utils::BaseLogConsumer { } + DDSENABLER_PARTICIPANTS_DllAPI void set_log_callback( DdsLogFunc callback) { diff --git a/ddsenabler_participants/include/ddsenabler_participants/serialization.hpp b/ddsenabler_participants/include/ddsenabler_participants/serialization.hpp index 7011d9d7..2f27df1f 100644 --- a/ddsenabler_participants/include/ddsenabler_participants/serialization.hpp +++ b/ddsenabler_participants/include/ddsenabler_participants/serialization.hpp @@ -51,26 +51,66 @@ std::string serialize_qos( ddspipe::core::types::TopicQoS deserialize_qos( const std::string& qos_str); +/** + * @brief Serialize a dynamic type into a \c DynamicTypesCollection. + * + * @param [in] type_name Name of the dynamic type + * @param [in] type_identifier Type identifier of the dynamic type + * @param [in,out] dynamic_types Collection to store the serialized dynamic type + * @return True if serialization was successful, false otherwise + */ bool serialize_dynamic_type( const std::string& type_name, const fastdds::dds::xtypes::TypeIdentifier& type_identifier, DynamicTypesCollection& dynamic_types); +/** + * @brief Serialize a dynamic type into a \c DynamicTypesCollection. + * + * @param [in] type_identifier Type identifier of the dynamic type + * @param [in] type_object Type object of the dynamic type + * @param [in] type_name Name of the dynamic type + * @param [in,out] dynamic_types Collection to store the serialized dynamic type + * @return True if serialization was successful, false otherwise + */ bool serialize_dynamic_type( const fastdds::dds::xtypes::TypeIdentifier& type_identifier, const fastdds::dds::xtypes::TypeObject& type_object, const std::string& type_name, DynamicTypesCollection& dynamic_types); +/** + * @brief Deserialize a dynamic type from a \c DynamicTypesCollection. + * + * @param [in] dynamic_type DynamicType to be deserialized + * @param [out] type_name Name of the deserialized dynamic type + * @param [out] type_identifier Type identifier of the deserialized dynamic type + * @param [out] type_object Type object of the deserialized dynamic type + * @return True if deserialization was successful, false otherwise + */ bool deserialize_dynamic_type( const DynamicType& dynamic_type, std::string& type_name, fastdds::dds::xtypes::TypeIdentifier& type_identifier, fastdds::dds::xtypes::TypeObject& type_object); +/** + * @brief Serialize a collection of dynamic types into a serialized payload. + * + * @param [in] dynamic_types Collection of dynamic types to be serialized + * @return Serialized payload containing the dynamic types + */ std::unique_ptr serialize_dynamic_types( const DynamicTypesCollection& dynamic_types); +/** + * @brief Deserialize a serialized payload containing dynamic types into a collection. + * + * @param [in] dynamic_types_payload Pointer to the serialized payload + * @param [in] dynamic_types_payload_size Size of the serialized payload + * @param [out] dynamic_types Collection to store the deserialized dynamic types + * @return True if deserialization was successful, false otherwise + */ bool deserialize_dynamic_types( const unsigned char* dynamic_types_payload, uint32_t dynamic_types_payload_size, diff --git a/ddsenabler_participants/src/cpp/CBHandler.cpp b/ddsenabler_participants/src/cpp/CBHandler.cpp index c2725c01..a4f03891 100644 --- a/ddsenabler_participants/src/cpp/CBHandler.cpp +++ b/ddsenabler_participants/src/cpp/CBHandler.cpp @@ -60,29 +60,18 @@ void CBHandler::add_schema( { std::lock_guard lock(mtx_); - assert(nullptr != dyn_type); - - const std::string& type_name = dyn_type->get_name().to_string(); - - // Check if it exists already - auto it = schemas_.find(type_name); - if (it != schemas_.end()) - { - return; - } - schemas_[type_name] = {type_id, dyn_type}; - - // Add to schemas map - EPROSIMA_LOG_INFO(DDSENABLER_CB_HANDLER, - "Adding schema with name " << type_name << "."); - - write_schema_(dyn_type, type_id); + add_schema_nts_(dyn_type, type_id); } void CBHandler::add_topic( const DdsTopic& topic) { - cb_writer_->write_topic(topic); + std::lock_guard lock(mtx_); + + EPROSIMA_LOG_INFO(DDSENABLER_CB_HANDLER, + "Adding topic: " << topic << "."); + + write_topic_nts_(topic); } void CBHandler::add_data( @@ -131,7 +120,7 @@ void CBHandler::add_data( throw utils::InconsistencyException(STR_ENTRY << "Received sample with no payload."); } - write_sample_(msg, dyn_type); + write_sample_nts_(msg, dyn_type); } bool CBHandler::get_type_identifier( @@ -147,6 +136,31 @@ bool CBHandler::get_type_identifier( return true; } + // Try to retrieve it from local registry + fastdds::dds::xtypes::TypeIdentifierPair type_ids; + if (fastdds::dds::RETCODE_OK == + fastdds::dds::DomainParticipantFactory::get_instance()->type_object_registry().get_type_identifiers( + type_name, type_ids)) + { + // Get complete type object + type_identifier = + (fastdds::dds::xtypes::EK_COMPLETE == + type_ids.type_identifier1()._d()) ? type_ids.type_identifier1() : type_ids.type_identifier2(); + fastdds::dds::xtypes::TypeObject type_object; + if (fastdds::dds::RETCODE_OK == + fastdds::dds::DomainParticipantFactory::get_instance()->type_object_registry().get_type_object( + type_identifier, type_object)) + { + // If already in the registry, just add it to schemas map. Also report to the user the schema and all + // associated data required for persistence in case she does not have it yet. + if (add_schema_nts_(type_identifier, type_object, true)) + { + return true; + } + // If failed to add schema from the type object found in the registry, attempt requesting it to the user + } + } + if (!type_req_callback_) { EPROSIMA_LOG_ERROR(DDSENABLER_CB_HANDLER, @@ -154,13 +168,29 @@ bool CBHandler::get_type_identifier( return false; } - unsigned char* serialized_type; + std::unique_ptr serialized_type; uint32_t serialized_type_size; - type_req_callback_(type_name.c_str(), serialized_type, serialized_type_size); - // TODO: handle fail case - // TODO: free resources allocated by user (serialized_type), or redesign interaction + if (!type_req_callback_(type_name.c_str(), serialized_type, serialized_type_size)) + { + EPROSIMA_LOG_ERROR(DDSENABLER_CB_HANDLER, + "Type request callback failed to retrieve " << type_name << " type."); + return false; + } + + // Register the type obtained through the type request callback + fastdds::dds::xtypes::TypeObject type_object; + if (!register_type_nts_(type_name, serialized_type.get(), serialized_type_size, type_identifier, type_object)) + { + EPROSIMA_LOG_ERROR(DDSENABLER_CB_HANDLER, + "Failed to register type " << type_name << "."); + return false; + } + + // Add to schemas map, but do not report it to the user as it is the exact same information we obtained through the + // type request callback. + add_schema_nts_(type_identifier, type_object, false); - return register_type_nts_(type_name, serialized_type, serialized_type_size, type_identifier); + return true; } bool CBHandler::get_serialized_data( @@ -190,8 +220,8 @@ bool CBHandler::get_serialized_data( return false; } - // Use XCDR1 for backwards compatibility (e.g. ROS 2 distributions prior to Kilt) - fastdds::dds::DynamicPubSubType pubsub_type(dyn_type); + // Use XCDR1 for backwards compatibility (e.g. ROS 2 distributions prior to Kilted) + fastdds::dds::DynamicPubSubType pubsub_type (dyn_type); uint32_t payload_size = pubsub_type.calculate_serialized_size(&dyn_data, fastdds::dds::DataRepresentationId::XCDR_DATA_REPRESENTATION); @@ -212,20 +242,67 @@ bool CBHandler::get_serialized_data( return true; } -void CBHandler::write_schema_( +void CBHandler::add_schema_nts_( + const fastdds::dds::DynamicType::_ref_type& dyn_type, + const fastdds::dds::xtypes::TypeIdentifier& type_id, + bool write_schema) +{ + assert(nullptr != dyn_type); + + const std::string& type_name = dyn_type->get_name().to_string(); + + // Check if it exists already + auto it = schemas_.find(type_name); + if (it != schemas_.end()) + { + return; + } + schemas_[type_name] = {type_id, dyn_type}; + + // Add to schemas map + EPROSIMA_LOG_INFO(DDSENABLER_CB_HANDLER, + "Adding schema with name " << type_name << "."); + + if (write_schema) + { + write_schema_nts_(dyn_type, type_id); + } +} + +bool CBHandler::add_schema_nts_( + const fastdds::dds::xtypes::TypeIdentifier& type_id, + const fastdds::dds::xtypes::TypeObject& type_obj, + bool write_schema) +{ + // Create a DynamicType from TypeObject + fastdds::dds::DynamicType::_ref_type dyn_type = + fastdds::dds::DynamicTypeBuilderFactory::get_instance()->create_type_w_type_object(type_obj) + ->build(); + if (!dyn_type) + { + EPROSIMA_LOG_ERROR(DDSENABLER_CB_HANDLER, + "Failed to create Dynamic Type from TypeObject."); + return false; + } + + add_schema_nts_(dyn_type, type_id, write_schema); + return true; +} + +void CBHandler::write_schema_nts_( const fastdds::dds::DynamicType::_ref_type& dyn_type, const fastdds::dds::xtypes::TypeIdentifier& type_id) { cb_writer_->write_schema(dyn_type, type_id); } -void CBHandler::write_topic_( +void CBHandler::write_topic_nts_( const DdsTopic& topic) { cb_writer_->write_topic(topic); } -void CBHandler::write_sample_( +void CBHandler::write_sample_nts_( const CBMessage& msg, const fastdds::dds::DynamicType::_ref_type& dyn_type) { @@ -236,10 +313,16 @@ bool CBHandler::register_type_nts_( const std::string& type_name, const unsigned char* serialized_type, uint32_t serialized_type_size, - fastdds::dds::xtypes::TypeIdentifier& type_identifier) + fastdds::dds::xtypes::TypeIdentifier& type_identifier, + fastdds::dds::xtypes::TypeObject& type_object) { DynamicTypesCollection dynamic_types; - serialization::deserialize_dynamic_types(serialized_type, serialized_type_size, dynamic_types); // TODO: handle fail case + if (!serialization::deserialize_dynamic_types(serialized_type, serialized_type_size, dynamic_types)) + { + EPROSIMA_LOG_ERROR(DDSENABLER_CB_HANDLER, + "Failed to deserialize dynamic types collection."); + return false; + } std::string _type_name; fastdds::dds::xtypes::TypeIdentifier _type_identifier; @@ -266,7 +349,6 @@ bool CBHandler::register_type_nts_( { EPROSIMA_LOG_ERROR(DDSENABLER_CB_HANDLER, "Failed to register " << dynamic_type.type_name() << " DynamicType."); - // TODO: check if trying to register a type for the second time would return OK or not return false; } } @@ -279,27 +361,11 @@ bool CBHandler::register_type_nts_( return false; } - fastdds::dds::DynamicType::_ref_type dyn_type = - fastdds::dds::DynamicTypeBuilderFactory::get_instance()->create_type_w_type_object(_type_object) - ->build(); - if (!dyn_type) - { - EPROSIMA_LOG_ERROR(DDSENABLER_CB_HANDLER, - "Failed to create Dynamic Type " << type_name); - return false; - } - - // Add to schemas map - EPROSIMA_LOG_INFO(DDSENABLER_CB_HANDLER, - "Adding schema with name " << type_name << "."); - schemas_[_type_name] = {_type_identifier, dyn_type}; - + // Assign type identifier and object after all types have been registered type_identifier = _type_identifier; - return true; + type_object = _type_object; - // TODO: analyze case where dependencies are not added to schemas map, so if afterwards the user tries to publish - // in one of the dependencies type, we will try to register the same type again -> will it fail? if not, will it - // skip registration but still return internal TypeIdentifier? + return true; } } /* namespace participants */ diff --git a/ddsenabler_participants/src/cpp/CBWriter.cpp b/ddsenabler_participants/src/cpp/CBWriter.cpp index 32d98dca..0369d9fd 100644 --- a/ddsenabler_participants/src/cpp/CBWriter.cpp +++ b/ddsenabler_participants/src/cpp/CBWriter.cpp @@ -44,7 +44,7 @@ void CBWriter::write_schema( const std::string& type_name = dyn_type->get_name().to_string(); - //Schema has not been registered + // Schema has not been registered EPROSIMA_LOG_INFO(DDSENABLER_CB_WRITER, "Writing schema: " << type_name << "."); @@ -85,13 +85,13 @@ void CBWriter::write_schema( return; } - //STORE SCHEMA - if (type_callback_) + // Notify type reception + if (type_notification_callback_) { - type_callback_( + type_notification_callback_( type_name.c_str(), ss_idl.str().c_str(), - (unsigned char*)types_collection_payload->data, + types_collection_payload->data, types_collection_payload->length, ss_data_holder.str().c_str() ); @@ -104,10 +104,11 @@ void CBWriter::write_topic( EPROSIMA_LOG_INFO(DDSENABLER_CB_WRITER, "Writting topic: " << topic.topic_name() << "."); - if (topic_callback_) + // Notify topic reception + if (topic_notification_callback_) { std::string serialized_qos = serialize_qos(topic.topic_qos); - topic_callback_( + topic_notification_callback_( topic.topic_name().c_str(), topic.type_name.c_str(), serialized_qos.c_str() @@ -124,7 +125,7 @@ void CBWriter::write_data( EPROSIMA_LOG_INFO(DDSENABLER_CB_WRITER, "Writing message from topic: " << msg.topic.topic_name() << "."); - // Get the data as JSON + // Get the dynamic data to be serialized into JSON fastdds::dds::DynamicData::_ref_type dyn_data = get_dynamic_data_(msg, dyn_type); if (nullptr == dyn_data) @@ -144,28 +145,14 @@ void CBWriter::write_data( return; } - // Create the base JSON structure + // Fill JSON object with the data nlohmann::json json_output; + fill_json_(json_output, msg, ss_dyn_data.str()); - // TODO: encapsulate and/or have tags in a constants header?? - std::stringstream ss_source_guid_prefix; - ss_source_guid_prefix << msg.source_guid.guid_prefix(); - json_output["id"] = ss_source_guid_prefix.str(); - json_output["type"] = "fastdds"; - json_output[msg.topic.topic_name()] = { - {"type", msg.topic.type_name}, - {"data", nlohmann::json::object()} - }; - - std::stringstream ss_instanceHandle; - ss_instanceHandle << msg.instanceHandle; - nlohmann::json parsed_dyn_data = nlohmann::json::parse(ss_dyn_data.str()); - json_output[msg.topic.topic_name()]["data"][ss_instanceHandle.str()] = parsed_dyn_data; - - //STORE DATA - if (data_callback_) + // Notify data reception + if (data_notification_callback_) { - data_callback_( + data_notification_callback_( msg.topic.topic_name().c_str(), json_output.dump(4).c_str(), msg.publish_time.to_ns() @@ -180,17 +167,63 @@ fastdds::dds::DynamicData::_ref_type CBWriter::get_dynamic_data_( // TODO fast this should not be done, but dyn types API is like it is. auto& data_no_const = const_cast(msg.payload); - // Create PubSub Type - // TODO: avoid creating this object each time -> store in a map - fastdds::dds::DynamicPubSubType pubsub_type(dyn_type); + // Create a DynamicData object using the DynamicType fastdds::dds::DynamicData::_ref_type dyn_data( fastdds::dds::DynamicDataFactory::get_instance()->create_data(dyn_type)); - pubsub_type.deserialize(data_no_const, &dyn_data); + // Deserialize data into the DynamicData object + if (!(get_pubsub_type_(dyn_type).deserialize(data_no_const, &dyn_data))) + { + EPROSIMA_LOG_ERROR(DDSENABLER_CB_WRITER, + "Failed to deserialize data for topic: " << msg.topic.topic_name()); + return nullptr; + } return dyn_data; } +fastdds::dds::DynamicPubSubType CBWriter::get_pubsub_type_( + const fastdds::dds::DynamicType::_ref_type& dyn_type) noexcept +{ + // Check if we already have this pubsub type + auto it = dynamic_pubsub_types_.find(dyn_type); + if (it != dynamic_pubsub_types_.end()) + { + return it->second; + } + + // Create a new pubsub type + fastdds::dds::DynamicPubSubType pubsub_type(dyn_type); + dynamic_pubsub_types_[dyn_type] = pubsub_type; + + return pubsub_type; +} + +void CBWriter::fill_json_( + nlohmann::json& json, + const CBMessage& msg, + const std::string& serialized_data) noexcept +{ + // Set id to be the source guid prefix + std::stringstream ss_source_guid_prefix; + ss_source_guid_prefix << msg.source_guid.guid_prefix(); + json["id"] = ss_source_guid_prefix.str(); + + // Set type to be fastdds + json["type"] = "fastdds"; + + // Insert type and data (to be filled below) with topic name as key + json[msg.topic.topic_name()] = { + {"type", msg.topic.type_name}, + {"data", nlohmann::json::object()} + }; + + // Insert data with instance handle as key + std::stringstream ss_instanceHandle; + ss_instanceHandle << msg.instanceHandle; + json[msg.topic.topic_name()]["data"][ss_instanceHandle.str()] = nlohmann::json::parse(serialized_data); +} + } /* namespace participants */ } /* namespace ddsenabler */ } /* namespace eprosima */ diff --git a/ddsenabler_participants/src/cpp/EnablerParticipant.cpp b/ddsenabler_participants/src/cpp/EnablerParticipant.cpp index ec1f4435..ecf7b0a1 100644 --- a/ddsenabler_participants/src/cpp/EnablerParticipant.cpp +++ b/ddsenabler_participants/src/cpp/EnablerParticipant.cpp @@ -59,9 +59,13 @@ std::shared_ptr EnablerParticipant::create_reader( reader = std::make_shared(id()); auto dds_topic = dynamic_cast(topic); readers_[dds_topic] = reader; - std::static_pointer_cast(schema_handler_)->add_topic(dds_topic); + // Only notify the discovery of topics that do not originate from a topic request callback + if (dds_topic.topic_discoverer() != this->id()) + { + std::static_pointer_cast(schema_handler_)->add_topic(dds_topic); + } } - cv_.notify_one(); + cv_.notify_all(); return reader; } @@ -84,13 +88,29 @@ bool EnablerParticipant::publish( return false; } - char* _type_name; - char* serialized_qos_content; - topic_req_callback_(topic_name.c_str(), _type_name, serialized_qos_content); // TODO: allow the user not to provide QoS + handle fail case - type_name = std::string(_type_name); // TODO: free resources allocated by user, or redesign interaction (same for serialized_qos_content) - std::string serialized_qos(serialized_qos_content); + std::string serialized_qos; + if (!topic_req_callback_(topic_name.c_str(), type_name, serialized_qos)) + { + EPROSIMA_LOG_ERROR(DDSENABLER_ENABLER_PARTICIPANT, + "Failed to publish data in topic " << topic_name << " : topic request callback failed."); + return false; + } - TopicQoS qos = serialization::deserialize_qos(serialized_qos); // TODO: handle fail case (try-catch?) + // Deserialize QoS if provided by the user (otherwise use default one) + TopicQoS qos; + if (!serialized_qos.empty()) + { + try + { + qos = serialization::deserialize_qos(serialized_qos); + } + catch (const std::exception& e) + { + EPROSIMA_LOG_ERROR(DDSENABLER_ENABLER_PARTICIPANT, + "Failed to deserialize QoS for topic " << topic_name << ": " << e.what()); + return false; + } + } fastdds::dds::xtypes::TypeIdentifier type_identifier; if (!std::static_pointer_cast(schema_handler_)->get_type_identifier(type_name, type_identifier)) @@ -108,10 +128,18 @@ bool EnablerParticipant::publish( this->discovery_database_->add_endpoint(rtps::CommonParticipant::simulate_endpoint(topic, this->id())); // Wait for reader to be created from discovery thread - cv_.wait(lck, [&] + // NOTE: Set a timeout to avoid a deadlock in case the reader is never created for some reason (e.g. the topic + // is blocked or the underlying DDS Pipe object is disabled/destroyed before the reader is created). + if (!cv_.wait_for(lck, std::chrono::seconds(5), [&] { return nullptr != (reader = lookup_reader_nts_(topic_name)); - }); // TODO: handle case when stopped before processing queue item + })) + { + EPROSIMA_LOG_ERROR(DDSENABLER_ENABLER_PARTICIPANT, + "Failed to create internal reader for topic " << topic_name << + " , please verify that the topic is allowed."); + return false; + } // (Optionally) wait for writer created in DDS participant to match with external readers, to avoid losing this // message when not using transient durability diff --git a/ddsenabler_participants/src/cpp/serialization.cpp b/ddsenabler_participants/src/cpp/serialization.cpp index d7fe42bd..b6848c91 100644 --- a/ddsenabler_participants/src/cpp/serialization.cpp +++ b/ddsenabler_participants/src/cpp/serialization.cpp @@ -188,7 +188,7 @@ bool serialize_dynamic_type( type_info, true)) { - EPROSIMA_LOG_WARNING(DDSENABLER_SERIALIZATION, + EPROSIMA_LOG_ERROR(DDSENABLER_SERIALIZATION, "Error getting TypeInformation for type " << type_name); return false; } @@ -207,7 +207,7 @@ bool serialize_dynamic_type( dependency_type_identifier, dependency_type_object)) { - EPROSIMA_LOG_WARNING(DDSENABLER_SERIALIZATION, + EPROSIMA_LOG_ERROR(DDSENABLER_SERIALIZATION, "Error getting TypeObject of dependency " << "for type " << type_name); return false; } @@ -227,7 +227,7 @@ bool serialize_dynamic_type( type_identifier, type_object)) { - EPROSIMA_LOG_WARNING(DDSENABLER_SERIALIZATION, "Error getting TypeObject for type " << type_name); + EPROSIMA_LOG_ERROR(DDSENABLER_SERIALIZATION, "Error getting TypeObject for type " << type_name); return false; } @@ -251,7 +251,7 @@ bool serialize_dynamic_type( } catch (const utils::InconsistencyException& e) { - EPROSIMA_LOG_WARNING(DDSENABLER_SERIALIZATION, "Error serializing DynamicType. Error message:\n " << e.what()); + EPROSIMA_LOG_ERROR(DDSENABLER_SERIALIZATION, "Error serializing DynamicType. Error message:\n " << e.what()); return false; } @@ -278,7 +278,7 @@ bool deserialize_dynamic_type( } catch (const utils::InconsistencyException& e) { - EPROSIMA_LOG_WARNING(DDSENABLER_SERIALIZATION, + EPROSIMA_LOG_ERROR(DDSENABLER_SERIALIZATION, "Failed to deserialize " << dynamic_type.type_name() << " DynamicType: " << e.what()); return false; } @@ -501,7 +501,12 @@ std::unique_ptr serialize_dynamic_types( fastdds::dds::TypeSupport type_support(new DynamicTypesCollectionPubSubType()); auto serialized_payload = std::make_unique( type_support.calculate_serialized_size(&dynamic_types, fastdds::dds::DEFAULT_DATA_REPRESENTATION)); - type_support.serialize(&dynamic_types, *serialized_payload, fastdds::dds::DEFAULT_DATA_REPRESENTATION); + if (!type_support.serialize(&dynamic_types, *serialized_payload, fastdds::dds::DEFAULT_DATA_REPRESENTATION)) + { + EPROSIMA_LOG_ERROR(DDSENABLER_SERIALIZATION, + "Failed to serialize dynamic types collection."); + return nullptr; + } return serialized_payload; } @@ -519,9 +524,14 @@ bool deserialize_dynamic_types( serialized_payload.data, dynamic_types_payload, dynamic_types_payload_size); - type_support.deserialize(serialized_payload, &dynamic_types); - // TODO: catch exception and return false + if (!type_support.deserialize(serialized_payload, &dynamic_types)) + { + EPROSIMA_LOG_ERROR(DDSENABLER_SERIALIZATION, + "Failed to deserialize dynamic types collection."); + return false; + } + return true; } diff --git a/ddsenabler_participants/test/DdsEnablerParticipantsTest.cpp b/ddsenabler_participants/test/DdsEnablerParticipantsTest.cpp index 96f24c2b..21b0ff2e 100644 --- a/ddsenabler_participants/test/DdsEnablerParticipantsTest.cpp +++ b/ddsenabler_participants/test/DdsEnablerParticipantsTest.cpp @@ -84,12 +84,10 @@ class CBHandlerTest : public participants::CBHandler cb_writer_ = std::make_unique(); // Set the callbacks - set_data_callback(test_data_callback); - set_type_callback(test_type_callback); - set_topic_callback(test_topic_notification_callback); + set_data_notification_callback(test_data_notification_callback); + set_type_notification_callback(test_type_notification_callback); + set_topic_notification_callback(test_topic_notification_callback); set_type_request_callback(test_type_request_callback); - - } // Expose protected members @@ -98,38 +96,39 @@ class CBHandlerTest : public participants::CBHandler using participants::CBHandler::unique_sequence_number_; // eprosima::ddsenabler::participants::DdsTypeRequest type_req_callback; - static void test_type_request_callback( - const char* typeName, - unsigned char*& serializedTypeInternal, - uint32_t& serializedTypeInternalSize) + static bool test_type_request_callback( + const char* type_name, + std::unique_ptr& serialized_type_internal, + uint32_t& serialized_type_internal_size) { - if(current_test_instance_ == nullptr) - return; + if (current_test_instance_ == nullptr) + return false; current_test_instance_->type_request_called++; + return true; } - // eprosima::ddsenabler::participants::DdsNotification data_callback; - static void test_data_callback( - const char* topicName, + // eprosima::ddsenabler::participants::DdsDataNotification data_callback; + static void test_data_notification_callback( + const char* topic_name, const char* json, - int64_t publishTime) + int64_t publish_time) { - if(current_test_instance_ == nullptr) + if (current_test_instance_ == nullptr) return; current_test_instance_->data_called_++; } // eprosima::ddsenabler::participants::DdsTypeNotification data_callback; - static void test_type_callback( - const char* typeName, - const char* serializedType, - const unsigned char* serializedTypeInternal, - uint32_t serializedTypeInternalSize, - const char* dataPlaceholder) + static void test_type_notification_callback( + const char* type_name, + const char* serialized_type, + const unsigned char* serialized_type_internal, + uint32_t serialized_type_internal_size, + const char* data_placeholder) { - if(current_test_instance_ == nullptr) + if (current_test_instance_ == nullptr) return; current_test_instance_->type_called_++; @@ -137,11 +136,11 @@ class CBHandlerTest : public participants::CBHandler // eprosima::ddsenabler::participants::DdsTopicNotification topic_callback; static void test_topic_notification_callback( - const char* topicName, - const char* typeName, - const char* serializedQos) + const char* topic_name, + const char* type_name, + const char* serialized_qos) { - if(current_test_instance_ == nullptr) + if (current_test_instance_ == nullptr) return; current_test_instance_->topic_called_++; diff --git a/ddsenabler_test/compose/test_cases/topics_json/config.json b/ddsenabler_test/compose/test_cases/topics_json/config.json index 0214a830..7637a2fa 100644 --- a/ddsenabler_test/compose/test_cases/topics_json/config.json +++ b/ddsenabler_test/compose/test_cases/topics_json/config.json @@ -18,7 +18,9 @@ } ] }, - "ddsenabler": null, + "ddsenabler": { + "initial-publish-wait": 500 + }, "specs": { "threads": 12, "logging": { diff --git a/ddsenabler_test/package.xml b/ddsenabler_test/package.xml index d64b3671..14cba5ac 100644 --- a/ddsenabler_test/package.xml +++ b/ddsenabler_test/package.xml @@ -4,7 +4,7 @@ ddsenabler_test 0.1.0 - *eprosima DDS Enabler* main C++ package. + *eprosima DDS Enabler* system tests package. Raul Sánchez-Mateos Eugenio Collado diff --git a/ddsenabler_yaml/README.md b/ddsenabler_yaml/README.md deleted file mode 100644 index 266dc745..00000000 --- a/ddsenabler_yaml/README.md +++ /dev/null @@ -1,43 +0,0 @@ -# eProsima DDS Enabler Yaml Module - -This library implements the required functions to translate a DDS Enabler configuration written in *yaml* -format into C++ source code. -It is powered by `yaml-cpp` library. - -It provides methods: - -- to create every type of object from a *yaml* node, -- to read a *yaml* file, and -- to interact with a *yaml* object using `YAML::Node` class from `yaml-cpp`. - ---- - -## Example of usage - -```cpp -// LOAD DDS ENABLER CONFIGURATION FROM FILE -eprosima::ddsenabler::yaml::EnablerConfiguration configuration("configuration.yaml"); - -``` - ---- - -## Dependencies - -* `yaml-cpp` -* `cpp_utils` -* `ddspipe_core` -* `ddspipe_participants` -* `ddspipe_yaml` -* `ddsenabler_participants` - ---- - -## How to use it in your project - -Just import library `ddsenabler_yaml` into your CMake project. - -```cmake -find_package(ddsenabler_yaml) -target_link_libraries(${LIBRARY_TARGET_NAME} ddsenabler_yaml) -``` diff --git a/ddsenabler_yaml/include/ddsenabler_yaml/EnablerConfiguration.hpp b/ddsenabler_yaml/include/ddsenabler_yaml/EnablerConfiguration.hpp index 3b97c51b..769837c6 100644 --- a/ddsenabler_yaml/include/ddsenabler_yaml/EnablerConfiguration.hpp +++ b/ddsenabler_yaml/include/ddsenabler_yaml/EnablerConfiguration.hpp @@ -76,25 +76,25 @@ class EnablerConfiguration protected: - void load_ddsenabler_configuration( + void load_ddsenabler_configuration_( const Yaml& yml); - void load_enabler_configuration( + void load_enabler_configuration_( const Yaml& yml, const ddspipe::yaml::YamlReaderVersion& version); - void load_specs_configuration( + void load_specs_configuration_( const Yaml& yml, const ddspipe::yaml::YamlReaderVersion& version); - void load_dds_configuration( + void load_dds_configuration_( const Yaml& yml, const ddspipe::yaml::YamlReaderVersion& version); - void load_ddsenabler_configuration_from_yaml_file( + void load_ddsenabler_configuration_from_yaml_file_( const std::string& file_path); - void load_ddsenabler_configuration_from_json_file( + void load_ddsenabler_configuration_from_json_file_( const std::string& file_path); }; diff --git a/ddsenabler_yaml/src/cpp/EnablerConfiguration.cpp b/ddsenabler_yaml/src/cpp/EnablerConfiguration.cpp index 628ab9d5..09d19936 100644 --- a/ddsenabler_yaml/src/cpp/EnablerConfiguration.cpp +++ b/ddsenabler_yaml/src/cpp/EnablerConfiguration.cpp @@ -129,7 +129,7 @@ EnablerConfiguration::EnablerConfiguration( { if (is_json(file_path)) { - load_ddsenabler_configuration_from_json_file(file_path); + load_ddsenabler_configuration_from_json_file_(file_path); } else { if (file_path.size() >= 5 && @@ -139,14 +139,14 @@ EnablerConfiguration::EnablerConfiguration( EPROSIMA_LOG_WARNING(DDSENABLER_YAML, "Failed to parse JSON configuration, treating as YAML."); } - load_ddsenabler_configuration_from_yaml_file(file_path); + load_ddsenabler_configuration_from_yaml_file_(file_path); } } EnablerConfiguration::EnablerConfiguration( const Yaml& yml) { - load_ddsenabler_configuration(yml); + load_ddsenabler_configuration_(yml); } bool EnablerConfiguration::is_valid( @@ -155,7 +155,7 @@ bool EnablerConfiguration::is_valid( return true; } -void EnablerConfiguration::load_ddsenabler_configuration( +void EnablerConfiguration::load_ddsenabler_configuration_( const Yaml& yml) { try @@ -171,24 +171,19 @@ void EnablerConfiguration::load_ddsenabler_configuration( simple_configuration = std::make_shared(); simple_configuration->id = "SimpleEnablerParticipant"; simple_configuration->app_id = "DDS_ENABLER"; - simple_configuration->app_metadata = ""; - simple_configuration->is_repeater = false; ///// // Create Enabler Participant Configuration enabler_configuration = std::make_shared(); enabler_configuration->id = "EnablerEnablerParticipant"; enabler_configuration->app_id = "DDS_ENABLER"; - // TODO: fill metadata field once its content has been defined. - enabler_configuration->app_metadata = ""; - enabler_configuration->is_repeater = false; ///// // Get optional Enabler configuration options if (YamlReader::is_tag_present(yml, ENABLER_ENABLER_TAG)) { auto enabler_yml = YamlReader::get_value_in_tag(yml, ENABLER_ENABLER_TAG); - load_enabler_configuration(enabler_yml, version); + load_enabler_configuration_(enabler_yml, version); } ///// @@ -197,7 +192,7 @@ void EnablerConfiguration::load_ddsenabler_configuration( if (YamlReader::is_tag_present(yml, SPECS_TAG)) { auto specs_yml = YamlReader::get_value_in_tag(yml, SPECS_TAG); - load_specs_configuration(specs_yml, version); + load_specs_configuration_(specs_yml, version); } ///// @@ -205,7 +200,7 @@ void EnablerConfiguration::load_ddsenabler_configuration( if (YamlReader::is_tag_present(yml, ENABLER_DDS_TAG)) { auto dds_yml = YamlReader::get_value_in_tag(yml, ENABLER_DDS_TAG); - load_dds_configuration(dds_yml, version); + load_dds_configuration_(dds_yml, version); } // Block ROS 2 services (RPC) topics @@ -225,8 +220,10 @@ void EnablerConfiguration::load_ddsenabler_configuration( ddspipe_configuration.blocklist.insert( utils::Heritable::make_heritable(rpc_response_topic)); - ddspipe_configuration.init_enabled = true; + // Enable manually after all callbacks are set to avoid missing notifications + ddspipe_configuration.init_enabled = false; + // NOTE: Trigger discovery also with readers to enable publish feature in their associated topics ddspipe_configuration.discovery_trigger = DiscoveryTrigger::ANY; } catch (const std::exception& e) @@ -237,7 +234,7 @@ void EnablerConfiguration::load_ddsenabler_configuration( } -void EnablerConfiguration::load_enabler_configuration( +void EnablerConfiguration::load_enabler_configuration_( const Yaml& yml, const YamlReaderVersion& version) { @@ -248,7 +245,7 @@ void EnablerConfiguration::load_enabler_configuration( } } -void EnablerConfiguration::load_specs_configuration( +void EnablerConfiguration::load_specs_configuration_( const Yaml& yml, const YamlReaderVersion& version) { @@ -267,7 +264,7 @@ void EnablerConfiguration::load_specs_configuration( } } -void EnablerConfiguration::load_dds_configuration( +void EnablerConfiguration::load_dds_configuration_( const Yaml& yml, const YamlReaderVersion& version) { @@ -340,7 +337,7 @@ void EnablerConfiguration::load_dds_configuration( } } -void EnablerConfiguration::load_ddsenabler_configuration_from_yaml_file( +void EnablerConfiguration::load_ddsenabler_configuration_from_yaml_file_( const std::string& file_path) { Yaml yml; @@ -363,10 +360,10 @@ void EnablerConfiguration::load_ddsenabler_configuration_from_yaml_file( EPROSIMA_LOG_WARNING(DDSENABLER_YAML, "No configuration file specified, using default values."); } - EnablerConfiguration::load_ddsenabler_configuration(yml); + EnablerConfiguration::load_ddsenabler_configuration_(yml); } -void EnablerConfiguration::load_ddsenabler_configuration_from_json_file( +void EnablerConfiguration::load_ddsenabler_configuration_from_json_file_( const std::string& file_path) { Yaml yml; @@ -423,7 +420,7 @@ void EnablerConfiguration::load_ddsenabler_configuration_from_json_file( EPROSIMA_LOG_WARNING(DDSENABLER_YAML, "No configuration file specified, using default values."); } - EnablerConfiguration::load_ddsenabler_configuration(yml); + EnablerConfiguration::load_ddsenabler_configuration_(yml); } } /* namespace yaml */ diff --git a/ddsenabler_yaml/test/resources/correct_config.json b/ddsenabler_yaml/test/resources/correct_config.json index 97c51b1d..4fd8c854 100644 --- a/ddsenabler_yaml/test/resources/correct_config.json +++ b/ddsenabler_yaml/test/resources/correct_config.json @@ -4,7 +4,9 @@ "dds": { "domain": 0 }, - "ddsenabler": null, + "ddsenabler": { + "initial-publish-wait": 500 + }, "specs": { "threads": 12, "logging": { diff --git a/ddsenabler_yaml/test/resources/full_config.json b/ddsenabler_yaml/test/resources/full_config.json index 3be31cdc..4bdfa292 100644 --- a/ddsenabler_yaml/test/resources/full_config.json +++ b/ddsenabler_yaml/test/resources/full_config.json @@ -23,7 +23,9 @@ } ] }, - "ddsenabler": null, + "ddsenabler": { + "initial-publish-wait": 500 + }, "specs": { "threads": 12, "logging": { diff --git a/docs/context_broker_interface.rst b/docs/context_broker_interface.rst index fb9bd256..6927b921 100644 --- a/docs/context_broker_interface.rst +++ b/docs/context_broker_interface.rst @@ -15,7 +15,7 @@ during the initialization process of the ``DDS Enabler`` by using the ``init_dds int init_dds_enabler( const char* ddsEnablerConfigFile, - participants::DdsNotification data_callback, + participants::DdsDataNotification data_callback, participants::DdsTypeNotification type_callback, participants::DdsLogFunc log_callback); From bebf129675e41468651f29b4458e04637cc64eaa Mon Sep 17 00:00:00 2001 From: Juan Lopez Fernandez Date: Tue, 27 May 2025 14:59:58 +0200 Subject: [PATCH 12/28] Uncrustify all Signed-off-by: Juan Lopez Fernandez --- ddsenabler/examples/CLIParser.hpp | 4 +- ddsenabler/include/ddsenabler/DDSEnabler.hpp | 3 +- ddsenabler/src/cpp/DDSEnabler.cpp | 11 ++-- ddsenabler/src/cpp/dds_enabler_runner.cpp | 6 +-- ddsenabler/test/DDSEnablerTester.hpp | 10 ++-- .../test/ddsEnablerTests/ReloadConfig.cpp | 54 +++++++++++++------ .../ddsenabler_participants/CBCallbacks.hpp | 12 ++--- .../ddsenabler_participants/CBHandler.hpp | 3 +- ddsenabler_participants/src/cpp/CBHandler.cpp | 4 +- .../src/cpp/EnablerParticipant.cpp | 2 +- .../test/DdsEnablerParticipantsTest.cpp | 22 +++++--- .../src/cpp/EnablerConfiguration.cpp | 18 ++++--- ddsenabler_yaml/test/DdsEnablerYamlTest.cpp | 6 +-- 13 files changed, 96 insertions(+), 59 deletions(-) diff --git a/ddsenabler/examples/CLIParser.hpp b/ddsenabler/examples/CLIParser.hpp index 2bcf1661..5a3a624d 100644 --- a/ddsenabler/examples/CLIParser.hpp +++ b/ddsenabler/examples/CLIParser.hpp @@ -45,7 +45,9 @@ class CLIParser static void print_help( uint8_t return_code) { - std::cout << "Usage: ddsenabler_example " << + std::cout << + "Usage: ddsenabler_example " + << std::endl; std::cout << "" << std::endl; diff --git a/ddsenabler/include/ddsenabler/DDSEnabler.hpp b/ddsenabler/include/ddsenabler/DDSEnabler.hpp index c9acd520..dde13965 100644 --- a/ddsenabler/include/ddsenabler/DDSEnabler.hpp +++ b/ddsenabler/include/ddsenabler/DDSEnabler.hpp @@ -117,7 +117,8 @@ class DDSEnabler const CallbackSet& callbacks); //! Store reference to DomainParticipantFactory to avoid Fast-DDS singletons being destroyed before they should - std::shared_ptr part_factory_ = eprosima::fastdds::dds::DomainParticipantFactory::get_shared_instance(); + std::shared_ptr part_factory_ = + eprosima::fastdds::dds::DomainParticipantFactory::get_shared_instance(); //! Configuration of the DDS Enabler yaml::EnablerConfiguration configuration_; diff --git a/ddsenabler/src/cpp/DDSEnabler.cpp b/ddsenabler/src/cpp/DDSEnabler.cpp index 02b61b78..ec5139c4 100644 --- a/ddsenabler/src/cpp/DDSEnabler.cpp +++ b/ddsenabler/src/cpp/DDSEnabler.cpp @@ -96,7 +96,7 @@ DDSEnabler::DDSEnabler( if (pipe_->enable() != utils::ReturnCode::RETCODE_OK) { throw utils::InitializationException( - utils::Formatter() << "Failed to enable DDS Pipe."); + utils::Formatter() << "Failed to enable DDS Pipe."); } } @@ -128,11 +128,13 @@ bool DDSEnabler::set_file_watcher( } else if (ret == utils::ReturnCode::RETCODE_NO_DATA) { - EPROSIMA_LOG_INFO(DDSENABLER_EXECUTION, "No relevant changes in configuration file " << file_path); + EPROSIMA_LOG_INFO(DDSENABLER_EXECUTION, + "No relevant changes in configuration file " << file_path); } else { - EPROSIMA_LOG_WARNING(DDSENABLER_EXECUTION, "Failed to reload configuration from file " << file_path); + EPROSIMA_LOG_WARNING(DDSENABLER_EXECUTION, + "Failed to reload configuration from file " << file_path); } } catch (const std::exception& e) @@ -143,7 +145,8 @@ bool DDSEnabler::set_file_watcher( }; // Creating FileWatcher event handler - file_watcher_handler_ = std::make_unique(file_watcher_callback, file_path); + file_watcher_handler_ = std::make_unique(file_watcher_callback, + file_path); return true; } diff --git a/ddsenabler/src/cpp/dds_enabler_runner.cpp b/ddsenabler/src/cpp/dds_enabler_runner.cpp index 67b7ace0..7e9a199b 100644 --- a/ddsenabler/src/cpp/dds_enabler_runner.cpp +++ b/ddsenabler/src/cpp/dds_enabler_runner.cpp @@ -47,9 +47,9 @@ bool create_dds_enabler( // Create DDS Enabler instance if (!create_dds_enabler( - configuration, - callbacks, - enabler)) + configuration, + callbacks, + enabler)) { EPROSIMA_LOG_ERROR(DDSENABLER_EXECUTION, "Failed to create DDS Enabler from configuration file: " << dds_enabler_config_file); diff --git a/ddsenabler/test/DDSEnablerTester.hpp b/ddsenabler/test/DDSEnablerTester.hpp index 71050613..e1cc5a4f 100644 --- a/ddsenabler/test/DDSEnablerTester.hpp +++ b/ddsenabler/test/DDSEnablerTester.hpp @@ -329,11 +329,11 @@ class DDSEnablerTester : public ::testing::Test //eprosima::ddsenabler::participants::DdsLogFunc log_callback; static void test_log_callback( - const char* fileName, - int lineNo, - const char* funcName, - int category, - const char* msg) + const char* fileName, + int lineNo, + const char* funcName, + int category, + const char* msg) { } diff --git a/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp b/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp index 54262085..68b990a8 100644 --- a/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp +++ b/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp @@ -70,21 +70,24 @@ bool test_type_request_callback( return true; } - //eprosima::ddsenabler::participants::DdsLogFunc log_callback; void test_log_callback( - const char* file_name, - int line_no, - const char* func_name, - int category, - const char* msg) + const char* file_name, + int line_no, + const char* func_name, + int category, + const char* msg) { } -void write_json_file(const std::string filePath, bool block) { +void write_json_file( + const std::string filePath, + bool block) +{ // The JSON template with a placeholder for the domain - std::string jsonTemplate = R"({ + std::string jsonTemplate = + R"({ "dds": { "ddsmodule": { "dds": { @@ -110,22 +113,31 @@ void write_json_file(const std::string filePath, bool block) { // Replace the %d placeholder with the provided domain char buffer[1024]; - snprintf(buffer, sizeof(buffer), jsonTemplate.c_str(), block ? "\n \"blocklist\": [\n {\n \"name\": \"*\"\n }\n ]," : ""); + snprintf(buffer, sizeof(buffer), + jsonTemplate.c_str(), + block ? "\n \"blocklist\": [\n {\n \"name\": \"*\"\n }\n ]," : ""); // Write the formatted JSON to the file std::ofstream outFile(filePath); - if (outFile.is_open()) { + if (outFile.is_open()) + { outFile << buffer; outFile.close(); - } else { + } + else + { throw std::ios_base::failure("Failed to open the file for writing."); } } -void write_yaml_file(const std::string filePath, bool block) { +void write_yaml_file( + const std::string filePath, + bool block) +{ // The JSON template with a placeholder for the domain - std::string Template = R"( + std::string Template = + R"( dds: domain: 0 @@ -144,10 +156,13 @@ void write_yaml_file(const std::string filePath, bool block) { // Write the formatted YAML to the file std::ofstream outFile(filePath); - if (outFile.is_open()) { + if (outFile.is_open()) + { outFile << buffer; outFile.close(); - } else { + } + else + { throw std::ios_base::failure("Failed to open the file for writing."); } } @@ -158,15 +173,20 @@ namespace eprosima { namespace ddsenabler { // Class that exposes the protected attribute configuration_ -class DDSEnablerAccessor : public DDSEnabler { +class DDSEnablerAccessor : public DDSEnabler +{ public: + using DDSEnabler::DDSEnabler; - const void get_allowed_topics(std::shared_ptr& ptr) const { + const void get_allowed_topics( + std::shared_ptr& ptr) const + { std::lock_guard lock(mutex_); ptr = std::make_shared( this->configuration_.ddspipe_configuration.allowlist, this->configuration_.ddspipe_configuration.blocklist); } + }; // Test the configuration reload when the json configuration file is modified diff --git a/ddsenabler_participants/include/ddsenabler_participants/CBCallbacks.hpp b/ddsenabler_participants/include/ddsenabler_participants/CBCallbacks.hpp index 46189ae1..4870c655 100644 --- a/ddsenabler_participants/include/ddsenabler_participants/CBCallbacks.hpp +++ b/ddsenabler_participants/include/ddsenabler_participants/CBCallbacks.hpp @@ -29,7 +29,7 @@ namespace participants { /** * DdsLogFunc - callback executed when consuming log messages */ -typedef void (*DdsLogFunc)( +typedef void (* DdsLogFunc)( const char* file_name, int line_no, const char* func_name, @@ -39,7 +39,7 @@ typedef void (*DdsLogFunc)( /** * DdsTypeNotification - callback for notifying the reception of DDS types */ -typedef void (*DdsTypeNotification)( +typedef void (* DdsTypeNotification)( const char* type_name, const char* serialized_type, const unsigned char* serialized_type_internal, @@ -49,7 +49,7 @@ typedef void (*DdsTypeNotification)( /** * DdsTopicNotification - callback for notifying the reception of DDS topics */ -typedef void (*DdsTopicNotification)( +typedef void (* DdsTopicNotification)( const char* topic_name, const char* type_name, const char* serialized_qos); @@ -57,7 +57,7 @@ typedef void (*DdsTopicNotification)( /** * DdsDataNotification - callback for notifying the reception of DDS data */ -typedef void (*DdsDataNotification)( +typedef void (* DdsDataNotification)( const char* topic_name, const char* json, int64_t publish_time); @@ -65,7 +65,7 @@ typedef void (*DdsDataNotification)( /** * DdsTopicRequest - callback for requesting information (type and QoS) of a DDS topic */ -typedef bool (*DdsTopicRequest)( +typedef bool (* DdsTopicRequest)( const char* topic_name, std::string& type_name, std::string& serialized_qos); @@ -73,7 +73,7 @@ typedef bool (*DdsTopicRequest)( /** * DdsTypeRequest - callback for requesting information (serialized description and size) of a DDS type */ -typedef bool (*DdsTypeRequest)( +typedef bool (* DdsTypeRequest)( const char* type_name, std::unique_ptr& serialized_type_internal, uint32_t& serialized_type_internal_size); diff --git a/ddsenabler_participants/include/ddsenabler_participants/CBHandler.hpp b/ddsenabler_participants/include/ddsenabler_participants/CBHandler.hpp index 72b650ad..4b020fc8 100644 --- a/ddsenabler_participants/include/ddsenabler_participants/CBHandler.hpp +++ b/ddsenabler_participants/include/ddsenabler_participants/CBHandler.hpp @@ -275,7 +275,8 @@ class CBHandler : public ddspipe::participants::ISchemaHandler std::unique_ptr cb_writer_; //! Schemas map - std::map> schemas_; + std::map> schemas_; //! Unique sequence number assigned to received messages. It is incremented with every sample added unsigned int unique_sequence_number_{0}; diff --git a/ddsenabler_participants/src/cpp/CBHandler.cpp b/ddsenabler_participants/src/cpp/CBHandler.cpp index a4f03891..30fed8dc 100644 --- a/ddsenabler_participants/src/cpp/CBHandler.cpp +++ b/ddsenabler_participants/src/cpp/CBHandler.cpp @@ -270,7 +270,7 @@ void CBHandler::add_schema_nts_( } bool CBHandler::add_schema_nts_( - const fastdds::dds::xtypes::TypeIdentifier& type_id, + const fastdds::dds::xtypes::TypeIdentifier& type_id, const fastdds::dds::xtypes::TypeObject& type_obj, bool write_schema) { @@ -357,7 +357,7 @@ bool CBHandler::register_type_nts_( { EPROSIMA_LOG_ERROR(DDSENABLER_CB_HANDLER, "Unexpected dynamic types collection format: " << type_name << " expected to be last item, found " << _type_name << - " instead."); + " instead."); return false; } diff --git a/ddsenabler_participants/src/cpp/EnablerParticipant.cpp b/ddsenabler_participants/src/cpp/EnablerParticipant.cpp index ecf7b0a1..d54eca15 100644 --- a/ddsenabler_participants/src/cpp/EnablerParticipant.cpp +++ b/ddsenabler_participants/src/cpp/EnablerParticipant.cpp @@ -84,7 +84,7 @@ bool EnablerParticipant::publish( { EPROSIMA_LOG_ERROR(DDSENABLER_ENABLER_PARTICIPANT, "Failed to publish data in topic " << topic_name << - " : topic is unknown and topic request callback not set."); + " : topic is unknown and topic request callback not set."); return false; } diff --git a/ddsenabler_participants/test/DdsEnablerParticipantsTest.cpp b/ddsenabler_participants/test/DdsEnablerParticipantsTest.cpp index 21b0ff2e..a13d0ee0 100644 --- a/ddsenabler_participants/test/DdsEnablerParticipantsTest.cpp +++ b/ddsenabler_participants/test/DdsEnablerParticipantsTest.cpp @@ -102,7 +102,9 @@ class CBHandlerTest : public participants::CBHandler uint32_t& serialized_type_internal_size) { if (current_test_instance_ == nullptr) + { return false; + } current_test_instance_->type_request_called++; return true; @@ -115,7 +117,9 @@ class CBHandlerTest : public participants::CBHandler int64_t publish_time) { if (current_test_instance_ == nullptr) + { return; + } current_test_instance_->data_called_++; } @@ -129,7 +133,9 @@ class CBHandlerTest : public participants::CBHandler const char* data_placeholder) { if (current_test_instance_ == nullptr) + { return; + } current_test_instance_->type_called_++; } @@ -141,7 +147,9 @@ class CBHandlerTest : public participants::CBHandler const char* serialized_qos) { if (current_test_instance_ == nullptr) + { return; + } current_test_instance_->topic_called_++; } @@ -166,9 +174,9 @@ struct KnownType }; bool test_create_publisher( - KnownType& a_type, - Topic** topic, - std::string topic_name_suffix = "topic_name") + KnownType& a_type, + Topic** topic, + std::string topic_name_suffix = "topic_name") { DomainParticipant* participant = DomainParticipantFactory::get_instance() ->create_participant(0, PARTICIPANT_QOS_DEFAULT); @@ -217,12 +225,12 @@ bool test_create_publisher( } ddspipe::core::types::DdsTopic new_schema( - int num_type, - DynamicType::_ref_type& dynamic_type, - xtypes::TypeIdentifierPair& type_id_pair) + int num_type, + DynamicType::_ref_type& dynamic_type, + xtypes::TypeIdentifierPair& type_id_pair) { KnownType k_type; - switch(num_type) + switch (num_type) { case 3: { diff --git a/ddsenabler_yaml/src/cpp/EnablerConfiguration.cpp b/ddsenabler_yaml/src/cpp/EnablerConfiguration.cpp index 09d19936..f8193f12 100644 --- a/ddsenabler_yaml/src/cpp/EnablerConfiguration.cpp +++ b/ddsenabler_yaml/src/cpp/EnablerConfiguration.cpp @@ -130,7 +130,8 @@ EnablerConfiguration::EnablerConfiguration( if (is_json(file_path)) { load_ddsenabler_configuration_from_json_file_(file_path); - } else + } + else { if (file_path.size() >= 5 && (file_path.substr(file_path.size() - 5) == ".json" || @@ -241,7 +242,8 @@ void EnablerConfiguration::load_enabler_configuration_( // Get initial publish wait if (YamlReader::is_tag_present(yml, ENABLER_INITIAL_PUBLISH_WAIT_TAG)) { - enabler_configuration->initial_publish_wait = YamlReader::get_nonnegative_int(yml, ENABLER_INITIAL_PUBLISH_WAIT_TAG); + enabler_configuration->initial_publish_wait = YamlReader::get_nonnegative_int(yml, + ENABLER_INITIAL_PUBLISH_WAIT_TAG); } } @@ -376,7 +378,7 @@ void EnablerConfiguration::load_ddsenabler_configuration_from_json_file_( if (!file.is_open()) { throw eprosima::utils::ConfigurationException( - utils::Formatter() << "Could not open JSON file"); + utils::Formatter() << "Could not open JSON file"); } // Parse the JSON file @@ -397,22 +399,22 @@ void EnablerConfiguration::load_ddsenabler_configuration_from_json_file_( else { throw eprosima::utils::ConfigurationException( - utils::Formatter() << - "\"ddsmodule\" not found or is not an object within \"dds\" in the JSON file"); + utils::Formatter() << + "\"ddsmodule\" not found or is not an object within \"dds\" in the JSON file"); } } else { throw eprosima::utils::ConfigurationException( - utils::Formatter() << "\"dds\" not found or is not an object in the JSON file"); + utils::Formatter() << "\"dds\" not found or is not an object in the JSON file"); } } catch (const std::exception& e) { throw eprosima::utils::ConfigurationException( - utils::Formatter() << "Error loading DDS Enabler configuration from file: <" << file_path << - "> :\n " << e.what()); + utils::Formatter() << "Error loading DDS Enabler configuration from file: <" << file_path << + "> :\n " << e.what()); } } else diff --git a/ddsenabler_yaml/test/DdsEnablerYamlTest.cpp b/ddsenabler_yaml/test/DdsEnablerYamlTest.cpp index bfec170e..9f5e26f7 100644 --- a/ddsenabler_yaml/test/DdsEnablerYamlTest.cpp +++ b/ddsenabler_yaml/test/DdsEnablerYamlTest.cpp @@ -125,7 +125,7 @@ TEST(DdsEnablerYamlTest, get_ddsenabler_incorrect_path_configuration_json) TEST(DdsEnablerYamlTest, get_ddsenabler_correct_configuration_json) { const char* path_str = "./resources/correct_config.json"; - + ASSERT_TRUE(std::filesystem::exists(path_str)); EnablerConfiguration configuration(path_str); @@ -148,7 +148,7 @@ TEST(DdsEnablerYamlTest, get_ddsenabler_correct_configuration_json) TEST(DdsEnablerYamlTest, get_ddsenabler_incorrect_n_threads_configuration_json) { const char* path_str = "./resources/incorrect_threads_config.json"; - + ASSERT_TRUE(std::filesystem::exists(path_str)); EXPECT_THROW({EnablerConfiguration configuration(path_str);}, std::exception); @@ -178,7 +178,7 @@ TEST(DdsEnablerYamlTest, get_ddsenabler_incorrect_path_configuration_yaml) TEST(DdsEnablerYamlTest, get_ddsenabler_full_configuration_json) { const char* path_str = "./resources/correct_config.json"; - + ASSERT_TRUE(std::filesystem::exists(path_str)); EnablerConfiguration configuration(path_str); From 18db200ffcca4b8687dcd8cdab2fe12fa46accef Mon Sep 17 00:00:00 2001 From: Juan Lopez Fernandez Date: Tue, 27 May 2025 15:38:37 +0200 Subject: [PATCH 13/28] Fix Windows compilation Signed-off-by: Juan Lopez Fernandez --- ddsenabler/project_settings.cmake | 2 +- .../ddsenabler_participants/EnablerParticipantConfiguration.hpp | 1 - ddsenabler_participants/project_settings.cmake | 2 +- ddsenabler_yaml/project_settings.cmake | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/ddsenabler/project_settings.cmake b/ddsenabler/project_settings.cmake index 4ceaf4a9..0b877c04 100644 --- a/ddsenabler/project_settings.cmake +++ b/ddsenabler/project_settings.cmake @@ -50,4 +50,4 @@ set(MODULE_VERSION_FILE_PATH "../VERSION") set(MODULE_CPP_VERSION - C++17) + C++20) diff --git a/ddsenabler_participants/include/ddsenabler_participants/EnablerParticipantConfiguration.hpp b/ddsenabler_participants/include/ddsenabler_participants/EnablerParticipantConfiguration.hpp index 9af09074..5d58779c 100644 --- a/ddsenabler_participants/include/ddsenabler_participants/EnablerParticipantConfiguration.hpp +++ b/ddsenabler_participants/include/ddsenabler_participants/EnablerParticipantConfiguration.hpp @@ -40,7 +40,6 @@ struct EnablerParticipantConfiguration : public ddspipe::participants::Participa // VARIABLES ///////////////////////// - DDSENABLER_PARTICIPANTS_DllAPI unsigned int initial_publish_wait {0u}; }; diff --git a/ddsenabler_participants/project_settings.cmake b/ddsenabler_participants/project_settings.cmake index c10c5c82..d2f12e6b 100644 --- a/ddsenabler_participants/project_settings.cmake +++ b/ddsenabler_participants/project_settings.cmake @@ -44,4 +44,4 @@ set(MODULE_THIRDPARTY_PATH "../thirdparty") set(MODULE_CPP_VERSION - C++17) + C++20) diff --git a/ddsenabler_yaml/project_settings.cmake b/ddsenabler_yaml/project_settings.cmake index bb1275dc..f92f2699 100644 --- a/ddsenabler_yaml/project_settings.cmake +++ b/ddsenabler_yaml/project_settings.cmake @@ -44,4 +44,4 @@ set(MODULE_THIRDPARTY_PATH "../thirdparty") set(MODULE_CPP_VERSION - C++17) + C++20) From e07a0e4d46c47c06f5dcd85f64a67969c58e9ca0 Mon Sep 17 00:00:00 2001 From: Juan Lopez Fernandez Date: Thu, 29 May 2025 12:32:30 +0200 Subject: [PATCH 14/28] Disable tests for unsupported optional types Signed-off-by: Juan Lopez Fernandez --- .../test/ddsEnablerTypedTests/CMakeLists.txt | 160 +++++++++--------- .../DdsEnablerTypedTest.cpp | 4 +- 2 files changed, 82 insertions(+), 82 deletions(-) diff --git a/ddsenabler/test/ddsEnablerTypedTests/CMakeLists.txt b/ddsenabler/test/ddsEnablerTypedTests/CMakeLists.txt index 7e776b41..e6cee2df 100644 --- a/ddsenabler/test/ddsEnablerTypedTests/CMakeLists.txt +++ b/ddsenabler/test/ddsEnablerTypedTests/CMakeLists.txt @@ -469,86 +469,86 @@ set(TEST_LIST ddsenabler_send_samples_MutableUnionStruct ddsenabler_send_samples_MutableWCharStruct ddsenabler_send_samples_InnerStructOptional - ddsenabler_send_samples_array_short_align_1_optional - ddsenabler_send_samples_array_short_align_2_optional - ddsenabler_send_samples_array_short_align_4_optional - ddsenabler_send_samples_array_short_optional - ddsenabler_send_samples_boolean_align_1_optional - ddsenabler_send_samples_boolean_align_2_optional - ddsenabler_send_samples_boolean_align_4_optional - ddsenabler_send_samples_boolean_optional - ddsenabler_send_samples_char_align_1_optional - ddsenabler_send_samples_char_align_2_optional - ddsenabler_send_samples_char_align_4_optional - ddsenabler_send_samples_char_optional - ddsenabler_send_samples_double_align_1_optional - ddsenabler_send_samples_double_align_2_optional - ddsenabler_send_samples_double_align_4_optional - ddsenabler_send_samples_double_optional - ddsenabler_send_samples_float_align_1_optional - ddsenabler_send_samples_float_align_2_optional - ddsenabler_send_samples_float_align_4_optional - ddsenabler_send_samples_float_optional - ddsenabler_send_samples_long_align_1_optional - ddsenabler_send_samples_long_align_2_optional - ddsenabler_send_samples_long_align_4_optional - ddsenabler_send_samples_long_optional - ddsenabler_send_samples_longdouble_align_1_optional - ddsenabler_send_samples_longdouble_align_2_optional - ddsenabler_send_samples_longdouble_align_4_optional - ddsenabler_send_samples_longdouble_optional - ddsenabler_send_samples_longlong_align_1_optional - ddsenabler_send_samples_longlong_align_2_optional - ddsenabler_send_samples_longlong_align_4_optional - ddsenabler_send_samples_longlong_optional - ddsenabler_send_samples_map_short_align_1_optional - ddsenabler_send_samples_map_short_align_2_optional - ddsenabler_send_samples_map_short_align_4_optional - ddsenabler_send_samples_map_short_optional - ddsenabler_send_samples_octet_align_1_optional - ddsenabler_send_samples_octet_align_2_optional - ddsenabler_send_samples_octet_align_4_optional - ddsenabler_send_samples_octet_optional - ddsenabler_send_samples_opt_struct_align_1_optional - ddsenabler_send_samples_opt_struct_align_2_optional - ddsenabler_send_samples_opt_struct_align_4_optional - ddsenabler_send_samples_opt_struct_optional - ddsenabler_send_samples_sequence_short_align_1_optional - ddsenabler_send_samples_sequence_short_align_2_optional - ddsenabler_send_samples_sequence_short_align_4_optional - ddsenabler_send_samples_sequence_short_optional - ddsenabler_send_samples_short_align_1_optional - ddsenabler_send_samples_short_align_2_optional - ddsenabler_send_samples_short_align_4_optional - ddsenabler_send_samples_short_optional - ddsenabler_send_samples_string_bounded_align_1_optional - ddsenabler_send_samples_string_bounded_align_2_optional - ddsenabler_send_samples_string_bounded_align_4_optional - ddsenabler_send_samples_string_bounded_optional - ddsenabler_send_samples_string_unbounded_align_1_optional - ddsenabler_send_samples_string_unbounded_align_2_optional - ddsenabler_send_samples_string_unbounded_align_4_optional - ddsenabler_send_samples_string_unbounded_optional - ddsenabler_send_samples_struct_align_1_optional - ddsenabler_send_samples_struct_align_2_optional - ddsenabler_send_samples_struct_align_4_optional - ddsenabler_send_samples_struct_optional - ddsenabler_send_samples_ulong_align_1_optional - ddsenabler_send_samples_ulong_align_2_optional - ddsenabler_send_samples_ulong_align_4_optional - ddsenabler_send_samples_ulong_optional - ddsenabler_send_samples_ulonglong_align_1_optional - ddsenabler_send_samples_ulonglong_align_2_optional - ddsenabler_send_samples_ulonglong_align_4_optional - ddsenabler_send_samples_ulonglong_optional - ddsenabler_send_samples_ushort_align_1_optional - ddsenabler_send_samples_ushort_align_2_optional - ddsenabler_send_samples_ushort_align_4_optional - ddsenabler_send_samples_ushort_optional - ddsenabler_send_samples_wchar_align_1_optional - ddsenabler_send_samples_wchar_align_2_optional - ddsenabler_send_samples_wchar_align_4_optional - ddsenabler_send_samples_wchar_optional + # ddsenabler_send_samples_array_short_align_1_optional + # ddsenabler_send_samples_array_short_align_2_optional + # ddsenabler_send_samples_array_short_align_4_optional + # ddsenabler_send_samples_array_short_optional + # ddsenabler_send_samples_boolean_align_1_optional + # ddsenabler_send_samples_boolean_align_2_optional + # ddsenabler_send_samples_boolean_align_4_optional + # ddsenabler_send_samples_boolean_optional + # ddsenabler_send_samples_char_align_1_optional + # ddsenabler_send_samples_char_align_2_optional + # ddsenabler_send_samples_char_align_4_optional + # ddsenabler_send_samples_char_optional + # ddsenabler_send_samples_double_align_1_optional + # ddsenabler_send_samples_double_align_2_optional + # ddsenabler_send_samples_double_align_4_optional + # ddsenabler_send_samples_double_optional + # ddsenabler_send_samples_float_align_1_optional + # ddsenabler_send_samples_float_align_2_optional + # ddsenabler_send_samples_float_align_4_optional + # ddsenabler_send_samples_float_optional + # ddsenabler_send_samples_long_align_1_optional + # ddsenabler_send_samples_long_align_2_optional + # ddsenabler_send_samples_long_align_4_optional + # ddsenabler_send_samples_long_optional + # ddsenabler_send_samples_longdouble_align_1_optional + # ddsenabler_send_samples_longdouble_align_2_optional + # ddsenabler_send_samples_longdouble_align_4_optional + # ddsenabler_send_samples_longdouble_optional + # ddsenabler_send_samples_longlong_align_1_optional + # ddsenabler_send_samples_longlong_align_2_optional + # ddsenabler_send_samples_longlong_align_4_optional + # ddsenabler_send_samples_longlong_optional + # ddsenabler_send_samples_map_short_align_1_optional + # ddsenabler_send_samples_map_short_align_2_optional + # ddsenabler_send_samples_map_short_align_4_optional + # ddsenabler_send_samples_map_short_optional + # ddsenabler_send_samples_octet_align_1_optional + # ddsenabler_send_samples_octet_align_2_optional + # ddsenabler_send_samples_octet_align_4_optional + # ddsenabler_send_samples_octet_optional + # ddsenabler_send_samples_opt_struct_align_1_optional + # ddsenabler_send_samples_opt_struct_align_2_optional + # ddsenabler_send_samples_opt_struct_align_4_optional + # ddsenabler_send_samples_opt_struct_optional + # ddsenabler_send_samples_sequence_short_align_1_optional + # ddsenabler_send_samples_sequence_short_align_2_optional + # ddsenabler_send_samples_sequence_short_align_4_optional + # ddsenabler_send_samples_sequence_short_optional + # ddsenabler_send_samples_short_align_1_optional + # ddsenabler_send_samples_short_align_2_optional + # ddsenabler_send_samples_short_align_4_optional + # ddsenabler_send_samples_short_optional + # ddsenabler_send_samples_string_bounded_align_1_optional + # ddsenabler_send_samples_string_bounded_align_2_optional + # ddsenabler_send_samples_string_bounded_align_4_optional + # ddsenabler_send_samples_string_bounded_optional + # ddsenabler_send_samples_string_unbounded_align_1_optional + # ddsenabler_send_samples_string_unbounded_align_2_optional + # ddsenabler_send_samples_string_unbounded_align_4_optional + # ddsenabler_send_samples_string_unbounded_optional + # ddsenabler_send_samples_struct_align_1_optional + # ddsenabler_send_samples_struct_align_2_optional + # ddsenabler_send_samples_struct_align_4_optional + # ddsenabler_send_samples_struct_optional + # ddsenabler_send_samples_ulong_align_1_optional + # ddsenabler_send_samples_ulong_align_2_optional + # ddsenabler_send_samples_ulong_align_4_optional + # ddsenabler_send_samples_ulong_optional + # ddsenabler_send_samples_ulonglong_align_1_optional + # ddsenabler_send_samples_ulonglong_align_2_optional + # ddsenabler_send_samples_ulonglong_align_4_optional + # ddsenabler_send_samples_ulonglong_optional + # ddsenabler_send_samples_ushort_align_1_optional + # ddsenabler_send_samples_ushort_align_2_optional + # ddsenabler_send_samples_ushort_align_4_optional + # ddsenabler_send_samples_ushort_optional + # ddsenabler_send_samples_wchar_align_1_optional + # ddsenabler_send_samples_wchar_align_2_optional + # ddsenabler_send_samples_wchar_align_4_optional + # ddsenabler_send_samples_wchar_optional ddsenabler_send_samples_BooleanStruct ddsenabler_send_samples_CharStruct ddsenabler_send_samples_DoubleStruct diff --git a/ddsenabler/test/ddsEnablerTypedTests/DdsEnablerTypedTest.cpp b/ddsenabler/test/ddsEnablerTypedTests/DdsEnablerTypedTest.cpp index ee43349a..16f7c5ea 100644 --- a/ddsenabler/test/ddsEnablerTypedTests/DdsEnablerTypedTest.cpp +++ b/ddsenabler/test/ddsEnablerTypedTests/DdsEnablerTypedTest.cpp @@ -660,7 +660,7 @@ DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_MutableUShortStruct, Mutabl DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_MutableUnionStruct, MutableUnionStructPubSubType); DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_MutableWCharStruct, MutableWCharStructPubSubType); DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_InnerStructOptional, InnerStructOptionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_array_short_align_1_optional, +/* DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_array_short_align_1_optional, array_short_align_1_optionalPubSubType); DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_array_short_align_2_optional, array_short_align_2_optionalPubSubType); @@ -757,7 +757,7 @@ DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_ushort_optional, ushort_opt DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_wchar_align_1_optional, wchar_align_1_optionalPubSubType); DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_wchar_align_2_optional, wchar_align_2_optionalPubSubType); DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_wchar_align_4_optional, wchar_align_4_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_wchar_optional, wchar_optionalPubSubType); +DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_wchar_optional, wchar_optionalPubSubType); */ DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_BooleanStruct, BooleanStructPubSubType); DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_CharStruct, CharStructPubSubType); DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_DoubleStruct, DoubleStructPubSubType); From 740dcc47e0916495161e8e775c70e6ce08eda592 Mon Sep 17 00:00:00 2001 From: Juan Lopez Fernandez Date: Thu, 29 May 2025 12:32:49 +0200 Subject: [PATCH 15/28] Refactor participant tests Signed-off-by: Juan Lopez Fernandez --- .../test/DdsEnablerParticipantsTest.cpp | 262 +++++++----------- 1 file changed, 94 insertions(+), 168 deletions(-) diff --git a/ddsenabler_participants/test/DdsEnablerParticipantsTest.cpp b/ddsenabler_participants/test/DdsEnablerParticipantsTest.cpp index a13d0ee0..58f662f3 100644 --- a/ddsenabler_participants/test/DdsEnablerParticipantsTest.cpp +++ b/ddsenabler_participants/test/DdsEnablerParticipantsTest.cpp @@ -29,7 +29,6 @@ #include #include - #include #include @@ -37,27 +36,12 @@ #include #include -#include - #include "types/DDSEnablerTestTypesPubSubTypes.hpp" using namespace eprosima; using namespace eprosima::fastdds::dds; using namespace eprosima::ddsenabler; -DynamicType::_ref_type create_schema( - ddspipe::core::types::DdsTopic& topic) -{ - DynamicTypeBuilderFactory::_ref_type factory {DynamicTypeBuilderFactory::get_instance()}; - - TypeDescriptor::_ref_type type_descriptor {traits::make_shared()}; - type_descriptor->kind(TK_STRUCTURE); - type_descriptor->name(topic.type_name); - DynamicTypeBuilder::_ref_type type_builder {factory->create_type(type_descriptor)}; - - return type_builder->build(); -} - class CBWriterTest : public participants::CBWriter { public: @@ -166,105 +150,88 @@ class CBHandlerTest : public participants::CBHandler CBHandlerTest* CBHandlerTest::current_test_instance_ = nullptr; -struct KnownType -{ - DynamicType::_ref_type dyn_type_; - TypeSupport type_sup_; - DataWriter* writer_ = nullptr; -}; - -bool test_create_publisher( - KnownType& a_type, - Topic** topic, - std::string topic_name_suffix = "topic_name") +void get_dynamic_type( + int num_type, + DynamicType::_ref_type& dynamic_type, + xtypes::TypeIdentifier& type_identifier, + ddspipe::core::types::DdsTopic& pipe_topic) { - DomainParticipant* participant = DomainParticipantFactory::get_instance() - ->create_participant(0, PARTICIPANT_QOS_DEFAULT); - if (participant == nullptr) + std::shared_ptr type_support; + switch (num_type) { - std::cout << "ERROR DDSEnablerTester: create_participant" << std::endl; - return false; + case 3: + { + type_support.reset(new DDSEnablerTestType3PubSubType()); + break; + } + case 2: + { + type_support.reset(new DDSEnablerTestType2PubSubType()); + break; + } + case 1: + default: + { + type_support.reset(new DDSEnablerTestType1PubSubType()); + break; + } } + type_support->register_type_object_representation(); + auto type_id_pair = type_support->type_identifiers(); - if (RETCODE_OK != a_type.type_sup_.register_type(participant)) - { - std::cout << "ERROR DDSEnablerTester: fail to register type: " << - a_type.type_sup_.get_type_name() << std::endl; - return false; - } + type_identifier = + (fastdds::dds::xtypes::EK_COMPLETE == + type_id_pair.type_identifier1()._d()) ? type_id_pair.type_identifier1() : type_id_pair.type_identifier2(); - Publisher* publisher = participant->create_publisher(PUBLISHER_QOS_DEFAULT); - if (publisher == nullptr) - { - std::cout << "ERROR DDSEnablerTester: create_publisher: " << - a_type.type_sup_.get_type_name() << std::endl; - return false; - } + xtypes::TypeObject type_obj; + ASSERT_EQ(RETCODE_OK, + DomainParticipantFactory::get_instance()->type_object_registry().get_type_object(type_identifier, + type_obj)); + dynamic_type = DynamicTypeBuilderFactory::get_instance()->create_type_w_type_object(type_obj)->build(); std::ostringstream topic_name; - topic_name << a_type.type_sup_.get_type_name() << topic_name_suffix; - *topic = participant->create_topic(topic_name.str(), a_type.type_sup_.get_type_name(), TOPIC_QOS_DEFAULT); - std::cout << (*topic)->get_name() << std::endl; - if (*topic == nullptr) - { - std::cout << "ERROR DDSEnablerTester: create_topic: " << - a_type.type_sup_.get_type_name() << std::endl; - return false; - } - - DataWriterQos wqos = publisher->get_default_datawriter_qos(); - a_type.writer_ = publisher->create_datawriter(*topic, wqos); - if (a_type.writer_ == nullptr) - { - std::cout << "ERROR DDSEnablerTester: create_datawriter: " << - a_type.type_sup_.get_type_name() << std::endl; - return false; - } - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - return true; + topic_name << type_support->get_name() << "_topic_name_" << std::to_string(num_type); + pipe_topic.m_topic_name = topic_name.str(); + pipe_topic.type_name = type_support->get_name(); + pipe_topic.type_identifiers = type_id_pair; } -ddspipe::core::types::DdsTopic new_schema( +void get_dynamic_type( int num_type, DynamicType::_ref_type& dynamic_type, - xtypes::TypeIdentifierPair& type_id_pair) + xtypes::TypeIdentifier& type_identifier) { - KnownType k_type; + ddspipe::core::types::DdsTopic _; + get_dynamic_type(num_type, dynamic_type, type_identifier, _); +} + +void get_data_payload( + int num_type, + eprosima::ddspipe::core::types::Payload& payload) +{ + std::shared_ptr type_support; switch (num_type) { case 3: { - k_type.type_sup_.reset(new DDSEnablerTestType3PubSubType()); + type_support.reset(new DDSEnablerTestType3PubSubType()); break; } case 2: { - k_type.type_sup_.reset(new DDSEnablerTestType2PubSubType()); + type_support.reset(new DDSEnablerTestType2PubSubType()); break; } case 1: default: { - k_type.type_sup_.reset(new DDSEnablerTestType1PubSubType()); + type_support.reset(new DDSEnablerTestType1PubSubType()); break; } } - - eprosima::fastdds::dds::Topic* topic = nullptr; - - std::string str_topic_name = "topic_name" + std::to_string(num_type); - test_create_publisher(k_type, &topic, str_topic_name); - - ddspipe::core::types::DdsTopic pipe_topic; - pipe_topic.m_topic_name = topic->get_name(); - pipe_topic.type_name = topic->get_type_name(); - - eprosima::fastdds::dds::DomainParticipantFactory::get_instance()->type_object_registry().get_type_identifiers( - topic->get_type_name(), type_id_pair); - pipe_topic.type_identifiers = type_id_pair; - - dynamic_type = create_schema(pipe_topic); - return pipe_topic; + void* data = type_support->create_data(); + ASSERT_TRUE(type_support->serialize(data, payload, DataRepresentationId::XCDR2_DATA_REPRESENTATION)); + type_support->delete_data(data); } TEST(DdsEnablerParticipantsTest, ddsenabler_participants_cb_handler_creation) @@ -295,26 +262,26 @@ TEST(DdsEnablerParticipantsTest, ddsenabler_participants_add_new_schemas) auto cb_handler_ = std::make_shared(handler_config, payload_pool_); ASSERT_NE(cb_handler_, nullptr); - xtypes::TypeIdentifierPair type_id_pair; + // Add a new schema + xtypes::TypeIdentifier type_id; DynamicType::_ref_type dynamic_type; - new_schema(1, dynamic_type, type_id_pair); + get_dynamic_type(1, dynamic_type, type_id); ASSERT_TRUE(cb_handler_->schemas_.empty()); ASSERT_EQ(cb_handler_->schemas_.size(), 0); - cb_handler_->add_schema(dynamic_type, type_id_pair.type_identifier1()); + cb_handler_->add_schema(dynamic_type, type_id); ASSERT_FALSE(cb_handler_->schemas_.empty()); ASSERT_EQ(cb_handler_->schemas_.size(), 1); ASSERT_EQ(cb_handler_->type_called_, 1); - - - xtypes::TypeIdentifierPair type_id_pair2; + // Add another schema for a different type + xtypes::TypeIdentifier type_id2; DynamicType::_ref_type dynamic_type2; - new_schema(2, dynamic_type2, type_id_pair2); + get_dynamic_type(2, dynamic_type2, type_id2); ASSERT_FALSE(cb_handler_->schemas_.empty()); ASSERT_EQ(cb_handler_->schemas_.size(), 1); - cb_handler_->add_schema(dynamic_type2, type_id_pair2.type_identifier1()); + cb_handler_->add_schema(dynamic_type2, type_id2); ASSERT_FALSE(cb_handler_->schemas_.empty()); ASSERT_EQ(cb_handler_->schemas_.size(), 2); ASSERT_EQ(cb_handler_->type_called_, 2); @@ -333,26 +300,26 @@ TEST(DdsEnablerParticipantsTest, ddsenabler_participants_add_same_type_schema) auto cb_handler_ = std::make_shared(handler_config, payload_pool_); ASSERT_NE(cb_handler_, nullptr); - xtypes::TypeIdentifierPair type_id_pair; + // Add a new schema + xtypes::TypeIdentifier type_id; DynamicType::_ref_type dynamic_type; - new_schema(1, dynamic_type, type_id_pair); + get_dynamic_type(1, dynamic_type, type_id); ASSERT_TRUE(cb_handler_->schemas_.empty()); ASSERT_EQ(cb_handler_->schemas_.size(), 0); - cb_handler_->add_schema(dynamic_type, type_id_pair.type_identifier1()); + cb_handler_->add_schema(dynamic_type, type_id); ASSERT_FALSE(cb_handler_->schemas_.empty()); ASSERT_EQ(cb_handler_->schemas_.size(), 1); ASSERT_EQ(cb_handler_->type_called_, 1); - - - xtypes::TypeIdentifierPair type_id_pair2; + // Add the same schema again + xtypes::TypeIdentifier type_id2; DynamicType::_ref_type dynamic_type2; - new_schema(1, dynamic_type2, type_id_pair2); + get_dynamic_type(1, dynamic_type2, type_id2); ASSERT_FALSE(cb_handler_->schemas_.empty()); ASSERT_EQ(cb_handler_->schemas_.size(), 1); - cb_handler_->add_schema(dynamic_type2, type_id_pair2.type_identifier1()); + cb_handler_->add_schema(dynamic_type2, type_id2); ASSERT_FALSE(cb_handler_->schemas_.empty()); ASSERT_EQ(cb_handler_->schemas_.size(), 1); ASSERT_EQ(cb_handler_->type_called_, 1); @@ -371,35 +338,23 @@ TEST(DdsEnablerParticipantsTest, ddsenabler_participants_add_data_with_schema) auto cb_handler_ = std::make_shared(handler_config, payload_pool_); ASSERT_NE(cb_handler_, nullptr); - xtypes::TypeIdentifierPair type_id_pair; + xtypes::TypeIdentifier type_identifier; DynamicType::_ref_type dynamic_type; - ddspipe::core::types::DdsTopic pipe_topic = new_schema(1, dynamic_type, type_id_pair); + ddspipe::core::types::DdsTopic pipe_topic; + get_dynamic_type(1, dynamic_type, type_identifier, pipe_topic); ASSERT_TRUE(cb_handler_->schemas_.empty()); ASSERT_EQ(cb_handler_->schemas_.size(), 0); - cb_handler_->add_schema(dynamic_type, type_id_pair.type_identifier1()); + cb_handler_->add_schema(dynamic_type, type_identifier); ASSERT_FALSE(cb_handler_->schemas_.empty()); ASSERT_EQ(cb_handler_->schemas_.size(), 1); ASSERT_EQ(cb_handler_->type_called_, 1); auto data = std::make_unique(); - eprosima::ddspipe::core::types::Payload payload; - - std::string content = - "{\n" - " \"color\": \"RED\",\n" - " \"shapesize\": 30,\n" - " \"x\": 198,\n" - " \"y\": 189\n" - "}"; - - payload.length = static_cast(content.length()); - payload.max_size = static_cast(content.length()); - payload.data = (unsigned char*)reinterpret_cast(content.data()); - - payload_pool_->get_payload(payload, data->payload); - payload.data = nullptr; // Set to nullptr after copy to avoid free on destruction + + payload_pool_->get_payload(1000, data->payload); data->payload_owner = payload_pool_.get(); + get_data_payload(1, data->payload); ASSERT_NO_THROW(cb_handler_->add_data(pipe_topic, *data)); // If the data has been added, the sequence number should be 1 @@ -420,29 +375,16 @@ TEST(DdsEnablerParticipantsTest, ddsenabler_participants_add_data_without_schema auto cb_handler_ = std::make_shared(handler_config, payload_pool_); ASSERT_NE(cb_handler_, nullptr); - xtypes::TypeIdentifierPair type_id_pair; + xtypes::TypeIdentifier type_id; DynamicType::_ref_type dynamic_type; - ddspipe::core::types::DdsTopic pipe_topic = new_schema(1, dynamic_type, type_id_pair); + ddspipe::core::types::DdsTopic pipe_topic; + get_dynamic_type(1, dynamic_type, type_id, pipe_topic); auto data = std::make_unique(); - eprosima::ddspipe::core::types::Payload payload; - - std::string content = - "{\n" - " \"color\": \"RED\",\n" - " \"shapesize\": 30,\n" - " \"x\": 198,\n" - " \"y\": 189\n" - "}"; - - payload.length = static_cast(content.length()); - payload.max_size = static_cast(content.length()); - payload.data = new unsigned char[payload.length]; - std::memcpy(payload.data, content.data(), payload.length); - - payload_pool_->get_payload(payload, data->payload); - payload.data = nullptr; // Set to nullptr after copy to avoid free on destruction + + payload_pool_->get_payload(1000, data->payload); data->payload_owner = payload_pool_.get(); + get_data_payload(1, data->payload); ASSERT_NO_THROW(cb_handler_->add_data(pipe_topic, *data)); // As there is no schema associated, the sequence number should still be 0 @@ -463,28 +405,16 @@ TEST(DdsEnablerParticipantsTest, ddsenabler_participants_write_schema_first_time auto cb_handler_ = std::make_shared(handler_config, payload_pool_); ASSERT_NE(cb_handler_, nullptr); - xtypes::TypeIdentifierPair type_id_pair; + xtypes::TypeIdentifier type_id; DynamicType::_ref_type dynamic_type; - ddspipe::core::types::DdsTopic pipe_topic = new_schema(1, dynamic_type, type_id_pair); + ddspipe::core::types::DdsTopic pipe_topic; + get_dynamic_type(1, dynamic_type, type_id, pipe_topic); auto data = std::make_unique(); - eprosima::ddspipe::core::types::Payload payload; - - std::string content = - "{\n" - " \"color\": \"RED\",\n" - " \"shapesize\": 30,\n" - " \"x\": 198,\n" - " \"y\": 189\n" - "}"; - - payload.length = static_cast(content.length()); - payload.max_size = static_cast(content.length()); - payload.data = (unsigned char*)reinterpret_cast(content.data()); - - payload_pool_->get_payload(payload, data->payload); - payload.data = nullptr; // Set to nullptr after copy to avoid free on destruction + + payload_pool_->get_payload(1000, data->payload); data->payload_owner = payload_pool_.get(); + get_data_payload(1, data->payload); participants::CBMessage msg; msg.sequence_number = 1; @@ -499,20 +429,16 @@ TEST(DdsEnablerParticipantsTest, ddsenabler_participants_write_schema_first_time // The data will be successfully written as the dynamic type exists and we are bypassing the handler schema check ASSERT_EQ(cb_handler_->data_called_, 1); - xtypes::TypeIdentifierPair type_id_pair2; + xtypes::TypeIdentifier type_id2; DynamicType::_ref_type dynamic_type2; - ddspipe::core::types::DdsTopic pipe_topic2 = new_schema(2, dynamic_type2, type_id_pair2); + ddspipe::core::types::DdsTopic pipe_topic2; + get_dynamic_type(2, dynamic_type2, type_id2, pipe_topic2); auto data2 = std::make_unique(); - eprosima::ddspipe::core::types::Payload payload2; - - payload2.length = static_cast(content.length()); - payload2.max_size = static_cast(content.length()); - payload2.data = (unsigned char*)reinterpret_cast(content.data()); - payload_pool_->get_payload(payload2, data2->payload); - payload2.data = nullptr; // Set to nullptr after copy to avoid free on destruction + payload_pool_->get_payload(1000, data2->payload); data2->payload_owner = payload_pool_.get(); + get_data_payload(2, data2->payload); participants::CBMessage msg2; msg2.sequence_number = 1; From 96edac6d4c5c7a59aebdde7bf8fee435ad77951b Mon Sep 17 00:00:00 2001 From: Juan Lopez Fernandez Date: Fri, 30 May 2025 13:09:17 +0200 Subject: [PATCH 16/28] Rename request callbacks to query Signed-off-by: Juan Lopez Fernandez --- ddsenabler/include/ddsenabler/CallbackSet.hpp | 4 ++-- ddsenabler/src/cpp/DDSEnabler.cpp | 8 +++---- ddsenabler/test/DDSEnablerTester.hpp | 18 +++++++-------- .../test/ddsEnablerTests/ReloadConfig.cpp | 22 +++++++++---------- .../ddsenabler_participants/CBCallbacks.hpp | 8 +++---- .../ddsenabler_participants/CBHandler.hpp | 10 ++++----- .../EnablerParticipant.hpp | 8 +++---- ddsenabler_participants/src/cpp/CBHandler.cpp | 12 +++++----- .../src/cpp/EnablerParticipant.cpp | 10 ++++----- .../test/DdsEnablerParticipantsTest.cpp | 16 +++++++------- 10 files changed, 58 insertions(+), 58 deletions(-) diff --git a/ddsenabler/include/ddsenabler/CallbackSet.hpp b/ddsenabler/include/ddsenabler/CallbackSet.hpp index 4d04ce7b..ee6af378 100644 --- a/ddsenabler/include/ddsenabler/CallbackSet.hpp +++ b/ddsenabler/include/ddsenabler/CallbackSet.hpp @@ -31,8 +31,8 @@ struct DdsCallbacks participants::DdsTypeNotification type_notification{nullptr}; participants::DdsTopicNotification topic_notification{nullptr}; participants::DdsDataNotification data_notification{nullptr}; - participants::DdsTypeRequest type_request{nullptr}; - participants::DdsTopicRequest topic_request{nullptr}; + participants::DdsTypeQuery type_query{nullptr}; + participants::DdsTopicQuery topic_query{nullptr}; }; /** diff --git a/ddsenabler/src/cpp/DDSEnabler.cpp b/ddsenabler/src/cpp/DDSEnabler.cpp index ec5139c4..fcf9669a 100644 --- a/ddsenabler/src/cpp/DDSEnabler.cpp +++ b/ddsenabler/src/cpp/DDSEnabler.cpp @@ -201,13 +201,13 @@ void DDSEnabler::set_internal_callbacks_( { cb_handler_->set_data_notification_callback(callbacks.dds.data_notification); } - if (callbacks.dds.type_request) + if (callbacks.dds.type_query) { - cb_handler_->set_type_request_callback(callbacks.dds.type_request); + cb_handler_->set_type_query_callback(callbacks.dds.type_query); } - if (callbacks.dds.topic_request) + if (callbacks.dds.topic_query) { - enabler_participant_->set_topic_request_callback(callbacks.dds.topic_request); + enabler_participant_->set_topic_query_callback(callbacks.dds.topic_query); } } diff --git a/ddsenabler/test/DDSEnablerTester.hpp b/ddsenabler/test/DDSEnablerTester.hpp index e1cc5a4f..9dcbcbe9 100644 --- a/ddsenabler/test/DDSEnablerTester.hpp +++ b/ddsenabler/test/DDSEnablerTester.hpp @@ -88,8 +88,8 @@ class DDSEnablerTester : public ::testing::Test .type_notification = test_type_notification_callback, .topic_notification = test_topic_notification_callback, .data_notification = test_data_notification_callback, - .type_request = test_type_request_callback, - .topic_request = test_topic_request_callback + .type_query = test_type_query_callback, + .topic_query = test_topic_query_callback } }; @@ -259,7 +259,7 @@ class DDSEnablerTester : public ::testing::Test return true; } - // eprosima::ddsenabler::participants::DdsDataNotification data_callback; + // eprosima::ddsenabler::participants::DdsDataNotification data_notification; static void test_data_notification_callback( const char* topic_name, const char* json, @@ -275,7 +275,7 @@ class DDSEnablerTester : public ::testing::Test } } - // eprosima::ddsenabler::participants::DdsTypeNotification data_callback; + // eprosima::ddsenabler::participants::DdsTypeNotification type_notification; static void test_type_notification_callback( const char* type_name, const char* serialized_type, @@ -293,7 +293,7 @@ class DDSEnablerTester : public ::testing::Test } } - // eprosima::ddsenabler::participants::DdsTopicNotification topic_callback; + // eprosima::ddsenabler::participants::DdsTopicNotification topic_notification static void test_topic_notification_callback( const char* topic_name, const char* type_name, @@ -309,8 +309,8 @@ class DDSEnablerTester : public ::testing::Test } } - // eprosima::ddsenabler::participants::DdsTopicRequest topic_req_callback; - static bool test_topic_request_callback( + // eprosima::ddsenabler::participants::DdsTopicQuery topic_query; + static bool test_topic_query_callback( const char* topic_name, std::string& type_name, std::string& serialized_qos) @@ -318,8 +318,8 @@ class DDSEnablerTester : public ::testing::Test return true; } - // eprosima::ddsenabler::participants::DdsTypeRequest type_req_callback; - static bool test_type_request_callback( + // eprosima::ddsenabler::participants::DdsTypeQuery type_query; + static bool test_type_query_callback( const char* type_name, std::unique_ptr& serialized_type_internal, uint32_t& serialized_type_internal_size) diff --git a/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp b/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp index 68b990a8..63ac3db5 100644 --- a/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp +++ b/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp @@ -26,7 +26,7 @@ static uint32_t data_callback_count = 0; // Empty callbacks just to create the enabler being tested -// eprosima::ddsenabler::participants::DdsDataNotification data_callback; +// eprosima::ddsenabler::participants::DdsDataNotification data_notification; void test_data_notification_callback( const char* topic_name, const char* json, @@ -34,7 +34,7 @@ void test_data_notification_callback( { } -// eprosima::ddsenabler::participants::DdsTypeNotification data_callback; +// eprosima::ddsenabler::participants::DdsTypeNotification type_notification; void test_type_notification_callback( const char* type_name, const char* serialized_type, @@ -44,7 +44,7 @@ void test_type_notification_callback( { } -// eprosima::ddsenabler::participants::DdsTopicNotification topic_callback; +// eprosima::ddsenabler::participants::DdsTopicNotification topic_notification; void test_topic_notification_callback( const char* topic_name, const char* type_name, @@ -52,8 +52,8 @@ void test_topic_notification_callback( { } -// eprosima::ddsenabler::participants::DdsTopicRequest topic_req_callback; -bool test_topic_request_callback( +// eprosima::ddsenabler::participants::DdsTopicQuery topic_query; +bool test_topic_query_callback( const char* topic_name, std::string& type_name, std::string& serialized_qos) @@ -61,8 +61,8 @@ bool test_topic_request_callback( return true; } -// eprosima::ddsenabler::participants::DdsTypeRequest type_req_callback; -bool test_type_request_callback( +// eprosima::ddsenabler::participants::DdsTypeQuery type_query; +bool test_type_query_callback( const char* type_name, std::unique_ptr& serialized_type_internal, uint32_t& serialized_type_internal_size) @@ -201,8 +201,8 @@ TEST(ReloadConfig, json) .type_notification = test_type_notification_callback, .topic_notification = test_topic_notification_callback, .data_notification = test_data_notification_callback, - .type_request = test_type_request_callback, - .topic_request = test_topic_request_callback + .type_query = test_type_query_callback, + .topic_query = test_topic_query_callback } }; @@ -243,8 +243,8 @@ TEST(ReloadConfig, yaml) .type_notification = test_type_notification_callback, .topic_notification = test_topic_notification_callback, .data_notification = test_data_notification_callback, - .type_request = test_type_request_callback, - .topic_request = test_topic_request_callback + .type_query = test_type_query_callback, + .topic_query = test_topic_query_callback } }; diff --git a/ddsenabler_participants/include/ddsenabler_participants/CBCallbacks.hpp b/ddsenabler_participants/include/ddsenabler_participants/CBCallbacks.hpp index 4870c655..50d19aaf 100644 --- a/ddsenabler_participants/include/ddsenabler_participants/CBCallbacks.hpp +++ b/ddsenabler_participants/include/ddsenabler_participants/CBCallbacks.hpp @@ -63,17 +63,17 @@ typedef void (* DdsDataNotification)( int64_t publish_time); /** - * DdsTopicRequest - callback for requesting information (type and QoS) of a DDS topic + * DdsTopicQuery - callback for requesting information (type and QoS) of a DDS topic */ -typedef bool (* DdsTopicRequest)( +typedef bool (* DdsTopicQuery)( const char* topic_name, std::string& type_name, std::string& serialized_qos); /** - * DdsTypeRequest - callback for requesting information (serialized description and size) of a DDS type + * DdsTypeQuery - callback for requesting information (serialized description and size) of a DDS type */ -typedef bool (* DdsTypeRequest)( +typedef bool (* DdsTypeQuery)( const char* type_name, std::unique_ptr& serialized_type_internal, uint32_t& serialized_type_internal_size); diff --git a/ddsenabler_participants/include/ddsenabler_participants/CBHandler.hpp b/ddsenabler_participants/include/ddsenabler_participants/CBHandler.hpp index 4b020fc8..e47d6d86 100644 --- a/ddsenabler_participants/include/ddsenabler_participants/CBHandler.hpp +++ b/ddsenabler_participants/include/ddsenabler_participants/CBHandler.hpp @@ -182,15 +182,15 @@ class CBHandler : public ddspipe::participants::ISchemaHandler } /** - * @brief Set the type request callback. + * @brief Set the type query callback. * * @param [in] callback Callback to be set. */ DDSENABLER_PARTICIPANTS_DllAPI - void set_type_request_callback( - participants::DdsTypeRequest callback) + void set_type_query_callback( + participants::DdsTypeQuery callback) { - type_req_callback_ = callback; + type_query_callback_ = callback; } protected: @@ -285,7 +285,7 @@ class CBHandler : public ddspipe::participants::ISchemaHandler std::mutex mtx_; //! Callback to request types from the user - DdsTypeRequest type_req_callback_; + DdsTypeQuery type_query_callback_; }; } /* namespace participants */ diff --git a/ddsenabler_participants/include/ddsenabler_participants/EnablerParticipant.hpp b/ddsenabler_participants/include/ddsenabler_participants/EnablerParticipant.hpp index fd31d994..4eed52ef 100644 --- a/ddsenabler_participants/include/ddsenabler_participants/EnablerParticipant.hpp +++ b/ddsenabler_participants/include/ddsenabler_participants/EnablerParticipant.hpp @@ -54,10 +54,10 @@ class EnablerParticipant : public ddspipe::participants::SchemaParticipant const std::string& json); DDSENABLER_PARTICIPANTS_DllAPI - void set_topic_request_callback( - participants::DdsTopicRequest callback) + void set_topic_query_callback( + participants::DdsTopicQuery callback) { - topic_req_callback_ = callback; + topic_query_callback_ = callback; } protected: @@ -75,7 +75,7 @@ class EnablerParticipant : public ddspipe::participants::SchemaParticipant std::condition_variable cv_; - DdsTopicRequest topic_req_callback_; + DdsTopicQuery topic_query_callback_; }; } /* namespace participants */ diff --git a/ddsenabler_participants/src/cpp/CBHandler.cpp b/ddsenabler_participants/src/cpp/CBHandler.cpp index 30fed8dc..3fbe3c51 100644 --- a/ddsenabler_participants/src/cpp/CBHandler.cpp +++ b/ddsenabler_participants/src/cpp/CBHandler.cpp @@ -161,23 +161,23 @@ bool CBHandler::get_type_identifier( } } - if (!type_req_callback_) + if (!type_query_callback_) { EPROSIMA_LOG_ERROR(DDSENABLER_CB_HANDLER, - "Type request callback not set."); + "Type query callback not set."); return false; } std::unique_ptr serialized_type; uint32_t serialized_type_size; - if (!type_req_callback_(type_name.c_str(), serialized_type, serialized_type_size)) + if (!type_query_callback_(type_name.c_str(), serialized_type, serialized_type_size)) { EPROSIMA_LOG_ERROR(DDSENABLER_CB_HANDLER, - "Type request callback failed to retrieve " << type_name << " type."); + "Type query callback failed to retrieve " << type_name << " type."); return false; } - // Register the type obtained through the type request callback + // Register the type obtained through the type query callback fastdds::dds::xtypes::TypeObject type_object; if (!register_type_nts_(type_name, serialized_type.get(), serialized_type_size, type_identifier, type_object)) { @@ -187,7 +187,7 @@ bool CBHandler::get_type_identifier( } // Add to schemas map, but do not report it to the user as it is the exact same information we obtained through the - // type request callback. + // type query callback. add_schema_nts_(type_identifier, type_object, false); return true; diff --git a/ddsenabler_participants/src/cpp/EnablerParticipant.cpp b/ddsenabler_participants/src/cpp/EnablerParticipant.cpp index d54eca15..ecd0fd78 100644 --- a/ddsenabler_participants/src/cpp/EnablerParticipant.cpp +++ b/ddsenabler_participants/src/cpp/EnablerParticipant.cpp @@ -59,7 +59,7 @@ std::shared_ptr EnablerParticipant::create_reader( reader = std::make_shared(id()); auto dds_topic = dynamic_cast(topic); readers_[dds_topic] = reader; - // Only notify the discovery of topics that do not originate from a topic request callback + // Only notify the discovery of topics that do not originate from a topic query callback if (dds_topic.topic_discoverer() != this->id()) { std::static_pointer_cast(schema_handler_)->add_topic(dds_topic); @@ -80,19 +80,19 @@ bool EnablerParticipant::publish( if (nullptr == reader) { - if (!topic_req_callback_) + if (!topic_query_callback_) { EPROSIMA_LOG_ERROR(DDSENABLER_ENABLER_PARTICIPANT, "Failed to publish data in topic " << topic_name << - " : topic is unknown and topic request callback not set."); + " : topic is unknown and topic query callback not set."); return false; } std::string serialized_qos; - if (!topic_req_callback_(topic_name.c_str(), type_name, serialized_qos)) + if (!topic_query_callback_(topic_name.c_str(), type_name, serialized_qos)) { EPROSIMA_LOG_ERROR(DDSENABLER_ENABLER_PARTICIPANT, - "Failed to publish data in topic " << topic_name << " : topic request callback failed."); + "Failed to publish data in topic " << topic_name << " : topic query callback failed."); return false; } diff --git a/ddsenabler_participants/test/DdsEnablerParticipantsTest.cpp b/ddsenabler_participants/test/DdsEnablerParticipantsTest.cpp index 58f662f3..b2204c95 100644 --- a/ddsenabler_participants/test/DdsEnablerParticipantsTest.cpp +++ b/ddsenabler_participants/test/DdsEnablerParticipantsTest.cpp @@ -71,7 +71,7 @@ class CBHandlerTest : public participants::CBHandler set_data_notification_callback(test_data_notification_callback); set_type_notification_callback(test_type_notification_callback); set_topic_notification_callback(test_topic_notification_callback); - set_type_request_callback(test_type_request_callback); + set_type_query_callback(test_type_query_callback); } // Expose protected members @@ -79,8 +79,8 @@ class CBHandlerTest : public participants::CBHandler using participants::CBHandler::cb_writer_; using participants::CBHandler::unique_sequence_number_; - // eprosima::ddsenabler::participants::DdsTypeRequest type_req_callback; - static bool test_type_request_callback( + // eprosima::ddsenabler::participants::DdsTypeQuery type_query; + static bool test_type_query_callback( const char* type_name, std::unique_ptr& serialized_type_internal, uint32_t& serialized_type_internal_size) @@ -90,11 +90,11 @@ class CBHandlerTest : public participants::CBHandler return false; } - current_test_instance_->type_request_called++; + current_test_instance_->type_query_called++; return true; } - // eprosima::ddsenabler::participants::DdsDataNotification data_callback; + // eprosima::ddsenabler::participants::DdsDataNotification data_notification; static void test_data_notification_callback( const char* topic_name, const char* json, @@ -108,7 +108,7 @@ class CBHandlerTest : public participants::CBHandler current_test_instance_->data_called_++; } - // eprosima::ddsenabler::participants::DdsTypeNotification data_callback; + // eprosima::ddsenabler::participants::DdsTypeNotification type_notification; static void test_type_notification_callback( const char* type_name, const char* serialized_type, @@ -124,7 +124,7 @@ class CBHandlerTest : public participants::CBHandler current_test_instance_->type_called_++; } - // eprosima::ddsenabler::participants::DdsTopicNotification topic_callback; + // eprosima::ddsenabler::participants::DdsTopicNotification topic_notification; static void test_topic_notification_callback( const char* topic_name, const char* type_name, @@ -138,7 +138,7 @@ class CBHandlerTest : public participants::CBHandler current_test_instance_->topic_called_++; } - uint32_t type_request_called = 0; + uint32_t type_query_called = 0; uint32_t data_called_ = 0; uint32_t type_called_ = 0; uint32_t topic_called_ = 0; From cb6ea313122dcd341d22e11f3c431e00bb7bbeec Mon Sep 17 00:00:00 2001 From: Juan Lopez Fernandez Date: Wed, 4 Jun 2025 14:54:24 +0200 Subject: [PATCH 17/28] Add publish Docker tests Signed-off-by: Juan Lopez Fernandez --- ddsenabler/examples/CLIParser.hpp | 279 ++++++++++++-- ddsenabler/examples/main.cpp | 294 +++++++++++--- ddsenabler/examples/utils.hpp | 364 ++++++++++++++++++ .../src/cpp/EnablerParticipant.cpp | 7 + ddsenabler_test/compose/CMakeLists.txt | 6 +- .../scripts/execute_and_validate_listener.py | 49 ++- .../execute_and_validate_subscriber.py | 27 +- .../scripts/execute_and_validate_talker.py | 2 +- .../publish/discovered_type/compose.yml | 40 ++ .../publish/discovered_type/config.yml | 5 + .../publish/discovered_type/samples/1 | 3 + .../publish/discovered_type/samples/2 | 3 + .../publish/discovered_type/samples/3 | 3 + .../publish/discovered_type/samples/4 | 3 + .../publish/discovered_type/samples/5 | 3 + .../publish/requested_type/compose.yml | 35 ++ .../publish/requested_type/config.yml | 9 + .../persistence/topics/test_topic.bin | Bin 0 -> 85 bytes .../persistence/types/Configuration.bin | Bin 0 -> 249 bytes .../publish/requested_type/samples/1 | 37 ++ .../publish/requested_type/samples/2 | 37 ++ .../publish/requested_type/samples/3 | 37 ++ .../publish/requested_type/samples/4 | 37 ++ .../publish/requested_type/samples/5 | 37 ++ .../reception/topics_json/compose.yml | 39 ++ .../{ => reception}/topics_json/config.json | 0 .../reception/topics_yaml/compose.yml | 39 ++ .../{ => reception}/topics_yaml/config.yml | 0 .../test_cases/topics_json/compose.yml | 37 -- .../test_cases/topics_yaml/compose.yml | 37 -- 30 files changed, 1282 insertions(+), 187 deletions(-) create mode 100644 ddsenabler/examples/utils.hpp create mode 100644 ddsenabler_test/compose/test_cases/publish/discovered_type/compose.yml create mode 100644 ddsenabler_test/compose/test_cases/publish/discovered_type/config.yml create mode 100644 ddsenabler_test/compose/test_cases/publish/discovered_type/samples/1 create mode 100644 ddsenabler_test/compose/test_cases/publish/discovered_type/samples/2 create mode 100644 ddsenabler_test/compose/test_cases/publish/discovered_type/samples/3 create mode 100644 ddsenabler_test/compose/test_cases/publish/discovered_type/samples/4 create mode 100644 ddsenabler_test/compose/test_cases/publish/discovered_type/samples/5 create mode 100644 ddsenabler_test/compose/test_cases/publish/requested_type/compose.yml create mode 100644 ddsenabler_test/compose/test_cases/publish/requested_type/config.yml create mode 100644 ddsenabler_test/compose/test_cases/publish/requested_type/persistence/topics/test_topic.bin create mode 100644 ddsenabler_test/compose/test_cases/publish/requested_type/persistence/types/Configuration.bin create mode 100644 ddsenabler_test/compose/test_cases/publish/requested_type/samples/1 create mode 100644 ddsenabler_test/compose/test_cases/publish/requested_type/samples/2 create mode 100644 ddsenabler_test/compose/test_cases/publish/requested_type/samples/3 create mode 100644 ddsenabler_test/compose/test_cases/publish/requested_type/samples/4 create mode 100644 ddsenabler_test/compose/test_cases/publish/requested_type/samples/5 create mode 100644 ddsenabler_test/compose/test_cases/reception/topics_json/compose.yml rename ddsenabler_test/compose/test_cases/{ => reception}/topics_json/config.json (100%) create mode 100644 ddsenabler_test/compose/test_cases/reception/topics_yaml/compose.yml rename ddsenabler_test/compose/test_cases/{ => reception}/topics_yaml/config.yml (100%) delete mode 100644 ddsenabler_test/compose/test_cases/topics_json/compose.yml delete mode 100644 ddsenabler_test/compose/test_cases/topics_yaml/compose.yml diff --git a/ddsenabler/examples/CLIParser.hpp b/ddsenabler/examples/CLIParser.hpp index 5a3a624d..a9469f4f 100644 --- a/ddsenabler/examples/CLIParser.hpp +++ b/ddsenabler/examples/CLIParser.hpp @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -28,11 +29,16 @@ class CLIParser struct example_config { - uint32_t expected_types_ = 0; - uint32_t expected_topics_ = 0; - uint32_t expected_data_ = 0; - uint32_t timeout_seconds = 30; - std::string config_file_path_ = ""; + uint32_t expected_types = 0; + uint32_t expected_topics = 0; + uint32_t expected_data = 0; + uint32_t timeout = 30; + std::string config_file_path = ""; + std::string persistence_path = ""; + std::string publish_path = ""; + std::string publish_topic = ""; + uint32_t publish_period = 500; + uint32_t publish_initial_wait = 0; }; /** @@ -45,22 +51,31 @@ class CLIParser static void print_help( uint8_t return_code) { - std::cout << - "Usage: ddsenabler_example " - << - std::endl; - std::cout << "" << - std::endl; - std::cout << "expected_types: number of types to be expected" << - std::endl; - std::cout << "expected_topics: number of topics to be expected" << - std::endl; - std::cout << "expected_data: number of data to be expected" << - std::endl; - std::cout << "timeout: time to wait before stopping the program if the data is not received" << - std::endl; - std::cout << "path/to/config/file: absolute path to the configuration file" << - std::endl; + std::cout << "Usage: ddsenabler_example [options]" << std::endl; + std::cout << "" << std::endl; + std::cout << "--config Path to the configuration file" << std::endl; + std::cout << " (Default: '')" << std::endl; + std::cout << "--expected-types Number of types expected to be received" << std::endl; + std::cout << " (Default: 0)" << std::endl; + std::cout << "--expected-topics Number of topics expected to be received" << std::endl; + std::cout << " (Default: 0)" << std::endl; + std::cout << "--expected-data Number of samples expected to be received" << std::endl; + std::cout << " (Default: 0)" << std::endl; + std::cout << "--timeout Time (seconds) to wait before stopping the" << std::endl; + std::cout << " program if expectations are not met" << std::endl; + std::cout << " (Default: 30)" << std::endl; + std::cout << "--persistence-path Path to the persistence directory" << std::endl; + std::cout << " (Default: '')" << std::endl; + std::cout << "--publish-path Path to the directory with the samples" << std::endl; + std::cout << " to be published" << std::endl; + std::cout << " (Default: '')" << std::endl; + std::cout << "--publish-topic Topic name in which samples are published" << std::endl; + std::cout << " (Default: '')" << std::endl; + std::cout << "--publish-period Data publication period in milliseconds" << std::endl; + std::cout << " (Default: 500)" << std::endl; + std::cout << "--publish-initial-wait Time (seconds) to wait before starting" << std::endl; + std::cout << " data publication" << std::endl; + std::cout << " (Default: 0)" << std::endl; std::exit(return_code); } @@ -79,23 +94,224 @@ class CLIParser { example_config config; - if (argc < 6) + if (argc < 2) { - std::cerr << "Missing entity argument" << std::endl; + std::cerr << "Configuration file path is required" << std::endl; print_help(EXIT_FAILURE); } - try + for (int i = 1; i < argc; ++i) { - config.expected_types_ = std::stoi(argv[1]); - config.expected_topics_ = std::stoi(argv[2]); - config.expected_data_ = std::stoi(argv[3]); - config.timeout_seconds = std::stoi(argv[4]); - config.config_file_path_ = argv[5]; + std::string arg = argv[i]; + + if (arg == "-h" || arg == "--help") + { + print_help(EXIT_SUCCESS); + } + else if (arg == "--config") + { + if (++i < argc) + { + config.config_file_path = argv[i]; + if (!std::filesystem::exists(config.config_file_path)) + { + std::cerr << "Invalid configuration file path: " << config.config_file_path << std::endl; + print_help(EXIT_FAILURE); + } + } + else + { + std::cerr << "Failed to parse --config argument" << std::endl; + print_help(EXIT_FAILURE); + } + } + else if (arg == "--expected-types") + { + if (++i < argc) + { + try + { + config.expected_types = static_cast(std::stoi(argv[i])); + } + catch (const std::exception& e) + { + std::cerr << "Invalid --expected-types argument " << std::string(argv[i]) << ": " << + std::string(e.what()) << std::endl; + print_help(EXIT_FAILURE); + } + } + else + { + std::cerr << "Failed to parse --expected-types argument" << std::endl; + print_help(EXIT_FAILURE); + } + } + else if (arg == "--expected-topics") + { + if (++i < argc) + { + try + { + config.expected_topics = static_cast(std::stoi(argv[i])); + } + catch (const std::exception& e) + { + std::cerr << "Invalid --expected-topics argument " << std::string(argv[i]) << ": " << + std::string(e.what()) << std::endl; + print_help(EXIT_FAILURE); + } + } + else + { + std::cerr << "Failed to parse --expected-topics argument" << std::endl; + print_help(EXIT_FAILURE); + } + } + else if (arg == "--expected-data") + { + if (++i < argc) + { + try + { + config.expected_data = static_cast(std::stoi(argv[i])); + } + catch (const std::exception& e) + { + std::cerr << "Invalid --expected-data argument " << std::string(argv[i]) << ": " << std::string( + e.what()) << std::endl; + print_help(EXIT_FAILURE); + } + } + else + { + std::cerr << "Failed to parse --expected-data argument" << std::endl; + print_help(EXIT_FAILURE); + } + } + else if (arg == "--timeout") + { + if (++i < argc) + { + try + { + config.timeout = static_cast(std::stoi(argv[i])); + } + catch (const std::exception& e) + { + std::cerr << "Invalid --timeout argument " << std::string(argv[i]) << ": " << std::string( + e.what()) << std::endl; + print_help(EXIT_FAILURE); + } + } + else + { + std::cerr << "Failed to parse --timeout argument" << std::endl; + print_help(EXIT_FAILURE); + } + } + else if (arg == "--persistence-path") + { + if (++i < argc) + { + config.persistence_path = argv[i]; + } + else + { + std::cerr << "Failed to parse --persistence-path argument" << std::endl; + print_help(EXIT_FAILURE); + } + } + else if (arg == "--publish-path") + { + if (++i < argc) + { + config.publish_path = argv[i]; + if (!std::filesystem::exists(config.publish_path) || + !std::filesystem::is_directory(config.publish_path)) + { + std::cerr << "Invalid publish path: " << config.publish_path << std::endl; + print_help(EXIT_FAILURE); + } + } + else + { + std::cerr << "Failed to parse --publish-path argument" << std::endl; + print_help(EXIT_FAILURE); + } + } + else if (arg == "--publish-topic") + { + if (++i < argc) + { + config.publish_topic = argv[i]; + } + else + { + std::cerr << "Failed to parse --publish-topic argument" << std::endl; + print_help(EXIT_FAILURE); + } + } + else if (arg == "--publish-period") + { + if (++i < argc) + { + try + { + config.publish_period = static_cast(std::stoi(argv[i])); + } + catch (const std::exception& e) + { + std::cerr << "Invalid --publish-period argument " << std::string(argv[i]) << ": " << + std::string( + e.what()) << std::endl; + print_help(EXIT_FAILURE); + } + } + else + { + std::cerr << "Failed to parse --publish-period argument" << std::endl; + print_help(EXIT_FAILURE); + } + } + else if (arg == "--publish-initial-wait") + { + if (++i < argc) + { + try + { + config.publish_initial_wait = static_cast(std::stoi(argv[i])); + } + catch (const std::exception& e) + { + std::cerr << "Invalid --publish-initial-wait argument " << std::string(argv[i]) << ": " << + std::string( + e.what()) << std::endl; + print_help(EXIT_FAILURE); + } + } + else + { + std::cerr << "Failed to parse --publish-initial-wait argument" << std::endl; + print_help(EXIT_FAILURE); + } + } + else + { + std::cerr << "Failed to parse unknown argument: " << arg << std::endl; + print_help(EXIT_FAILURE); + } } - catch (const std::exception& e) + + if (config.config_file_path.empty()) { - EPROSIMA_LOG_ERROR(CLI_PARSER, "Error parsing command line arguments: " << e.what()); + std::cerr << "Configuration file path is required" << std::endl; + print_help(EXIT_FAILURE); + } + + // Check that if publish path is set, publish topic is also set + if (!config.publish_path.empty() && config.publish_topic.empty()) + { + std::cerr << "Publish topic is required when publish path is set" << std::endl; print_help(EXIT_FAILURE); } @@ -129,4 +345,3 @@ class CLIParser } }; - diff --git a/ddsenabler/examples/main.cpp b/ddsenabler/examples/main.cpp index 6a20d9fc..c26ef504 100644 --- a/ddsenabler/examples/main.cpp +++ b/ddsenabler/examples/main.cpp @@ -17,23 +17,35 @@ * */ +#include #include +#include +#include #include +#include #include +#include #include +#include -#include "CLIParser.hpp" #include "ddsenabler/dds_enabler_runner.hpp" #include "ddsenabler/DDSEnabler.hpp" +#include "CLIParser.hpp" +#include "utils.hpp" + +CLIParser::example_config config; uint32_t received_types_ = 0; uint32_t received_topics_ = 0; uint32_t received_data_ = 0; -std::mutex type_received_mutex_; -std::mutex topic_received_mutex_; -std::mutex data_received_mutex_; +std::mutex app_mutex_; +std::condition_variable app_cv_; bool stop_app_ = false; +const std::string SAMPLES_SUBDIR = "samples"; +const std::string TYPES_SUBDIR = "types"; +const std::string TOPICS_SUBDIR = "topics"; + // Static type notification callback static void test_type_notification_callback( const char* type_name, @@ -42,24 +54,92 @@ static void test_type_notification_callback( uint32_t serialized_type_internal_size, const char* data_placeholder) { - std::lock_guard lock(type_received_mutex_); + bool notify = false; + { + std::lock_guard lock(app_mutex_); + notify = ++received_types_ >= config.expected_types; + std::cout << "Type callback received: " << type_name << ", Total types: " << + received_types_ << std::endl << serialized_type << std::endl << std::endl; + if (!config.persistence_path.empty() && + !save_type_to_file((std::filesystem::path(config.persistence_path) / TYPES_SUBDIR).string(), type_name, + serialized_type_internal, serialized_type_internal_size)) + { + std::cerr << "Failed to save type: " << type_name << std::endl; + } + } + if (notify) + { + app_cv_.notify_all(); + } +} + +// Static type query callback +static bool test_type_query_callback( + const char* type_name, + std::unique_ptr& serialized_type_internal, + uint32_t& serialized_type_internal_size) +{ + if (config.persistence_path.empty()) + { + std::cerr << "Persistence path is not set, cannot query type: " << type_name << std::endl; + return false; + } - received_types_++; - std::cout << "Type callback received: " << type_name << ", Total types: " << - received_types_ << std::endl; + // Load the type from file + if (!load_type_from_file((std::filesystem::path(config.persistence_path) / TYPES_SUBDIR).string(), type_name, + serialized_type_internal, serialized_type_internal_size)) + { + std::cerr << "Failed to load type: " << type_name << std::endl; + return false; + } + return true; } // Static topic notification callback static void test_topic_notification_callback( const char* topic_name, const char* type_name, - const char* serializedQos) + const char* serialized_qos) { - std::lock_guard lock(topic_received_mutex_); + bool notify = false; + { + std::lock_guard lock(app_mutex_); + notify = ++received_topics_ >= config.expected_topics; + std::cout << "Topic callback received: " << topic_name << " of type " << type_name << ", Total topics: " << + received_topics_ << std::endl << serialized_qos << std::endl << std::endl; + if (!config.persistence_path.empty() && + !save_topic_to_file((std::filesystem::path(config.persistence_path) / TOPICS_SUBDIR).string(), topic_name, + type_name, serialized_qos)) + { + std::cerr << "Failed to save topic: " << topic_name << std::endl; + } + } + if (notify) + { + app_cv_.notify_all(); + } +} + +// Static type query callback +static bool test_topic_query_callback( + const char* topic_name, + std::string& type_name, + std::string& serialized_qos) +{ + if (config.persistence_path.empty()) + { + std::cerr << "Persistence path is not set, cannot query topic: " << topic_name << std::endl; + return false; + } - received_topics_++; - std::cout << "Topic callback received: " << topic_name << " of type " << type_name << ", Total topics: " << - received_topics_ << std::endl; + // Load the topic from file + if (!load_topic_from_file((std::filesystem::path(config.persistence_path) / TOPICS_SUBDIR).string(), topic_name, type_name, + serialized_qos)) + { + std::cerr << "Failed to load topic: " << topic_name << std::endl; + return false; + } + return true; } // Static data notification callback @@ -68,39 +148,146 @@ static void test_data_notification_callback( const char* json, int64_t publish_time) { - std::lock_guard lock(data_received_mutex_); - - received_data_++; - std::cout << "Data callback received: " << topic_name << ", Total data: " << - received_data_ << ", data: " << json << std::endl; + bool notify = false; + { + std::lock_guard lock(app_mutex_); + notify = ++received_data_ >= config.expected_data; + std::cout << "Data callback received: " << topic_name << ", Total data: " << + received_data_ << std::endl << json << std::endl << std::endl; + if (!config.persistence_path.empty() && + !save_data_to_file((std::filesystem::path(config.persistence_path) / SAMPLES_SUBDIR).string(), topic_name, json, + publish_time)) + { + std::cerr << "Failed to save data for topic: " << topic_name << std::endl; + } + } + if (notify) + { + app_cv_.notify_all(); + } } -int get_received_types() +bool validate_received( + const CLIParser::example_config& config) { - std::lock_guard lock(type_received_mutex_); + return (received_types_ >= config.expected_types) && + (received_topics_ >= config.expected_topics) && + (received_data_ >= config.expected_data); +} - return received_types_; +bool expected_received( + const CLIParser::example_config& config) +{ + if (!config.expected_types && !config.expected_topics && !config.expected_data) + { + // No expectations set, return false to avoid immediate exit + return false; + } + return validate_received(config); } -int get_received_topics() +void init_persistence( + const std::string& persistence_path) { - std::lock_guard lock(topic_received_mutex_); + auto ensure_directory_exists = [](const std::filesystem::path& path) + { + if (!std::filesystem::exists(path) && !std::filesystem::create_directories(path)) + { + std::cerr << "Failed to create directory: " << path << std::endl; + } + }; - return received_topics_; + if (!persistence_path.empty()) + { + ensure_directory_exists(persistence_path); + std::vector subdirs = {SAMPLES_SUBDIR, TYPES_SUBDIR, TOPICS_SUBDIR}; + for (const auto& sub : subdirs) + { + ensure_directory_exists(std::filesystem::path(persistence_path) / sub); + } + } } -int get_received_data() +void publish_routine( + std::shared_ptr enabler, + const std::string& publish_path, + const std::string& topic_name, + uint32_t publish_period, + uint32_t publish_initial_wait, + std::mutex& app_mutex, + bool& stop_app) { - std::lock_guard lock(data_received_mutex_); + // Wait a bit before starting to publish so types and topics can be discovered + std::this_thread::sleep_for(std::chrono::milliseconds(publish_initial_wait)); + + std::vector> sample_files; + for (const auto& entry : std::filesystem::directory_iterator(publish_path)) + { + if (entry.is_regular_file()) + { + std::string filename = entry.path().filename().string(); + try + { + // assumes name is just a number + sample_files.emplace_back(entry.path(), static_cast(std::stoll(filename))); + } + catch (const std::invalid_argument& e) + { + std::cerr << "Skipping non-numeric file: " << filename << std::endl; + } + } + } + + // Sort files by numeric value + std::sort(sample_files.begin(), sample_files.end(), + [](const auto& a, const auto& b) + { + return a.second < b.second; + }); + + for (const auto& [path, number] : sample_files) + { + { + std::lock_guard lock(app_mutex); + if (stop_app) + { + std::cout << "Publish routine stopped." << std::endl; + return; + } + } + std::ifstream file(path, std::ios::binary); + if (file) + { + std::string file_content((std::istreambuf_iterator(file)), std::istreambuf_iterator()); - return received_data_; + if (enabler->publish(topic_name, file_content)) + { + std::cout << "Published content from file: " << path.filename() << " in topic: " + << topic_name << std::endl; + } + else + { + std::cerr << "Failed to publish content from file: " << path.filename() << " in topic: " + << topic_name << std::endl; + } + std::this_thread::sleep_for(std::chrono::milliseconds(publish_period)); + } + else + { + std::cerr << "Failed to open file: " << path << std::endl; + } + } } void signal_handler( int signum) { std::cout << "Signal " << CLIParser::parse_signal(signum) << " received, stopping..." << std::endl; - stop_app_ = true; + { + std::lock_guard lock(app_mutex_); + stop_app_ = true; + } + app_cv_.notify_all(); } int main( @@ -109,18 +296,34 @@ int main( { using namespace eprosima::ddsenabler; - CLIParser::example_config config = CLIParser::parse_cli_options(argc, argv); + config = CLIParser::parse_cli_options(argc, argv); + + init_persistence(config.persistence_path); CallbackSet callbacks{ .dds = { .type_notification = test_type_notification_callback, .topic_notification = test_topic_notification_callback, - .data_notification = test_data_notification_callback + .data_notification = test_data_notification_callback, + .type_query = test_type_query_callback, + .topic_query = test_topic_query_callback } }; std::shared_ptr enabler; - create_dds_enabler(config.config_file_path_.c_str(), callbacks, enabler); + if (!create_dds_enabler(config.config_file_path.c_str(), callbacks, enabler)) + { + std::cerr << "Failed to create DDS Enabler with the provided configuration." << std::endl; + return EXIT_FAILURE; + } + + std::thread publish_thread; + if (!config.publish_path.empty()) + { + publish_thread = std::thread(publish_routine, + enabler, config.publish_path, config.publish_topic, config.publish_period, config.publish_initial_wait, std::ref( + app_mutex_), std::ref(stop_app_)); + } signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); @@ -129,24 +332,27 @@ int main( signal(SIGHUP, signal_handler); #endif // _WIN32 - // Loop until timeout seconds - auto end_time = std::chrono::steady_clock::now() + std::chrono::seconds(config.timeout_seconds); - while (std::chrono::steady_clock::now() < end_time) + int ret_code = EXIT_SUCCESS; { - std::this_thread::sleep_for(std::chrono::milliseconds(1000)); - if (stop_app_) + std::unique_lock lock(app_mutex_); + if (app_cv_.wait_for(lock, std::chrono::seconds(config.timeout), + [] + { + return stop_app_ || expected_received(config); + })) { - return EXIT_SUCCESS; + ret_code = EXIT_SUCCESS; } - else if (get_received_types() >= config.expected_types_ && - get_received_topics() >= config.expected_topics_ && - get_received_data() >= config.expected_data_) + else { - std::cout << "Received enough data, stopping..." << std::endl; - return EXIT_SUCCESS; + std::cerr << "Timeout reached, stopping..." << std::endl; + ret_code = validate_received(config) ? EXIT_SUCCESS : EXIT_FAILURE; } } - std::cout << "Timeout reached, stopping..." << std::endl; - return EXIT_FAILURE; + if (publish_thread.joinable()) + { + publish_thread.join(); + } + return ret_code; } diff --git a/ddsenabler/examples/utils.hpp b/ddsenabler/examples/utils.hpp new file mode 100644 index 00000000..e49c73ed --- /dev/null +++ b/ddsenabler/examples/utils.hpp @@ -0,0 +1,364 @@ +// Copyright 2025 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include + +#include + +#pragma once + +// TODO: move these methods somewhere they can be reused + +std::string safe_file_name( + const std::string& name) +{ + std::string safe_name = name; + for (auto& c : safe_name) + { + if (c == ':' || c == '/' || c == '\\') + { + c = '_'; + } + } + return safe_name; +} + +bool save_type_to_file( + const std::string& directory, + const char* type_name, + const unsigned char*& serialized_type_internal, + uint32_t serialized_type_internal_size) +{ + // Check if directory exists + if (!std::filesystem::exists(directory)) + { + std::cerr << "Directory does not exist: " << directory << std::endl; + return false; + } + + // Remove problematic characters + std::string safe_type_name = safe_file_name(type_name); + + // Construct full file path + auto file_path = std::filesystem::path(directory) / (safe_type_name + ".bin"); + + // Check if already exists, do nothing if it does + if (std::filesystem::exists(file_path)) + { + std::cout << "File already exists: " << file_path << std::endl; + return true; + } + + // Open file in binary mode + std::ofstream ofs(file_path, std::ios::binary); + if (!ofs) + { + std::cerr << "Error opening file for writing: " << file_path << std::endl; + return false; + } + + // Write the binary data + ofs.write(reinterpret_cast(serialized_type_internal), serialized_type_internal_size); + + if (!ofs.good()) + { + std::cerr << "Error writing to file: " << file_path << std::endl; + return false; + } + + ofs.close(); + return true; +} + +bool load_type_from_file( + const std::string& directory, + const char* type_name, + std::unique_ptr& serialized_type_internal, + uint32_t& serialized_type_internal_size) +{ + // Check if directory exists + if (!std::filesystem::exists(directory)) + { + std::cerr << "Directory does not exist: " << directory << std::endl; + return false; + } + + // Remove problematic characters + std::string safe_type_name = safe_file_name(type_name); + + // Construct full file path + auto file_path = std::filesystem::path(directory) / (safe_type_name + ".bin"); + + // Check if exists + if (!std::filesystem::exists(file_path)) + { + std::cerr << "File does not exist: " << file_path << std::endl; + return false; + } + + // Open file in binary mode, position at end to get size + std::ifstream ifs(file_path, std::ios::binary | std::ios::ate); + if (!ifs) + { + std::cerr << "Error opening file for reading: " << file_path << std::endl; + return false; + } + + // Get file size + std::streamsize size = ifs.tellg(); + if (size <= 0) + { + std::cerr << "File is empty or invalid: " << file_path << std::endl; + return false; + } + serialized_type_internal_size = static_cast(size); + + // Allocate memory with unique_ptr + std::unique_ptr temp_buffer(new unsigned char[serialized_type_internal_size]); + + // Read the data + ifs.seekg(0, std::ios::beg); + if (!ifs.read(reinterpret_cast(temp_buffer.get()), serialized_type_internal_size)) + { + std::cerr << "Error reading file: " << file_path << std::endl; + serialized_type_internal_size = 0; + return false; + } + + // Transfer ownership and cast to const + serialized_type_internal = std::unique_ptr(std::move(temp_buffer)); + + return true; +} + +bool save_topic_to_file( + const std::string& directory, + const char* topic_name, + const char* type_name, + const char* serialized_qos) +{ + // Check if directory exists + if (!std::filesystem::exists(directory)) + { + std::cerr << "Directory does not exist: " << directory << std::endl; + return false; + } + + // Remove problematic characters + std::string safe_topic_name = safe_file_name(topic_name); + + // Construct full file path + auto file_path = std::filesystem::path(directory) / (safe_topic_name + ".bin"); + + // Check if already exists, do nothing if it does + if (std::filesystem::exists(file_path)) + { + std::cout << "File already exists: " << file_path << std::endl; + return true; + } + + // Open file in binary mode + std::ofstream ofs(file_path, std::ios::binary); + if (!ofs) + { + std::cerr << "Error opening file for writing: " << file_path << std::endl; + return false; + } + + // Write type name + uint32_t len_type_name = static_cast(std::strlen(type_name)); + ofs.write(reinterpret_cast(&len_type_name), sizeof(len_type_name)); + ofs.write(type_name, len_type_name); + + // Write serialized QoS + uint32_t len_serialized_qos = static_cast(std::strlen(serialized_qos)); + ofs.write(reinterpret_cast(&len_serialized_qos), sizeof(len_serialized_qos)); + ofs.write(serialized_qos, len_serialized_qos); + + if (!ofs.good()) + { + std::cerr << "Error writing to file: " << file_path << std::endl; + return false; + } + + ofs.close(); + return true; +} + +bool load_topic_from_file( + const std::string& directory, + const char* topic_name, + std::string& type_name, + std::string& serialized_qos) +{ + // Check if directory exists + if (!std::filesystem::exists(directory)) + { + std::cerr << "Directory does not exist: " << directory << std::endl; + return false; + } + + // Remove problematic characters + std::string safe_topic_name = safe_file_name(topic_name); + + // Construct full file path + auto file_path = std::filesystem::path(directory) / (safe_topic_name + ".bin"); + + // Check if exists + if (!std::filesystem::exists(file_path)) + { + std::cerr << "File does not exist: " << file_path << std::endl; + return false; + } + + // Open file in binary mode + std::ifstream ifs(file_path, std::ios::binary); + if (!ifs) + { + std::cerr << "Error opening file for reading: " << file_path << std::endl; + return false; + } + + uint32_t len_type_name = 0, len_serialized_qos = 0; + + // Read type name length + ifs.read(reinterpret_cast(&len_type_name), sizeof(len_type_name)); + if (!ifs.good() || len_type_name == 0) + { + std::cerr << "Error reading type name length." << std::endl; + return false; + } + + // Read type name + std::vector type_name_buffer(len_type_name); + ifs.read(type_name_buffer.data(), len_type_name); + if (!ifs.good()) + { + std::cerr << "Error reading type name." << std::endl; + return false; + } + + // Read serialized QoS length + ifs.read(reinterpret_cast(&len_serialized_qos), sizeof(len_serialized_qos)); + if (!ifs.good() || len_serialized_qos == 0) + { + std::cerr << "Error reading serialized qos length." << std::endl; + return false; + } + + // Read serialized QoS + std::vector serialized_qos_buffer(len_serialized_qos); + ifs.read(serialized_qos_buffer.data(), len_serialized_qos); + if (!ifs.good()) + { + std::cerr << "Error reading serialized qos." << std::endl; + return false; + } + + type_name.assign(type_name_buffer.begin(), type_name_buffer.end()); + serialized_qos.assign(serialized_qos_buffer.begin(), serialized_qos_buffer.end()); + + return true; +} + +bool save_data_to_file( + const std::string& directory, + const std::string& topic_name, + const std::string& json, + int64_t publish_time) +{ + // Check if directory exists + if (!std::filesystem::exists(directory)) + { + std::cerr << "Directory does not exist: " << directory << std::endl; + return false; + } + + // Remove problematic characters + std::string safe_topic_name = safe_file_name(topic_name); + + // Construct topic folder path + auto topic_path = std::filesystem::path(directory) / safe_topic_name; + + // Create directory if it does not exist + if (!std::filesystem::exists(topic_path) && !std::filesystem::create_directories(topic_path)) + { + std::cerr << "Error creating directory: " << topic_path << std::endl; + return false; + } + + // Construct full file path + auto file_path = topic_path / std::to_string(publish_time); + + // Check if exists, fail if it does + if (std::filesystem::exists(file_path)) + { + std::cerr << "File already exists: " << file_path << std::endl; + return false; + } + + // Open file in text mode + std::ofstream ofs(file_path); + if (!ofs) + { + std::cerr << "Error opening file for writing: " << file_path << std::endl; + return false; + } + + // Check if JSON is valid + nlohmann::json full_json; + try + { + full_json = nlohmann::json::parse(json); + } + catch (const nlohmann::json::parse_error& e) + { + std::cerr << "Error parsing JSON: " << e.what() << std::endl; + return false; + } + + // Extract the DDS data + auto it = full_json.find(topic_name); + if (it == full_json.end()) + { + std::cerr << "Error: JSON does not contain data for topic: " << topic_name << std::endl; + return false; + } + nlohmann::json& json_data = (*it)["data"]; + + if (json_data.empty()) + { + std::cerr << "Error: No data found for topic: " << topic_name << std::endl; + return false; + } + + if (json_data.size() > 1) + { + std::cerr << "Warning: Multiple data entries found for topic: " << topic_name + << ". Only the first one will be written to file." << std::endl; + } + + // Write DDS data only + ofs << std::setw(4) << json_data.begin().value(); + if (!ofs.good()) + { + std::cerr << "Error writing to file: " << file_path << std::endl; + return false; + } + + ofs.close(); + return true; +} diff --git a/ddsenabler_participants/src/cpp/EnablerParticipant.cpp b/ddsenabler_participants/src/cpp/EnablerParticipant.cpp index ecd0fd78..0bb1cca2 100644 --- a/ddsenabler_participants/src/cpp/EnablerParticipant.cpp +++ b/ddsenabler_participants/src/cpp/EnablerParticipant.cpp @@ -73,6 +73,13 @@ bool EnablerParticipant::publish( const std::string& topic_name, const std::string& json) { + if (topic_name.empty()) + { + EPROSIMA_LOG_ERROR(DDSENABLER_ENABLER_PARTICIPANT, + "Failed to publish data: topic name is empty."); + return false; + } + std::unique_lock lck(mtx_); std::string type_name; diff --git a/ddsenabler_test/compose/CMakeLists.txt b/ddsenabler_test/compose/CMakeLists.txt index 9f319434..f855833b 100644 --- a/ddsenabler_test/compose/CMakeLists.txt +++ b/ddsenabler_test/compose/CMakeLists.txt @@ -14,8 +14,10 @@ # Name of files to test set(TESTS - topics_yaml - topics_json + publish/discovered_type + publish/requested_type + reception/topics_json + reception/topics_yaml ) file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test_cases DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/ddsenabler_test/compose/scripts/execute_and_validate_listener.py b/ddsenabler_test/compose/scripts/execute_and_validate_listener.py index bcc7f24c..5a628bf6 100644 --- a/ddsenabler_test/compose/scripts/execute_and_validate_listener.py +++ b/ddsenabler_test/compose/scripts/execute_and_validate_listener.py @@ -35,6 +35,12 @@ def parse_options(): description=(DESCRIPTION), usage=(USAGE) ) + parser.add_argument( + '-s', + '--samples', + type=int, + help='Samples to receive.' + ) parser.add_argument( '-t', '--timeout', @@ -72,7 +78,7 @@ def _listener_command(args): """ command = [ 'python3', - '/opt/ros/humble/lib/demo_nodes_py/listener'] + '/opt/ros/jazzy/lib/demo_nodes_py/listener'] return command @@ -112,6 +118,31 @@ def _listener_validate_duplicates(stdout_parsed, stderr_parsed): return ret +def _listener_validate( + stdout_parsed, + stderr_parsed, + samples, + duplicates_allow): + + # Check default validator + ret_code = validation.validate_default(stdout_parsed, stderr_parsed) + + if duplicates_allow != -1: + duplicated_n = len(validation.find_duplicates(stdout_parsed)) + if duplicated_n > duplicates_allow: + log.logger.error( + f'{duplicated_n} duplicated messages found. ' + f'Maximum allowed {duplicates_allow}.') + return validation.ReturnCode.NOT_VALID_MESSAGES + + if samples is not None and len(stdout_parsed) != samples: + log.logger.error(f'Number of messages received: {len(stdout_parsed)}. ' + f'Expected {samples}') + return validation.ReturnCode.NOT_VALID_MESSAGES + + return ret_code + + if __name__ == '__main__': # Parse arguments @@ -124,11 +155,13 @@ def _listener_validate_duplicates(stdout_parsed, stderr_parsed): # Prepare command command = _listener_command(args) - _listener_validate_function = None - if args.allow_duplicates: - _listener_validate_function = _listener_validate_duplicates - else: - _listener_validate_function = validation.validate_default + validate_func = (lambda stdout_parsed, stderr_parsed: ( + _listener_validate( + stdout_parsed=stdout_parsed, + stderr_parsed=stderr_parsed, + samples=args.samples, + duplicates_allow=args.allow_duplicates + ))) # Run command and validate ret_code = validation.run_and_validate( @@ -136,9 +169,9 @@ def _listener_validate_duplicates(stdout_parsed, stderr_parsed): timeout=args.timeout, delay=args.delay, parse_output_function=_listener_parse_output, - validate_output_function=_listener_validate_function, + validate_output_function=validate_func, timeout_as_error=False) - print(f'listener validator exited with code {ret_code}') + log.logger.info(f'listener validator exited with code {ret_code}') exit(ret_code.value) diff --git a/ddsenabler_test/compose/scripts/execute_and_validate_subscriber.py b/ddsenabler_test/compose/scripts/execute_and_validate_subscriber.py index e549fd3f..aac603b1 100644 --- a/ddsenabler_test/compose/scripts/execute_and_validate_subscriber.py +++ b/ddsenabler_test/compose/scripts/execute_and_validate_subscriber.py @@ -176,7 +176,7 @@ def _subscriber_validate( ret_code = validation.validate_default(stdout_parsed['messages'], stderr_parsed) if duplicates_allow != -1: - duplicated_n = len(find_duplicates(stdout_parsed['messages'])) + duplicated_n = len(validation.find_duplicates(stdout_parsed['messages'])) if duplicated_n > duplicates_allow: log.logger.error( f'{duplicated_n} duplicated messages found. ' @@ -208,31 +208,6 @@ def _subscriber_validate( return ret_code -def find_duplicates(data): - """ - Find duplicates in a list os strings. - - :param data: List of strings - :return: List of tuples with the index of the duplicated strings - """ - # TODO: add more logic so duplicated allow are only first messages - duplicates = [] - lines_seen = {} - - for idx, line in enumerate(data): - if line not in lines_seen: - lines_seen[line] = idx - else: - duplicates.append((lines_seen[line], idx)) - - if duplicates: - log.logger.info('Found duplicated messages') - else: - log.logger.debug('None duplicated messages found') - - return duplicates - - def check_transient(data): """ Check that messages go from 0 to N without gaps. diff --git a/ddsenabler_test/compose/scripts/execute_and_validate_talker.py b/ddsenabler_test/compose/scripts/execute_and_validate_talker.py index e635f295..7ef698af 100644 --- a/ddsenabler_test/compose/scripts/execute_and_validate_talker.py +++ b/ddsenabler_test/compose/scripts/execute_and_validate_talker.py @@ -67,7 +67,7 @@ def _talker_command(args): """ command = [ 'python3', - '/opt/ros/humble/lib/demo_nodes_py/talker'] + '/opt/ros/jazzy/lib/demo_nodes_py/talker'] return command diff --git a/ddsenabler_test/compose/test_cases/publish/discovered_type/compose.yml b/ddsenabler_test/compose/test_cases/publish/discovered_type/compose.yml new file mode 100644 index 00000000..667bbdfc --- /dev/null +++ b/ddsenabler_test/compose/test_cases/publish/discovered_type/compose.yml @@ -0,0 +1,40 @@ +# Test description: +# expected_types = 1 +# expected_topics = 1 +# timeout = 5 +# config_file_path_: allowed only /chatter topic +# This test case checks the DDS Enabler is able to publish data in a topic that has previously been discovered. +# The DDS Enabler is created after the listener, and before the first message is published an active wait of 2 +# seconds is introduced to let the enabler receive the topic and type information from the listener. +# It is checked that the listener receives all messages (guaranteed by reliability QoS). + +services: + + # ENABLER + ddsenabler: + image: ${DDSENABLER_COMPOSE_TEST_DOCKER_IMAGE} + container_name: ddsenabler + depends_on: + - listener # Ensure listener is ready before ddsenabler starts so it can discover the type + networks: + - std_net + volumes: + - ./config.yml:/config/config.yml + - ./samples:/samples + command: ./build/ddsenabler/examples/ddsenabler_example --config /config/config.yml --timeout 5 --expected-types 1 --expected-topics 1 --publish-path /samples --publish-topic rt/chatter --publish-period 200 --publish-initial-wait 2000 + + listener: + image: ${DDSENABLER_COMPOSE_TEST_ROS2_DOCKER_IMAGE} + container_name: listener + networks: + - std_net + environment: + - ROS_DOMAIN_ID=33 + volumes: + - ../../../scripts:/scripts + command: python3 /scripts/execute_and_validate_listener.py --timeout 5 --samples 5 + +networks: + std_net: + default: + driver: none diff --git a/ddsenabler_test/compose/test_cases/publish/discovered_type/config.yml b/ddsenabler_test/compose/test_cases/publish/discovered_type/config.yml new file mode 100644 index 00000000..29663de6 --- /dev/null +++ b/ddsenabler_test/compose/test_cases/publish/discovered_type/config.yml @@ -0,0 +1,5 @@ +dds: + domain: 33 + + allowlist: + - name: "rt/chatter" diff --git a/ddsenabler_test/compose/test_cases/publish/discovered_type/samples/1 b/ddsenabler_test/compose/test_cases/publish/discovered_type/samples/1 new file mode 100644 index 00000000..2f813e6c --- /dev/null +++ b/ddsenabler_test/compose/test_cases/publish/discovered_type/samples/1 @@ -0,0 +1,3 @@ +{ + "data": "Hello World: 1" +} diff --git a/ddsenabler_test/compose/test_cases/publish/discovered_type/samples/2 b/ddsenabler_test/compose/test_cases/publish/discovered_type/samples/2 new file mode 100644 index 00000000..35641d7f --- /dev/null +++ b/ddsenabler_test/compose/test_cases/publish/discovered_type/samples/2 @@ -0,0 +1,3 @@ +{ + "data": "Hello World: 2" +} diff --git a/ddsenabler_test/compose/test_cases/publish/discovered_type/samples/3 b/ddsenabler_test/compose/test_cases/publish/discovered_type/samples/3 new file mode 100644 index 00000000..cae03a51 --- /dev/null +++ b/ddsenabler_test/compose/test_cases/publish/discovered_type/samples/3 @@ -0,0 +1,3 @@ +{ + "data": "Hello World: 3" +} diff --git a/ddsenabler_test/compose/test_cases/publish/discovered_type/samples/4 b/ddsenabler_test/compose/test_cases/publish/discovered_type/samples/4 new file mode 100644 index 00000000..112b310d --- /dev/null +++ b/ddsenabler_test/compose/test_cases/publish/discovered_type/samples/4 @@ -0,0 +1,3 @@ +{ + "data": "Hello World: 4" +} diff --git a/ddsenabler_test/compose/test_cases/publish/discovered_type/samples/5 b/ddsenabler_test/compose/test_cases/publish/discovered_type/samples/5 new file mode 100644 index 00000000..5c53f169 --- /dev/null +++ b/ddsenabler_test/compose/test_cases/publish/discovered_type/samples/5 @@ -0,0 +1,3 @@ +{ + "data": "Hello World: 5" +} diff --git a/ddsenabler_test/compose/test_cases/publish/requested_type/compose.yml b/ddsenabler_test/compose/test_cases/publish/requested_type/compose.yml new file mode 100644 index 00000000..55dc00a7 --- /dev/null +++ b/ddsenabler_test/compose/test_cases/publish/requested_type/compose.yml @@ -0,0 +1,35 @@ +# Test description: +# This test case checks the DDS Enabler is able to publish data in an unknown topic. +# The topic and type information is requested to the user through callbacks. +# The subscriber is created after the DDS Enabler has published all data. +# It is checked that the subscriber receives all messages (guaranteed by reliability and durability QoS). + +services: + + # ENABLER + ddsenabler: + image: ${DDSENABLER_COMPOSE_TEST_DOCKER_IMAGE} + container_name: ddsenabler + networks: + - std_net + volumes: + - ./config.yml:/config/config.yml + - ./samples:/samples + - ./persistence:/persistence + command: ./build/ddsenabler/examples/ddsenabler_example --config /config/config.yml --timeout 5 --publish-path /samples --publish-topic test_topic --publish-period 200 --persistence-path /persistence + + subscriber: + image: ${DDSENABLER_COMPOSE_TEST_DOCKER_IMAGE} + container_name: subscriber + depends_on: + - ddsenabler + networks: + - std_net + volumes: + - ../../../scripts:/scripts + command: sh -c "sleep 1 && python3 /scripts/execute_and_validate_subscriber.py --exe build/fastdds_configuration_example/configuration --samples 5 --timeout 4 --args '--samples 5 --domain 33 --name test_topic --reliable --transient-local --keep-all'" + +networks: + std_net: + default: + driver: none diff --git a/ddsenabler_test/compose/test_cases/publish/requested_type/config.yml b/ddsenabler_test/compose/test_cases/publish/requested_type/config.yml new file mode 100644 index 00000000..f21cb3c3 --- /dev/null +++ b/ddsenabler_test/compose/test_cases/publish/requested_type/config.yml @@ -0,0 +1,9 @@ +dds: + domain: 33 + + topics: + - name: "test_topic" + type: "Configuration" + qos: + reliability: true + durability: true diff --git a/ddsenabler_test/compose/test_cases/publish/requested_type/persistence/topics/test_topic.bin b/ddsenabler_test/compose/test_cases/publish/requested_type/persistence/topics/test_topic.bin new file mode 100644 index 0000000000000000000000000000000000000000..b8a97d01e4d9b9a5f0906f13dd39b24a0cfa48c4 GIT binary patch literal 85 zcmd;OU|?|0&r8cpFD*(e$;{7l016bP=42)&W#(j-R9Y#N6qTlOr2u771oF%CQj3Z+ VG7GE}(h_ruQ@OHJD^pXT900p&9fkk^ literal 0 HcmV?d00001 diff --git a/ddsenabler_test/compose/test_cases/publish/requested_type/persistence/types/Configuration.bin b/ddsenabler_test/compose/test_cases/publish/requested_type/persistence/types/Configuration.bin new file mode 100644 index 0000000000000000000000000000000000000000..b289339d8299935eed1df3fbd44a3a96295655a3 GIT binary patch literal 249 zcmXv|%MOAt5G?WT-M Date: Wed, 4 Jun 2025 14:54:58 +0200 Subject: [PATCH 18/28] Compile example in CI Signed-off-by: Juan Lopez Fernandez --- .github/workflows/reusable-workflow.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/reusable-workflow.yml b/.github/workflows/reusable-workflow.yml index cabcc123..47a7964e 100644 --- a/.github/workflows/reusable-workflow.yml +++ b/.github/workflows/reusable-workflow.yml @@ -72,7 +72,7 @@ jobs: uses: eProsima/eProsima-CI/multiplatform/colcon_build_test@main with: packages_names: ${{ env.code_packages_names }} - cmake_args: -DBUILD_TESTS=ON -DCMAKE_BUILD_TYPE=${{ matrix.cmake_build_type }} + cmake_args: -DBUILD_TESTS=ON -DCMAKE_BUILD_TYPE=${{ matrix.cmake_build_type }} -DCOMPILE_EXAMPLES=ON workspace_dependencies: install ctest_args: --label-exclude "xfail" colcon_meta_file: src/.github/workflows/configurations/${{ runner.os }}/colcon.meta From 5c07ab61d71f9739fa26b2981b7b72d93fb7879e Mon Sep 17 00:00:00 2001 From: Juan Lopez Fernandez Date: Wed, 4 Jun 2025 14:55:33 +0200 Subject: [PATCH 19/28] Polish public API and export missing Dlls Signed-off-by: Juan Lopez Fernandez --- ddsenabler/include/ddsenabler/DDSEnabler.hpp | 5 ++ .../include/ddsenabler/dds_enabler_runner.hpp | 37 +++++++------ ddsenabler/src/cpp/dds_enabler_runner.cpp | 54 ++++++++++++------- 3 files changed, 60 insertions(+), 36 deletions(-) diff --git a/ddsenabler/include/ddsenabler/DDSEnabler.hpp b/ddsenabler/include/ddsenabler/DDSEnabler.hpp index dde13965..76c3a10f 100644 --- a/ddsenabler/include/ddsenabler/DDSEnabler.hpp +++ b/ddsenabler/include/ddsenabler/DDSEnabler.hpp @@ -42,6 +42,7 @@ #include #include +#include namespace eprosima { namespace ddsenabler { @@ -61,6 +62,7 @@ class DDSEnabler * @param configuration: Structure encapsulating all enabler configuration options. * @param callbacks: Set of callbacks to be used by the enabler. */ + DDSENABLER_DllAPI DDSEnabler( const yaml::EnablerConfiguration& configuration, const CallbackSet& callbacks); @@ -72,6 +74,7 @@ class DDSEnabler * * @return \c true if operation was succesful, \c false otherwise. */ + DDSENABLER_DllAPI bool set_file_watcher( const std::string& file_path); @@ -84,6 +87,7 @@ class DDSEnabler * @return \c RETCODE_NO_DATA if new allowed topics list is the same as the previous one * @return \c RETCODE_ERROR if any other error has occurred. */ + DDSENABLER_DllAPI utils::ReturnCode reload_configuration( yaml::EnablerConfiguration& new_configuration); @@ -94,6 +98,7 @@ class DDSEnabler * @param json: The JSON message to publish. * @return \c true if the message was published successfully, \c false otherwise. */ + DDSENABLER_DllAPI bool publish( const std::string& topic_name, const std::string& json); diff --git a/ddsenabler/include/ddsenabler/dds_enabler_runner.hpp b/ddsenabler/include/ddsenabler/dds_enabler_runner.hpp index 44821575..0cfd6974 100644 --- a/ddsenabler/include/ddsenabler/dds_enabler_runner.hpp +++ b/ddsenabler/include/ddsenabler/dds_enabler_runner.hpp @@ -19,33 +19,38 @@ #pragma once -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - #include #include #include +#include + namespace eprosima { namespace ddsenabler { +/** + * @brief Create a DDS Enabler instance from a configuration file path. + * + * @param configuration_path Path to the configuration file. + * @param callbacks Set of callbacks to be used by the DDS Enabler. + * @param enabler Output parameter to hold the created DDS Enabler instance. + * @return true if the DDS Enabler was created successfully, false otherwise. + */ +DDSENABLER_DllAPI bool create_dds_enabler( - const char* ddsEnablerConfigFile, + const char* configuration_path, const CallbackSet& callbacks, std::shared_ptr& enabler); - +/** + * @brief Create a DDS Enabler instance from a configuration object. + * + * @param configuration DDS Enabler configuration object. + * @param callbacks Set of callbacks to be used by the DDS Enabler. + * @param enabler Output parameter to hold the created DDS Enabler instance. + * @return true if the DDS Enabler was created successfully, false otherwise. + */ +DDSENABLER_DllAPI bool create_dds_enabler( yaml::EnablerConfiguration configuration, const CallbackSet& callbacks, diff --git a/ddsenabler/src/cpp/dds_enabler_runner.cpp b/ddsenabler/src/cpp/dds_enabler_runner.cpp index 7e9a199b..fbdce61a 100644 --- a/ddsenabler/src/cpp/dds_enabler_runner.cpp +++ b/ddsenabler/src/cpp/dds_enabler_runner.cpp @@ -19,9 +19,13 @@ #include +#include +#include #include #include +#include + #include #include @@ -32,35 +36,44 @@ namespace eprosima { namespace ddsenabler { bool create_dds_enabler( - const char* ddsEnablerConfigFile, + const char* configuration_path, const CallbackSet& callbacks, std::shared_ptr& enabler) { std::string dds_enabler_config_file = ""; - if (ddsEnablerConfigFile != NULL) + if (configuration_path != NULL) { - dds_enabler_config_file = ddsEnablerConfigFile; + dds_enabler_config_file = configuration_path; } - // Load configuration from file - eprosima::ddsenabler::yaml::EnablerConfiguration configuration(dds_enabler_config_file); - - // Create DDS Enabler instance - if (!create_dds_enabler( - configuration, - callbacks, - enabler)) + try { - EPROSIMA_LOG_ERROR(DDSENABLER_EXECUTION, - "Failed to create DDS Enabler from configuration file: " << dds_enabler_config_file); - return false; - } + // Load configuration from file + eprosima::ddsenabler::yaml::EnablerConfiguration configuration(dds_enabler_config_file); + + // Create DDS Enabler instance + if (!create_dds_enabler( + configuration, + callbacks, + enabler)) + { + EPROSIMA_LOG_ERROR(DDSENABLER_EXECUTION, + "Failed to create DDS Enabler from configuration file: " << dds_enabler_config_file); + return false; + } - // Set the file watcher to reload the configuration if the file changes - if (!enabler->set_file_watcher(dds_enabler_config_file)) + // Set the file watcher to reload the configuration if the file changes + if (!enabler->set_file_watcher(dds_enabler_config_file)) + { + EPROSIMA_LOG_ERROR(DDSENABLER_EXECUTION, + "Failed to set file watcher."); + return false; + } + } + catch (const eprosima::utils::ConfigurationException& e) { EPROSIMA_LOG_ERROR(DDSENABLER_EXECUTION, - "Failed to set file watcher."); + "Error Loading DDS Enabler Configuration. Error message:\n " << e.what()); return false; } @@ -79,8 +92,9 @@ bool create_dds_enabler( eprosima::utils::Formatter error_msg; if (!configuration.is_valid(error_msg)) { - throw eprosima::utils::ConfigurationException( - eprosima::utils::Formatter() << "Invalid configuration: " << error_msg); + EPROSIMA_LOG_ERROR(DDSENABLER_EXECUTION, + "Invalid configuration: " << error_msg); + return false; } // Logging From ea367104b7384fbab100d6b218914fa67a5d95d2 Mon Sep 17 00:00:00 2001 From: Juan Lopez Fernandez Date: Wed, 4 Jun 2025 14:56:17 +0200 Subject: [PATCH 20/28] Remove nlohmann JSON include in headers Signed-off-by: Juan Lopez Fernandez --- .../ddsenabler_participants/CBWriter.hpp | 14 ------ ddsenabler_participants/src/cpp/CBWriter.cpp | 46 ++++++++----------- 2 files changed, 20 insertions(+), 40 deletions(-) diff --git a/ddsenabler_participants/include/ddsenabler_participants/CBWriter.hpp b/ddsenabler_participants/include/ddsenabler_participants/CBWriter.hpp index 034ee0d7..b240c300 100644 --- a/ddsenabler_participants/include/ddsenabler_participants/CBWriter.hpp +++ b/ddsenabler_participants/include/ddsenabler_participants/CBWriter.hpp @@ -20,8 +20,6 @@ #include -#include - #include #include #include @@ -130,18 +128,6 @@ class CBWriter fastdds::dds::DynamicPubSubType get_pubsub_type_( const fastdds::dds::DynamicType::_ref_type& dyn_type) noexcept; - /** - * @brief Fills a JSON object with the data from a CBMessage. - * - * @param [in,out] json JSON object to be filled. - * @param [in] msg CBMessage containing the data used to fill the JSON object. - * @param [in] serialized_data Serialized data to be added to the JSON object. - */ - void fill_json_( - nlohmann::json& json, - const CBMessage& msg, - const std::string& serialized_data) noexcept; - // Callbacks to notify the CB DdsDataNotification data_notification_callback_; DdsTypeNotification type_notification_callback_; diff --git a/ddsenabler_participants/src/cpp/CBWriter.cpp b/ddsenabler_participants/src/cpp/CBWriter.cpp index 0369d9fd..5f4c6ab2 100644 --- a/ddsenabler_participants/src/cpp/CBWriter.cpp +++ b/ddsenabler_participants/src/cpp/CBWriter.cpp @@ -147,7 +147,26 @@ void CBWriter::write_data( // Fill JSON object with the data nlohmann::json json_output; - fill_json_(json_output, msg, ss_dyn_data.str()); + { + // Set id to be the source guid prefix + std::stringstream ss_source_guid_prefix; + ss_source_guid_prefix << msg.source_guid.guid_prefix(); + json_output["id"] = ss_source_guid_prefix.str(); + + // Set type to be fastdds + json_output["type"] = "fastdds"; + + // Insert type and data (to be filled below) with topic name as key + json_output[msg.topic.topic_name()] = { + {"type", msg.topic.type_name}, + {"data", nlohmann::json::object()} + }; + + // Insert data with instance handle as key + std::stringstream ss_instanceHandle; + ss_instanceHandle << msg.instanceHandle; + json_output[msg.topic.topic_name()]["data"][ss_instanceHandle.str()] = nlohmann::json::parse(ss_dyn_data.str()); + } // Notify data reception if (data_notification_callback_) @@ -199,31 +218,6 @@ fastdds::dds::DynamicPubSubType CBWriter::get_pubsub_type_( return pubsub_type; } -void CBWriter::fill_json_( - nlohmann::json& json, - const CBMessage& msg, - const std::string& serialized_data) noexcept -{ - // Set id to be the source guid prefix - std::stringstream ss_source_guid_prefix; - ss_source_guid_prefix << msg.source_guid.guid_prefix(); - json["id"] = ss_source_guid_prefix.str(); - - // Set type to be fastdds - json["type"] = "fastdds"; - - // Insert type and data (to be filled below) with topic name as key - json[msg.topic.topic_name()] = { - {"type", msg.topic.type_name}, - {"data", nlohmann::json::object()} - }; - - // Insert data with instance handle as key - std::stringstream ss_instanceHandle; - ss_instanceHandle << msg.instanceHandle; - json[msg.topic.topic_name()]["data"][ss_instanceHandle.str()] = nlohmann::json::parse(serialized_data); -} - } /* namespace participants */ } /* namespace ddsenabler */ } /* namespace eprosima */ From 4588279e08f31dd10d15320e6b17b29608d80279 Mon Sep 17 00:00:00 2001 From: Juan Lopez Fernandez Date: Wed, 4 Jun 2025 14:56:33 +0200 Subject: [PATCH 21/28] Uncrustify Signed-off-by: Juan Lopez Fernandez --- ddsenabler/examples/main.cpp | 12 +- .../DdsEnablerTypedTest.cpp | 158 +++++++++--------- 2 files changed, 87 insertions(+), 83 deletions(-) diff --git a/ddsenabler/examples/main.cpp b/ddsenabler/examples/main.cpp index c26ef504..92e153d6 100644 --- a/ddsenabler/examples/main.cpp +++ b/ddsenabler/examples/main.cpp @@ -108,7 +108,8 @@ static void test_topic_notification_callback( std::cout << "Topic callback received: " << topic_name << " of type " << type_name << ", Total topics: " << received_topics_ << std::endl << serialized_qos << std::endl << std::endl; if (!config.persistence_path.empty() && - !save_topic_to_file((std::filesystem::path(config.persistence_path) / TOPICS_SUBDIR).string(), topic_name, + !save_topic_to_file((std::filesystem::path(config.persistence_path) / TOPICS_SUBDIR).string(), + topic_name, type_name, serialized_qos)) { std::cerr << "Failed to save topic: " << topic_name << std::endl; @@ -133,7 +134,8 @@ static bool test_topic_query_callback( } // Load the topic from file - if (!load_topic_from_file((std::filesystem::path(config.persistence_path) / TOPICS_SUBDIR).string(), topic_name, type_name, + if (!load_topic_from_file((std::filesystem::path(config.persistence_path) / TOPICS_SUBDIR).string(), topic_name, + type_name, serialized_qos)) { std::cerr << "Failed to load topic: " << topic_name << std::endl; @@ -155,7 +157,8 @@ static void test_data_notification_callback( std::cout << "Data callback received: " << topic_name << ", Total data: " << received_data_ << std::endl << json << std::endl << std::endl; if (!config.persistence_path.empty() && - !save_data_to_file((std::filesystem::path(config.persistence_path) / SAMPLES_SUBDIR).string(), topic_name, json, + !save_data_to_file((std::filesystem::path(config.persistence_path) / SAMPLES_SUBDIR).string(), + topic_name, json, publish_time)) { std::cerr << "Failed to save data for topic: " << topic_name << std::endl; @@ -321,7 +324,8 @@ int main( if (!config.publish_path.empty()) { publish_thread = std::thread(publish_routine, - enabler, config.publish_path, config.publish_topic, config.publish_period, config.publish_initial_wait, std::ref( + enabler, config.publish_path, config.publish_topic, config.publish_period, + config.publish_initial_wait, std::ref( app_mutex_), std::ref(stop_app_)); } diff --git a/ddsenabler/test/ddsEnablerTypedTests/DdsEnablerTypedTest.cpp b/ddsenabler/test/ddsEnablerTypedTests/DdsEnablerTypedTest.cpp index 16f7c5ea..9daefcda 100644 --- a/ddsenabler/test/ddsEnablerTypedTests/DdsEnablerTypedTest.cpp +++ b/ddsenabler/test/ddsEnablerTypedTests/DdsEnablerTypedTest.cpp @@ -662,102 +662,102 @@ DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_MutableWCharStruct, Mutable DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_InnerStructOptional, InnerStructOptionalPubSubType); /* DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_array_short_align_1_optional, array_short_align_1_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_array_short_align_2_optional, + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_array_short_align_2_optional, array_short_align_2_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_array_short_align_4_optional, + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_array_short_align_4_optional, array_short_align_4_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_array_short_optional, array_short_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_boolean_align_1_optional, boolean_align_1_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_boolean_align_2_optional, boolean_align_2_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_boolean_align_4_optional, boolean_align_4_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_boolean_optional, boolean_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_char_align_1_optional, char_align_1_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_char_align_2_optional, char_align_2_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_char_align_4_optional, char_align_4_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_char_optional, char_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_double_align_1_optional, double_align_1_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_double_align_2_optional, double_align_2_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_double_align_4_optional, double_align_4_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_double_optional, double_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_float_align_1_optional, float_align_1_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_float_align_2_optional, float_align_2_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_float_align_4_optional, float_align_4_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_float_optional, float_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_long_align_1_optional, long_align_1_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_long_align_2_optional, long_align_2_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_long_align_4_optional, long_align_4_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_long_optional, long_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_longdouble_align_1_optional, + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_array_short_optional, array_short_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_boolean_align_1_optional, boolean_align_1_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_boolean_align_2_optional, boolean_align_2_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_boolean_align_4_optional, boolean_align_4_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_boolean_optional, boolean_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_char_align_1_optional, char_align_1_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_char_align_2_optional, char_align_2_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_char_align_4_optional, char_align_4_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_char_optional, char_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_double_align_1_optional, double_align_1_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_double_align_2_optional, double_align_2_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_double_align_4_optional, double_align_4_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_double_optional, double_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_float_align_1_optional, float_align_1_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_float_align_2_optional, float_align_2_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_float_align_4_optional, float_align_4_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_float_optional, float_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_long_align_1_optional, long_align_1_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_long_align_2_optional, long_align_2_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_long_align_4_optional, long_align_4_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_long_optional, long_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_longdouble_align_1_optional, longdouble_align_1_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_longdouble_align_2_optional, + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_longdouble_align_2_optional, longdouble_align_2_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_longdouble_align_4_optional, + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_longdouble_align_4_optional, longdouble_align_4_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_longdouble_optional, longdouble_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_longlong_align_1_optional, longlong_align_1_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_longlong_align_2_optional, longlong_align_2_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_longlong_align_4_optional, longlong_align_4_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_longlong_optional, longlong_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_map_short_align_1_optional, map_short_align_1_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_map_short_align_2_optional, map_short_align_2_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_map_short_align_4_optional, map_short_align_4_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_map_short_optional, map_short_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_octet_align_1_optional, octet_align_1_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_octet_align_2_optional, octet_align_2_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_octet_align_4_optional, octet_align_4_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_octet_optional, octet_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_opt_struct_align_1_optional, + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_longdouble_optional, longdouble_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_longlong_align_1_optional, longlong_align_1_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_longlong_align_2_optional, longlong_align_2_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_longlong_align_4_optional, longlong_align_4_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_longlong_optional, longlong_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_map_short_align_1_optional, map_short_align_1_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_map_short_align_2_optional, map_short_align_2_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_map_short_align_4_optional, map_short_align_4_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_map_short_optional, map_short_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_octet_align_1_optional, octet_align_1_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_octet_align_2_optional, octet_align_2_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_octet_align_4_optional, octet_align_4_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_octet_optional, octet_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_opt_struct_align_1_optional, opt_struct_align_1_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_opt_struct_align_2_optional, + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_opt_struct_align_2_optional, opt_struct_align_2_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_opt_struct_align_4_optional, + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_opt_struct_align_4_optional, opt_struct_align_4_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_opt_struct_optional, opt_struct_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_sequence_short_align_1_optional, + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_opt_struct_optional, opt_struct_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_sequence_short_align_1_optional, sequence_short_align_1_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_sequence_short_align_2_optional, + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_sequence_short_align_2_optional, sequence_short_align_2_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_sequence_short_align_4_optional, + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_sequence_short_align_4_optional, sequence_short_align_4_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_sequence_short_optional, sequence_short_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_short_align_1_optional, short_align_1_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_short_align_2_optional, short_align_2_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_short_align_4_optional, short_align_4_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_short_optional, short_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_string_bounded_align_1_optional, + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_sequence_short_optional, sequence_short_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_short_align_1_optional, short_align_1_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_short_align_2_optional, short_align_2_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_short_align_4_optional, short_align_4_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_short_optional, short_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_string_bounded_align_1_optional, string_bounded_align_1_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_string_bounded_align_2_optional, + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_string_bounded_align_2_optional, string_bounded_align_2_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_string_bounded_align_4_optional, + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_string_bounded_align_4_optional, string_bounded_align_4_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_string_bounded_optional, string_bounded_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_string_unbounded_align_1_optional, + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_string_bounded_optional, string_bounded_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_string_unbounded_align_1_optional, string_unbounded_align_1_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_string_unbounded_align_2_optional, + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_string_unbounded_align_2_optional, string_unbounded_align_2_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_string_unbounded_align_4_optional, + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_string_unbounded_align_4_optional, string_unbounded_align_4_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_string_unbounded_optional, string_unbounded_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_struct_align_1_optional, struct_align_1_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_struct_align_2_optional, struct_align_2_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_struct_align_4_optional, struct_align_4_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_struct_optional, struct_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_ulong_align_1_optional, ulong_align_1_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_ulong_align_2_optional, ulong_align_2_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_ulong_align_4_optional, ulong_align_4_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_ulong_optional, ulong_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_ulonglong_align_1_optional, ulonglong_align_1_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_ulonglong_align_2_optional, ulonglong_align_2_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_ulonglong_align_4_optional, ulonglong_align_4_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_ulonglong_optional, ulonglong_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_ushort_align_1_optional, ushort_align_1_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_ushort_align_2_optional, ushort_align_2_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_ushort_align_4_optional, ushort_align_4_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_ushort_optional, ushort_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_wchar_align_1_optional, wchar_align_1_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_wchar_align_2_optional, wchar_align_2_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_wchar_align_4_optional, wchar_align_4_optionalPubSubType); -DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_wchar_optional, wchar_optionalPubSubType); */ + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_string_unbounded_optional, string_unbounded_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_struct_align_1_optional, struct_align_1_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_struct_align_2_optional, struct_align_2_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_struct_align_4_optional, struct_align_4_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_struct_optional, struct_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_ulong_align_1_optional, ulong_align_1_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_ulong_align_2_optional, ulong_align_2_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_ulong_align_4_optional, ulong_align_4_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_ulong_optional, ulong_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_ulonglong_align_1_optional, ulonglong_align_1_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_ulonglong_align_2_optional, ulonglong_align_2_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_ulonglong_align_4_optional, ulonglong_align_4_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_ulonglong_optional, ulonglong_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_ushort_align_1_optional, ushort_align_1_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_ushort_align_2_optional, ushort_align_2_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_ushort_align_4_optional, ushort_align_4_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_ushort_optional, ushort_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_wchar_align_1_optional, wchar_align_1_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_wchar_align_2_optional, wchar_align_2_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_wchar_align_4_optional, wchar_align_4_optionalPubSubType); + DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_wchar_optional, wchar_optionalPubSubType); */ DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_BooleanStruct, BooleanStructPubSubType); DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_CharStruct, CharStructPubSubType); DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_DoubleStruct, DoubleStructPubSubType); From 79d9c1988767c95984030272f0aabda0bdac77cc Mon Sep 17 00:00:00 2001 From: Juan Lopez Fernandez Date: Fri, 6 Jun 2025 12:23:21 +0200 Subject: [PATCH 22/28] Add missing doxygen of public API Signed-off-by: Juan Lopez Fernandez --- ddsenabler/include/ddsenabler/CallbackSet.hpp | 12 +++++ .../include/ddsenabler/dds_enabler_runner.hpp | 12 ++--- .../ddsenabler_participants/CBCallbacks.hpp | 46 +++++++++++++++---- 3 files changed, 56 insertions(+), 14 deletions(-) diff --git a/ddsenabler/include/ddsenabler/CallbackSet.hpp b/ddsenabler/include/ddsenabler/CallbackSet.hpp index ee6af378..0f3fc0af 100644 --- a/ddsenabler/include/ddsenabler/CallbackSet.hpp +++ b/ddsenabler/include/ddsenabler/CallbackSet.hpp @@ -28,10 +28,19 @@ namespace ddsenabler { */ struct DdsCallbacks { + //! Callback for notifying the reception of DDS types participants::DdsTypeNotification type_notification{nullptr}; + + //! Callback for notifying the reception of DDS topics participants::DdsTopicNotification topic_notification{nullptr}; + + //! Callback for notifying the reception of DDS data participants::DdsDataNotification data_notification{nullptr}; + + //! Callback for requesting information of a DDS type participants::DdsTypeQuery type_query{nullptr}; + + //! Callback for requesting information of a DDS topic participants::DdsTopicQuery topic_query{nullptr}; }; @@ -40,7 +49,10 @@ struct DdsCallbacks */ struct CallbackSet { + //! Callback executed when consuming log messages participants::DdsLogFunc log{nullptr}; + + //! DDS related callbacks DdsCallbacks dds; }; diff --git a/ddsenabler/include/ddsenabler/dds_enabler_runner.hpp b/ddsenabler/include/ddsenabler/dds_enabler_runner.hpp index 0cfd6974..ea51c40a 100644 --- a/ddsenabler/include/ddsenabler/dds_enabler_runner.hpp +++ b/ddsenabler/include/ddsenabler/dds_enabler_runner.hpp @@ -32,9 +32,9 @@ namespace ddsenabler { /** * @brief Create a DDS Enabler instance from a configuration file path. * - * @param configuration_path Path to the configuration file. - * @param callbacks Set of callbacks to be used by the DDS Enabler. - * @param enabler Output parameter to hold the created DDS Enabler instance. + * @param [in] configuration_path Path to the configuration file. + * @param [in] callbacks Set of callbacks to be used by the DDS Enabler. + * @param [out] enabler Output parameter to hold the created DDS Enabler instance. * @return true if the DDS Enabler was created successfully, false otherwise. */ DDSENABLER_DllAPI @@ -45,9 +45,9 @@ bool create_dds_enabler( /** * @brief Create a DDS Enabler instance from a configuration object. * - * @param configuration DDS Enabler configuration object. - * @param callbacks Set of callbacks to be used by the DDS Enabler. - * @param enabler Output parameter to hold the created DDS Enabler instance. + * @param [in] configuration DDS Enabler configuration object. + * @param [in] callbacks Set of callbacks to be used by the DDS Enabler. + * @param [out] enabler Output parameter to hold the created DDS Enabler instance. * @return true if the DDS Enabler was created successfully, false otherwise. */ DDSENABLER_DllAPI diff --git a/ddsenabler_participants/include/ddsenabler_participants/CBCallbacks.hpp b/ddsenabler_participants/include/ddsenabler_participants/CBCallbacks.hpp index 50d19aaf..cb5dc971 100644 --- a/ddsenabler_participants/include/ddsenabler_participants/CBCallbacks.hpp +++ b/ddsenabler_participants/include/ddsenabler_participants/CBCallbacks.hpp @@ -28,6 +28,12 @@ namespace participants { /** * DdsLogFunc - callback executed when consuming log messages + * + * @param [in] file_name Name of the file where the log was generated + * @param [in] line_no Line number in the file where the log was generated + * @param [in] func_name Name of the function where the log was generated + * @param [in] category Category of the log message + * @param [in] msg Log message content */ typedef void (* DdsLogFunc)( const char* file_name, @@ -38,6 +44,12 @@ typedef void (* DdsLogFunc)( /** * DdsTypeNotification - callback for notifying the reception of DDS types + * + * @param [in] type_name Name of the received type + * @param [in] serialized_type Serialized type in IDL format + * @param [in] serialized_type_internal Serialized type in internal format + * @param [in] serialized_type_internal_size Size of the serialized type in internal format + * @param [in] data_placeholder JSON data placeholder */ typedef void (* DdsTypeNotification)( const char* type_name, @@ -48,6 +60,10 @@ typedef void (* DdsTypeNotification)( /** * DdsTopicNotification - callback for notifying the reception of DDS topics + * + * @param [in] topic_name Name of the received topic + * @param [in] type_name Name of the type associated with the topic + * @param [in] serialized_qos Serialized Quality of Service (QoS) of the topic */ typedef void (* DdsTopicNotification)( const char* topic_name, @@ -56,28 +72,42 @@ typedef void (* DdsTopicNotification)( /** * DdsDataNotification - callback for notifying the reception of DDS data + * + * @param [in] topic_name Name of the topic from which the data was received + * @param [in] json JSON representation of the data + * @param [in] publish_time Time (nanoseconds since epoch) when the data was published */ typedef void (* DdsDataNotification)( const char* topic_name, const char* json, int64_t publish_time); -/** - * DdsTopicQuery - callback for requesting information (type and QoS) of a DDS topic - */ -typedef bool (* DdsTopicQuery)( - const char* topic_name, - std::string& type_name, - std::string& serialized_qos); - /** * DdsTypeQuery - callback for requesting information (serialized description and size) of a DDS type + * + * @param [in] type_name Name of the type to query + * @param [out] serialized_type_internal Pointer to the serialized type in internal format + * @param [out] serialized_type_internal_size Size of the serialized type in internal format + * @return \c true if the type was found and the information was retrieved successfully, \c false otherwise */ typedef bool (* DdsTypeQuery)( const char* type_name, std::unique_ptr& serialized_type_internal, uint32_t& serialized_type_internal_size); +/** + * DdsTopicQuery - callback for requesting information (type and QoS) of a DDS topic + * + * @param [in] topic_name Name of the topic to query + * @param [out] type_name Name of the type associated with the topic + * @param [out] serialized_qos Serialized Quality of Service (QoS) of the topic + * @return \c true if the topic was found and the information was retrieved successfully, \c false otherwise + */ +typedef bool (* DdsTopicQuery)( + const char* topic_name, + std::string& type_name, + std::string& serialized_qos); + } /* namespace participants */ } /* namespace ddsenabler */ } /* namespace eprosima */ From 1ce12dd4b6d43a8be997bc41a17f3c644c0856b9 Mon Sep 17 00:00:00 2001 From: Juan Lopez Fernandez Date: Thu, 12 Jun 2025 10:38:36 +0200 Subject: [PATCH 23/28] Apply suggestions Signed-off-by: Juan Lopez Fernandez --- ddsenabler/examples/main.cpp | 91 ++++++++++++++----- ddsenabler/project_settings.cmake | 2 +- ddsenabler/test/DDSEnablerTester.hpp | 9 +- .../test/ddsEnablerTests/ReloadConfig.cpp | 4 +- .../test/ddsEnablerTypedTests/CMakeLists.txt | 1 + .../DdsEnablerTypedTest.cpp | 1 + .../ddsenabler_participants/CBWriter.hpp | 5 + .../project_settings.cmake | 2 +- .../publish/discovered_type/compose.yml | 2 +- .../publish/requested_type/compose.yml | 2 +- ddsenabler_yaml/project_settings.cmake | 2 +- .../src/cpp/EnablerConfiguration.cpp | 4 +- ddsenabler_yaml/test/DdsEnablerYamlTest.cpp | 18 +++- .../test/resources/correct_config.json | 2 +- .../test/resources/full_config.json | 2 +- 15 files changed, 108 insertions(+), 39 deletions(-) diff --git a/ddsenabler/examples/main.cpp b/ddsenabler/examples/main.cpp index 92e153d6..638f9c72 100644 --- a/ddsenabler/examples/main.cpp +++ b/ddsenabler/examples/main.cpp @@ -46,6 +46,32 @@ const std::string SAMPLES_SUBDIR = "samples"; const std::string TYPES_SUBDIR = "types"; const std::string TOPICS_SUBDIR = "topics"; +// Static log callback +void test_log_callback( + const char* file_name, + int line_no, + const char* func_name, + int category, + const char* msg) +{ + // NOTE: Default stdout logs can be disabled via configuration ("logging": {"stdout": false}) to avoid duplicated traces + + std::stringstream ss; + ss << file_name << ":" << line_no << " (" << func_name << "): " << msg << std::endl; + if (category == eprosima::utils::Log::Kind::Info) + { + std::cout << "[INFO] " << ss.str(); + } + else if (category == eprosima::utils::Log::Kind::Warning) + { + std::cerr << "[WARNING] " << ss.str(); + } + else if (category == eprosima::utils::Log::Kind::Error) + { + std::cerr << "[ERROR] " << ss.str(); + } +} + // Static type notification callback static void test_type_notification_callback( const char* type_name, @@ -211,20 +237,11 @@ void init_persistence( } } -void publish_routine( - std::shared_ptr enabler, - const std::string& publish_path, - const std::string& topic_name, - uint32_t publish_period, - uint32_t publish_initial_wait, - std::mutex& app_mutex, - bool& stop_app) +void get_sorted_files( + const std::string& directory, + std::vector>& files) { - // Wait a bit before starting to publish so types and topics can be discovered - std::this_thread::sleep_for(std::chrono::milliseconds(publish_initial_wait)); - - std::vector> sample_files; - for (const auto& entry : std::filesystem::directory_iterator(publish_path)) + for (const auto& entry : std::filesystem::directory_iterator(directory)) { if (entry.is_regular_file()) { @@ -232,7 +249,7 @@ void publish_routine( try { // assumes name is just a number - sample_files.emplace_back(entry.path(), static_cast(std::stoll(filename))); + files.emplace_back(entry.path(), static_cast(std::stoll(filename))); } catch (const std::invalid_argument& e) { @@ -242,22 +259,32 @@ void publish_routine( } // Sort files by numeric value - std::sort(sample_files.begin(), sample_files.end(), + std::sort(files.begin(), files.end(), [](const auto& a, const auto& b) { return a.second < b.second; }); +} + +void publish_routine( + std::shared_ptr enabler, + const std::string& publish_path, + const std::string& topic_name, + uint32_t publish_period, + uint32_t publish_initial_wait, + std::mutex& app_mutex, + std::condition_variable& app_cv, + bool& stop_app) +{ + // Wait a bit before starting to publish so types and topics can be discovered + std::this_thread::sleep_for(std::chrono::milliseconds(publish_initial_wait)); + + // Get collection of files to publish, sorted in increasing order by their name (assumed to be numeric) + std::vector> sample_files; + get_sorted_files(publish_path, sample_files); for (const auto& [path, number] : sample_files) { - { - std::lock_guard lock(app_mutex); - if (stop_app) - { - std::cout << "Publish routine stopped." << std::endl; - return; - } - } std::ifstream file(path, std::ios::binary); if (file) { @@ -273,12 +300,23 @@ void publish_routine( std::cerr << "Failed to publish content from file: " << path.filename() << " in topic: " << topic_name << std::endl; } - std::this_thread::sleep_for(std::chrono::milliseconds(publish_period)); } else { std::cerr << "Failed to open file: " << path << std::endl; } + + // Wait publish period or until stop signal is received + std::unique_lock lock(app_mutex); + if (app_cv.wait_for(lock, std::chrono::milliseconds(publish_period), + [&stop_app] + { + return stop_app; + })) + { + std::cout << "Publish routine stopped." << std::endl; + return; + } } } @@ -299,11 +337,14 @@ int main( { using namespace eprosima::ddsenabler; + eprosima::utils::Log::ReportFilenames(true); + config = CLIParser::parse_cli_options(argc, argv); init_persistence(config.persistence_path); CallbackSet callbacks{ + .log = test_log_callback, .dds = { .type_notification = test_type_notification_callback, .topic_notification = test_topic_notification_callback, @@ -326,7 +367,7 @@ int main( publish_thread = std::thread(publish_routine, enabler, config.publish_path, config.publish_topic, config.publish_period, config.publish_initial_wait, std::ref( - app_mutex_), std::ref(stop_app_)); + app_mutex_), std::ref(app_cv_), std::ref(stop_app_)); } signal(SIGINT, signal_handler); diff --git a/ddsenabler/project_settings.cmake b/ddsenabler/project_settings.cmake index 0b877c04..4ceaf4a9 100644 --- a/ddsenabler/project_settings.cmake +++ b/ddsenabler/project_settings.cmake @@ -50,4 +50,4 @@ set(MODULE_VERSION_FILE_PATH "../VERSION") set(MODULE_CPP_VERSION - C++20) + C++17) diff --git a/ddsenabler/test/DDSEnablerTester.hpp b/ddsenabler/test/DDSEnablerTester.hpp index 9dcbcbe9..ac36207c 100644 --- a/ddsenabler/test/DDSEnablerTester.hpp +++ b/ddsenabler/test/DDSEnablerTester.hpp @@ -123,10 +123,13 @@ class DDSEnablerTester : public ::testing::Test } CallbackSet callbacks{ + .log = test_log_callback, .dds = { .type_notification = test_type_notification_callback, .topic_notification = test_topic_notification_callback, - .data_notification = test_data_notification_callback + .data_notification = test_data_notification_callback, + .type_query = test_type_query_callback, + .topic_query = test_topic_query_callback } }; @@ -315,7 +318,7 @@ class DDSEnablerTester : public ::testing::Test std::string& type_name, std::string& serialized_qos) { - return true; + return false; } // eprosima::ddsenabler::participants::DdsTypeQuery type_query; @@ -324,7 +327,7 @@ class DDSEnablerTester : public ::testing::Test std::unique_ptr& serialized_type_internal, uint32_t& serialized_type_internal_size) { - return true; + return false; } //eprosima::ddsenabler::participants::DdsLogFunc log_callback; diff --git a/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp b/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp index 63ac3db5..76b82e84 100644 --- a/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp +++ b/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp @@ -58,7 +58,7 @@ bool test_topic_query_callback( std::string& type_name, std::string& serialized_qos) { - return true; + return false; } // eprosima::ddsenabler::participants::DdsTypeQuery type_query; @@ -67,7 +67,7 @@ bool test_type_query_callback( std::unique_ptr& serialized_type_internal, uint32_t& serialized_type_internal_size) { - return true; + return false; } //eprosima::ddsenabler::participants::DdsLogFunc log_callback; diff --git a/ddsenabler/test/ddsEnablerTypedTests/CMakeLists.txt b/ddsenabler/test/ddsEnablerTypedTests/CMakeLists.txt index e6cee2df..0de57b01 100644 --- a/ddsenabler/test/ddsEnablerTypedTests/CMakeLists.txt +++ b/ddsenabler/test/ddsEnablerTypedTests/CMakeLists.txt @@ -469,6 +469,7 @@ set(TEST_LIST ddsenabler_send_samples_MutableUnionStruct ddsenabler_send_samples_MutableWCharStruct ddsenabler_send_samples_InnerStructOptional + # TODO: comment out when optionals are supported # ddsenabler_send_samples_array_short_align_1_optional # ddsenabler_send_samples_array_short_align_2_optional # ddsenabler_send_samples_array_short_align_4_optional diff --git a/ddsenabler/test/ddsEnablerTypedTests/DdsEnablerTypedTest.cpp b/ddsenabler/test/ddsEnablerTypedTests/DdsEnablerTypedTest.cpp index 9daefcda..01aa630a 100644 --- a/ddsenabler/test/ddsEnablerTypedTests/DdsEnablerTypedTest.cpp +++ b/ddsenabler/test/ddsEnablerTypedTests/DdsEnablerTypedTest.cpp @@ -660,6 +660,7 @@ DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_MutableUShortStruct, Mutabl DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_MutableUnionStruct, MutableUnionStructPubSubType); DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_MutableWCharStruct, MutableWCharStructPubSubType); DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_InnerStructOptional, InnerStructOptionalPubSubType); +// TODO: comment out when optionals are supported /* DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_array_short_align_1_optional, array_short_align_1_optionalPubSubType); DEFINE_DDSENABLER_TYPED_TEST(ddsenabler_send_samples_array_short_align_2_optional, diff --git a/ddsenabler_participants/include/ddsenabler_participants/CBWriter.hpp b/ddsenabler_participants/include/ddsenabler_participants/CBWriter.hpp index b240c300..6456f6c2 100644 --- a/ddsenabler_participants/include/ddsenabler_participants/CBWriter.hpp +++ b/ddsenabler_participants/include/ddsenabler_participants/CBWriter.hpp @@ -33,6 +33,11 @@ namespace eprosima { namespace ddsenabler { namespace participants { +/** + * @brief Helper class encapsulating the logic to write data, topics and schemas to the CB. + * + * @warning This class is not thread-safe. + */ class CBWriter { diff --git a/ddsenabler_participants/project_settings.cmake b/ddsenabler_participants/project_settings.cmake index d2f12e6b..c10c5c82 100644 --- a/ddsenabler_participants/project_settings.cmake +++ b/ddsenabler_participants/project_settings.cmake @@ -44,4 +44,4 @@ set(MODULE_THIRDPARTY_PATH "../thirdparty") set(MODULE_CPP_VERSION - C++20) + C++17) diff --git a/ddsenabler_test/compose/test_cases/publish/discovered_type/compose.yml b/ddsenabler_test/compose/test_cases/publish/discovered_type/compose.yml index 667bbdfc..4e6a437f 100644 --- a/ddsenabler_test/compose/test_cases/publish/discovered_type/compose.yml +++ b/ddsenabler_test/compose/test_cases/publish/discovered_type/compose.yml @@ -6,7 +6,7 @@ # This test case checks the DDS Enabler is able to publish data in a topic that has previously been discovered. # The DDS Enabler is created after the listener, and before the first message is published an active wait of 2 # seconds is introduced to let the enabler receive the topic and type information from the listener. -# It is checked that the listener receives all messages (guaranteed by reliability QoS). +# It is checked that the listener receives all messages (guaranteed by reliable reliability QoS, which is ROS 2 default). services: diff --git a/ddsenabler_test/compose/test_cases/publish/requested_type/compose.yml b/ddsenabler_test/compose/test_cases/publish/requested_type/compose.yml index 55dc00a7..ef716078 100644 --- a/ddsenabler_test/compose/test_cases/publish/requested_type/compose.yml +++ b/ddsenabler_test/compose/test_cases/publish/requested_type/compose.yml @@ -2,7 +2,7 @@ # This test case checks the DDS Enabler is able to publish data in an unknown topic. # The topic and type information is requested to the user through callbacks. # The subscriber is created after the DDS Enabler has published all data. -# It is checked that the subscriber receives all messages (guaranteed by reliability and durability QoS). +# It is checked that the subscriber receives all messages (guaranteed by reliable reliability and transient local durability QoS). services: diff --git a/ddsenabler_yaml/project_settings.cmake b/ddsenabler_yaml/project_settings.cmake index f92f2699..bb1275dc 100644 --- a/ddsenabler_yaml/project_settings.cmake +++ b/ddsenabler_yaml/project_settings.cmake @@ -44,4 +44,4 @@ set(MODULE_THIRDPARTY_PATH "../thirdparty") set(MODULE_CPP_VERSION - C++20) + C++17) diff --git a/ddsenabler_yaml/src/cpp/EnablerConfiguration.cpp b/ddsenabler_yaml/src/cpp/EnablerConfiguration.cpp index f8193f12..bbd5d3f9 100644 --- a/ddsenabler_yaml/src/cpp/EnablerConfiguration.cpp +++ b/ddsenabler_yaml/src/cpp/EnablerConfiguration.cpp @@ -224,7 +224,9 @@ void EnablerConfiguration::load_ddsenabler_configuration_( // Enable manually after all callbacks are set to avoid missing notifications ddspipe_configuration.init_enabled = false; - // NOTE: Trigger discovery also with readers to enable publish feature in their associated topics + // Trigger discovery also with readers in order to enable the publish feature in their associated topics + // NOTE: discovering a reader is not a requirement for the publish feature, as the related type and topic can be + // requested to the user if the corresponding callbacks are set. ddspipe_configuration.discovery_trigger = DiscoveryTrigger::ANY; } catch (const std::exception& e) diff --git a/ddsenabler_yaml/test/DdsEnablerYamlTest.cpp b/ddsenabler_yaml/test/DdsEnablerYamlTest.cpp index 9f5e26f7..d8cd522a 100644 --- a/ddsenabler_yaml/test/DdsEnablerYamlTest.cpp +++ b/ddsenabler_yaml/test/DdsEnablerYamlTest.cpp @@ -29,9 +29,10 @@ TEST(DdsEnablerYamlTest, get_ddsenabler_correct_configuration_yaml) const char* yml_str = R"( dds: - domain: 0 + domain: 4 ddsenabler: + initial-publish-wait: 500 specs: threads: 12 @@ -51,6 +52,9 @@ TEST(DdsEnablerYamlTest, get_ddsenabler_correct_configuration_yaml) utils::Formatter error_msg; ASSERT_TRUE(configuration.is_valid(error_msg)); + + ASSERT_EQ(configuration.simple_configuration->domain.domain_id, 4); + ASSERT_EQ(configuration.enabler_configuration->initial_publish_wait, 500); ASSERT_EQ(configuration.n_threads, 12); ASSERT_TRUE(configuration.ddspipe_configuration.log_configuration.is_valid(error_msg)); @@ -112,6 +116,9 @@ TEST(DdsEnablerYamlTest, get_ddsenabler_default_values_configuration_yaml) utils::Formatter error_msg; ASSERT_TRUE(configuration.is_valid(error_msg)); + + ASSERT_EQ(configuration.simple_configuration->domain.domain_id, 0); + ASSERT_EQ(configuration.enabler_configuration->initial_publish_wait, 0); ASSERT_EQ(configuration.n_threads, DEFAULT_N_THREADS); } @@ -133,6 +140,9 @@ TEST(DdsEnablerYamlTest, get_ddsenabler_correct_configuration_json) utils::Formatter error_msg; ASSERT_TRUE(configuration.is_valid(error_msg)); + + ASSERT_EQ(configuration.simple_configuration->domain.domain_id, 4); + ASSERT_EQ(configuration.enabler_configuration->initial_publish_wait, 500); ASSERT_EQ(configuration.n_threads, 12); ASSERT_TRUE(configuration.ddspipe_configuration.log_configuration.is_valid(error_msg)); @@ -165,6 +175,9 @@ TEST(DdsEnablerYamlTest, get_ddsenabler_default_values_configuration_json) utils::Formatter error_msg; ASSERT_TRUE(configuration.is_valid(error_msg)); + + ASSERT_EQ(configuration.simple_configuration->domain.domain_id, 0); + ASSERT_EQ(configuration.enabler_configuration->initial_publish_wait, 0); ASSERT_EQ(configuration.n_threads, DEFAULT_N_THREADS); } @@ -186,6 +199,9 @@ TEST(DdsEnablerYamlTest, get_ddsenabler_full_configuration_json) utils::Formatter error_msg; ASSERT_TRUE(configuration.is_valid(error_msg)); + + ASSERT_EQ(configuration.simple_configuration->domain.domain_id, 4); + ASSERT_EQ(configuration.enabler_configuration->initial_publish_wait, 500); ASSERT_EQ(configuration.n_threads, 12); } diff --git a/ddsenabler_yaml/test/resources/correct_config.json b/ddsenabler_yaml/test/resources/correct_config.json index 4fd8c854..ac20b8db 100644 --- a/ddsenabler_yaml/test/resources/correct_config.json +++ b/ddsenabler_yaml/test/resources/correct_config.json @@ -2,7 +2,7 @@ "dds": { "ddsmodule": { "dds": { - "domain": 0 + "domain": 4 }, "ddsenabler": { "initial-publish-wait": 500 diff --git a/ddsenabler_yaml/test/resources/full_config.json b/ddsenabler_yaml/test/resources/full_config.json index 4bdfa292..71e64565 100644 --- a/ddsenabler_yaml/test/resources/full_config.json +++ b/ddsenabler_yaml/test/resources/full_config.json @@ -2,7 +2,7 @@ "dds": { "ddsmodule": { "dds": { - "domain": 0, + "domain": 4, "allowlist": [ { "name": "*" From 71da6f2b2b133ae52aefc8b47fe15aed73558416 Mon Sep 17 00:00:00 2001 From: Juan Lopez Fernandez Date: Thu, 12 Jun 2025 11:11:34 +0200 Subject: [PATCH 24/28] Add .gitignore Signed-off-by: Juan Lopez Fernandez --- .gitignore | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..d666beed --- /dev/null +++ b/.gitignore @@ -0,0 +1,64 @@ + +### C++ ### +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +### Vim ### +# swap +[._]*.s[a-w][a-z] +[._]s[a-w][a-z] +# session +Session.vim +# temporary +.netrwhist +*~ +# auto-generated tag files +tags + +build/ +install/ +log/ + +### Visual Studio ### +.vs + +### Visual Studio Code ### +.vscode + +### Documentation ### +docs/rst/_static/css/online_eprosima_rtd_theme.css + + +### Python ### +# Precompile files +__pycache__ From 7eb18b292ec6633c6bc7e96db93bb0c92cd956c9 Mon Sep 17 00:00:00 2001 From: Juan Lopez Fernandez Date: Thu, 12 Jun 2025 14:09:42 +0200 Subject: [PATCH 25/28] Apply pending suggestion Signed-off-by: Juan Lopez Fernandez --- .../include/ddsenabler_participants/CBWriter.hpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/ddsenabler_participants/include/ddsenabler_participants/CBWriter.hpp b/ddsenabler_participants/include/ddsenabler_participants/CBWriter.hpp index 6456f6c2..c10b8596 100644 --- a/ddsenabler_participants/include/ddsenabler_participants/CBWriter.hpp +++ b/ddsenabler_participants/include/ddsenabler_participants/CBWriter.hpp @@ -103,16 +103,6 @@ class CBWriter protected: - /** - * @brief Writes the type information used in this topic the first time it is received. - * - * @param [in] msg Pointer to the data. - * @param [in] dyn_type DynamicType containing the type information required. - */ - void write_schema_( - const CBMessage& msg, - const fastdds::dds::DynamicType::_ref_type& dyn_type); - /** * @brief Returns the dyn_data of a dyn_type. * From 94a83923a469980783299ba878c3c7698c4aedf9 Mon Sep 17 00:00:00 2001 From: Juan Lopez Fernandez Date: Fri, 13 Jun 2025 10:32:12 +0200 Subject: [PATCH 26/28] Remove use of designated initializers (Windows...) Signed-off-by: Juan Lopez Fernandez --- ddsenabler/examples/main.cpp | 14 +++++----- ddsenabler/test/DDSEnablerTester.hpp | 28 +++++++++---------- .../test/ddsEnablerTests/ReloadConfig.cpp | 28 +++++++++---------- 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/ddsenabler/examples/main.cpp b/ddsenabler/examples/main.cpp index 638f9c72..9976c3f6 100644 --- a/ddsenabler/examples/main.cpp +++ b/ddsenabler/examples/main.cpp @@ -344,13 +344,13 @@ int main( init_persistence(config.persistence_path); CallbackSet callbacks{ - .log = test_log_callback, - .dds = { - .type_notification = test_type_notification_callback, - .topic_notification = test_topic_notification_callback, - .data_notification = test_data_notification_callback, - .type_query = test_type_query_callback, - .topic_query = test_topic_query_callback + test_log_callback, + { + test_type_notification_callback, + test_topic_notification_callback, + test_data_notification_callback, + test_type_query_callback, + test_topic_query_callback } }; diff --git a/ddsenabler/test/DDSEnablerTester.hpp b/ddsenabler/test/DDSEnablerTester.hpp index ac36207c..a3c65e43 100644 --- a/ddsenabler/test/DDSEnablerTester.hpp +++ b/ddsenabler/test/DDSEnablerTester.hpp @@ -83,13 +83,13 @@ class DDSEnablerTester : public ::testing::Test configuration.simple_configuration->domain = DOMAIN_; CallbackSet callbacks{ - .log = test_log_callback, - .dds = { - .type_notification = test_type_notification_callback, - .topic_notification = test_topic_notification_callback, - .data_notification = test_data_notification_callback, - .type_query = test_type_query_callback, - .topic_query = test_topic_query_callback + test_log_callback, + { + test_type_notification_callback, + test_topic_notification_callback, + test_data_notification_callback, + test_type_query_callback, + test_topic_query_callback } }; @@ -123,13 +123,13 @@ class DDSEnablerTester : public ::testing::Test } CallbackSet callbacks{ - .log = test_log_callback, - .dds = { - .type_notification = test_type_notification_callback, - .topic_notification = test_topic_notification_callback, - .data_notification = test_data_notification_callback, - .type_query = test_type_query_callback, - .topic_query = test_topic_query_callback + test_log_callback, + { + test_type_notification_callback, + test_topic_notification_callback, + test_data_notification_callback, + test_type_query_callback, + test_topic_query_callback } }; diff --git a/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp b/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp index 76b82e84..e41581d9 100644 --- a/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp +++ b/ddsenabler/test/ddsEnablerTests/ReloadConfig.cpp @@ -196,13 +196,13 @@ TEST(ReloadConfig, json) write_json_file(configfile, false); CallbackSet callbacks{ - .log = test_log_callback, - .dds = { - .type_notification = test_type_notification_callback, - .topic_notification = test_topic_notification_callback, - .data_notification = test_data_notification_callback, - .type_query = test_type_query_callback, - .topic_query = test_topic_query_callback + test_log_callback, + { + test_type_notification_callback, + test_topic_notification_callback, + test_data_notification_callback, + test_type_query_callback, + test_topic_query_callback } }; @@ -238,13 +238,13 @@ TEST(ReloadConfig, yaml) write_yaml_file(configfile, 0); CallbackSet callbacks{ - .log = test_log_callback, - .dds = { - .type_notification = test_type_notification_callback, - .topic_notification = test_topic_notification_callback, - .data_notification = test_data_notification_callback, - .type_query = test_type_query_callback, - .topic_query = test_topic_query_callback + test_log_callback, + { + test_type_notification_callback, + test_topic_notification_callback, + test_data_notification_callback, + test_type_query_callback, + test_topic_query_callback } }; From bdbf445de14689410baf53fb6f475e3b956c862d Mon Sep 17 00:00:00 2001 From: Juan Lopez Fernandez Date: Fri, 13 Jun 2025 10:48:01 +0200 Subject: [PATCH 27/28] Super NIT Signed-off-by: Juan Lopez Fernandez --- ddsenabler/src/cpp/dds_enabler_runner.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/ddsenabler/src/cpp/dds_enabler_runner.cpp b/ddsenabler/src/cpp/dds_enabler_runner.cpp index fbdce61a..aa58fd1a 100644 --- a/ddsenabler/src/cpp/dds_enabler_runner.cpp +++ b/ddsenabler/src/cpp/dds_enabler_runner.cpp @@ -85,7 +85,6 @@ bool create_dds_enabler( const CallbackSet& callbacks, std::shared_ptr& enabler) { - // Encapsulating execution in block to erase all memory correctly before closing process try { // Verify that the configuration is correct From b2ced8f6bfaceb27372e299eda7d3e50e097ab41 Mon Sep 17 00:00:00 2001 From: Juan Lopez Fernandez Date: Fri, 13 Jun 2025 11:11:02 +0200 Subject: [PATCH 28/28] Pull ROS 2 image before running tests Signed-off-by: Juan Lopez Fernandez --- .github/workflows/docker-reusable-workflow.yml | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/.github/workflows/docker-reusable-workflow.yml b/.github/workflows/docker-reusable-workflow.yml index 531eb4de..22753ac9 100644 --- a/.github/workflows/docker-reusable-workflow.yml +++ b/.github/workflows/docker-reusable-workflow.yml @@ -82,10 +82,21 @@ jobs: -t ${{ env.DDSENABLER_COMPOSE_TEST_DOCKER_IMAGE }} \ -f Dockerfile . - # Check Docker images exist - - name: Check if Docker images exist + # Check DDS Enabler Docker images exist + - name: Check if DDS Enabler Docker images exist run: | - [ -n "$(docker images -q ${{ env.DDSENABLER_COMPOSE_TEST_DOCKER_IMAGE }})" ] || echo "DDS Enabler Docker image does not exists" + [ -n "$(docker images -q ${{ env.DDSENABLER_COMPOSE_TEST_DOCKER_IMAGE }})" ] || echo "DDS Enabler Docker image does not exist" + + # Pull ROS 2 Docker image + - name: Pull ROS 2 Docker image + run: | + docker image pull \ + ${{ env.DDSENABLER_COMPOSE_TEST_ROS2_DOCKER_IMAGE }} + + # Check ROS 2 Docker images exist + - name: Check if ROS 2 Docker images exist + run: | + [ -n "$(docker images -q ${{ env.DDSENABLER_COMPOSE_TEST_ROS2_DOCKER_IMAGE }})" ] || echo "ROS 2 Docker image does not exist" - name: Download dependencies and install requirements uses: ./src/.github/actions/project_dependencies