Skip to content

Commit d1cead3

Browse files
committed
Initial implementation of MQTT-SN protocol.
0 parents  commit d1cead3

10 files changed

+577
-0
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
build*
2+
.vscode
3+

CMakeLists.txt

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
cmake_minimum_required (VERSION 3.5)
2+
project ("cc.mqttsn.commsdsl")
3+
4+
# Additional variables to be used if needed
5+
# ---------------------------
6+
# OUTPUT_DIR - Path to output directory. If not provided <build_dir>/output one is used.
7+
# COMMSDSL2COMMS - Path to "commsdsl2comms" binary.
8+
# COMMSDSL2COMMS_EXTRA_ARGS - Extra arguments to pass to "commsdsl2comms"
9+
10+
set (COMMSDSL_TGT "commsdsl_tgt")
11+
if ("${COMMSDSL2COMMS}" STREQUAL "")
12+
include(ExternalProject)
13+
set (commsdsl2comms_tag "develop")
14+
set (commsdsl2comms_main_dir "${CMAKE_BINARY_DIR}/commsdsl")
15+
set (commsdsl2comms_src_dir "${commsdsl2comms_main_dir}/src")
16+
set (commsdsl2comms_bin_dir "${commsdsl2comms_main_dir}/build")
17+
set (commsdsl2comms_install_dir "${commsdsl2comms_main_dir}/install")
18+
19+
set (boost_static_libs_param)
20+
if (Boost_USE_STATIC_LIBS)
21+
set (boost_static_libs_param "-DBoost_USE_STATIC_LIBS=ON")
22+
endif()
23+
24+
ExternalProject_Add(
25+
"${COMMSDSL_TGT}"
26+
PREFIX "${commsdsl2comms_bin_dir}"
27+
STAMP_DIR "${commsdsl2comms_bin_dir}"
28+
GIT_REPOSITORY "https://github.com/arobenko/commsdsl.git"
29+
GIT_TAG "${commsdsl2comms_tag}"
30+
SOURCE_DIR "${commsdsl2comms_src_dir}"
31+
CMAKE_ARGS
32+
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX=${commsdsl2comms_install_dir}
33+
-DCOMMSDSL_NO_TESTS=ON -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
34+
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DBOOST_ROOT=${BOOST_ROOT}
35+
${boost_static_libs_param}
36+
BINARY_DIR "${commsdsl2comms_bin_dir}"
37+
)
38+
39+
set (COMMSDSL2COMMS "${commsdsl2comms_install_dir}/bin/commsdsl2comms")
40+
41+
if (UNIX)
42+
set (COMMSDSL2COMMS "${COMMSDSL2COMMS}.sh")
43+
endif ()
44+
endif ()
45+
46+
set (schema_file "${CMAKE_SOURCE_DIR}/dsl/schema.xml")
47+
set (tmp_dir "${CMAKE_BINARY_DIR}/output.tmp")
48+
set (code_input_dir "${CMAKE_SOURCE_DIR}/src")
49+
50+
if ("${OUTPUT_DIR}" STREQUAL "")
51+
set (OUTPUT_DIR "${CMAKE_BINARY_DIR}/output")
52+
endif ()
53+
54+
set (code_input_param)
55+
if (EXISTS "${code_input_dir}/")
56+
set (code_input_param "-c${code_input_dir}")
57+
endif()
58+
59+
file (GLOB_RECURSE src_files ${code_input_dir})
60+
61+
set (extra_dep)
62+
if (TARGET ${COMMSDSL_TGT})
63+
set (extra_dep ${COMMSDSL_TGT})
64+
endif ()
65+
66+
add_custom_command(
67+
OUTPUT ${tmp_dir}
68+
DEPENDS ${schema_file} ${src_files} ${extra_dep}
69+
COMMAND ${CMAKE_COMMAND} -E remove_directory ${tmp_dir}
70+
COMMAND ${COMMSDSL2COMMS} ${COMMSDSL2COMMS_EXTRA_ARGS} --warn-as-err -o ${tmp_dir} -c ${code_input_dir} ${schema_file}
71+
)
72+
73+
set (output_tgt ${name}_output_tgt)
74+
add_custom_target(${PROJECT_NAME} ALL
75+
COMMAND ${CMAKE_COMMAND}
76+
-DGENERATED="${tmp_dir}" -DOUTPUT="${OUTPUT_DIR}"
77+
-P "${CMAKE_CURRENT_LIST_DIR}/CopyGenerated.cmake"
78+
DEPENDS ${tmp_dir} "${CMAKE_CURRENT_LIST_DIR}/CopyGenerated.cmake" ${schema_file} ${code_input_dir})
79+
80+

CopyGenerated.cmake

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# GENERATED
2+
# OUTPUT
3+
4+
function (copyIfDifferent generated output)
5+
file(GLOB_RECURSE genFiles RELATIVE "${generated}/" "${generated}/*")
6+
foreach( f ${genFiles} )
7+
set(dest "${output}/${f}")
8+
set(src "${generated}/${f}")
9+
#message (STATUS "Copying ${src} -> ${dest}")
10+
execute_process(
11+
COMMAND ${CMAKE_COMMAND}
12+
-E copy_if_different ${src} ${dest})
13+
endforeach()
14+
endfunction ()
15+
16+
function (deleteRemoved generated output)
17+
file(GLOB_RECURSE genFiles RELATIVE "${generated}/" "${generated}/*")
18+
file(GLOB_RECURSE outFiles RELATIVE "${output}/" "${output}/*")
19+
cmake_policy(SET CMP0057 NEW)
20+
foreach( f ${outFiles} )
21+
if (NOT "${f}" IN_LIST genFiles)
22+
message (STATUS "Removing: ${output}/${f}")
23+
execute_process(
24+
COMMAND ${CMAKE_COMMAND} -E remove ${output}/${f})
25+
endif ()
26+
endforeach()
27+
endfunction ()
28+
29+
if (("${GENERATED}" STREQUAL "") OR ("${OUTPUT}" STREQUAL ""))
30+
message (FATAL_ERROR "Bad directory name(s)")
31+
endif ()
32+
33+
message (STATUS "Copying: ${GENERATED} --> ${OUTPUT}")
34+
copyIfDifferent ("${GENERATED}" "${OUTPUT}")
35+
deleteRemoved ("${GENERATED}" "${OUTPUT}")

dsl/schema.xml

+223
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<schema name="mqttsn"
3+
id="1"
4+
endian="big">
5+
<fields>
6+
<enum name="MsgId" type="uint8" semanticType="messageId" >
7+
<validValue name="Advertise" val="0x0" displayName="ADVERTISE" />
8+
<validValue name="Searchgw" val="0x1" displayName="SEARCHGW" />
9+
<validValue name="Gwinfo" val="0x2" displayName="GWINFO" />
10+
<validValue name="Connect" val="0x4" displayName="CONNECT" />
11+
<validValue name="Connack" val="0x5" displayName="CONNACK" />
12+
<validValue name="Willtopicreq" val="0x6" displayName="WILLTOPICREQ" />
13+
<validValue name="Willtopic" val="0x7" displayName="WILLTOPIC" />
14+
<validValue name="Willmsgreq" val="0x8" displayName="WILLMSGREQ" />
15+
<validValue name="Willmsg" val="0x9" displayName="WILLMSG" />
16+
<validValue name="Register" val="0xa" displayName="REGISTER" />
17+
<validValue name="Regack" val="0xb" displayName="REGACK" />
18+
<validValue name="Publish" val="0xc" displayName="PUBLISH" />
19+
<validValue name="Puback" val="0xd" displayName="PUBACK" />
20+
<validValue name="Pubcomp" val="0xe" displayName="PUBCOMP" />
21+
<validValue name="Pubrec" val="0xf" displayName="PUBREC" />
22+
<validValue name="Pubrel" val="0x10" displayName="PUBREL" />
23+
<validValue name="Subscribe" val="0x12" displayName="SUBSCRIBE" />
24+
<validValue name="Suback" val="0x13" displayName="SUBACK" />
25+
<validValue name="Unsubscribe" val="0x14" displayName="UNSUBSCRIBE" />
26+
<validValue name="Unsuback" val="0x15" displayName="UNSUBACK" />
27+
<validValue name="Pingreq" val="0x16" displayName="PINGREQ" />
28+
<validValue name="Pingresp" val="0x17" displayName="PINGRESP" />
29+
<validValue name="Disconnect" val="0x18" displayName="DISCONNECT" />
30+
<validValue name="Willtopicupd" val="0x1a" displayName="WILLTOPICUPD" />
31+
<validValue name="Willtopicresp" val="0x1b" displayName="WILLTOPICRESP" />
32+
<validValue name="Willmsgupd" val="0x1c" displayName="WILLMSGUPD" />
33+
<validValue name="Willmsgresp" val="0x1d" displayName="WILLMSGRESP" />
34+
</enum>
35+
<bundle name="MsgLengthField" displayName="Length">
36+
<int name="short" type="uint8" serOffset="1" displayOffset="1"/>
37+
<optional name="long">
38+
<field>
39+
<int name="long" type="uint16" serOffset="3" displayOffset="3"/>
40+
</field>
41+
<cond value="$short = 0" />
42+
</optional>
43+
</bundle>
44+
<int name="GwId" type="uint8" />
45+
<int name="Duration" type="uint16" units="seconds" />
46+
<int name="Radius" type="uint8">
47+
<special name="BroadcastToAll" val="0" />
48+
</int>
49+
<data name="GwAdd" />
50+
<enum name="QoS" type="uint8">
51+
<validValue name="AtMostOnceDelivery" val="0" />
52+
<validValue name="AtLeastOnceDelivery" val="1" />
53+
<validValue name="ExactlyOnceDelivery" val="2" />
54+
</enum>
55+
<bitfield name="Flags">
56+
<enum name="TopicIdType" type="uint8" bitLength="2">
57+
<validValue name="NormalTopicId" val="0" />
58+
<validValue name="PredefinedTopicId" val="1" />
59+
<validValue name="TopicName" val="2" />
60+
</enum>
61+
<set name="mid" bitLength="3" displayName="_">
62+
<bit name="CleanSession" idx="0" />
63+
<bit name="Will" idx="1" />
64+
<bit name="Retain" idx="2" />
65+
</set>
66+
<enum name="QoS" reuse="QoS" bitLength="2" />
67+
<set name="high" bitLength="1" displayName="_">
68+
<bit name="Dup" idx="0" />
69+
</set>
70+
</bitfield>
71+
<int name="ProtocolId" type="uint8" defaultValue="0x1" validValue="0x1" />
72+
<string name="ClientId" />
73+
<enum name="ReturnCode" type="uint8">
74+
<validValue name="Accepted" val="0" />
75+
<validValue name="Congestion" val="1" />
76+
<validValue name="InvalidTopicId" val="2" />
77+
<validValue name="NotSupported" val="3" />
78+
</enum>
79+
<string name="WillTopic" />
80+
<data name="WillMsg" />
81+
<int name="TopicId" type="uint16" validRange="[0x0, 0xfffe]" />
82+
<int name="MessageId" type="uint16" displayName="MsgId"/>
83+
<string name="TopicName" />
84+
<data name="Data" />
85+
86+
87+
<int name="Length" type="uint16" />
88+
<string name="String" lengthPrefix="Length" />
89+
<data name="BinData" lengthPrefix="Length" />
90+
<string reuse="String" name="ProtocolName" defaultValue="MQTT" displayName="Protocol Name"/>
91+
<int name="PacketId" type="uint16" displayName="Packet ID"/>
92+
93+
</fields>
94+
95+
<frame name="Frame">
96+
<custom name="Length" field="MsgLengthField" />
97+
<id name="Id" field="MsgId" />
98+
<payload name="Data" />
99+
</frame>
100+
101+
<message name="Advertise" id="MsgId.Advertise" displayName="ADVERTISE">
102+
<ref name="GwId" field="GwId" />
103+
<ref name="Duration" field="Duration" />
104+
</message>
105+
106+
<message name="Searchgw" id="MsgId.Searchgw" displayName="SEARCHGW">
107+
<ref name="Radius" field="Radius" />
108+
</message>
109+
110+
<message name="Gwinfo" id="MsgId.Gwinfo" displayName="GWINFO">
111+
<ref name="GwId" field="GwId" />
112+
<ref name="GwAdd" field="GwAdd" />
113+
</message>
114+
115+
<message name="Connect" id="MsgId.Connect" displayName="CONNECT">
116+
<ref name="Flags" field="Flags" />
117+
<ref name="ProtocolId" field="ProtocolId" />
118+
<ref name="Duration" field="Duration" />
119+
<ref name="ClientId" field="ClientId" />
120+
</message>
121+
122+
<message name="Connack" id="MsgId.Connack" displayName="CONNACK">
123+
<ref name="ReturnCode" field="ReturnCode" />
124+
</message>
125+
126+
<message name="Willtopicreq" id="MsgId.Willtopicreq" displayName="WILLTOPICREQ" />
127+
128+
<message name="Willtopic" id="MsgId.Willtopic" displayName="WILLTOPIC">
129+
<ref name="Flags" field="Flags" />
130+
<ref name="WillTopic" field="WillTopic" />
131+
</message>
132+
133+
<message name="Willmsgreq" id="MsgId.Willmsgreq" displayName="WILLMSGREQ" />
134+
135+
<message name="Willmsg" id="MsgId.Willmsg" displayName="WILLMSG">
136+
<ref name="WillMsg" field="WillMsg" />
137+
</message>
138+
139+
<message name="Register" id="MsgId.Register" displayName="REGISTER">
140+
<ref name="TopicId" field="TopicId" />
141+
<ref name="MsgId" field="MessageId" />
142+
<ref name="TopicName" field="TopicName" />
143+
</message>
144+
145+
<message name="Regack" id="MsgId.Regack" displayName="REGACK">
146+
<ref name="TopicId" field="TopicId" />
147+
<ref name="MsgId" field="MessageId" />
148+
<ref name="ReturnCode" field="ReturnCode" />
149+
</message>
150+
151+
<message name="Publish" id="MsgId.Publish" displayName="PUBLISH">
152+
<ref name="Flags" field="Flags" />
153+
<ref name="TopicId" field="TopicId" />
154+
<ref name="MsgId" field="MessageId" />
155+
<ref name="Data" field="Data" />
156+
</message>
157+
158+
<message name="Puback" id="MsgId.Puback" displayName="PUBACK">
159+
<ref name="TopicId" field="TopicId" />
160+
<ref name="MsgId" field="MessageId" />
161+
<ref name="ReturnCode" field="ReturnCode" />
162+
</message>
163+
164+
<message name="Pubrec" id="MsgId.Pubrec" displayName="PUBREC">
165+
<ref name="MsgId" field="MessageId" />
166+
</message>
167+
168+
<message name="Pubrel" id="MsgId.Pubrel" displayName="PUBREL" copyFieldsFrom="Pubrec" />
169+
170+
<message name="Pubcomp" id="MsgId.Pubcomp" displayName="PUBCOMP" copyFieldsFrom="Pubrec" />
171+
172+
<message name="Subscribe" id="MsgId.Subscribe" displayName="SUBSCRIBE">
173+
<ref name="Flags" field="Flags" />
174+
<ref name="MsgId" field="MessageId" />
175+
<optional name="TopicId" defaultMode="exists" externalModeCtrl="true">
176+
<ref name="TopicId" field="TopicId" />
177+
</optional>
178+
<optional name="TopicName" defaultMode="missing" externalModeCtrl="true">
179+
<ref name="TopicName" field="TopicName" />
180+
</optional>
181+
</message>
182+
183+
<message name="Suback" id="MsgId.Suback" displayName="SUBACK">
184+
<ref name="Flags" field="Flags" />
185+
<ref name="TopicId" field="TopicId" />
186+
<ref name="MsgId" field="MessageId" />
187+
<ref name="ReturnCode" field="ReturnCode" />
188+
</message>
189+
190+
<message name="Unsubscribe" id="MsgId.Unsubscribe" displayName="UNSUBSCRIBE" copyFieldsFrom="Subscribe" />
191+
192+
<message name="Unsuback" id="MsgId.Unsuback" displayName="UNSUBACK">
193+
<ref name="MsgId" field="MessageId" />
194+
</message>
195+
196+
<message name="Pingreq" id="MsgId.Pingreq" displayName="PINGREQ">
197+
<ref name="ClientId" field="ClientId" />
198+
</message>
199+
200+
<message name="Pingresp" id="MsgId.Pingresp" displayName="PINGRESP" />
201+
202+
<message name="Disconnect" id="MsgId.Disconnect" displayName="DISCONNECT">
203+
<optional name="Duration" defaultMode="missing">
204+
<ref name="Duration" field="Duration" />
205+
</optional>
206+
</message>
207+
208+
<message name="Willtopicupd" id="MsgId.Willtopicupd" displayName="WILLTOPICUPD">
209+
<ref name="WillTopic" field="WillTopic" />
210+
</message>
211+
212+
<message name="Willmsgupd" id="MsgId.Willmsgupd" displayName="WILLMSGUPD">
213+
<ref name="WillMsg" field="WillMsg" />
214+
</message>
215+
216+
<message name="Willtopicresp" id="MsgId.Willtopicresp" displayName="WILLTOPICRESP">
217+
<ref name="ReturnCode" field="ReturnCode" />
218+
</message>
219+
220+
<message name="Willmsgresp" id="MsgId.Willmsgresp" displayName="WILLMSGRESP" >
221+
<copyFieldsFrom value="Willtopicresp" />
222+
</message>
223+
</schema>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/// @brief Extra function to get current length value
2+
std::size_t getLengthValue() const
3+
{
4+
if (field_short().value() != 0U) {
5+
return static_cast<std::size_t>(field_short().value());
6+
}
7+
8+
GASSERT(field_long().doesExist());
9+
return static_cast<std::size_t>(field_long().field().value());
10+
}
11+
12+
/// @brief Extra function to set current length value
13+
void setLengthValue(std::size_t value)
14+
{
15+
if (value <= 0xfe) {
16+
field_short().value() = static_cast<std::uint8_t>(value);
17+
field_long().setMissing();
18+
return;
19+
}
20+
21+
field_short().value() = 0U;
22+
field_long().setExists();
23+
field_long().field().value() = static_cast<std::uint16_t>(value);
24+
}

0 commit comments

Comments
 (0)