2. System Handle¶
As explained in the Introduction, a single integration-service
instance can route any number of topics or services to/from any number of middlewares.
This occurs through the use of System Handles, which are system-specific plugins that allows a certain middleware or communication protocol to speak the same language used by the Integration Service, that is, Extensible and Dynamic Topic Types for DDS (xTypes).

2.1. Built-in System Handles¶
This section provides an insight over the existing built-in System Handles provided along with Integration Service for connecting the core with the following middlewares or communication protocols:
Protocol |
System Handle overview |
---|---|
Fast DDS |
|
FIWARE |
|
ROS 1 |
|
ROS 2 |
|
WebSocket |
Additional System Handles can be implemented by users, in order to have the desired middlewares joining the Integration Service world. Adding a new System Handle automatically allows communication with the rest of the protocols already available in this ecosystem.
2.2. Implementation¶
This section provides an overview of the architecture of a System Handle, by depicting the class inheritance structure and specifying the methods which need to be implemented in order to create a custom System Handle.
Here you can find a diagram of a System Handle class inheritance structure.

Each System Handle must inherit, directly or indirectly, from the SystemHandle
superclass.
Depending on the nature of each protocol, it should implement the derived classes using multiple inheritance
from TopicSubscriberSystem
, TopicPublisherSystem
, ServiceClientSystem
,
and/or ServiceProviderSystem
.
To simplify this inheritance, classes TopicSystem
, ServiceSystem
, and FullSystem
are available to inherit from.
In the diagram below, the architecture of a generic “Full” System Handle and its integration into Integration Service is shown.

To ease the implementation, the new system::SystemHandle
will inherit from FullSystem
. The following sections will explain
the methods to be implemented.
To implement the TopicPublisher
, ServiceClient
, and ServiceProvider
interfaces, the most direct
way is to create child classes, respectively system::Publisher
, system::Client
,
and system::Server
. An additional class system::Subscriber
may be useful to manage the subscribers
created. In the example shown in the diagram above, the system::SystemHandle
will contain the needed instances of these classes, but any approach may be valid if the interfaces are met.
2.2.1. SystemHandle Class¶
All System Handles must implement the configure
, okay
, and spin_once
methods that belong to
the superclass:
bool configure(
const RequiredTypes& types,
const YAML::Node& configuration,
TypeRegistry& type_registry);
bool okay() const = 0;
bool spin_once();
The configure
method is called to setup the System Handle with the associated configuration
,
defined in the YAML file that is passed to it.
The types that the SH needs to manage to implement the communication are passed to this method via the types
argument, whereas the new types created by the System Handle are expected to be filled in the type_registry
.
The okay
method is called by Integration Service to check if the System Handle is working. This method will
verify internally if the middleware has any problem.
The spin_once
method is called by Integration Service to allow spinning to those middlewares that need it.
2.2.2. TopicSubscriberSystem Class¶
This kind of system must implement the subscribe
and the is_internal_message
method:
using SubscriptionCallback = std::function<void(const xtypes::DynamicData& message, void* filter_handle)>;
bool subscribe(
const std::string& topic_name,
const xtypes::DynamicType& message_type,
SubscriptionCallback callback,
const YAML::Node& configuration);
bool is_internal_message(
void* filter_handle);
Integration Service will call the subscribe
method in order to create a new subscriber
to the topic topic_name
using message_type
type, plus an optional configuration
.
Once the middleware system receives a message from the subscription, the message must be translated
into the message_type
and the System Handle must invoke the callback
with the translated message.
The callback
will be called only if the is_internal_message
method returns false
.
This prevents Integration Service from recursively send messages within itself, for example,
if a publisher and a subscriber are created pointing to the same topic. Users must define,
for each middleware, the type of the filter_handle parameter, and cast it accordingly.
Some protocols, such as WebSocket, might not need to filter its messages at all; in that case,
this method can be simply implemented as a return false;
clause.
2.2.3. TopicPublisherSystem Class¶
This kind of system must implement the advertise
method:
std::shared_ptr<TopicPublisher> advertise(
const std::string& topic_name,
const xtypes::DynamicType& message_type,
const YAML::Node& configuration);
Integration Service will call this method in order to create a new TopicPublisher
to the topic topic_name
using message_type
type, and optional configuration
.
The TopicPublisher
is an interface that must be implemented by a Publisher
in order to allow
Integration Service to publish messages to the target middleware.
This interface defines a single method publish
:
bool publish(const xtypes::DynamicData& message);
When Integration Service needs to publish to the middleware system it will call the
TopicPublisher::publish
method, with a message that must be translated from the
message_type
parameter by the advertise
method above.
2.2.4. ServiceClientSystem Class¶
This kind of system must implement the create_client_proxy
method:
using RequestCallback =
std::function<void(
const xtypes::DynamicData& request,
ServiceClient& client,
std::shared_ptr<void> call_handle)>;
bool create_client_proxy(
const std::string& service_name,
const xtypes::DynamicType& service_type,
RequestCallback callback,
const YAML::Node& configuration);
Integration Service will call this method in order to create a new ServiceClient
to the service service_name
using the service_type
type, plus an optional
configuration
. This ServiceClient
will be provided as an argument in the
callback
invocation when a response is received.
The ServiceClient
is an interface that must be implemented by a Client
in order to allow
Integration Service to relate a request with its reply.
This is done by providing a call_handle
both in the call_service
method from
ServiceProvider
and in the callback
from create_client_proxy
method.
When the reply is received by another System Handle, its ServiceProvider
will call the
receive_response
method from the Client
:
void receive_response(
std::shared_ptr<void> call_handle,
const xtypes::DynamicData& response);
The receive_response
:
Translates the
response
fromservice_type
and relate thecall_handle
, if needed, to its middleware’s request;Replies to its middleware.
2.2.5. ServiceProviderSystem Class¶
This kind of system must implement the create_service_proxy
method:
std::shared_ptr<ServiceProvider> create_service_proxy(
const std::string& service_name,
const xtypes::DynamicType& service_type,
const YAML::Node& configuration);
Integration Service will call this method in order to create a new ServiceProvider
to the
service service_name
using the service_type
type, plus an optional configuration
.
The ServiceProvider
is and interface that must be implemented by a Server
in order to allow Integration Service to request (or call) a service from the target middleware.
void call_service(
const xtypes::DynamicData& request,
ServiceClient& client,
std::shared_ptr<void> call_handle);
This call_service
method will translate the request
from service_type
and will call its
middleware service, which stores the related call_handle
and client
. Once it receives the response
from its middleware, it must translate back the response and retrieve the call_handle
and client
related. Then, it will invoke the receive_response
method from the client using the call_handle
as argument.
2.3. Sequence diagrams¶
The following diagrams illustrate the previous sections using a generic System Handle.
2.3.1. TopicPublisher flow¶

2.3.2. TopicSubscriber flow¶

2.3.3. ServiceClient flow¶
Note that a ServiceClient
acts as a client for Integration Service and as a server for the middleware.

2.3.4. ServiceProvider flow¶
Note that a ServiceProvider
acts as a server for Integration Service and as a client for the middleware.
