# DDS
The OMG Data Distribution Service (DDS™) is a middleware protocol and API standard for data-centric connectivity from the Object Management Group® (OMG®) (opens new window). It integrates the components of a system together, providing low-latency data connectivity, extreme reliability, and a scalable architecture that business and mission-critical Internet of Things (IoT) applications need.
Cyclone DDS (opens new window) is a high performing, OMG-DDS standard based data sharing technology which allows system designers to create digital twins of their systems' entities to share their states, events, data-streams and messages on the network in real-time and fault-tolerant way.
# DDS to MQTT Proxy
Here we combine dds with mqtt. So DDS node can communicate with MQTT broker.

# Building
# Iceoryx
If you have no plan to use Iceoryx, just skip this step.
$ git clone https://github.com/eclipse-iceoryx/iceoryx.git
$ cd iceoryx
$ git checkout release_2.0
$ mkdir build && cd build
$ cmake -G Ninja -DCMAKE_INSTALL_PREFIX={USER_LIBRARY_PATH} ../iceoryx_meta
$ ninja
$ sudo ninja install
2
3
4
5
6
7
# CycloneDDS
$ git clone https://github.com/eclipse-cyclonedds/cyclonedds.git
$ cd cyclonedds
$ mkdir build && cd build
$ cmake -G Ninja -DCMAKE_INSTALL_PREFIX={USER_LIBRARY_PATH} -DCMAKE_PREFIX_PATH={USER_LIBRARY_PATH} -DBUILD_EXAMPLES=ON ..
$ ninja
$ sudo ninja install
2
3
4
5
6
Specify you installation path by
USER_LIBRARY_PATH
.
# DDS Proxy on NanoMQ_CLI
# Building idl-serial-code-gen
Build IDL
code generator.
$ git clone https://github.com/nanomq/idl-serial.git
$ cd idl-serial
$ mkdir build && cd build
$ cmake -G Ninja -DCMAKE_INSTALL_PREFIX={USER_LIBRARY_PATH}..
$ ninja
$ sudo ninja install
2
3
4
5
6
# Build NanoMQ with DDS Proxy
- Specify idl file path by cmake option
IDL_FILE_PATH
(default path:etc/idl/dds_type.idl
), enable DDS by-DBUILD_DDS_PROXY=ON
;
$ git clone https://github.com/emqx/nanomq.git
$ cd nanomq
$ mkdir build && cd build
$ cmake -G Ninja -DIDL_FILE_PATH={IDL_PATH} -DCMAKE_PREFIX_PATH={USER_LIBRARY_PATH} -DBUILD_DDS_PROXY=ON ..
$ ninja
$ sudo ninja install
2
3
4
5
6
- Check if
dds
client is built innanomq_cli
;
$ ./nanomq_cli/nanomq_cli
nanomq_cli { pub | sub | conn | nngproxy | nngcat | dds } [--help]
available tools:
* pub
* sub
* conn
* nngproxy
* nngcat
* dds
Copyright 2022 EMQ Edge Computing Team
2
3
4
5
6
7
8
9
10
11
12
$ ./nanomq_cli/nanomq_cli dds
nanomq_cli dds { sub | pub | proxy } [--help]
available apps:
* sub
* pub
* proxy
2
3
4
5
6
7
# Quick start
# Configuration
# Configuring DDS Proxy
# DDS subscription and MQTT publish
DDS Topic for subscribe
forward_rules.dds_to_mqtt.from_dds = "MQTTCMD/topic1"
MQTT Topic for publish
forward_rules.dds_to_mqtt.to_mqtt = "DDS/topic1"
Specify dds structure name for subscribe
forward_rules.dds_to_mqtt.struct_name = "remote_control_result_t"
# MQTT subscription and DDS publish
MQTT Topic for subscribe
forward_rules.dds_to_mqtt.from_dds = "DDSCMD/topic1"
DDS Topic for publish
forward_rules.dds_to_mqtt.to_mqtt = "MQTT/topic1"
Specify dds structure name for publish
forward_rules.dds_to_mqtt.struct_name = "remote_control_req_t"
Note: The struct_name
must be included in the IDL
file .
## Forwarding rules
forward_rules = {
## DDS to MQTT
dds_to_mqtt = {
from_dds = "MQTTCMD/topic1"
to_mqtt = "DDS/topic1"
struct_name = "remote_control_result_t"
}
## MQTT to DDS
mqtt_to_dds = {
from_mqtt = "DDSCMD/topic1"
to_dds = "MQTT/topic1"
struct_name = "remote_control_req_t"
}
}
## DDS Configuration
dds {
# # dds domain id
# # default: 0
# # Value: uint32
domain_id = 0
shared_memory = {
# # Enable shared memory transport.
# # Iceoryx is required if enable shared memory transport.
# #
# # Default: false
# # Value: boolean
enable = false
# # controls the output of the iceoryx runtime and can be set to, in order of decreasing output:
# # log level: verbose, debug, info, warn, error, fatal, off
# # Default: info
# # Value: enum
log_level = info
}
}
## MQTT client Configuration
mqtt {
connector {
# # Bridge address: host:port .
# #
# # Value: String
# # Example: mqtt-tcp://127.0.0.1:1883
# # tls+mqtt-tcp://127.0.0.1:8883
server = "mqtt-tcp://127.0.0.1:1883"
# # Protocol version of the bridge.
# #
# # Value: Enum
# # - 5: mqttv5
# # - 4: mqttv311
# # - 3: mqttv31
proto_ver = 4
# # The ClientId of a remote bridge.
# # Default random string.
# #
# # Value: String
# clientid="bridge_client"
# # Ping: interval of a downward bridge.
# #
# # Value: Duration
# # Default: 10 seconds
keepalive = 60s
# # The Clean start flag of a remote bridge.
# #
# # Value: boolean
# # Default: false
# #
# # NOTE: Some IoT platforms require clean_start
# # must be set to 'true'
clean_start = false
# # The username for a remote bridge.
# #
# # Value: String
username = username
# # The password for a remote bridge.
# #
# # Value: String
password = passwd
ssl {
# # enable ssl
# #
# # Value: true | false
enable = false
# # Ssl key password
# # String containing the user's password. Only used if the private keyfile
# # is password-protected.
# #
# # Value: String
key_password = "yourpass"
# # Ssl keyfile
# # Path of the file containing the client's private key.
# #
# # Value: File
keyfile = "/etc/certs/key.pem"
# # Ssl cert file
# # Path of the file containing the client certificate.
# #
# # Value: File
certfile = "/etc/certs/cert.pem"
# # Ssl ca cert file
# # Path of the file containing the server's root CA certificate.
# #
# # This certificate is used to identify the AWS IoT server and is publicly
# # available.
# #
# # Value: File
cacertfile = "/etc/certs/cacert.pem"
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# Running
# Iceoryx
If you don't want to start running Cyclone DDS with shared memory exchange or haven't enabled shared memory transpot layer, just skip the following steps
Create an example
iceoryx
configuration file which has a memory pool of 2^15 blocks which can store data types of 16384 bytes (+ 64 byte header = 16448 byte block):[general] version = 1 [[segment]] [[segment.mempool]] size = 16448 count = 32768
1
2
3
4
5
6
7
8Please save this file as iox_config.toml in your own directory.
Start
RouDi
iniceoryx
in a terminal.$ cd {USER_LIBRARY_PATH} $ bin/iox-roudi -c iox_config.toml
1
2
# DDS Proxy
- Start MQTT Broker
$ nanomq start
or
$ emqx start
- Start DDS Proxy
$ ./nanomq_cli dds proxy --conf nanomq_dds_gateway.conf
- Start MQTT client and subscribe topic
DDS/topic1
$ ./nanomq_cli sub --url "mqtt-tcp://127.0.0.1:1883" -t "DDS/topic1"
- Start DDS client, specify structure name
remote_control_result_t
and publish message ( JSON format ) to DDS topicMQTTCMD/topic1
$ ./nanomq_cli dds pub -t "MQTTCMD/topic1" --struct "remote_control_result_t" -m '{
"req_result_code": 1,
"req_token": [1,2,3,4,5,6],
"req_result_msg": [7,8,9,10,11],
"req_id": [12,13,14],
"req_token_len": 6,
"req_id_len": 3
}'
2
3
4
5
6
7
8
- Start DDS client to subscribe DDS topic
MQTT/topic1
and specify structure nameremote_control_req_t
$ ./nanomq_cli dds sub -t "MQTT/topic1" --struct "remote_control_req_t"
- Start MQTT client to publish message ( JSON format) to MQTT topic
DDSCMD/topic1
$ ./nanomq_cli pub --url "mqtt-tcp://127.0.0.1:1883" -t "DDSCMD/topic1" -m '{
"req": 1,
"req_id": [15,16],
"req_id_len": 2
}'
2
3
4
5