diff --git a/.vscode/settings.json b/.vscode/settings.json
index 1e4a5cb51a682ae308bb4bc66aa04bc5dded9a33..418de16bdb77a6fe9e3032f6f2dc1a65c8d6d814 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -93,7 +93,8 @@
         "qpair": "cpp",
         "qstring": "cpp",
         "qregularexpression": "cpp",
-        "qmessagebox": "cpp"
+        "qmessagebox": "cpp",
+        "regex": "cpp"
     },
     "editor.defaultFormatter": "chiehyu.vscode-astyle",
     "[xml]": {
diff --git a/Core/xmlobject.cpp b/Core/xmlobject.cpp
index 2c6692e767e4c6942246e5ed7b3cf79192450b66..e452463fcd42b93d2894a469c891a2af88bf9d91 100644
--- a/Core/xmlobject.cpp
+++ b/Core/xmlobject.cpp
@@ -1,22 +1,21 @@
 #include "xmlobject.h"
 
-#include <QTextStream>
 #include <QFile>
+#include <QTextStream>
 
-XmlObject::XmlObject(const QString& objectName) {
-    setObjectName(objectName);
-}
+XmlObject::XmlObject(const QString& objectName) { setObjectName(objectName); }
 
-XmlObject::XmlObject(const XmlObject& other) {
-    copy(other);
-}
+XmlObject::XmlObject(const XmlObject& other) { copy(other); }
 
-bool XmlObject::loadFromFile(const QString& filePath) {
+bool XmlObject::loadFromFile(const QString& filePath)
+{
     bool result = false;
     QFile file(filePath);
-    if(file.exists() && file.open(QIODevice::ReadOnly)) {
+    if (file.exists() && file.open(QIODevice::ReadOnly))
+    {
         QString msgDefFileContent = QTextStream(&file).readAll();
-        if(msgDefFileContent != "") {
+        if (msgDefFileContent != "")
+        {
             this->fromXml(msgDefFileContent);
             result = true;
         }
@@ -25,10 +24,12 @@ bool XmlObject::loadFromFile(const QString& filePath) {
     return result;
 }
 
-bool XmlObject::writeToFile(const QString& filePath, const QString& codec) const {
+bool XmlObject::writeToFile(const QString& filePath, const QString& codec) const
+{
     bool result = false;
     QFile file(filePath);
-    if(file.open(QIODevice::WriteOnly)) {
+    if (file.open(QIODevice::WriteOnly))
+    {
         QTextStream textStream(&file);
         textStream.setCodec(codec.toUtf8());
         textStream << this->toXml();
@@ -38,7 +39,8 @@ bool XmlObject::writeToFile(const QString& filePath, const QString& codec) const
     return result;
 }
 
-QString XmlObject::toXml() const {
+QString XmlObject::toXml() const
+{
     QString output;
     QXmlStreamWriter xWriter(&output);
     xWriter.setAutoFormatting(true);
@@ -46,93 +48,108 @@ QString XmlObject::toXml() const {
     return output;
 }
 
-
-void XmlObject::toXml(QXmlStreamWriter* xmlWriter) const {
+void XmlObject::toXml(QXmlStreamWriter* xmlWriter) const
+{
     xmlWriter->writeStartElement(xmlObjectName);
 
-    for(QString key : attributes.keys()) {
+    for (QString key : attributes.keys())
+    {
         xmlWriter->writeAttribute(key, attributes[key]);
     }
 
-    if(getTextValue() != "" && childCount() == 0) {
+    if (getTextValue() != "" && childCount() == 0)
+    {
         xmlWriter->writeCharacters(getTextValue());
     }
 
-    for(XmlObject c : childList) {
+    for (XmlObject c : childList)
+    {
         c.toXml(xmlWriter);
     }
 
     xmlWriter->writeEndElement();
 }
 
-void XmlObject::fromXml(const QString& txt) {
+void XmlObject::fromXml(const QString& txt)
+{
     QXmlStreamReader xReader(txt);
     xReader.readNextStartElement();
     fromXml(&xReader);
 }
 
-void XmlObject::fromXml(QXmlStreamReader* xmlReader) {
+void XmlObject::fromXml(QXmlStreamReader* xmlReader)
+{
     childList.clear();
     attributes.clear();
-    if(xmlReader->isStartElement()) {
+    if (xmlReader->isStartElement())
+    {
         setObjectName(xmlReader->name().toString());
-        for(auto attr : xmlReader->attributes()) {
+        for (auto attr : xmlReader->attributes())
+        {
             attributes[attr.name().toString()] = attr.value().toString();
         }
     }
 
-    while(!xmlReader->atEnd()) {
+    while (!xmlReader->atEnd())
+    {
         xmlReader->readNext();
 
-        if(xmlReader->isCharacters() && !xmlReader->isWhitespace()) {
+        if (xmlReader->isCharacters() && !xmlReader->isWhitespace())
+        {
             setTextValue(xmlReader->text().toString());
-        } else if(xmlReader->isStartElement()) {
+        }
+        else if (xmlReader->isStartElement())
+        {
             XmlObject c;
             c.fromXml(xmlReader);
             childList.append(c);
-        } else if(xmlReader->isEndElement()) {
+        }
+        else if (xmlReader->isEndElement())
+        {
             return;
         }
     }
 }
 
-void XmlObject::copy(const XmlObject& other) {
+void XmlObject::copy(const XmlObject& other)
+{
     childList.clear();
     attributes.clear();
     setObjectName(other.getObjectName());
     setTextValue(other.getTextValue());
-    for(QString attr : other.attributes.keys()) {
+    for (QString attr : other.attributes.keys())
+    {
         attributes[attr] = other.attributes[attr];
     }
-    for(int i = 0; i < other.childCount(); i++) {
+    for (int i = 0; i < other.childCount(); i++)
+    {
         addChild(other.childAt(i));
     }
 }
 
+QString XmlObject::getTextValue() const { return textValue; }
 
-QString XmlObject::getTextValue() const {
-    return textValue;
-}
+void XmlObject::setTextValue(const QString& value) { textValue = value; }
 
-void XmlObject::setTextValue(const QString& value) {
-    textValue = value;
-}
-
-QList<XmlObject*> XmlObject::deepSearchObjects(const QString& objectName) {
-    auto pred = [objectName](const XmlObject * obj) {
-        return obj->getObjectName() == objectName;
-    };
+QList<XmlObject*> XmlObject::deepSearchObjects(const QString& objectName)
+{
+    auto pred = [objectName](const XmlObject* obj)
+    { return obj->getObjectName() == objectName; };
     return deepSearchObjects(pred);
 }
 
-QList<XmlObject*> XmlObject::deepSearchObjects(std::function<bool (const XmlObject* obj)> predicate) {
+QList<XmlObject*> XmlObject::deepSearchObjects(
+    std::function<bool(const XmlObject* obj)> predicate)
+{
     QList<XmlObject*> results;
 
-    if(predicate(this)) {
+    if (predicate(this))
+    {
         results.append(this);
     }
 
-    for(int i = 0; i < childCount(); i++) {
+    for (int i = 0; i < childCount(); i++)
+    {
         XmlObject* child = getChild(i);
         results.append(child->deepSearchObjects(predicate));
     }
@@ -140,75 +157,83 @@ QList<XmlObject*> XmlObject::deepSearchObjects(std::function<bool (const XmlObje
     return results;
 }
 
-void XmlObject::operator =(const XmlObject& other) {
-    copy(other);
-}
+void XmlObject::operator=(const XmlObject& other) { copy(other); }
 
-void XmlObject::removeChild(int i) {
-    if( i < childCount())
+void XmlObject::removeChild(int i)
+{
+    if (i < childCount())
         childList.removeAt(i);
 }
 
-void XmlObject::swapChildAt(int i, int j) {
-    if(i > 0 && j > 0 && i < childCount() && j < childCount()) {
+void XmlObject::swapChildAt(int i, int j)
+{
+    if (i > 0 && j > 0 && i < childCount() && j < childCount())
+    {
         childList.swapItemsAt(i, j);
     }
 }
 
-QString XmlObject::getChildObjectValue(const QString& objectName) {
-    for(XmlObject child : childList) {
-        if(child.getObjectName() == objectName) {
+QString XmlObject::getChildObjectValue(const QString& objectName)
+{
+    for (XmlObject child : childList)
+    {
+        if (child.getObjectName() == objectName)
+        {
             return child.getTextValue();
         }
     }
     return "";
 }
 
-void XmlObject::clearAttributes() {
-    attributes.clear();
-}
+void XmlObject::clearAttributes() { attributes.clear(); }
 
-void XmlObject::clearChilds() {
-    childList.clear();
-}
+void XmlObject::clearChilds() { childList.clear(); }
 
-void XmlObject::reset() {
+void XmlObject::reset()
+{
     setObjectName("");
     clearChilds();
     clearAttributes();
 }
 
-bool XmlObject::isEmpty() {
-    return getObjectName() == "" && childList.isEmpty() && getTextValue() == "" && attributes.isEmpty();
+bool XmlObject::isEmpty()
+{
+    return getObjectName() == "" && childList.isEmpty() &&
+           getTextValue() == "" && attributes.isEmpty();
 }
 
-
-QString XmlObject::getAttribute(const QString& name, const QString& defaultValue) const {
-    if(attributes.contains(name)) {
+QString XmlObject::getAttribute(const QString& name,
+                                const QString& defaultValue) const
+{
+    if (attributes.contains(name))
+    {
         return attributes[name];
     }
 
     return defaultValue;
 }
 
-bool XmlObject::hasAttribute(const QString& name) const {
+bool XmlObject::hasAttribute(const QString& name) const
+{
     return attributes.contains(name);
 }
 
-int XmlObject::attributeCount() const {
-    return attributes.count();
-}
+int XmlObject::attributeCount() const { return attributes.count(); }
 
-QMapIterator<QString, QString> XmlObject::attributesIterator() const {
+QMapIterator<QString, QString> XmlObject::attributesIterator() const
+{
     return QMapIterator<QString, QString>(attributes);
 }
 
-bool XmlObject::getIntAttribute(const QString& name, int& value) const {
+bool XmlObject::getAttribute(const QString& name, int& value) const
+{
     QString val = getAttribute(name);
     bool ok;
-    if(val != "") {
+    if (val != "")
+    {
         int temp = val.toInt(&ok);
-        if(ok) {
+        if (ok)
+        {
             value = temp;
             return true;
         }
@@ -216,12 +241,15 @@ bool XmlObject::getIntAttribute(const QString& name, int& value) const {
     return false;
 }
 
-bool XmlObject::getFloatAttribute(const QString& name, float& value) const {
+bool XmlObject::getAttribute(const QString& name, float& value) const
+{
     QString val = getAttribute(name);
     bool ok;
-    if(val != "") {
+    if (val != "")
+    {
         float temp = val.toFloat(&ok);
-        if(ok) {
+        if (ok)
+        {
             value = temp;
             return true;
         }
@@ -229,48 +257,49 @@ bool XmlObject::getFloatAttribute(const QString& name, float& value) const {
     return false;
 }
 
-void XmlObject::addAttribute(const QString& name, const QString& value) {
+void XmlObject::addAttribute(const QString& name, const QString& value)
+{
     attributes[name] = value;
 }
 
-void XmlObject::addAttribute(const QString& name, int value) {
+void XmlObject::addAttribute(const QString& name, int value)
+{
     addAttribute(name, QString::number(value));
 }
 
-int XmlObject::addChild(const XmlObject& c) {
+void XmlObject::addAttribute(const QString& name, float value)
+{
+    addAttribute(name, QString::number(value));
+}
+
+int XmlObject::addChild(const XmlObject& c)
+{
     childList.append(c);
     return childList.count() - 1;
 }
 
-void XmlObject::addChilds(const QList<XmlObject>& childs) {
+void XmlObject::addChilds(const QList<XmlObject>& childs)
+{
     childList.append(childs);
 }
 
-QString XmlObject::getObjectName() const {
-    return xmlObjectName;
-}
+QString XmlObject::getObjectName() const { return xmlObjectName; }
 
-void XmlObject::setObjectName(const QString& value) {
-    xmlObjectName = value;
-}
+void XmlObject::setObjectName(const QString& value) { xmlObjectName = value; }
 
-int XmlObject::childCount() const {
-    return childList.count();
-}
+int XmlObject::childCount() const { return childList.count(); }
 
-XmlObject XmlObject::childAt(int index) const {
-    return childList.at(index);
-}
+XmlObject XmlObject::childAt(int index) const { return childList.at(index); }
 
-XmlObject XmlObject::searchChild(const QString& name) const {
-    for(int i = 0; i < childCount(); i++) {
-        if(childList[i].getObjectName() == name) {
-            return childList[i];
-        }
-    }
-    return XmlObject();
-}
+int XmlObject::searchChild(const QString& name) const
+{
+    for (int i = 0; i < childCount(); i++)
+        if (childList[i].getObjectName() == name)
+            return i;
 
-XmlObject* XmlObject::getChild(int index) {
-    return &childList[index];
+    return -1;
 }
+
+XmlObject* XmlObject::getChild(int index) { return &childList[index]; }
+
+QMap<QString, QString> XmlObject::getAttributes() const { return attributes; }
\ No newline at end of file
diff --git a/Core/xmlobject.h b/Core/xmlobject.h
index 9f133a17d46379b6555e88e2c203cb5a9e073462..22080dbc0475d4379c70d8523fb9177363fac9d6 100644
--- a/Core/xmlobject.h
+++ b/Core/xmlobject.h
@@ -1,39 +1,43 @@
 #ifndef XMLOBJECT_H
 #define XMLOBJECT_H
 
-
 #include <QMap>
-#include <QXmlStreamWriter>
-#include <QXmlStreamReader>
 #include <QMapIterator>
+#include <QXmlStreamReader>
+#include <QXmlStreamWriter>
 
-class XmlObject {
-  public:
+class XmlObject
+{
+public:
     XmlObject(const QString& objectName = "Object");
     XmlObject(const XmlObject& other);
 
     bool loadFromFile(const QString& filePath);
-    bool writeToFile(const QString& filePath, const QString& codec = "UTF-8") const;
+    bool writeToFile(const QString& filePath,
+                     const QString& codec = "UTF-8") const;
 
     QString toXml() const;
     void fromXml(const QString& txt);
 
-    QString getAttribute(const QString& name, const QString& defaultValue = "") const;
+    QString getAttribute(const QString& name,
+                         const QString& defaultValue = "") const;
     bool hasAttribute(const QString& name) const;
     int attributeCount() const;
     QMapIterator<QString, QString> attributesIterator() const;
 
     /*
-     * Get the value of "value" if the attribute with name "name" exist and is an integer
+     * Get the value of "value" if the attribute with name "name" exist and is
+     * an integer
      */
-    bool getIntAttribute(const QString& name, int& value) const;
-    bool getFloatAttribute(const QString& name, float& value) const;
+    bool getAttribute(const QString& name, int& value) const;
+    bool getAttribute(const QString& name, float& value) const;
     /*
      * addAttribute create a new attribute with name "name" and value "value"
      * If the attribute already exist, it change its value
      */
     void addAttribute(const QString& name, const QString& value);
     void addAttribute(const QString& name, int value);
+    void addAttribute(const QString& name, float value);
     int addChild(const XmlObject& c);
     void addChilds(const QList<XmlObject>& childs);
 
@@ -42,7 +46,7 @@ class XmlObject {
 
     int childCount() const;
     XmlObject childAt(int index) const;
-    XmlObject searchChild(const QString& name) const;
+    int searchChild(const QString& name) const;
     /*
      * getChild Returns the child at index position as a modifiable reference.
      * index must be a valid index position in the list
@@ -59,10 +63,11 @@ class XmlObject {
     /*
      * deepSearchObjects return all the child objects that satisfy the predicate
      */
-    QList<XmlObject*> deepSearchObjects(std::function<bool(const XmlObject* obj)> predicate);
+    QList<XmlObject*> deepSearchObjects(
+        std::function<bool(const XmlObject* obj)> predicate);
     QList<XmlObject*> deepSearchObjects(const QString& objectName);
 
-    void operator = (const XmlObject& other );
+    void operator=(const XmlObject& other);
     void removeChild(int i);
 
     /*
@@ -78,17 +83,19 @@ class XmlObject {
     void reset();
 
     bool isEmpty();
-  protected:
+
+    QMap<QString, QString> getAttributes() const;
+
+protected:
     void toXml(QXmlStreamWriter* xmlWriter) const;
     void fromXml(QXmlStreamReader* xmlReader);
     void copy(const XmlObject& other);
 
-  private:
+private:
     QMap<QString, QString> attributes;
     QList<XmlObject> childList;
-    QString textValue = "";
+    QString textValue     = "";
     QString xmlObjectName = "";
-
 };
 
-#endif // XMLOBJECT_H
+#endif  // XMLOBJECT_H
diff --git a/Modules/CommandPad/MessageFormElement.cpp b/Modules/CommandPad/MessageFormElement.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b0feed91cf32e1ae82f6f13785ef53af601ac59b
--- /dev/null
+++ b/Modules/CommandPad/MessageFormElement.cpp
@@ -0,0 +1,311 @@
+#include "MessageFormElement.h"
+
+#include <Modules/skywardhubstrings.h>
+
+MessageFormElement::MessageFormElement() {}
+
+MessageFormElement::~MessageFormElement()
+{
+    for (auto key : comboBoxMap.keys())
+    {
+        delete comboBoxMap[key].first;
+        delete comboBoxMap[key].second;
+    }
+
+    for (auto key : floatMap.keys())
+    {
+        delete std::get<0>(floatMap[key]);
+        delete std::get<1>(floatMap[key]);
+    }
+
+    for (auto key : integerMap.keys())
+    {
+        delete std::get<0>(integerMap[key]);
+        delete std::get<1>(integerMap[key]);
+    }
+}
+
+bool MessageFormElement::addComboBox(QString id, QString label,
+                                     const QMap<QString, int>& options)
+{
+    if (!comboBoxMap.contains(id) && !floatMap.contains(id) &&
+        !integerMap.contains(id))
+    {
+        auto* comboBox = new QComboBox;
+        comboBox->setSizePolicy(
+            QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum));
+
+        for (auto key : options.keys())
+            comboBox->addItem(key, options[key]);
+
+        comboBoxMap[id] = {new QLabel(label), comboBox};
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+bool MessageFormElement::addFloat(QString id, QString label, float min,
+                                  float max, int decimals)
+{
+    if (!comboBoxMap.contains(id) && !floatMap.contains(id) &&
+        !integerMap.contains(id))
+    {
+        auto* lineEdit = new QLineEdit;
+        lineEdit->setSizePolicy(
+            QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum));
+        lineEdit->setValidator(new QDoubleValidator(min, max, decimals));
+        floatMap[id] = {new QLabel(label), lineEdit, min, max, decimals};
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+bool MessageFormElement::addInteger(QString id, QString label, int min, int max)
+{
+    if (!comboBoxMap.contains(id) && !floatMap.contains(id) &&
+        !integerMap.contains(id))
+    {
+        auto* lineEdit = new QLineEdit;
+        lineEdit->setSizePolicy(
+            QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum));
+        lineEdit->setValidator(new QIntValidator(min, max));
+        integerMap[id] = {new QLabel(label), lineEdit, min, max};
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+XmlObject MessageFormElement::toXmlObject()
+{
+    XmlObject comboBoxList("combo_box_list");
+    for (auto key : comboBoxMap.keys())
+    {
+        auto comboBox = comboBoxMap[key];
+        XmlObject comboBoxXml("combo_box");
+        comboBoxXml.addAttribute("id", key);
+        comboBoxXml.addAttribute("label", comboBox.first->text());
+        comboBoxXml.addAttribute("text", comboBox.second->currentText());
+        comboBoxList.addChild(comboBoxXml);
+    }
+
+    XmlObject floatList("float_list");
+    for (auto key : floatMap.keys())
+    {
+        auto floatField = floatMap[key];
+        XmlObject floatFieldXml("float_field");
+        floatFieldXml.addAttribute("id", key);
+        floatFieldXml.addAttribute("label", std::get<0>(floatField)->text());
+        floatFieldXml.addAttribute("text", std::get<1>(floatField)->text());
+        floatFieldXml.addAttribute("min", std::get<2>(floatField));
+        floatFieldXml.addAttribute("max", std::get<3>(floatField));
+        floatFieldXml.addAttribute("decimals", std::get<4>(floatField));
+        floatList.addChild(floatFieldXml);
+    }
+
+    XmlObject integerList("integer_list");
+    for (auto key : floatMap.keys())
+    {
+        auto integerField = floatMap[key];
+        XmlObject integerFieldXml("integer_field");
+        integerFieldXml.addAttribute("id", key);
+        integerFieldXml.addAttribute("label",
+                                     std::get<0>(integerField)->text());
+        integerFieldXml.addAttribute("text", std::get<1>(integerField)->text());
+        integerFieldXml.addAttribute("min", std::get<2>(integerField));
+        integerFieldXml.addAttribute("max", std::get<3>(integerField));
+        integerList.addChild(integerFieldXml);
+    }
+
+    XmlObject configuration("configuration");
+    configuration.addChild(comboBoxList);
+    configuration.addChild(floatList);
+    configuration.addChild(integerList);
+
+    return configuration;
+}
+
+void MessageFormElement::fromXmlObject(const XmlObject& obj)
+{
+    int comboBoxListIndex = obj.searchChild("combo_box_list");
+    if (comboBoxListIndex != -1)
+    {
+        auto comboBoxList = obj.childAt(comboBoxListIndex);
+        for (int i = 0; i < comboBoxList.childCount(); i++)
+        {
+            auto comboBoxXml = comboBoxList.childAt(i);
+            auto key         = comboBoxXml.getAttribute("id");
+            if (comboBoxMap.contains(key))
+            {
+                auto comboBox = comboBoxMap[key];
+                comboBox.first->setText(comboBoxXml.getAttribute("label"));
+                comboBox.second->setCurrentText(
+                    comboBoxXml.getAttribute("text"));
+            }
+        }
+    }
+
+    int floatListIndex = obj.searchChild("float_list");
+    if (floatListIndex != -1)
+    {
+        auto floatList = obj.childAt(floatListIndex);
+        for (int i = 0; i < floatList.childCount(); i++)
+        {
+            auto floatFieldXml = floatList.childAt(i);
+            auto key           = floatFieldXml.getAttribute("id");
+            if (floatMap.contains(key))
+            {
+                auto floatField = floatMap[key];
+                std::get<0>(floatField)
+                    ->setText(floatFieldXml.getAttribute("label"));
+                std::get<1>(floatField)
+                    ->setText(floatFieldXml.getAttribute("text"));
+                floatFieldXml.getAttribute("min", std::get<2>(floatField));
+                floatFieldXml.getAttribute("max", std::get<3>(floatField));
+                floatFieldXml.getAttribute("decimals", std::get<4>(floatField));
+                std::get<1>(floatField)
+                    ->setValidator(new QDoubleValidator(
+                        std::get<2>(floatField), std::get<3>(floatField),
+                        std::get<4>(floatField)));
+            }
+        }
+    }
+
+    int integerListIndex = obj.searchChild("integer_list");
+    if (integerListIndex != -1)
+    {
+        auto floatList = obj.childAt(integerListIndex);
+        for (int i = 0; i < floatList.childCount(); i++)
+        {
+            auto integerFieldXml = floatList.childAt(i);
+            auto key             = integerFieldXml.getAttribute("id");
+            if (integerMap.contains(key))
+            {
+                auto integerField = integerMap[key];
+                std::get<0>(integerField)
+                    ->setText(integerFieldXml.getAttribute("label"));
+                std::get<1>(integerField)
+                    ->setText(integerFieldXml.getAttribute("text"));
+                integerFieldXml.getAttribute("min", std::get<2>(integerField));
+                integerFieldXml.getAttribute("max", std::get<3>(integerField));
+                std::get<1>(integerField)
+                    ->setValidator(new QIntValidator(
+                        std::get<2>(integerField), std::get<3>(integerField)));
+            }
+        }
+    }
+}
+
+void MessageFormElement::applyToGridLayout(QGridLayout* layout)
+{
+    for (auto key : comboBoxMap.keys())
+    {
+        auto label    = comboBoxMap[key].first;
+        auto comboBox = comboBoxMap[key].second;
+
+        int rows = layout->rowCount();
+        layout->addWidget(label, rows, 0, Qt::AlignRight);
+        layout->addWidget(comboBox, rows, 1);
+
+        label->show();
+        comboBox->show();
+    }
+
+    for (auto key : floatMap.keys())
+    {
+        auto label      = std::get<0>(floatMap[key]);
+        auto floatField = std::get<1>(floatMap[key]);
+
+        int rows = layout->rowCount();
+        layout->addWidget(label, rows, 0, Qt::AlignRight);
+        layout->addWidget(floatField, rows, 1);
+
+        label->show();
+        floatField->show();
+    }
+
+    for (auto key : integerMap.keys())
+    {
+        auto label        = std::get<0>(integerMap[key]);
+        auto integerField = std::get<1>(integerMap[key]);
+
+        int rows = layout->rowCount();
+        layout->addWidget(label, rows, 0, Qt::AlignRight);
+        layout->addWidget(integerField, rows, 1);
+
+        label->show();
+        integerField->show();
+    }
+}
+
+void MessageFormElement::removeFromGridLayout(QGridLayout* layout)
+{
+    for (auto key : comboBoxMap.keys())
+    {
+        auto label    = comboBoxMap[key].first;
+        auto comboBox = comboBoxMap[key].second;
+
+        layout->removeWidget(label);
+        layout->removeWidget(comboBox);
+
+        label->hide();
+        comboBox->hide();
+    }
+
+    for (auto key : floatMap.keys())
+    {
+        auto label      = std::get<0>(floatMap[key]);
+        auto floatField = std::get<1>(floatMap[key]);
+
+        layout->removeWidget(label);
+        layout->removeWidget(floatField);
+
+        label->hide();
+        floatField->hide();
+    }
+
+    for (auto key : integerMap.keys())
+    {
+        auto label        = std::get<0>(integerMap[key]);
+        auto integerField = std::get<1>(integerMap[key]);
+
+        layout->removeWidget(label);
+        layout->removeWidget(integerField);
+
+        label->hide();
+        integerField->hide();
+    }
+}
+
+ModuleMessage MessageFormElement::prepareMessage(const QString& messageId)
+{
+    ModuleMessage message(SkywardHubStrings::commandsTopic + "/" + messageId);
+
+    for (auto key : comboBoxMap.keys())
+    {
+        auto comboBox = comboBoxMap[key].second;
+        message.setField(key, (uint64_t)comboBox->currentData().toInt());
+    }
+
+    for (auto key : floatMap.keys())
+    {
+        auto floatField = std::get<1>(floatMap[key]);
+        message.setField(key, floatField->text());
+    }
+
+    for (auto key : integerMap.keys())
+    {
+        auto integerField = std::get<1>(integerMap[key]);
+        message.setField(key, integerField->text());
+    }
+
+    return message;
+}
\ No newline at end of file
diff --git a/Modules/CommandPad/MessageFormElement.h b/Modules/CommandPad/MessageFormElement.h
new file mode 100644
index 0000000000000000000000000000000000000000..81946d49e7000e38e15db99bd564601a6fbd796a
--- /dev/null
+++ b/Modules/CommandPad/MessageFormElement.h
@@ -0,0 +1,61 @@
+#pragma once
+
+#include <Core/Message/modulemessage.h>
+#include <Core/xmlobject.h>
+
+#include <QComboBox>
+#include <QGridLayout>
+#include <QLabel>
+#include <QLineEdit>
+#include <QMap>
+#include <QString>
+
+class MessageFormElement
+{
+public:
+    MessageFormElement();
+
+    ~MessageFormElement();
+
+    /**
+     * @brief Adds a new combo box field to the form.
+     *
+     * @return false if there is already a field with the given id.
+     */
+    bool addComboBox(QString id, QString label,
+                     const QMap<QString, int>& options);
+
+    /**
+     * @brief Adds a new float field to the form.
+     *
+     * @return false if there is already a field with the given id.
+     */
+    bool addFloat(QString id, QString label,
+                  float min    = std::numeric_limits<float>::min(),
+                  float max    = std::numeric_limits<float>::max(),
+                  int decimals = 2);
+
+    /**
+     * @brief Adds a new integer field to the form.
+     *
+     * @return false if there is already a field with the given id.
+     */
+    bool addInteger(QString id, QString label,
+                    int min = std::numeric_limits<int>::min(),
+                    int max = std::numeric_limits<int>::max());
+
+    XmlObject toXmlObject();
+
+    void fromXmlObject(const XmlObject& obj);
+
+    void applyToGridLayout(QGridLayout* layout);
+
+    void removeFromGridLayout(QGridLayout* layout);
+
+    ModuleMessage prepareMessage(const QString& messageId);
+
+private:
+    QMap<QString, QPair<QLabel*, QComboBox*>> comboBoxMap;
+    QMap<QString, std::tuple<QLabel*, QLineEdit*, float, float, int>> floatMap;
+    QMap<QString, std::tuple<QLabel*, QLineEdit*, int, int>> integerMap;
+};
diff --git a/Modules/CommandPad/commandpad.cpp b/Modules/CommandPad/commandpad.cpp
index 2967182168f612c798885e882ea226846d73a83b..411d82bf656926ab6b537a71f289c051d8ef1830 100644
--- a/Modules/CommandPad/commandpad.cpp
+++ b/Modules/CommandPad/commandpad.cpp
@@ -2,253 +2,252 @@
 
 #include <QVBoxLayout>
 
-const QMap<QString, uint8_t> CommandPad::systemTMList{
-    {"MAV_SYS_ID", 1},           {"MAV_FSM_ID", 2},
-    {"MAV_PIN_OBS_ID", 3},       {"MAV_LOGGER_ID", 4},
-    {"MAV_MAVLINK_STATS", 5},    {"MAV_TASK_STATS_ID", 6},
-    {"MAV_ADA_ID", 8},           {"MAV_NAS_ID", 9},
-    {"MAV_CAN_ID", 10},          {"MAV_FLIGHT_ID", 11},
-    {"MAV_FLIGHT_STATS_ID", 12}, {"MAV_SENSORS_STATE_ID", 13}};
-
-const QMap<QString, uint8_t> CommandPad::sensorsTMList = {
-    {"MAV_GPS_ID", 1},
-    {"MAV_BMX160_ID", 2},
-    {"MAV_VN100_ID", 3},
-    {"MAV_MPU9250_ID", 4},
-    {"MAV_ADS_ID", 5},
-    {"MAV_MS5803_ID", 6},
-    {"MAV_BME280_ID", 7},
-    {"MAV_CURRENT_SENSE_ID", 8},
-    {"MAV_LIS3MDL_ID", 9},
-    {"MAV_DPL_PRESS_ID", 10},
-    {"MAV_STATIC_PRESS_ID", 11},
-    {"MAV_PITOT_PRESS_ID", 12},
-    {"MAV_BATTERY_VOLTAGE_ID", 13},
-    {"MAV_STRAIN_GAUGE_ID", 14},
+#include "Modules/Mavlink/mavlinkversionheader.h"
+
+const QStringList CommandPad::messagesList{
+    "PING_TC",
+    "COMMAND_TC",
+    "SYSTEM_TM_REQUEST_TC",
+    "SENSOR_TM_REQUEST_TC",
+    "SERVO_TM_REQUEST_TC",
+    "SET_SERVO_ANGLE_TC",
+    "WIGGLE_SERVO_TC",
+    "RESET_SERVO_TC",
+    "SET_REFERENCE_ALTITUDE_TC",
+    "SET_REFERENCE_TEMPERATURE_TC",
+    "SET_ORIENTATION_TC",
+    "SET_COORDINATES_TC",
+    "RAW_EVENT_TC",
+    "SET_DEPLOYMENT_ALTITUDE_TC",
+    "SET_TARGET_COORDINATES_TC",
+    "SET_ALGORITHM_TC",
 };
 
-const QMap<QString, uint8_t> CommandPad::mavCommandList = {
-    {"MAV_CMD_ARM", 1},
-    {"MAV_CMD_DISARM", 2},
-    {"MAV_CMD_CALIBRATE", 3},
-    {"MAV_CMD_FORCE_INIT", 4},
-    {"MAV_CMD_FORCE_LAUNCH", 5},
-    {"MAV_CMD_FORCE_LANDING", 6},
-    {"MAV_CMD_FORCE_APOGEE", 7},
-    {"MAV_CMD_FORCE_EXPULSION", 8},
-    {"MAV_CMD_FORCE_MAIN", 9},
-    {"MAV_CMD_START_LOGGING", 10},
-    {"MAV_CMD_CLOSE_LOG", 11},
-    {"MAV_CMD_FORCE_REBOOT", 12},
-    {"MAV_CMD_ENTER_TEST_MODE", 13},
-    {"MAV_CMD_EXIT_TEST_MODE", 14},
-    {"MAV_CMD_START_RECORDING", 15},
-    {"MAV_CMD_STOP_RECORDING", 16},
+const QMap<QString, int> CommandPad::systemTmList{
+    {"MAV_SYS_ID", MAV_SYS_ID},
+    {"MAV_FSM_ID", MAV_FSM_ID},
+    {"MAV_PIN_OBS_ID", MAV_PIN_OBS_ID},
+    {"MAV_LOGGER_ID", MAV_LOGGER_ID},
+    {"MAV_MAVLINK_STATS", MAV_MAVLINK_STATS},
+    {"MAV_TASK_STATS_ID", MAV_TASK_STATS_ID},
+    {"MAV_ADA_ID", MAV_ADA_ID},
+    {"MAV_NAS_ID", MAV_NAS_ID},
+    {"MAV_CAN_ID", MAV_CAN_ID},
+    {"MAV_FLIGHT_ID", MAV_FLIGHT_ID},
+    {"MAV_STATS_ID", MAV_STATS_ID},
+    {"MAV_SENSORS_STATE_ID", MAV_SENSORS_STATE_ID},
 };
 
-const QMap<QString, uint8_t> CommandPad::servosList = {
-    {"AIRBRAKES_SERVO", 1},
-    {"EXPULSION_SERVO", 2},
-    {"PARAFOIL_SERVO1", 3},
-    {"PARAFOIL_SERVO2", 4},
+const QMap<QString, int> CommandPad::sensorsList{
+    {"MAV_GPS_ID", MAV_GPS_ID},
+    {"MAV_BMX160_ID", MAV_BMX160_ID},
+    {"MAV_VN100_ID", MAV_VN100_ID},
+    {"MAV_MPU9250_ID", MAV_MPU9250_ID},
+    {"MAV_ADS_ID", MAV_ADS_ID},
+    {"MAV_MS5803_ID", MAV_MS5803_ID},
+    {"MAV_BME280_ID", MAV_BME280_ID},
+    {"MAV_CURRENT_SENSE_ID", MAV_CURRENT_SENSE_ID},
+    {"MAV_LIS3MDL_ID", MAV_LIS3MDL_ID},
+    {"MAV_DPL_PRESS_ID", MAV_DPL_PRESS_ID},
+    {"MAV_STATIC_PRESS_ID", MAV_STATIC_PRESS_ID},
+    {"MAV_PITOT_PRESS_ID", MAV_PITOT_PRESS_ID},
+    {"MAV_BATTERY_VOLTAGE_ID", MAV_BATTERY_VOLTAGE_ID},
+    {"MAV_STRAIN_GAUGE_ID", MAV_STRAIN_GAUGE_ID},
 };
 
-CommandPad::CommandPad(QWidget *parent) : DefaultModule(parent) {
+const QMap<QString, int> CommandPad::commandsList{
+    {"MAV_CMD_ARM", MAV_CMD_ARM},
+    {"MAV_CMD_DISARM", MAV_CMD_DISARM},
+    {"MAV_CMD_CALIBRATE", MAV_CMD_CALIBRATE},
+    {"MAV_CMD_FORCE_INIT", MAV_CMD_FORCE_INIT},
+    {"MAV_CMD_FORCE_LAUNCH", MAV_CMD_FORCE_LAUNCH},
+    {"MAV_CMD_FORCE_LANDING", MAV_CMD_FORCE_LANDING},
+    {"MAV_CMD_FORCE_APOGEE", MAV_CMD_FORCE_APOGEE},
+    {"MAV_CMD_FORCE_EXPULSION", MAV_CMD_FORCE_EXPULSION},
+    {"MAV_CMD_FORCE_MAIN", MAV_CMD_FORCE_MAIN},
+    {"MAV_CMD_START_LOGGING", MAV_CMD_START_LOGGING},
+    {"MAV_CMD_CLOSE_LOG", MAV_CMD_CLOSE_LOG},
+    {"MAV_CMD_FORCE_REBOOT", MAV_CMD_FORCE_REBOOT},
+    {"MAV_CMD_ENTER_TEST_MODE", MAV_CMD_ENTER_TEST_MODE},
+    {"MAV_CMD_EXIT_TEST_MODE", MAV_CMD_EXIT_TEST_MODE},
+    {"MAV_CMD_START_RECORDING", MAV_CMD_START_RECORDING},
+    {"MAV_CMD_STOP_RECORDING", MAV_CMD_STOP_RECORDING},
+};
+
+const QMap<QString, int> CommandPad::servosList{
+    {"AIRBRAKES_SERVO", AIRBRAKES_SERVO},
+    {"EXPULSION_SERVO", EXPULSION_SERVO},
+    {"PARAFOIL_SERVO1", PARAFOIL_SERVO1},
+    {"PARAFOIL_SERVO2", PARAFOIL_SERVO2},
+};
+
+CommandPad::CommandPad(QWidget *parent) : DefaultModule(parent)
+{
     setupUi();
     defaultContextMenuSetup();
 }
 
-CommandPad::~CommandPad() {}
+CommandPad::~CommandPad()
+{
+    delete messagesListComboBox;
+    for (auto key : formElements.keys())
+        delete formElements[key];
+    delete formGridLayout;
+}
 
 QWidget *CommandPad::toWidget() { return this; }
 
-XmlObject CommandPad::toXmlObject() {
-    return XmlObject(getName(ModuleId::COMMANDPAD));
-}
+XmlObject CommandPad::toXmlObject()
+{
+    XmlObject obj = XmlObject(getName(ModuleId::COMMANDPAD));
 
-void CommandPad::fromXmlObject(const XmlObject &xmlObject) {
-    Q_UNUSED(xmlObject);
+    auto key = messagesListComboBox->currentText();
+    if (formElements.contains(key))
+    {
+        obj.addAttribute("message_id", key);
+        obj.addChild(formElements[key]->toXmlObject());
+    }
+
+    return obj;
 }
 
-#define _CMD(id, strName)                     \
-    QWidget *id = new QWidget;                \
-    QFormLayout *id##_form = new QFormLayout; \
-    id->setLayout(id##_form);                 \
-    stacked->addWidget(id);                   \
-    commandComboBox->addItem(strName);
-
-#define _CMD_FLOAT_PROP(id, idProperty)                           \
-    QLineEdit *id##_##idProperty = new QLineEdit;                 \
-    id##_##idProperty->setValidator(                              \
-        new QDoubleValidator(-10000.0, 10000.0, 3, this));        \
-    id##_##idProperty->setSizePolicy(                             \
-        QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed)); \
-    id##_form->addRow(tr(#idProperty ": "), id##_##idProperty);
-
-#define _CMD_UINT8_PROP(id, idProperty)                               \
-    QLineEdit *id##_##idProperty = new QLineEdit;                     \
-    id##_##idProperty->setValidator(new QIntValidator(0, 255, this)); \
-    id##_##idProperty->setSizePolicy(                                 \
-        QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));     \
-    id##_form->addRow(tr(#idProperty ": "), id##_##idProperty);
-
-#define _CMD_COMBO_PROP(id, idProperty, map)                      \
-    QComboBox *id##_##idProperty = new QComboBox;                 \
-    id##_##idProperty->setSizePolicy(                             \
-        QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed)); \
-    id##_##idProperty->insertItems(0, map.keys());                \
-    id##_form->addRow(tr(#idProperty ": "), id##_##idProperty);
-
-#define _CMD_END
-
-#define _SEND(id, strName)                                             \
-    if (commandComboBox->currentText() == strName) {                   \
-        QTime time = QTime::currentTime();                             \
-        ModuleMessage message(SkywardHubStrings::commandsTopic + "/" + \
-                              strName);                                \
-        message.setField("timestamp", (uint64_t)time.msecsSinceStartOfDay());
-
-#define _SEND_FLOAT_PROP(id, idProperty) \
-    message.setField(#idProperty, id##_##idProperty->text().toDouble());
-
-#define _SEND_UINT8_PROP(id, idProperty) \
-    message.setField(#idProperty, (uint64_t)id##_##idProperty->text().toInt());
-
-#define _SEND_COMBO_PROP(id, idProperty, map) \
-    message.setField(#idProperty,             \
-                     (uint64_t)map[id##_##idProperty->currentText()]);
-
-#define _SEND_END                                           \
-    getCore()->getModuleMessagesBroker()->publish(message); \
+void CommandPad::fromXmlObject(const XmlObject &obj)
+{
+    int configurationIndex = obj.searchChild("configuration");
+    if (obj.hasAttribute("message_id") && configurationIndex != -1)
+    {
+        auto key = obj.getAttribute("message_id");
+
+        if (formElements.contains(key))
+        {
+            auto configuration = obj.childAt(configurationIndex);
+            formElements[key]->fromXmlObject(configuration);
+            messagesListComboBox->setCurrentText(key);
+        }
     }
+}
+
+void CommandPad::removeWidgetsFromForm()
+{
+    QLayoutItem *child;
+    while ((child = formGridLayout->takeAt(0)) != nullptr)
+        formGridLayout->removeWidget(child->widget());
+}
 
-void CommandPad::setupUi() {
-    QStackedWidget *stacked = new QStackedWidget;
+void CommandPad::setupUi()
+{
+    QVBoxLayout *outerLayout = new QVBoxLayout;
+    outerLayout->addStretch();
 
-    QComboBox *commandComboBox = new QComboBox;
-    commandComboBox->setSizePolicy(
+    messagesListComboBox = new QComboBox;
+    messagesListComboBox->setSizePolicy(
         QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
-    connect(commandComboBox,
-            QOverload<int>::of(&QComboBox::currentIndexChanged), this,
-            [=](int idx) { stacked->setCurrentIndex(idx); });
-
-    QFormLayout *form = new QFormLayout;
-    form->addRow(tr("Select command: "), commandComboBox);
-
-    _CMD(ping, "PING_TC")
-    _CMD_END
-    _CMD(command, "COMMAND_TC")
-    _CMD_COMBO_PROP(command, command_id, mavCommandList)
-    _CMD_END
-    _CMD(systemTelemetry, "SYSTEM_TM_REQUEST_TC")
-    _CMD_COMBO_PROP(systemTelemetry, tm_id, systemTMList)
-    _CMD_END
-    _CMD(sensorTelemetry, "SENSOR_TM_REQUEST_TC")
-    _CMD_COMBO_PROP(sensorTelemetry, sensor_id, sensorsTMList)
-    _CMD_END
-    _CMD(servoTelemetry, "SERVO_TM_REQUEST_TC")
-    _CMD_COMBO_PROP(servoTelemetry, servo_id, servosList)
-    _CMD_END
-    _CMD(setServoAngle, "SET_SERVO_ANGLE_TC")
-    _CMD_COMBO_PROP(setServoAngle, servo_id, servosList)
-    _CMD_FLOAT_PROP(setServoAngle, angle)
-    _CMD_END
-    _CMD(wiggleServo, "WIGGLE_SERVO_TC")
-    _CMD_COMBO_PROP(wiggleServo, servo_id, servosList)
-    _CMD_END
-    _CMD(resetServo, "RESET_SERVO_TC")
-    _CMD_COMBO_PROP(resetServo, servo_id, servosList)
-    _CMD_END
-    _CMD(setReferenceAltitude, "SET_REFERENCE_ALTITUDE_TC")
-    _CMD_FLOAT_PROP(setReferenceAltitude, ref_altitude)
-    _CMD_END
-    _CMD(setReferenceTemperature, "SET_REFERENCE_TEMPERATURE_TC")
-    _CMD_FLOAT_PROP(setReferenceTemperature, ref_temp)
-    _CMD_END
-    _CMD(setDeploymentAltitude, "SET_DEPLOYMENT_ALTITUDE_TC")
-    _CMD_FLOAT_PROP(setDeploymentAltitude, dpl_altitude)
-    _CMD_END
-    _CMD(setOrientation, "SET_ORIENTATION_TC")
-    _CMD_FLOAT_PROP(setOrientation, yaw)
-    _CMD_FLOAT_PROP(setOrientation, pitch)
-    _CMD_FLOAT_PROP(setOrientation, roll)
-    _CMD_END
-    _CMD(setCoordinates, "SET_COORDINATES_TC")
-    _CMD_FLOAT_PROP(setCoordinates, latitude)
-    _CMD_FLOAT_PROP(setCoordinates, longitude)
-    _CMD_END
-    _CMD(rawEvent, "RAW_EVENT_TC")
-    _CMD_UINT8_PROP(rawEvent, topic_id)
-    _CMD_UINT8_PROP(rawEvent, event_id)
-    _CMD_END
-    _CMD(targetCoordinates, "SET_TARGET_COORDINATES_TC")
-    _CMD_FLOAT_PROP(targetCoordinates, latitude)
-    _CMD_FLOAT_PROP(targetCoordinates, longitude)
-    _CMD_END
-    _CMD(algorithm, "SET_ALGORITHM_TC")
-    _CMD_UINT8_PROP(algorithm, algorithm_number)
-    _CMD_END
-
-    QPushButton *send = new QPushButton(tr("Send"));
-    connect(send, &QPushButton::clicked, [=]() {
-        _SEND(ping, "PING_TC")
-        _SEND_END
-        _SEND(command, "COMMAND_TC")
-        _SEND_COMBO_PROP(command, command_id, mavCommandList)
-        _SEND_END
-        _SEND(systemTelemetry, "SYSTEM_TM_REQUEST_TC")
-        _SEND_COMBO_PROP(systemTelemetry, tm_id, systemTMList)
-        _SEND_END
-        _SEND(sensorTelemetry, "SENSOR_TM_REQUEST_TC")
-        _SEND_COMBO_PROP(sensorTelemetry, sensor_id, sensorsTMList)
-        _SEND_END
-        _SEND(servoTelemetry, "SERVO_TM_REQUEST_TC")
-        _SEND_COMBO_PROP(servoTelemetry, servo_id, servosList)
-        _SEND_END
-        _SEND(setServoAngle, "SET_SERVO_ANGLE_TC")
-        _SEND_COMBO_PROP(setServoAngle, servo_id, servosList)
-        _SEND_FLOAT_PROP(setServoAngle, angle)
-        _SEND_END
-        _SEND(wiggleServo, "WIGGLE_SERVO_TC")
-        _SEND_COMBO_PROP(wiggleServo, servo_id, servosList)
-        _SEND_END
-        _SEND(resetServo, "RESET_SERVO_TC")
-        _SEND_COMBO_PROP(resetServo, servo_id, servosList)
-        _SEND_END
-        _SEND(setReferenceAltitude, "SET_REFERENCE_ALTITUDE_TC")
-        _SEND_FLOAT_PROP(setReferenceAltitude, ref_altitude)
-        _SEND_END
-        _SEND(setReferenceTemperature, "SET_REFERENCE_TEMPERATURE_TC")
-        _SEND_FLOAT_PROP(setReferenceTemperature, ref_temp)
-        _SEND_END
-        _SEND(setDeploymentAltitude, "SET_DEPLOYMENT_ALTITUDE_TC")
-        _SEND_FLOAT_PROP(setDeploymentAltitude, dpl_altitude)
-        _SEND_END
-        _SEND(setOrientation, "SET_ORIENTATION_TC")
-        _SEND_FLOAT_PROP(setOrientation, yaw)
-        _SEND_FLOAT_PROP(setOrientation, pitch)
-        _SEND_FLOAT_PROP(setOrientation, roll)
-        _SEND_END
-        _SEND(setCoordinates, "SET_COORDINATES_TC")
-        _SEND_FLOAT_PROP(setCoordinates, latitude)
-        _SEND_FLOAT_PROP(setCoordinates, longitude)
-        _SEND_END
-        _SEND(rawEvent, "RAW_EVENT_TC")
-        _SEND_UINT8_PROP(rawEvent, topic_id)
-        _SEND_UINT8_PROP(rawEvent, event_id)
-        _SEND_END
-        _SEND(targetCoordinates, "SET_TARGET_COORDINATES_TC")
-        _SEND_FLOAT_PROP(targetCoordinates, latitude)
-        _SEND_FLOAT_PROP(targetCoordinates, longitude)
-        _SEND_END
-        _SEND(algorithm, "SET_ALGORITHM_TC")
-        _SEND_UINT8_PROP(algorithm, algorithm_number)
-        _SEND_END
-    });
-
-    QVBoxLayout *layout = new QVBoxLayout;
-    layout->addLayout(form);
-    layout->addWidget(stacked);
-    layout->addWidget(send);
-    setLayout(layout);
+    messagesListComboBox->addItems(messagesList);
+    outerLayout->addWidget(messagesListComboBox);
+
+    formGridLayout = new QGridLayout;
+    outerLayout->addLayout(formGridLayout);
+
+    QPushButton *sendButton = new QPushButton("Send");
+    outerLayout->addWidget(sendButton);
+
+    setLayout(outerLayout);
+
+    MessageFormElement *element;
+
+    element                 = new MessageFormElement();
+    formElements["PING_TC"] = element;
+
+    element = new MessageFormElement();
+    element->addComboBox("command_id", "Command:", commandsList);
+    formElements["COMMAND_TC"] = element;
+
+    element = new MessageFormElement();
+    element->addComboBox("tm_id", "Telemetry:", systemTmList);
+    formElements["SYSTEM_TM_REQUEST_TC"] = element;
+
+    element = new MessageFormElement();
+    element->addComboBox("sensor_id", "Sensor:", sensorsList);
+    formElements["SENSOR_TM_REQUEST_TC"] = element;
+
+    element = new MessageFormElement();
+    element->addComboBox("servo_id", "Servo:", servosList);
+    formElements["SERVO_TM_REQUEST_TC"] = element;
+
+    element = new MessageFormElement();
+    element->addComboBox("servo_id", "Servo:", servosList);
+    element->addFloat("angle", "Angle:", 0, 180, 2);
+    formElements["SET_SERVO_ANGLE_TC"] = element;
+
+    element = new MessageFormElement();
+    element->addComboBox("servo_id", "Servo:", servosList);
+    formElements["WIGGLE_SERVO_TC"] = element;
+
+    element = new MessageFormElement();
+    element->addComboBox("servo_id", "Servo:", servosList);
+    formElements["RESET_SERVO_TC"] = element;
+
+    element = new MessageFormElement();
+    element->addFloat("ref_altitude", "Altitude:", 0, 9999, 2);
+    formElements["SET_REFERENCE_ALTITUDE_TC"] = element;
+
+    element = new MessageFormElement();
+    element->addFloat("ref_temp", "Temperature:", 0, 999, 2);
+    formElements["SET_REFERENCE_TEMPERATURE_TC"] = element;
+
+    element = new MessageFormElement();
+    element->addFloat("yaw", "Yaw:", -180, 180, 2);
+    element->addFloat("pitch", "Pitch:", -180, 180, 2);
+    element->addFloat("roll", "Roll:", -180, 180, 2);
+    formElements["SET_ORIENTATION_TC"] = element;
+
+    element = new MessageFormElement();
+    element->addFloat("latitude", "Latitude:", -90, 90, 6);
+    element->addFloat("longitude", "Longitude:", -90, 90, 6);
+    formElements["SET_COORDINATES_TC"] = element;
+
+    element = new MessageFormElement();
+    element->addInteger("topic_id", "Topic:", 0, 999);
+    element->addInteger("event_id", "Event:", 0, 999);
+    formElements["RAW_EVENT_TC"] = element;
+
+    element = new MessageFormElement();
+    element->addFloat("ref_altitude", "Altitude:", 0, 9999, 2);
+    formElements["SET_DEPLOYMENT_ALTITUDE_TC"] = element;
+
+    element = new MessageFormElement();
+    element->addFloat("latitude", "Latitude:", -90, 90, 6);
+    element->addFloat("longitude", "Longitude:", -90, 90, 6);
+    formElements["SET_TARGET_COORDINATES_TC"] = element;
+
+    element = new MessageFormElement();
+    element->addInteger("algorithm_number", "Algorithm:", 0, 999);
+    formElements["SET_ALGORITHM_TC"] = element;
+
+    // Set default value
+    currentMessage = "PING_TC";
+    messagesListComboBox->setCurrentText(currentMessage);
+
+    connect(messagesListComboBox, &QComboBox::currentTextChanged, this,
+            [=](QString key)
+            {
+                if (formElements.contains(key))
+                {
+                    formElements[currentMessage]->removeFromGridLayout(
+                        formGridLayout);
+                    formElements[key]->applyToGridLayout(formGridLayout);
+                    currentMessage = key;
+                }
+            });
+
+    connect(sendButton, &QPushButton::clicked,
+            [=]()
+            {
+                auto key = messagesListComboBox->currentText();
+                if (formElements.contains(key))
+                {
+                    auto message = formElements[key]->prepareMessage(key);
+                    getCore()->getModuleMessagesBroker()->publish(message);
+                }
+            });
 }
diff --git a/Modules/CommandPad/commandpad.h b/Modules/CommandPad/commandpad.h
index 44bb73ef8f88130789c817bd18bca72e7a1ade4c..32427b2562aab947ec5cb3a389a1afdca87e98a7 100644
--- a/Modules/CommandPad/commandpad.h
+++ b/Modules/CommandPad/commandpad.h
@@ -1,16 +1,22 @@
 #ifndef COMMANDPAD_H
 #define COMMANDPAD_H
 
+#include <tuple>
+
+#include "MessageFormElement.h"
 #include "Modules/DefaultModule/defaultmodule.h"
 
-class CommandPad : public DefaultModule {
+class CommandPad : public DefaultModule
+{
     Q_OBJECT
 
-  public:
-    static const QMap<QString, uint8_t> systemTMList;
-    static const QMap<QString, uint8_t> sensorsTMList;
-    static const QMap<QString, uint8_t> mavCommandList;
-    static const QMap<QString, uint8_t> servosList;
+public:
+    static const QStringList messagesList;
+
+    static const QMap<QString, int> systemTmList;
+    static const QMap<QString, int> sensorsList;
+    static const QMap<QString, int> commandsList;
+    static const QMap<QString, int> servosList;
 
     explicit CommandPad(QWidget* parent = nullptr);
     ~CommandPad();
@@ -20,10 +26,14 @@ class CommandPad : public DefaultModule {
     XmlObject toXmlObject() override;
     void fromXmlObject(const XmlObject& xmlObject) override;
 
-  private:
+private:
+    void removeWidgetsFromForm();
     void setupUi();
 
-    QComboBox* commandComboBox;
+    QString currentMessage;
+    QComboBox* messagesListComboBox;
+    QMap<QString, MessageFormElement*> formElements;
+    QGridLayout* formGridLayout;
 };
 
-#endif // COMMANDPAD_H
+#endif  // COMMANDPAD_H
diff --git a/Modules/Splitter/splittermodule.cpp b/Modules/Splitter/splittermodule.cpp
index 7818a89c17cc264dc308d45754dad682efd4af0e..0b1d7e300c65d0755fa8e200ca9d38f64dac6df6 100644
--- a/Modules/Splitter/splittermodule.cpp
+++ b/Modules/Splitter/splittermodule.cpp
@@ -113,7 +113,7 @@ void SplitterModule::fromXmlObject(const XmlObject& xmlObject)
 void SplitterModule::initialize(const XmlObject& params)
 {
     int orientation;
-    if (params.getIntAttribute("Orientation", orientation))
+    if (params.getAttribute("Orientation", orientation))
     {
         if (orientation == Qt::Vertical)
         {
diff --git a/Modules/ValuesConverterViewer/valueelement.cpp b/Modules/ValuesConverterViewer/valueelement.cpp
index 91a42b4b08abd1108c75c423d8bd2513c769a2f8..31d3f425927e4623da877eeebdc5d05db5d59eb1 100644
--- a/Modules/ValuesConverterViewer/valueelement.cpp
+++ b/Modules/ValuesConverterViewer/valueelement.cpp
@@ -1,22 +1,19 @@
 #include "valueelement.h"
 
-#include <QRadioButton>
-
 #include <QDebug>
+#include <QRadioButton>
 
-ValueElement::ValueElement() {
+ValueElement::ValueElement() {}
 
-}
+ValueElement::~ValueElement() {}
 
-ValueElement::~ValueElement() {
+ValueElement::ValueElement(const ValueElement& other) { copy(other); }
 
-}
-
-ValueElement::ValueElement(const ValueElement& other) {
-    copy(other);
-}
-
-ValueElement::ValueElement(const QString& name, const QString& topic, const QString& receivedValue, const QString& displayedValue, const QString& color, const QString& outputTopic) {
+ValueElement::ValueElement(const QString& name, const QString& topic,
+                           const QString& receivedValue,
+                           const QString& displayedValue, const QString& color,
+                           const QString& outputTopic)
+{
     setName(name);
     setTopic(topic);
     setReceivedValue(receivedValue);
@@ -25,56 +22,46 @@ ValueElement::ValueElement(const QString& name, const QString& topic, const QStr
     setOutputTopic(outputTopic);
 }
 
-ValueElement ValueElement::operator=(const ValueElement& other) {
+ValueElement ValueElement::operator=(const ValueElement& other)
+{
     copy(other);
     return *this;
 }
 
-QString ValueElement::getName() const {
-    return name;
-}
+QString ValueElement::getName() const { return name; }
 
-void ValueElement::setName(const QString& value) {
-    name = value;
-}
+void ValueElement::setName(const QString& value) { name = value; }
 
-QString ValueElement::getTopic() const {
-    return topic;
-}
+QString ValueElement::getTopic() const { return topic; }
 
-void ValueElement::setTopic(const QString& value) {
-    topic = value;
-}
+void ValueElement::setTopic(const QString& value) { topic = value; }
 
-QString ValueElement::getReceivedValue() const {
-    return receivedValue;
-}
+QString ValueElement::getReceivedValue() const { return receivedValue; }
 
-void ValueElement::setReceivedValue(const QString& value) {
+void ValueElement::setReceivedValue(const QString& value)
+{
     receivedValue = value;
 }
 
-QString ValueElement::getDisplayedValue() const {
-    return displayedValue;
-}
+QString ValueElement::getDisplayedValue() const { return displayedValue; }
 
-void ValueElement::setDisplayedValue(const QString& value) {
+void ValueElement::setDisplayedValue(const QString& value)
+{
     displayedValue = value;
 }
 
-QString ValueElement::getColor() const {
-    return color;
-}
+QString ValueElement::getColor() const { return color; }
 
-void ValueElement::setColor(const QString& value) {
-    color = value;
-}
+void ValueElement::setColor(const QString& value) { color = value; }
 
-QString ValueElement::toString() const {
-    return getName() + ": " + getTopic() + " [" + getReceivedValue() + " = " + getDisplayedValue() + "] color=" + getColor();
+QString ValueElement::toString() const
+{
+    return getName() + ": " + getTopic() + " [" + getReceivedValue() + " = " +
+           getDisplayedValue() + "] color=" + getColor();
 }
 
-XmlObject ValueElement::toXmlObject() const {
+XmlObject ValueElement::toXmlObject() const
+{
     XmlObject obj("Rule");
     obj.addAttribute("name", getName());
     obj.addAttribute("topic", getTopic());
@@ -86,11 +73,14 @@ XmlObject ValueElement::toXmlObject() const {
     return obj;
 }
 
-bool ValueElement::fromXmlObject(const XmlObject& xmlObject) {
+bool ValueElement::fromXmlObject(const XmlObject& xmlObject)
+{
     bool result = false;
-    if(xmlObject.getObjectName() == "Rule" && xmlObject.hasAttribute("name")) {
+    if (xmlObject.getObjectName() == "Rule" && xmlObject.hasAttribute("name"))
+    {
         QString name = xmlObject.getAttribute("name");
-        if(name != "") {
+        if (name != "")
+        {
             setName(name);
             result = true;
         }
@@ -102,14 +92,17 @@ bool ValueElement::fromXmlObject(const XmlObject& xmlObject) {
         setOutputTopic(xmlObject.getAttribute("outputTopic"));
 
         int display = 1;
-        if(xmlObject.getIntAttribute("displayInView", display) && (display == 0 || display == 1)) {
+        if (xmlObject.getAttribute("displayInView", display) &&
+            (display == 0 || display == 1))
+        {
             setDisplayInView(display);
         }
     }
     return result;
 }
 
-void ValueElement::copy(const ValueElement& other) {
+void ValueElement::copy(const ValueElement& other)
+{
     setName(other.getName());
     setTopic(other.getTopic());
     setReceivedValue(other.getReceivedValue());
@@ -119,39 +112,31 @@ void ValueElement::copy(const ValueElement& other) {
     setDisplayInView(other.isDisplayInView());
 }
 
-bool ValueElement::isDisplayInView() const {
-    return displayInView;
-}
+bool ValueElement::isDisplayInView() const { return displayInView; }
 
-void ValueElement::setDisplayInView(bool value) {
-    displayInView = value;
-}
+void ValueElement::setDisplayInView(bool value) { displayInView = value; }
 
-QString ValueElement::getOutputTopic() const {
-    return outputTopic;
-}
+QString ValueElement::getOutputTopic() const { return outputTopic; }
 
-void ValueElement::setOutputTopic(const QString& value) {
-    outputTopic = value;
-}
+void ValueElement::setOutputTopic(const QString& value) { outputTopic = value; }
 
-bool ValueElement::isEmitActive() const {
-    return outputTopic != "";
-}
+bool ValueElement::isEmitActive() const { return outputTopic != ""; }
 
-QString ValueElement::getCurrentValue() const {
-    return currentValue;
-}
+QString ValueElement::getCurrentValue() const { return currentValue; }
 
-bool ValueElement::updateCurrentValue(const QString& value) {
-    if(getReceivedValue() == "" || value == getReceivedValue()) {
-        if(getDisplayedValue() != "") {
+bool ValueElement::updateCurrentValue(const QString& value)
+{
+    if (getReceivedValue() == "" || value == getReceivedValue())
+    {
+        if (getDisplayedValue() != "")
+        {
             currentValue = getDisplayedValue();
-        } else {
+        }
+        else
+        {
             currentValue = value;
         }
         return true;
     }
     return false;
 }
-
diff --git a/Modules/ValuesConverterViewer/valuesconverterviewermodule.cpp b/Modules/ValuesConverterViewer/valuesconverterviewermodule.cpp
index 8adf3113eb150c68806b4b4061f5de5fcb912d70..21c6361ead1e1ea8ebc63b677f047a3debdbf504 100644
--- a/Modules/ValuesConverterViewer/valuesconverterviewermodule.cpp
+++ b/Modules/ValuesConverterViewer/valuesconverterviewermodule.cpp
@@ -1,53 +1,59 @@
 #include "valuesconverterviewermodule.h"
-#include "ui_valuesconverterviewermodule.h"
 
-#include "valuesviewerconfigpanel.h"
-#include "Core/modulemessagesbroker.h"
 #include "Core/Message/topicandfieldfilter.h"
+#include "Core/modulemessagesbroker.h"
+#include "ui_valuesconverterviewermodule.h"
+#include "valuesviewerconfigpanel.h"
 
-ValuesConverterViewerModule::ValuesConverterViewerModule(QWidget* parent) : DefaultModule(parent), ui(new Ui::ValuesConverterViewerModule) {
+ValuesConverterViewerModule::ValuesConverterViewerModule(QWidget* parent)
+    : DefaultModule(parent), ui(new Ui::ValuesConverterViewerModule)
+{
     ui->setupUi(this);
     defaultContextMenuSetup();
 
-    getCore()->getModuleMessagesBroker()->subscribe({"*"}, this, [this](const ModuleMessage & msg) {
-        onMsgReceived(msg);
-    });
+    getCore()->getModuleMessagesBroker()->subscribe(
+        {"*"}, this, [this](const ModuleMessage& msg) { onMsgReceived(msg); });
 }
 
-ValuesConverterViewerModule::~ValuesConverterViewerModule() {
+ValuesConverterViewerModule::~ValuesConverterViewerModule()
+{
     clearLabels();
     getCore()->getModuleMessagesBroker()->unsubscribe({"*"}, this);
     delete ui;
 }
 
+QWidget* ValuesConverterViewerModule::toWidget() { return this; }
 
-QWidget* ValuesConverterViewerModule::toWidget() {
-    return this;
-}
-
-XmlObject ValuesConverterViewerModule::toXmlObject() {
+XmlObject ValuesConverterViewerModule::toXmlObject()
+{
     XmlObject obj(getName(ModuleId::VALUESCONVERTERVIEWER));
 
     obj.addAttribute("Columns", QString::number(columns));
 
-    for(int i = 0; i < rules.count(); i++) {
+    for (int i = 0; i < rules.count(); i++)
+    {
         obj.addChild(rules[i].toXmlObject());
     }
     return obj;
 }
 
-void ValuesConverterViewerModule::fromXmlObject(const XmlObject& xmlObject) {
-    if(xmlObject.getObjectName() == getName(ModuleId::VALUESCONVERTERVIEWER)) {
+void ValuesConverterViewerModule::fromXmlObject(const XmlObject& xmlObject)
+{
+    if (xmlObject.getObjectName() == getName(ModuleId::VALUESCONVERTERVIEWER))
+    {
 
         int col;
-        if(xmlObject.getIntAttribute("Columns", col)) {
+        if (xmlObject.getAttribute("Columns", col))
+        {
             columns = col;
         }
 
-        for(int i = 0; i < xmlObject.childCount(); i++) {
+        for (int i = 0; i < xmlObject.childCount(); i++)
+        {
             XmlObject child = xmlObject.childAt(i);
             ValueElement el;
-            if(el.fromXmlObject(child)) {
+            if (el.fromXmlObject(child))
+            {
                 addRule(el);
             }
         }
@@ -55,101 +61,129 @@ void ValuesConverterViewerModule::fromXmlObject(const XmlObject& xmlObject) {
     }
 }
 
-void ValuesConverterViewerModule::onConfigureClicked() {
+void ValuesConverterViewerModule::onConfigureClicked()
+{
     ValuesViewerConfigPanel* sPanel = new ValuesViewerConfigPanel();
     sPanel->setRules(rules);
     sPanel->setColumnsCount(columns);
-    connect(sPanel, &ValuesViewerConfigPanel::configurationSaved, this, &ValuesConverterViewerModule::onConfigurationSaved);
+    connect(sPanel, &ValuesViewerConfigPanel::configurationSaved, this,
+            &ValuesConverterViewerModule::onConfigurationSaved);
     sPanel->show();
 }
 
-void ValuesConverterViewerModule::onConfigurationSaved(ValuesViewerConfigPanel* sPanel) {
+void ValuesConverterViewerModule::onConfigurationSaved(
+    ValuesViewerConfigPanel* sPanel)
+{
     setRules(sPanel->getRules());
     columns = sPanel->getColumnsCount();
 
     createLabels();
 }
 
-void ValuesConverterViewerModule::addCustomActionsToMenu() {
+void ValuesConverterViewerModule::addCustomActionsToMenu()
+{
     QAction* configure = new QAction("Configure");
-    connect(configure, &QAction::triggered, this, &ValuesConverterViewerModule::onConfigureClicked);
+    connect(configure, &QAction::triggered, this,
+            &ValuesConverterViewerModule::onConfigureClicked);
     addActionToMenu(configure);
 }
 
-QLabel* ValuesConverterViewerModule::createView(const ValueElement& el) const {
+QLabel* ValuesConverterViewerModule::createView(const ValueElement& el) const
+{
     QLabel* label = new QLabel();
     label->setText(el.getName());
     label->setAlignment(Qt::AlignCenter);
     return label;
 }
 
-void ValuesConverterViewerModule::clearLabels() {
-    while(labels.count() > 0) {
+void ValuesConverterViewerModule::clearLabels()
+{
+    while (labels.count() > 0)
+    {
         QLabel* l = labels[0];
         labels.removeAll(l);
         delete l;
     }
 }
 
-void ValuesConverterViewerModule::createLabels() {
+void ValuesConverterViewerModule::createLabels()
+{
     clearLabels();
-    if(columns <= 0) {
+    if (columns <= 0)
+    {
         columns = minColNumber;
     }
 
     int col = 0;
     int row = 0;
-    for (int i = 0; i < rules.count(); i++ ) {
+    for (int i = 0; i < rules.count(); i++)
+    {
         QLabel* label;
 
         int labelIndex = findLabelIndexByName(rules[i].getName());
-        if(labelIndex >= 0 && labelIndex < labels.count()) {
+        if (labelIndex >= 0 && labelIndex < labels.count())
+        {
             label = labels[labelIndex];
-        } else {
+        }
+        else
+        {
             label = createView(rules[i]);
-            if(col == columns) {
+            if (col == columns)
+            {
                 col = 0;
                 row++;
             }
 
-            if(rules[i].isDisplayInView()) {
+            if (rules[i].isDisplayInView())
+            {
                 ui->mainLayout_grid->addWidget(label, row, col);
                 col++;
             }
         }
         labels.append(label);
-
     }
 }
 
-void ValuesConverterViewerModule::addRule(const ValueElement& el) {
+void ValuesConverterViewerModule::addRule(const ValueElement& el)
+{
     rules.append(el);
 }
 
-void ValuesConverterViewerModule::setRules(const QList<ValueElement>& rList) {
+void ValuesConverterViewerModule::setRules(const QList<ValueElement>& rList)
+{
     clearRules();
-    for (int i = 0; i < rList.count(); i++ ) {
+    for (int i = 0; i < rList.count(); i++)
+    {
         addRule(rList[i]);
     }
 }
 
-void ValuesConverterViewerModule::onMsgReceived(const ModuleMessage& msg) {
+void ValuesConverterViewerModule::onMsgReceived(const ModuleMessage& msg)
+{
     MessageField value;
 
-    for (int i = 0; i < rules.count(); i++ ) {
-        if(TopicAndFieldFilter::fromStringUnsafe(rules[i].getTopic()).matchMessage(msg, value)) {
-            if(rules[i].updateCurrentValue(value.getString())) {
+    for (int i = 0; i < rules.count(); i++)
+    {
+        if (TopicAndFieldFilter::fromStringUnsafe(rules[i].getTopic())
+                .matchMessage(msg, value))
+        {
+            if (rules[i].updateCurrentValue(value.getString()))
+            {
                 QTime time(0, 0, 0, 0);
                 uint64_t ms = msg.getField("timestamp").getUInteger(0);
-                time = time.addMSecs(ms);
+                time        = time.addMSecs(ms);
 
                 QString str = "(" + time.toString("HH:mm:ss") + ")\n";
-                labels[i]->setText(rules[i].getName() + "\n" + str + rules[i].getCurrentValue());
-                if(rules[i].getColor() != "") {
-                    labels[i]->setStyleSheet("color:" + rules[i].getColor() + ";");
+                labels[i]->setText(rules[i].getName() + "\n" + str +
+                                   rules[i].getCurrentValue());
+                if (rules[i].getColor() != "")
+                {
+                    labels[i]->setStyleSheet("color:" + rules[i].getColor() +
+                                             ";");
                 }
 
-                if(rules[i].isEmitActive()) {
+                if (rules[i].isEmitActive())
+                {
                     ModuleMessage convertedMsg(msg);
                     convertedMsg.setField("value", rules[i].getCurrentValue());
                     convertedMsg.setTopic(rules[i].getOutputTopic());
@@ -160,27 +194,37 @@ void ValuesConverterViewerModule::onMsgReceived(const ModuleMessage& msg) {
     }
 }
 
-void ValuesConverterViewerModule::clearRules() {
-    for (int i = 0; i < rules.count(); i++ ) {
-        if(rules[i].getTopic() != "") {
-            getCore()->getModuleMessagesBroker()->unsubscribe(rules[i].getTopic(), this);
+void ValuesConverterViewerModule::clearRules()
+{
+    for (int i = 0; i < rules.count(); i++)
+    {
+        if (rules[i].getTopic() != "")
+        {
+            getCore()->getModuleMessagesBroker()->unsubscribe(
+                rules[i].getTopic(), this);
         }
     }
     rules.clear();
 }
 
-int ValuesConverterViewerModule::findLabelIndexByName(const QString& name) {
-    for (int i = 0; i < labels.count(); i++ ) {
-        if(labels[i]->text() == name) {
+int ValuesConverterViewerModule::findLabelIndexByName(const QString& name)
+{
+    for (int i = 0; i < labels.count(); i++)
+    {
+        if (labels[i]->text() == name)
+        {
             return i;
         }
     }
     return -1;
 }
 
-bool ValuesConverterViewerModule::isTopicPresent(const QString& topic) {
-    for (int i = 0; i < rules.count(); i++ ) {
-        if(rules[i].getTopic() == topic) {
+bool ValuesConverterViewerModule::isTopicPresent(const QString& topic)
+{
+    for (int i = 0; i < rules.count(); i++)
+    {
+        if (rules[i].getTopic() == topic)
+        {
             return true;
         }
     }
diff --git a/Modules/skywardhubstrings.h b/Modules/skywardhubstrings.h
index d4270ebe3cfa52e1ede46f49daccdebe0592e309..6c8739ebd3d0dc814d7042bad3c4f24c1dba1f81 100644
--- a/Modules/skywardhubstrings.h
+++ b/Modules/skywardhubstrings.h
@@ -6,14 +6,19 @@
 namespace SkywardHubStrings
 {
 
-static const QString defaultConfigurationFolder   = "SkywardHubConfig";
-static const QString defaultSettingsFilePath      = defaultConfigurationFolder + "/" + "settings.xml";
-static const QString defaultPrefabsFolderName     = "Prefabs";
-static const QString defaultLogsFolder            = defaultConfigurationFolder + "/" + "Logs";
-static const QString defaultStreamFile            = defaultConfigurationFolder + "/" + "StreamFile.txt";
-static const QString defaultPrefabsFolder         = defaultConfigurationFolder + "/" + defaultPrefabsFolderName + "/";
+static const QString defaultConfigurationFolder = "SkywardHubConfig";
+static const QString defaultSettingsFilePath =
+    defaultConfigurationFolder + "/" + "settings.xml";
+static const QString defaultPrefabsFolderName = "Prefabs";
+static const QString defaultLogsFolder =
+    defaultConfigurationFolder + "/" + "Logs";
+static const QString defaultStreamFile =
+    defaultConfigurationFolder + "/" + "StreamFile.txt";
+static const QString defaultPrefabsFolder =
+    defaultConfigurationFolder + "/" + defaultPrefabsFolderName + "/";
 static const QString defaultConfigurationFileName = "default.xml";
-static const QString defaultConfigurationIconPath = defaultConfigurationFolder + "/" + "defaultConfigIcon.svg";
+static const QString defaultConfigurationIconPath =
+    defaultConfigurationFolder + "/" + "defaultConfigIcon.svg";
 
 // Xml Tags Name
 static const QString skywardHubInitFileTag             = "LoadOnLaunch";
@@ -25,26 +30,31 @@ static const QString configurationDescriptionAttribute = "Description";
 
 // Output Messages
 static const QString settingsSavedCorrectlyMsg = "Settings saved";
-static const QString serialPortClosedErrorMsg  = "Mavlink >> Error, Serial port closed, impossible to write msg";
-static const QString imageViewerInfo           = "Double click on a label to open the settings panel";
+static const QString serialPortClosedErrorMsg =
+    "Mavlink >> Error, Serial port closed, impossible to write msg";
+static const QString imageViewerInfo =
+    "Double click on a label to open the settings panel";
 
 // Topics
 static const QString commandsTopic                = "TelemetryCommand";
 static const QString treeViewerReceivingBaseTopic = "TreeViewer";
 
-static const QString logCommandsTopic                              = "LogCommands";
-static const QString raw_event_id                                  = "event_id";
-static const QString raw_event_topic_id                            = "topic_id";
-static const QString mavlink_orientation_tc_yaw_name               = "yaw";
-static const QString mavlink_orientation_tc_pitch_name             = "pitch";
-static const QString mavlink_orientation_tc_roll_name              = "roll";
-static const QString mavlink_quality_link_topic                    = "MavlinkLinkQuality";
-static const QString mavlink_received_msg_topic                    = "Mav";
-static const QString mavlink_initial_coordinates_tc_latitude_name  = "latitude";
-static const QString mavlink_initial_coordinates_tc_longitude_name = "longitude";
-
-static const QString mavlink_received_msg_ACK_topic  = mavlink_received_msg_topic + "/ACK_TM";
-static const QString mavlink_received_msg_NACK_topic = mavlink_received_msg_topic + "/NACK_TM";
+static const QString logCommandsTopic                  = "LogCommands";
+static const QString raw_event_id                      = "event_id";
+static const QString raw_event_topic_id                = "topic_id";
+static const QString mavlink_orientation_tc_yaw_name   = "yaw";
+static const QString mavlink_orientation_tc_pitch_name = "pitch";
+static const QString mavlink_orientation_tc_roll_name  = "roll";
+static const QString mavlink_quality_link_topic        = "MavlinkLinkQuality";
+static const QString mavlink_received_msg_topic        = "Mav";
+static const QString mavlink_initial_coordinates_tc_latitude_name = "latitude";
+static const QString mavlink_initial_coordinates_tc_longitude_name =
+    "longitude";
+
+static const QString mavlink_received_msg_ACK_topic =
+    mavlink_received_msg_topic + "/ACK_TM";
+static const QString mavlink_received_msg_NACK_topic =
+    mavlink_received_msg_topic + "/NACK_TM";
 
 };  // namespace SkywardHubStrings
 
diff --git a/SkywardHub.pro b/SkywardHub.pro
index 40c31260621626001c693ee0ce75fe98dfa1aa74..bd2e71e719ca89dc814b4eb93b197b42ecff0079 100644
--- a/SkywardHub.pro
+++ b/SkywardHub.pro
@@ -31,6 +31,7 @@ SOURCES += \
     Core/skywardhubcore.cpp \
     Core/xmlobject.cpp \
     Modules/CommandPad/commandpad.cpp \
+    Modules/CommandPad/MessageFormElement.cpp \
     Modules/DefaultModule/defaultmodule.cpp \
     Modules/Empty/emptymodule.cpp \
     Modules/FileStream/filestreammodule.cpp \
@@ -84,6 +85,7 @@ HEADERS += \
     Core/skywardhubcore.h \
     Core/xmlobject.h \
     Modules/CommandPad/commandpad.h \
+    Modules/CommandPad/MessageFormElement.h \
     Modules/DefaultModule/defaultmodule.h \
     Modules/Empty/emptymodule.h \
     Modules/FileStream/filestreammodule.h \