You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2022/06/19 10:17:23 UTC

[plc4x] 01/02: chore(protocols/mqtt): Added a first draft of a mqtt5 mspec

This is an automated email from the ASF dual-hosted git repository.

cdutz pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 754baec81913b1af6592302660e8f84984da0ba5
Author: cdutz <ch...@c-ware.de>
AuthorDate: Sun Jun 19 12:16:37 2022 +0200

    chore(protocols/mqtt): Added a first draft of a mqtt5 mspec
---
 protocols/mqtt/pom.xml                             |  43 ++
 .../apache/plc4x/protocol/mqtt/MqttProtocol.java   |  42 ++
 ...e.plc4x.plugins.codegenerator.protocol.Protocol |  19 +
 .../src/main/resources/protocols/mqtt/mqtt.mspec   | 438 +++++++++++++++++++++
 .../protocols/mqtt/ParserSerializerTestsuite.xml   |  81 ++++
 protocols/pom.xml                                  |   1 +
 6 files changed, 624 insertions(+)

diff --git a/protocols/mqtt/pom.xml b/protocols/mqtt/pom.xml
new file mode 100644
index 0000000000..68a7cdfeb2
--- /dev/null
+++ b/protocols/mqtt/pom.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you 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
+
+      https://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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.plc4x</groupId>
+    <artifactId>plc4x-protocols</artifactId>
+    <version>0.10.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>plc4x-protocols-mqtt</artifactId>
+
+  <name>Protocols: MQTT</name>
+  <description>Protocol specifications for the MQTT protocols</description>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4x-code-generation-protocol-base-mspec</artifactId>
+      <version>0.10.0-SNAPSHOT</version>
+    </dependency>
+  </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/protocols/mqtt/src/main/java/org/apache/plc4x/protocol/mqtt/MqttProtocol.java b/protocols/mqtt/src/main/java/org/apache/plc4x/protocol/mqtt/MqttProtocol.java
new file mode 100644
index 0000000000..762ebac9b9
--- /dev/null
+++ b/protocols/mqtt/src/main/java/org/apache/plc4x/protocol/mqtt/MqttProtocol.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.plc4x.protocol.mqtt;
+
+import org.apache.plc4x.plugins.codegenerator.language.mspec.parser.MessageFormatParser;
+import org.apache.plc4x.plugins.codegenerator.language.mspec.protocol.ProtocolHelpers;
+import org.apache.plc4x.plugins.codegenerator.language.mspec.protocol.ValidatableTypeContext;
+import org.apache.plc4x.plugins.codegenerator.protocol.Protocol;
+import org.apache.plc4x.plugins.codegenerator.protocol.TypeContext;
+import org.apache.plc4x.plugins.codegenerator.types.exceptions.GenerationException;
+
+public class MqttProtocol implements Protocol, ProtocolHelpers {
+
+    @Override
+    public String getName() {
+        return "mqtt";
+    }
+
+    @Override
+    public TypeContext getTypeContext() throws GenerationException {
+        ValidatableTypeContext typeContext = new MessageFormatParser().parse(getMspecStream());
+        typeContext.validate();
+        return typeContext;
+    }
+
+}
diff --git a/protocols/mqtt/src/main/resources/META-INF/services/org.apache.plc4x.plugins.codegenerator.protocol.Protocol b/protocols/mqtt/src/main/resources/META-INF/services/org.apache.plc4x.plugins.codegenerator.protocol.Protocol
new file mode 100644
index 0000000000..275a851d97
--- /dev/null
+++ b/protocols/mqtt/src/main/resources/META-INF/services/org.apache.plc4x.plugins.codegenerator.protocol.Protocol
@@ -0,0 +1,19 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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
+#
+#     https://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.
+#
+org.apache.plc4x.protocol.mqtt.MqttProtocol
diff --git a/protocols/mqtt/src/main/resources/protocols/mqtt/mqtt.mspec b/protocols/mqtt/src/main/resources/protocols/mqtt/mqtt.mspec
new file mode 100644
index 0000000000..94879f85ad
--- /dev/null
+++ b/protocols/mqtt/src/main/resources/protocols/mqtt/mqtt.mspec
@@ -0,0 +1,438 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+[discriminatedType MQTT_ControlPacket    byteOrder='BIG_ENDIAN'
+    [discriminator MQTT_ControlPacketType packetType                                        ]
+    [abstract uint 8 remainingLength                                                        ]
+    [typeSwitch packetType
+        ['CONNECT' MQTT_ControlPacket_CONNECT
+            // Fixed Header
+            [reserved uint 4                 '0x0'                                          ]
+            [simple   uint 8                 remainingLength                                ]
+            // Variable Header
+            [simple   MQTT_String            protocolName                                   ]
+            [simple   uint 8                 protocolVersion                                ]
+            // Connect flags start
+            [simple   bit                    userNameFlagSet                                ]
+            [simple   bit                    passwordFlagSet                                ]
+            [simple   bit                    willRetainFlagSet                              ]
+            [simple   uint 2                 willQosLevel                                   ]
+            [simple   bit                    willFlagSet                                    ]
+            // Actually a session start ...
+            [simple   bit                    cleanStartFlagSet                              ]
+            [reserved bit                    'false'                                        ]
+            // Connect flags end
+            [simple   uint 16                keepAlive                                      ]
+
+            // Properties
+            [simple   uint 32                propertyLength        encoding='"varLenUint32"']
+            [array    MQTT_Property          properties     length 'propertyLength'         ]
+
+            // Payload
+            [simple   MQTT_String            clientId                                       ]
+            // TODO: If willFlagSet is true, the will properties come here (3.1.3.2)
+            // TODO: If willFlagSet is true, the will topic comes here (3.1.3.3)
+            // TODO: If willFlagSet is true, the will payload comes here (3.1.3.4)
+            // If userNameFlagSet, here comes the username. (String)
+            [optional MQTT_String            username       'userNameFlagSet'               ]
+            // If passwordFlagSet, here comes the password. (String)
+            [optional MQTT_String            password       'passwordFlagSet'               ]
+        ]
+        ['CONNACK' MQTT_ControlPacket_CONNACK
+            // Fixed Header
+            [reserved uint 4                 '0x0'                                          ]
+            [simple   uint 8                 remainingLength                                ]
+            // Variable Header
+            // Acknowledge flags start
+            [reserved uint 7                 '0x00'                                         ]
+            [simple   bit                    sessionPresentFlagSet                          ]
+            // Acknowledge flags end
+            [simple   MQTT_ReasonCode        reasonCode                                     ]
+
+            // Properties
+            [optional uint 32                propertyLength 'remainingLength - curPos < 4'       encoding='"varLenUint32"']
+            [array    MQTT_Property          properties     length '(propertyLength != null) ? propertyLength : 0']
+        ]
+        ['PUBLISH' MQTT_ControlPacket_PUBLISH
+            // Fixed Header
+            [simple   bit                    dup                                            ]
+            [simple   MQTT_QOS               qos                                            ]
+            [simple   bit                    retain                                         ]
+            [simple   uint 8                 remainingLength                                ]
+            // Variable Header
+            [simple   MQTT_String            topicName                                      ]
+            [optional uint 16                packetIdentifier 'qos != MQTT_QOS.AT_MOST_ONCE']
+
+            // Properties
+            [optional uint 32                propertyLength 'remainingLength - curPos < 4'       encoding='"varLenUint32"']
+            [array    MQTT_Property          properties     length '(propertyLength != null) ? propertyLength : 0']
+
+            // Payload
+            [array    byte                   payload      count 'remainingLength - curPos'  ]
+        ]
+        // Used if QOS = 1
+        ['PUBACK' MQTT_ControlPacket_PUBACK
+            // Fixed Header
+            [reserved uint 4                 '0x0'                                          ]
+            [simple   uint 8                 remainingLength                                ]
+            // Variable Header
+            [simple   uint 16                packetIdentifier                               ]
+            [optional MQTT_ReasonCode        reasonCode     'remainingLength - curPos < 3'  ]
+
+            // Properties
+            [optional uint 32                propertyLength 'remainingLength - curPos < 4'       encoding='"varLenUint32"']
+            [array    MQTT_Property          properties     length '(propertyLength != null) ? propertyLength : 0']
+        ]
+        // Used if QOS = 2
+        ['PUBREC' MQTT_ControlPacket_PUBREC
+            // Fixed Header
+            [reserved uint 4                 '0x0'                                          ]
+            [simple   uint 8                 remainingLength                                ]
+            // Variable Header
+            [simple   uint 16                packetIdentifier                               ]
+            [optional MQTT_ReasonCode        reasonCode     'remainingLength - curPos < 3'  ]
+
+            // Properties
+            [optional uint 32                propertyLength 'remainingLength - curPos < 4'       encoding='"varLenUint32"']
+            [array    MQTT_Property          properties     length '(propertyLength != null) ? propertyLength : 0']
+        ]
+        ['PUBREL' MQTT_ControlPacket_PUBREL
+            // Fixed Header
+            [reserved uint 4                 '0x0'                                          ]
+            [simple   uint 8                 remainingLength                                ]
+            // Variable Header
+            [simple   uint 16                packetIdentifier                               ]
+            [optional MQTT_ReasonCode        reasonCode     'remainingLength - curPos < 3'  ]
+
+            // Properties
+            [optional uint 32                propertyLength 'remainingLength - curPos < 4'       encoding='"varLenUint32"']
+            [array    MQTT_Property          properties     length '(propertyLength != null) ? propertyLength : 0']
+        ]
+        ['PUBCOMP' MQTT_ControlPacket_PUBCOMP
+            // Fixed Header
+            [reserved uint 4                 '0x0'                                          ]
+            [simple   uint 8                 remainingLength                                ]
+            // Variable Header
+            [simple   uint 16                packetIdentifier                               ]
+            [optional MQTT_ReasonCode        reasonCode     'remainingLength - curPos < 3'  ]
+
+            // Properties
+            [optional uint 32                propertyLength 'remainingLength - curPos < 4'       encoding='"varLenUint32"']
+            [array    MQTT_Property          properties     length '(propertyLength != null) ? propertyLength : 0']
+        ]
+        ['SUBSCRIBE' MQTT_ControlPacket_SUBSCRIBE
+            // Fixed Header
+            [reserved uint 4                 '0x0'                                          ]
+            [simple   uint 8                 remainingLength                                ]
+            // Variable Header
+            [simple   uint 16                packetIdentifier                               ]
+
+            // Properties
+            [optional uint 32                propertyLength 'remainingLength - curPos < 4'       encoding='"varLenUint32"']
+            [array    MQTT_Property          properties     length '(propertyLength != null) ? propertyLength : 0']
+
+            // Payload
+            [array    Filter                 filters      count 'remainingLength - curPos'  ]
+        ]
+        ['SUBACK' MQTT_ControlPacket_SUBACK
+            // Fixed Header
+            [reserved uint 4                 '0x0'                                          ]
+            [simple   uint 8                 remainingLength                                ]
+            // Variable Header
+            [simple   uint 16                packetIdentifier                               ]
+
+            // Properties
+            [optional uint 32                propertyLength 'remainingLength - curPos < 4'       encoding='"varLenUint32"']
+            [array    MQTT_Property          properties     length '(propertyLength != null) ? propertyLength : 0']
+
+            // Payload
+            [array    MQTT_ReasonCode        results        count 'remainingLength - curPos'    ]
+        ]
+        ['UNSUBSCRIBE' MQTT_ControlPacket_UNSUBSCRIBE
+            // Fixed Header
+            [reserved uint 4                 '0x0'                                              ]
+            [simple   uint 8                 remainingLength                                    ]
+            // Variable Header
+            [simple   uint 16                packetIdentifier                                   ]
+
+            // Properties
+            [optional uint 32                propertyLength 'remainingLength - curPos < 4'       encoding='"varLenUint32"']
+            [array    MQTT_Property          properties     length '(propertyLength != null) ? propertyLength : 0']
+
+            // Payload
+            [array    MQTT_String            filters        count 'remainingLength - curPos'    ]
+        ]
+        ['UNSUBACK' MQTT_ControlPacket_UNSUBACK
+            // Fixed Header
+            [reserved uint 4                 '0x0'                                              ]
+            [simple   uint 8                 remainingLength                                    ]
+            // Variable Header
+            [simple   uint 16                packetIdentifier                                   ]
+
+            // Properties
+            [optional uint 32                propertyLength 'remainingLength - curPos < 4'       encoding='"varLenUint32"']
+            [array    MQTT_Property          properties     length '(propertyLength != null) ? propertyLength : 0']
+
+            // Payload
+            [array    MQTT_ReasonCode        results        count 'remainingLength - curPos'    ]
+        ]
+        ['PINGREQ' MQTT_ControlPacket_PINGREQ
+            // Fixed Header
+            [reserved uint 4                 '0x0'                                              ]
+            [simple   uint 8                 remainingLength                                    ]
+        ]
+        ['PINGRESP' MQTT_ControlPacket_PINGRESP
+            // Fixed Header
+            [reserved uint 4                 '0x0'                                              ]
+            [simple   uint 8                 remainingLength                                    ]
+        ]
+        ['DISCONNECT' MQTT_ControlPacket_DISCONNECT
+            // Fixed Header
+            [reserved uint 4                 '0x0'                                              ]
+            [simple   uint 8                 remainingLength                                    ]
+            // Variable Header
+            [simple   MQTT_ReasonCode        reason                                             ]
+        ]
+        ['AUTH' MQTT_ControlPacket_AUTH
+            // Fixed Header
+            [reserved uint 4                 '0x0'                                              ]
+            [simple   uint 8                 remainingLength                                    ]
+            // Variable Header
+            [simple   MQTT_ReasonCode        reason                                             ]
+
+            // Properties
+            [optional uint 32                propertyLength 'remainingLength - curPos < 4'       encoding='"varLenUint32"']
+            [array    MQTT_Property          properties     length '(propertyLength != null) ? propertyLength : 0']
+        ]
+    ]
+]
+
+[discriminatedType MQTT_Property
+    [simple MQTT_PropertyType propertyType]
+    [typeSwitch propertyType
+        ['PAYLOAD_FORMAT_INDICATOR'          MQTT_Property_PAYLOAD_FORMAT_INDICATOR
+            [simple uint 8                   value                              ]
+        ]
+        ['MESSAGE_EXPIRY_INTERVAL'           MQTT_Property_MESSAGE_EXPIRY_INTERVAL
+            [simple uint 32                  value                              ]
+        ]
+        ['CONTENT_TYPE'                      MQTT_Property_CONTENT_TYPE
+            [simple   MQTT_String            value                              ]
+        ]
+        ['RESPONSE_TOPIC'                    MQTT_Property_RESPONSE_TOPIC
+            [simple   MQTT_String            value                              ]
+        ]
+        ['CORRELATION_DATA'                  MQTT_Property_CORRELATION_DATA
+            // TODO: Find out what "Binary Data" means ...
+        ]
+        ['SUBSCRIPTION_IDENTIFIER'           MQTT_Property_SUBSCRIPTION_IDENTIFIER
+            [simple uint 32                  value     encoding='"varLenUint32"']
+        ]
+        ['SESSION_EXPIRY_INTERVAL'           MQTT_Property_EXPIRY_INTERVAL
+            [simple uint 32                  value                              ]
+        ]
+        ['ASSIGNED_CLIENT_IDENTIFIER'        MQTT_Property_ASSIGNED_CLIENT_IDENTIFIER
+            [simple   MQTT_String            value                              ]
+        ]
+        ['SERVER_KEEP_ALIVE'                 MQTT_Property_SERVER_KEEP_ALIVE
+            [simple uint 16                  value                              ]
+        ]
+        ['AUTHENTICATION_METHOD'             MQTT_Property_AUTHENTICATION_METHOD
+            [simple   MQTT_String            value                              ]
+        ]
+        ['AUTHENTICATION_DATA'               MQTT_Property_AUTHENTICATION_DATA
+            // TODO: Find out what "Binary Data" means ...
+        ]
+        ['REQUEST_PROBLEM_INFORMATION'       MQTT_Property_REQUEST_PROBLEM_INFORMATION
+            // TODO: Probably an enum
+            [simple uint 8                   value                              ]
+        ]
+        ['WILL_DELAY_INTERVAL'               MQTT_Property_WILL_DELAY_INTERVAL
+            [simple uint 32                  value                              ]
+        ]
+        ['REQUEST_RESPONSE_INFORMATION'      MQTT_Property_REQUEST_RESPONSE_INFORMATION
+            // TODO: Probably an enum
+            [simple uint 8                   value                              ]
+        ]
+        ['RESPONSE_INFORMATION'              MQTT_Property_RESPONSE_INFORMATION
+            [simple   MQTT_String            value                              ]
+        ]
+        ['SERVER_REFERENCE'                  MQTT_Property_SERVER_REFERENCE
+            [simple   MQTT_String            value                              ]
+        ]
+        ['REASON_STRING'                     MQTT_Property_REASON_STRING
+            [simple   MQTT_String            value                              ]
+        ]
+        ['RECEIVE_MAXIMUM'                   MQTT_Property_RECEIVE_MAXIMUM
+            [simple uint 16                  value                              ]
+        ]
+        ['TOPIC_ALIAS_MAXIMUM'               MQTT_Property_TOPIC_ALIAS_MAXIMUM
+            [simple uint 16                  value                              ]
+        ]
+        ['TOPIC_ALIAS'                       MQTT_Property_TOPIC_ALIAS
+            [simple uint 16                  value                              ]
+        ]
+        ['MAXIMUM_QOS'                       MQTT_Property_MAXIMUM_QOS
+            [simple uint 8                   value                              ]
+        ]
+        ['RETAIN_AVAILABLE'                  MQTT_Property_RETAIN_AVAILABLE
+            [simple uint 8                   value                              ]
+        ]
+        ['USER_PROPERTY'                     MQTT_Property_USER_PROPERTY
+            [simple   MQTT_String            name                               ]
+            [simple   MQTT_String            value                              ]
+        ]
+        ['MAXIMUM_PACKET_SIZE'               MQTT_Property_MAXIMUM_PACKET_SIZE
+            [simple uint 32                  value                              ]
+        ]
+        ['WILDCARD_SUBSCRIPTION_AVAILABLE'   MQTT_Property_WILDCARD_SUBSCRIPTION_AVAILABLE
+            [simple uint 8                   value                              ]
+        ]
+        ['SUBSCRIPTION_IDENTIFIER_AVAILABLE' MQTT_Property_SUBSCRIPTION_IDENTIFIER_AVAILABLE
+            [simple uint 8                   value                              ]
+        ]
+        ['SHARED_SUBSCRIPTION_AVAILABLE'     MQTT_Property_SHARED_SUBSCRIPTION_AVAILABLE
+            [simple uint 8                   value                              ]
+        ]
+    ]
+]
+
+[type Filter
+    [simple   MQTT_String         filter        ]
+    // Subscription Options Start
+    [reserved uint 2              '0x0'         ]
+    // Don't forward to clients with a client id equal to the sending one
+    [simple   MQTT_RetainHandling retainHandling]
+    [simple   bit                 retain        ]
+    [simple   bit                 noLocal       ]
+    [simple   MQTT_QOS            maxQos        ]
+    // Subscription Options End
+]
+
+[type MQTT_String
+    [implicit uint 16                stringLength 'STR_LEN(value)']
+    [simple   vstring 'stringLength * 8' value                        ]
+]
+
+[enum uint 4 MQTT_ControlPacketType
+    ['0x0' RESERVED   ]
+    ['0x1' CONNECT    ]
+    ['0x2' CONNACK    ]
+    ['0x3' PUBLISH    ]
+    ['0x4' PUBACK     ]
+    ['0x5' PUBREC     ]
+    ['0x6' PUBREL     ]
+    ['0x7' PUBCOMP    ]
+    ['0x8' SUBSCRIBE  ]
+    ['0x9' SUBACK     ]
+    ['0xA' UNSUBSCRIBE]
+    ['0xB' UNSUBACK   ]
+    ['0xC' PINGREQ    ]
+    ['0xD' PINGRESP   ]
+    ['0xE' DISCONNECT ]
+    ['0xF' AUTH       ]
+]
+
+[enum uint 8 MQTT_PropertyType
+    ['0x01' PAYLOAD_FORMAT_INDICATOR         ]
+    ['0x02' MESSAGE_EXPIRY_INTERVAL          ]
+    ['0x03' CONTENT_TYPE                     ]
+    ['0x08' RESPONSE_TOPIC                   ]
+    ['0x09' CORRELATION_DATA                 ]
+    ['0x0B' SUBSCRIPTION_IDENTIFIER          ]
+    ['0x11' SESSION_EXPIRY_INTERVAL          ]
+    ['0x12' ASSIGNED_CLIENT_IDENTIFIER       ]
+    ['0x13' SERVER_KEEP_ALIVE                ]
+    ['0x15' AUTHENTICATION_METHOD            ]
+    ['0x16' AUTHENTICATION_DATA              ]
+    ['0x17' REQUEST_PROBLEM_INFORMATION      ]
+    ['0x18' WILL_DELAY_INTERVAL              ]
+    ['0x19' REQUEST_RESPONSE_INFORMATION     ]
+    ['0x1A' RESPONSE_INFORMATION             ]
+    ['0x1C' SERVER_REFERENCE                 ]
+    ['0x1F' REASON_STRING                    ]
+    ['0x21' RECEIVE_MAXIMUM                  ]
+    ['0x22' TOPIC_ALIAS_MAXIMUM              ]
+    ['0x23' TOPIC_ALIAS                      ]
+    ['0x24' MAXIMUM_QOS                      ]
+    ['0x25' RETAIN_AVAILABLE                 ]
+    ['0x26' USER_PROPERTY                    ]
+    ['0x27' MAXIMUM_PACKET_SIZE              ]
+    ['0x28' WILDCARD_SUBSCRIPTION_AVAILABLE  ]
+    ['0x29' SUBSCRIPTION_IDENTIFIER_AVAILABLE]
+    ['0x2A' SHARED_SUBSCRIPTION_AVAILABLE    ]
+]
+
+[enum uint 8 MQTT_ReasonCode                       (bit connackResponse, bit pubackPubrecResponse, bit pubrelPubcompResponse, bit subackResponse, bit unsubackResponse, bit disconnectReason, bit authReason)
+    ['0X00' SUCCESS                                ['true'             , 'true'                  , 'true'                   , 'true'            , 'true'              , 'true'              , 'true'       ]]
+    ['0X01' GRANTED_QOS_1                          ['false'            , 'false'                 , 'false'                  , 'true'            , 'false'             , 'false'             , 'false'      ]]
+    ['0X02' GRANTED_QOS_2                          ['false'            , 'false'                 , 'false'                  , 'true'            , 'false'             , 'false'             , 'false'      ]]
+    ['0X04' DISCONNECT_WITH_WILL_MESSAGE           ['false'            , 'false'                 , 'false'                  , 'false'           , 'false'             , 'true'              , 'false'      ]]
+    ['0x10' NO_MATCHING_SUBSCRIBERS                ['false'            , 'true'                  , 'false'                  , 'false'           , 'false'             , 'false'             , 'false'      ]]
+    ['0x11' NO_SUBSCRIPTION_EXISTED                ['false'            , 'false'                 , 'false'                  , 'false'           , 'true'              , 'false'             , 'false'      ]]
+    ['0X18' CONTINUE_AUTHENTICATION                ['false'            , 'false'                 , 'false'                  , 'false'           , 'false'             , 'false'             , 'true'       ]]
+    ['0X19' RE_AUTHENTICATE                        ['false'            , 'false'                 , 'false'                  , 'false'           , 'false'             , 'false'             , 'true'       ]]
+    ['0X80' UNSPECIFIED_ERROR                      ['true'             , 'true'                  , 'false'                  , 'true'            , 'true'              , 'true'              , 'false'      ]]
+    ['0X81' MALFORMED_PACKET                       ['true'             , 'false'                 , 'false'                  , 'false'           , 'false'             , 'true'              , 'false'      ]]
+    ['0X82' PROTOCOL_ERROR                         ['true'             , 'false'                 , 'false'                  , 'false'           , 'false'             , 'true'              , 'false'      ]]
+    ['0X83' IMPLEMENTATION_SPECIFIC_ERROR          ['true'             , 'true'                  , 'false'                  , 'true'            , 'true'              , 'true'              , 'false'      ]]
+    ['0X84' UNSUPPORTED_PROTOCOL_VERSION           ['true'             , 'false'                 , 'false'                  , 'false'           , 'false'             , 'false'             , 'false'      ]]
+    ['0X85' CLIENT_IDENTIFIER_NOT_VALID            ['true'             , 'false'                 , 'false'                  , 'false'           , 'false'             , 'false'             , 'false'      ]]
+    ['0X86' BAD_USER_NAME_OR_PASSWORD              ['true'             , 'false'                 , 'false'                  , 'false'           , 'false'             , 'false'             , 'false'      ]]
+    ['0X87' NOT_AUTHORIZED                         ['true'             , 'true'                  , 'false'                  , 'true'            , 'true'              , 'true'              , 'false'      ]]
+    ['0X88' SERVER_UNAVAILABLE                     ['true'             , 'false'                 , 'false'                  , 'false'           , 'false'             , 'false'             , 'false'      ]]
+    ['0X89' SERVER_BUSY                            ['true'             , 'false'                 , 'false'                  , 'false'           , 'false'             , 'true'              , 'false'      ]]
+    ['0X8A' BANNED                                 ['true'             , 'false'                 , 'false'                  , 'false'           , 'false'             , 'false'             , 'false'      ]]
+    ['0X8B' SERVER_SHUTTING_DOWN                   ['false'            , 'false'                 , 'false'                  , 'false'           , 'false'             , 'true'              , 'false'      ]]
+    ['0X8C' BAD_AUTHENTICATION_METHOD              ['true'             , 'false'                 , 'false'                  , 'false'           , 'false'             , 'false'             , 'false'      ]]
+    ['0X8D' KEEP_ALIVE_TIMEOUT                     ['false'            , 'false'                 , 'false'                  , 'false'           , 'false'             , 'true'              , 'false'      ]]
+    ['0X8E' SESSION_TAKEN_OVER                     ['false'            , 'false'                 , 'false'                  , 'false'           , 'false'             , 'true'              , 'false'      ]]
+    ['0X8F' TOPIC_FILTER_INVALID                   ['false'            , 'false'                 , 'false'                  , 'true'            , 'true'              , 'true'              , 'false'      ]]
+    ['0X90' TOPIC_NAME_INVALID                     ['true'             , 'true'                  , 'false'                  , 'false'           , 'false'             , 'true'              , 'false'      ]]
+    ['0X91' PACKET_IDENTIFIER_IN_USE               ['false'            , 'true'                  , 'false'                  , 'true'            , 'true'              , 'false'             , 'false'      ]]
+    ['0X92' PACKET_IDENTIFIER_NOT_FOUND            ['false'            , 'false'                 , 'true'                   , 'false'           , 'false'             , 'false'             , 'false'      ]]
+    ['0X93' RECEIVE_MAXIMUM_EXCEEDED               ['false'            , 'false'                 , 'false'                  , 'false'           , 'false'             , 'true'              , 'false'      ]]
+    ['0X94' TOPIC_ALIAS_INVALID                    ['false'            , 'false'                 , 'false'                  , 'false'           , 'false'             , 'true'              , 'false'      ]]
+    ['0X95' PACKET_TOO_LARGE                       ['true'             , 'false'                 , 'false'                  , 'false'           , 'false'             , 'true'              , 'false'      ]]
+    ['0X96' MESSAGE_RATE_TO_HIGH                   ['false'            , 'false'                 , 'false'                  , 'false'           , 'false'             , 'true'              , 'false'      ]]
+    ['0X97' QUOTA_EXCEEDED                         ['true'             , 'true'                  , 'false'                  , 'true'            , 'false'             , 'true'              , 'false'      ]]
+    ['0X98' ADMINISTRATIVE_ACTION                  ['false'            , 'false'                 , 'false'                  , 'false'           , 'false'             , 'true'              , 'false'      ]]
+    ['0X99' PAYLOAD_FORMAT_INVALID                 ['true'             , 'true'                  , 'false'                  , 'false'           , 'false'             , 'true'              , 'false'      ]]
+    ['0X9A' RETAIN_NOT_SUPPORTED                   ['true'             , 'false'                 , 'false'                  , 'false'           , 'false'             , 'true'              , 'false'      ]]
+    ['0X9B' QOS_NOT_SUPPORTED                      ['true'             , 'false'                 , 'false'                  , 'false'           , 'false'             , 'true'              , 'false'      ]]
+    ['0X9C' USE_ANOTHER_SERVER                     ['true'             , 'false'                 , 'false'                  , 'false'           , 'false'             , 'true'              , 'false'      ]]
+    ['0X9D' SERVER_MOVED                           ['true'             , 'false'                 , 'false'                  , 'false'           , 'false'             , 'true'              , 'false'      ]]
+    ['0X9E' SHARED_SUBSCRIPTIONS_NOT_SUPPORTED     ['false'            , 'false'                 , 'false'                  , 'true'            , 'false'             , 'true'              , 'false'      ]]
+    ['0X9F' CONNECTION_RATE_EXCEEDED               ['true'             , 'false'                 , 'false'                  , 'false'           , 'false'             , 'true'              , 'false'      ]]
+    ['0XA0' MAXIMUM_CONNECT_TIME                   ['false'            , 'false'                 , 'false'                  , 'false'           , 'false'             , 'true'              , 'false'      ]]
+    ['0XA1' SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED ['false'            , 'false'                 , 'false'                  , 'true'            , 'false'             , 'true'              , 'false'      ]]
+    ['0XA2' WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED   ['false'            , 'false'                 , 'false'                  , 'true'            , 'false'             , 'true'              , 'false'      ]]
+]
+
+[enum uint 2 MQTT_QOS
+    ['0x0' AT_MOST_ONCE ]
+    ['0x1' AT_LEAST_ONCE]
+    ['0x2' EXACTLY_ONCE ]
+]
+
+[enum uint 2 MQTT_RetainHandling
+    ['0x0' SEND_RETAINED_MESSAGES_AT_THE_TIME_OF_THE_SUBSCRIBE                                  ]
+    ['0x1' SEND_RETAINED_MESSAGES_AT_SUBSCRIBE_ONLY_IF_THE_SUBSCRIPTION_DOES_NOT_CURRENTLY_EXIST]
+    ['0x2' DO_NOT_SEND_RETAINED_MESSAGES_AT_THE_TIME_OF_SUBSCRIBE                               ]
+]
diff --git a/protocols/mqtt/src/test/resources/protocols/mqtt/ParserSerializerTestsuite.xml b/protocols/mqtt/src/test/resources/protocols/mqtt/ParserSerializerTestsuite.xml
new file mode 100644
index 0000000000..1719da4cd3
--- /dev/null
+++ b/protocols/mqtt/src/test/resources/protocols/mqtt/ParserSerializerTestsuite.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you 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.
+  -->
+<test:testsuite xmlns:test="https://plc4x.apache.org/schemas/parser-serializer-testsuite.xsd"
+                byteOrder="BIG_ENDIAN">
+
+  <name>MQTT5</name>
+
+  <protocolName>mqtt</protocolName>
+  <outputFlavor>read-write</outputFlavor>
+
+  <testcase>
+    <name>MQTT Connection Request</name>
+    <raw>101d00044d51545405c200050000066c776d71747400037472790003747279</raw>
+    <root-type>MQTT_ControlPacket</root-type>
+    <xml>
+      <MQTT_ControlPacket>
+        <packetType>
+          <MQTT_ControlPacketType dataType="uint" bitLength="4" stringRepresentation="CONNECT">1</MQTT_ControlPacketType>
+        </packetType>
+        <MQTT_ControlPacket_CONNECT>
+          <reserved dataType="uint" bitLength="4">0</reserved>
+          <remainingLength dataType="uint" bitLength="8">29</remainingLength>
+          <protocolName>
+            <MQTT_String>
+              <stringLength dataType="uint" bitLength="16">4</stringLength>
+              <value dataType="string" bitLength="32" encoding="UTF-8">MQTT</value>
+            </MQTT_String>
+          </protocolName>
+          <protocolVersion dataType="uint" bitLength="8">5</protocolVersion>
+          <userNameFlagSet dataType="bit" bitLength="1">true</userNameFlagSet>
+          <passwordFlagSet dataType="bit" bitLength="1">true</passwordFlagSet>
+          <willRetainFlagSet dataType="bit" bitLength="1">false</willRetainFlagSet>
+          <willQosLevel dataType="uint" bitLength="2">0</willQosLevel>
+          <willFlagSet dataType="bit" bitLength="1">false</willFlagSet>
+          <cleanStartFlagSet dataType="bit" bitLength="1">true</cleanStartFlagSet>
+          <reserved dataType="bit" bitLength="1">false</reserved>
+          <keepAlive dataType="uint" bitLength="16">5</keepAlive>
+          <value dataType="uint" bitLength="8">0</value>
+          <properties isList="true">
+          </properties>
+          <clientId>
+            <MQTT_String>
+              <stringLength dataType="uint" bitLength="16">6</stringLength>
+              <value dataType="string" bitLength="48" encoding="UTF-8">lwmqtt</value>
+            </MQTT_String>
+          </clientId>
+          <username>
+            <MQTT_String>
+              <stringLength dataType="uint" bitLength="16">3</stringLength>
+              <value dataType="string" bitLength="24" encoding="UTF-8">try</value>
+            </MQTT_String>
+          </username>
+          <password>
+            <MQTT_String>
+              <stringLength dataType="uint" bitLength="16">3</stringLength>
+              <value dataType="string" bitLength="24" encoding="UTF-8">try</value>
+            </MQTT_String>
+          </password>
+        </MQTT_ControlPacket_CONNECT>
+      </MQTT_ControlPacket>
+    </xml>
+  </testcase>
+
+</test:testsuite>
\ No newline at end of file
diff --git a/protocols/pom.xml b/protocols/pom.xml
index 7030565277..34d650b49c 100644
--- a/protocols/pom.xml
+++ b/protocols/pom.xml
@@ -45,6 +45,7 @@
     <module>genericcan</module>
     <module>knxnetip</module>
     <module>modbus</module>
+    <module>mqtt</module>
     <module>opcua</module>
     <module>plc4x</module>
     <module>profinet</module>