From 239a350bce666031acd522635038106e995eb8ae Mon Sep 17 00:00:00 2001
From: angelozangari <angelo.zangari10@gmail.com>
Date: Sat, 16 Sep 2023 10:57:41 +0200
Subject: [PATCH 1/6] [Modules] update state viewer indexes

---
 src/shared/Modules/StateViewer/StatesList.h | 59 +++++++++++++++------
 1 file changed, 42 insertions(+), 17 deletions(-)

diff --git a/src/shared/Modules/StateViewer/StatesList.h b/src/shared/Modules/StateViewer/StatesList.h
index 2ff26e40..cfc8239b 100644
--- a/src/shared/Modules/StateViewer/StatesList.h
+++ b/src/shared/Modules/StateViewer/StatesList.h
@@ -28,39 +28,64 @@ namespace StatesList
 // Rockets states
 enum class State : int
 {
-    INVALID = 0,
+    ON_GROUND = 0,
     INIT,
     INIT_ERROR,
-    SENSORS_CALIBRATION,
-    ALGOS_CALIBRATION,
+    INIT_DONE,
+    CALIBRATE_SENSORS,
+    CALIBRATE_ALGORITHMS,
     DISARMED,
     TEST_MODE,
     ARMED,
-    ASCENDING,
+    IGNITION,
+    FLYING,
+    POWERED_ASCENT,
+    UNPOWERED_ASCENT,
     DROGUE_DESCENT,
     TERMINAL_DESCENT,
     LANDED,
+    INVALID,
 };
 
 // Groundstation labels
 static const QList<QString> statesLabels{
-    "INIT",      "TEST\nMODE",      "SENSORS\nCALIBRATION", "DISARMED", "ARMED",
-    "ASCENDING", "DROGUE\nDESCENT", "TERMINAL\nDESCENT",    "LANDED",
+    "ON_GROUND",
+    "INIT",
+    "INIT\nERROR",
+    "INIT\nDONE",
+    "CALIBRATE\nSENSORS",
+    "CALIBRATE\nALGORITHMS",
+    "DISARMED",
+    "TEST\nMODE",
+    "ARMED",
+    "IGNITION",
+    "FLYING",
+    "POWERED\nASCENT",
+    "UNPOWERED\nASCENT",
+    "DROGUE\nDESCENT",
+    "TERMINAL\nDESCENT",
+    "LANDED",
+    "INVALID",
 };
 
 // Map from rocket states to groundstation labels
 static const QMap<State, int> statesIndexes{
-    {State::INIT, 0},
-    {State::INIT_ERROR, 0},
-    {State::TEST_MODE, 1},
-    {State::SENSORS_CALIBRATION, 2},
-    {State::ALGOS_CALIBRATION, 2},
-    {State::DISARMED, 3},
-    {State::ARMED, 4},
-    {State::ASCENDING, 5},
-    {State::DROGUE_DESCENT, 6},
-    {State::TERMINAL_DESCENT, 7},
-    {State::LANDED, 8},
+    {State::INIT, 1},
+    {State::INIT_ERROR, 2},
+    {State::INIT_DONE, 3},
+    {State::CALIBRATE_SENSORS, 4},
+    {State::CALIBRATE_ALGORITHMS, 5},
+    {State::DISARMED, 6},
+    {State::TEST_MODE, 7},
+    {State::ARMED, 8},
+    {State::IGNITION, 9},
+    {State::FLYING, 10},
+    {State::POWERED_ASCENT, 11},
+    {State::UNPOWERED_ASCENT, 12},
+    {State::DROGUE_DESCENT, 13},
+    {State::TERMINAL_DESCENT, 14},
+    {State::LANDED, 15},
+    {State::INVALID, 16},
 };
 
 }  // namespace StatesList
\ No newline at end of file
-- 
GitLab


From 8caa1e2327282dc1bcaf08001d161f458e7f3414 Mon Sep 17 00:00:00 2001
From: Davide Mor <davide.mor@skywarder.eu>
Date: Sun, 17 Sep 2023 00:55:21 +0200
Subject: [PATCH 2/6] [StateViewer] Reduced the number of visualized states

---
 .../Modules/StateViewer/StateViewer.cpp       |  6 ++-
 src/shared/Modules/StateViewer/StatesList.h   | 39 ++++++++-----------
 2 files changed, 22 insertions(+), 23 deletions(-)

diff --git a/src/shared/Modules/StateViewer/StateViewer.cpp b/src/shared/Modules/StateViewer/StateViewer.cpp
index c9551928..c5402c41 100644
--- a/src/shared/Modules/StateViewer/StateViewer.cpp
+++ b/src/shared/Modules/StateViewer/StateViewer.cpp
@@ -102,7 +102,11 @@ void StateViewerModule::onMsgReceived(const Message& msg)
     StatesList::State state =
         static_cast<StatesList::State>(field.getUnsignedInteger());
 
-    if (state == StatesList::State::INVALID)
+    // Skip invalid and macro states
+    if (state == StatesList::State::INVALID ||
+        state == StatesList::State::ON_GROUND ||
+        state == StatesList::State::IGNITION ||
+        state == StatesList::State::FLYING)
         return;
 
     if (state != currentState)
diff --git a/src/shared/Modules/StateViewer/StatesList.h b/src/shared/Modules/StateViewer/StatesList.h
index cfc8239b..d602b9aa 100644
--- a/src/shared/Modules/StateViewer/StatesList.h
+++ b/src/shared/Modules/StateViewer/StatesList.h
@@ -49,43 +49,38 @@ enum class State : int
 
 // Groundstation labels
 static const QList<QString> statesLabels{
-    "ON_GROUND",
     "INIT",
-    "INIT\nERROR",
-    "INIT\nDONE",
     "CALIBRATE\nSENSORS",
     "CALIBRATE\nALGORITHMS",
     "DISARMED",
     "TEST\nMODE",
     "ARMED",
-    "IGNITION",
-    "FLYING",
     "POWERED\nASCENT",
     "UNPOWERED\nASCENT",
     "DROGUE\nDESCENT",
     "TERMINAL\nDESCENT",
     "LANDED",
-    "INVALID",
 };
 
 // Map from rocket states to groundstation labels
 static const QMap<State, int> statesIndexes{
-    {State::INIT, 1},
-    {State::INIT_ERROR, 2},
-    {State::INIT_DONE, 3},
-    {State::CALIBRATE_SENSORS, 4},
-    {State::CALIBRATE_ALGORITHMS, 5},
-    {State::DISARMED, 6},
-    {State::TEST_MODE, 7},
-    {State::ARMED, 8},
-    {State::IGNITION, 9},
-    {State::FLYING, 10},
-    {State::POWERED_ASCENT, 11},
-    {State::UNPOWERED_ASCENT, 12},
-    {State::DROGUE_DESCENT, 13},
-    {State::TERMINAL_DESCENT, 14},
-    {State::LANDED, 15},
-    {State::INVALID, 16},
+    {State::INVALID, -1},
+    {State::ON_GROUND, -1},
+    {State::IGNITION, -1},
+    {State::FLYING, -1},
+    {State::INIT, 0},
+    {State::INIT_ERROR, 0},
+    {State::INIT_DONE, 0},
+    {State::CALIBRATE_SENSORS, 1},
+    {State::CALIBRATE_ALGORITHMS, 2},
+    {State::DISARMED, 3},
+    {State::TEST_MODE, 4},
+    {State::ARMED, 5},
+    {State::POWERED_ASCENT, 6},
+    {State::UNPOWERED_ASCENT, 7},
+    {State::DROGUE_DESCENT, 8},
+    {State::TERMINAL_DESCENT, 9},
+    {State::LANDED, 10}
 };
 
 }  // namespace StatesList
\ No newline at end of file
-- 
GitLab


From 96b784106665ecf1acdb4f0e758f2489504fd689 Mon Sep 17 00:00:00 2001
From: Davide Mor <davide.mor@skywarder.eu>
Date: Sun, 17 Sep 2023 01:18:14 +0200
Subject: [PATCH 3/6] [StateViewer] Added Payload state viewer

---
 CMakeLists.txt                                |   3 +-
 SkywardHub.pro                                |   3 +-
 .../MainStateViewer/MainStateViewer.cpp       | 147 ++++++++++++++++++
 .../MainStateViewer.h}                        |  10 +-
 .../MainStatesList.h}                         |   2 +-
 src/shared/Modules/ModuleInfo.h               |   3 +-
 src/shared/Modules/ModulesList.cpp            |  18 ++-
 .../PayloadStateViewer.cpp}                   |  51 +++---
 .../PayloadStateViewer/PayloadStateViewer.h   |  54 +++++++
 .../PayloadStateViewer/PayloadStatesList.h    |  77 +++++++++
 10 files changed, 327 insertions(+), 41 deletions(-)
 create mode 100644 src/shared/Modules/MainStateViewer/MainStateViewer.cpp
 rename src/shared/Modules/{StateViewer/StateViewer.h => MainStateViewer/MainStateViewer.h} (85%)
 rename src/shared/Modules/{StateViewer/StatesList.h => MainStateViewer/MainStatesList.h} (98%)
 rename src/shared/Modules/{StateViewer/StateViewer.cpp => PayloadStateViewer/PayloadStateViewer.cpp} (67%)
 create mode 100644 src/shared/Modules/PayloadStateViewer/PayloadStateViewer.h
 create mode 100644 src/shared/Modules/PayloadStateViewer/PayloadStatesList.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index eb70d9bc..7f092728 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -80,7 +80,8 @@ add_executable(groundstation
     src/shared/Modules/OutgoingMessagesViewer/OutgoingMessagesViewerModule.cpp
     src/shared/Modules/Splitter/Splitter.cpp
     src/shared/Modules/OrientationVisualizer/OrientationVisualizer.cpp
-    src/shared/Modules/StateViewer/StateViewer.cpp
+    src/shared/Modules/MainStateViewer/MainStateViewer.cpp
+    src/shared/Modules/PayloadStateViewer/PayloadStateViewer.cpp
     src/shared/Modules/Tabs/TabsModule.cpp
     src/shared/Modules/Test/TestModule.cpp
     src/shared/Modules/TimerController/TimerControllerModule.cpp
diff --git a/SkywardHub.pro b/SkywardHub.pro
index e90dd506..e6877463 100644
--- a/SkywardHub.pro
+++ b/SkywardHub.pro
@@ -27,7 +27,8 @@ SOURCES += \
     src/shared/Modules/OutgoingMessagesViewer/OutgoingMessagesViewerModule.cpp \
     src/shared/Modules/TimerController/TimerControllerModule.cpp \
     src/shared/Modules/OrientationVisualizer/OrientationVisualizer.cpp \
-    src/shared/Modules/StateViewer/StateViewer.cpp \
+    src/shared/Modules/MainStateViewer/MainStateViewer.cpp \
+    src/shared/Modules/PayloadStateViewer/PayloadStateViewer.cpp \
     src/shared/Modules/FileStream/FileStreamModule.cpp \
     src/shared/Modules/Graph/Graph.cpp \
     src/shared/Modules/Test/TestModule.cpp \
diff --git a/src/shared/Modules/MainStateViewer/MainStateViewer.cpp b/src/shared/Modules/MainStateViewer/MainStateViewer.cpp
new file mode 100644
index 00000000..4776e98f
--- /dev/null
+++ b/src/shared/Modules/MainStateViewer/MainStateViewer.cpp
@@ -0,0 +1,147 @@
+/*
+ * This file is part of Skyward Hub.
+ *
+ * Skyward Hub is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * Skyward Hub is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Skyward Hub. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "MainStateViewer.h"
+
+#include <Components/FilterSelector/FilterSelector.h>
+#include <Core/MessageBroker/MessageBroker.h>
+
+MainStateViewerModule::MainStateViewerModule(QWidget* parent) : DefaultModule(parent)
+{
+    setupUi();
+    defaultContextMenuSetup();
+}
+
+MainStateViewerModule::~MainStateViewerModule()
+{
+    getCore()->getMessageBroker()->unsubscribe(filter, this);
+}
+
+QWidget* MainStateViewerModule::toWidget() { return this; }
+
+XmlObject MainStateViewerModule::toXmlObject()
+{
+    XmlObject obj(getName(ModuleId::MAINSTATEVIEWER));
+
+    obj.addAttribute("filter", filter.toString());
+
+    return obj;
+}
+
+void MainStateViewerModule::fromXmlObject(const XmlObject& xmlObject)
+{
+    if (xmlObject.getObjectName() == getName(ModuleId::MAINSTATEVIEWER))
+    {
+        auto filter = Filter::fromString(xmlObject.getAttribute("filter"));
+        setFilter(filter);
+    }
+}
+
+void MainStateViewerModule::setupUi()
+{
+    outerLayout = new QHBoxLayout;
+    outerLayout->setContentsMargins(0, 0, 0, 0);
+    outerLayout->setSpacing(0);
+
+    for (auto labelText : MainStatesList::statesLabels)
+    {
+        QLabel* label = new QLabel;
+        label->setText(labelText);
+        label->setAlignment(Qt::AlignCenter);
+        label->setContentsMargins(4, 4, 4, 4);
+        outerLayout->addWidget(label);
+    }
+
+    setLayout(outerLayout);
+}
+
+void MainStateViewerModule::addCustomActionsToMenu()
+{
+    QAction* action = new QAction("Choose topic and field");
+    connect(action, &QAction::triggered, this,
+            &MainStateViewerModule::onConfigureClicked);
+
+    addActionToMenu(action);
+}
+
+void MainStateViewerModule::onConfigureClicked()
+{
+    FilterSelector::selectFilter(
+        filter, [this](const Filter& newFilter) { setFilter(newFilter); });
+}
+
+void MainStateViewerModule::setFilter(const Filter& newFilter)
+{
+    getCore()->getMessageBroker()->unsubscribe(filter, this);
+    getCore()->getMessageBroker()->subscribe(
+        newFilter, this,
+        [this](const Message& message, const Filter& filter)
+        { onMsgReceived(message); });
+    filter = newFilter;
+}
+
+void MainStateViewerModule::onMsgReceived(const Message& msg)
+{
+    Field field = msg.getField("fmm_state");
+
+    MainStatesList::State state =
+        static_cast<MainStatesList::State>(field.getUnsignedInteger());
+
+    // Skip invalid and macro states
+    if (state == MainStatesList::State::INVALID ||
+        state == MainStatesList::State::ON_GROUND ||
+        state == MainStatesList::State::IGNITION ||
+        state == MainStatesList::State::FLYING)
+        return;
+
+    if (state != currentState)
+    {
+        currentState = static_cast<MainStatesList::State>(state);
+
+        QString baseStyle =
+            "border-bottom-width:1px;border-left-width:1px;border-top-width:"
+            "1px;border-radius:0;";
+        QString currentStateStyle =
+            "background-color:yellow; color:black;" + baseStyle;
+        QString completedStyle = "background-color:green;" + baseStyle;
+        QString errorStyle     = "background-color:red;" + baseStyle;
+
+        int index  = MainStatesList::statesIndexes[currentState];
+        auto label = outerLayout->itemAt(index)->widget();
+
+        if (currentState == MainStatesList::State::INIT_ERROR)
+            label->setStyleSheet(errorStyle);
+        else
+            label->setStyleSheet(currentStateStyle);
+
+        // Set as completed every state before the current
+        for (int i = index - 1; i >= 0; i--)
+            outerLayout->itemAt(i)->widget()->setStyleSheet(completedStyle);
+
+        // Reset every state after the current
+        for (int i = index + 1; i < MainStatesList::statesLabels.count(); i++)
+            outerLayout->itemAt(i)->widget()->setStyleSheet(baseStyle);
+
+        auto tmp = outerLayout->itemAt(MainStatesList::statesLabels.count() - 1)
+                       ->widget()
+                       ->styleSheet();
+        outerLayout->itemAt(MainStatesList::statesLabels.count() - 1)
+            ->widget()
+            ->setStyleSheet(tmp + "border-right-width:1px;");
+    }
+}
diff --git a/src/shared/Modules/StateViewer/StateViewer.h b/src/shared/Modules/MainStateViewer/MainStateViewer.h
similarity index 85%
rename from src/shared/Modules/StateViewer/StateViewer.h
rename to src/shared/Modules/MainStateViewer/MainStateViewer.h
index a9ed415a..20d85b68 100644
--- a/src/shared/Modules/StateViewer/StateViewer.h
+++ b/src/shared/Modules/MainStateViewer/MainStateViewer.h
@@ -25,15 +25,15 @@
 #include <QLabel>
 #include <QWidget>
 
-#include "StatesList.h"
+#include "MainStatesList.h"
 
-class StateViewerModule : public DefaultModule
+class MainStateViewerModule : public DefaultModule
 {
     Q_OBJECT
 
 public:
-    explicit StateViewerModule(QWidget* parent = nullptr);
-    ~StateViewerModule();
+    explicit MainStateViewerModule(QWidget* parent = nullptr);
+    ~MainStateViewerModule();
 
     QWidget* toWidget() override;
 
@@ -50,5 +50,5 @@ private:
     QHBoxLayout* outerLayout;
 
     Filter filter;
-    StatesList::State currentState;
+    MainStatesList::State currentState;
 };
diff --git a/src/shared/Modules/StateViewer/StatesList.h b/src/shared/Modules/MainStateViewer/MainStatesList.h
similarity index 98%
rename from src/shared/Modules/StateViewer/StatesList.h
rename to src/shared/Modules/MainStateViewer/MainStatesList.h
index d602b9aa..afbf389a 100644
--- a/src/shared/Modules/StateViewer/StatesList.h
+++ b/src/shared/Modules/MainStateViewer/MainStatesList.h
@@ -22,7 +22,7 @@
 #include <QMap>
 #include <QString>
 
-namespace StatesList
+namespace MainStatesList
 {
 
 // Rockets states
diff --git a/src/shared/Modules/ModuleInfo.h b/src/shared/Modules/ModuleInfo.h
index 57771cc8..c28dad47 100644
--- a/src/shared/Modules/ModuleInfo.h
+++ b/src/shared/Modules/ModuleInfo.h
@@ -36,7 +36,8 @@ enum ModuleId
     UDP_MAVLINK,
     FILESTREAM,
     ORIENTATION_VISUALIZER,
-    STATEVIEWER,
+    MAINSTATEVIEWER,
+    PAYLOADSTATEVIEWER,
     VALUESCONVERTERVIEWER,
     TIMER_CONTROLLER,
     MODULETEST,
diff --git a/src/shared/Modules/ModulesList.cpp b/src/shared/Modules/ModulesList.cpp
index 0d2cb472..90442806 100644
--- a/src/shared/Modules/ModulesList.cpp
+++ b/src/shared/Modules/ModulesList.cpp
@@ -26,12 +26,13 @@
 #include <Modules/FileStream/FileStreamModule.h>
 #include <Modules/Graph/Graph.h>
 #include <Modules/IncomingMessagesViewer/IncomingMessagesViewerModule.h>
+#include <Modules/MainStateViewer/MainStateViewer.h>
 #include <Modules/Mavlink/SerialMavlinkModule.h>
 #include <Modules/Mavlink/UdpMavlinkModule.h>
 #include <Modules/OrientationVisualizer/OrientationVisualizer.h>
 #include <Modules/OutgoingMessagesViewer/OutgoingMessagesViewerModule.h>
+#include <Modules/PayloadStateViewer/PayloadStateViewer.h>
 #include <Modules/Splitter/Splitter.h>
-#include <Modules/StateViewer/StateViewer.h>
 #include <Modules/Tabs/TabsModule.h>
 #include <Modules/Test/TestModule.h>
 #include <Modules/TimerController/TimerControllerModule.h>
@@ -110,10 +111,17 @@ void ModulesList::createModuleList()
     fileStream.setFactory([]() { return new FileStreamModule(); });
     addModuleInfo(fileStream);
 
-    ModuleInfo stateViewer(ModuleId::STATEVIEWER, "StateViewer",
-                           ModuleCategory::DATAVISUAL);
-    stateViewer.setFactory([]() { return new StateViewerModule(); });
-    addModuleInfo(stateViewer);
+    ModuleInfo mainStateViewer(ModuleId::MAINSTATEVIEWER, "MainStateViewer",
+                               ModuleCategory::DATAVISUAL);
+    mainStateViewer.setFactory([]() { return new MainStateViewerModule(); });
+    addModuleInfo(mainStateViewer);
+
+    ModuleInfo payloadStateViewer(ModuleId::PAYLOADSTATEVIEWER,
+                                  "PayloadStateViewer",
+                                  ModuleCategory::DATAVISUAL);
+    payloadStateViewer.setFactory([]()
+                                  { return new PayloadStateViewerModule(); });
+    addModuleInfo(payloadStateViewer);
 
     ModuleInfo valuesConverterViewer(ModuleId::VALUESCONVERTERVIEWER,
                                      "ValuesConverterViewer",
diff --git a/src/shared/Modules/StateViewer/StateViewer.cpp b/src/shared/Modules/PayloadStateViewer/PayloadStateViewer.cpp
similarity index 67%
rename from src/shared/Modules/StateViewer/StateViewer.cpp
rename to src/shared/Modules/PayloadStateViewer/PayloadStateViewer.cpp
index c5402c41..d05eacee 100644
--- a/src/shared/Modules/StateViewer/StateViewer.cpp
+++ b/src/shared/Modules/PayloadStateViewer/PayloadStateViewer.cpp
@@ -16,49 +16,49 @@
  *
  */
 
-#include "StateViewer.h"
+#include "PayloadStateViewer.h"
 
 #include <Components/FilterSelector/FilterSelector.h>
 #include <Core/MessageBroker/MessageBroker.h>
 
-StateViewerModule::StateViewerModule(QWidget* parent) : DefaultModule(parent)
+PayloadStateViewerModule::PayloadStateViewerModule(QWidget* parent) : DefaultModule(parent)
 {
     setupUi();
     defaultContextMenuSetup();
 }
 
-StateViewerModule::~StateViewerModule()
+PayloadStateViewerModule::~PayloadStateViewerModule()
 {
     getCore()->getMessageBroker()->unsubscribe(filter, this);
 }
 
-QWidget* StateViewerModule::toWidget() { return this; }
+QWidget* PayloadStateViewerModule::toWidget() { return this; }
 
-XmlObject StateViewerModule::toXmlObject()
+XmlObject PayloadStateViewerModule::toXmlObject()
 {
-    XmlObject obj(getName(ModuleId::STATEVIEWER));
+    XmlObject obj(getName(ModuleId::PAYLOADSTATEVIEWER));
 
     obj.addAttribute("filter", filter.toString());
 
     return obj;
 }
 
-void StateViewerModule::fromXmlObject(const XmlObject& xmlObject)
+void PayloadStateViewerModule::fromXmlObject(const XmlObject& xmlObject)
 {
-    if (xmlObject.getObjectName() == getName(ModuleId::STATEVIEWER))
+    if (xmlObject.getObjectName() == getName(ModuleId::PAYLOADSTATEVIEWER))
     {
         auto filter = Filter::fromString(xmlObject.getAttribute("filter"));
         setFilter(filter);
     }
 }
 
-void StateViewerModule::setupUi()
+void PayloadStateViewerModule::setupUi()
 {
     outerLayout = new QHBoxLayout;
     outerLayout->setContentsMargins(0, 0, 0, 0);
     outerLayout->setSpacing(0);
 
-    for (auto labelText : StatesList::statesLabels)
+    for (auto labelText : PayloadStatesList::statesLabels)
     {
         QLabel* label = new QLabel;
         label->setText(labelText);
@@ -70,22 +70,22 @@ void StateViewerModule::setupUi()
     setLayout(outerLayout);
 }
 
-void StateViewerModule::addCustomActionsToMenu()
+void PayloadStateViewerModule::addCustomActionsToMenu()
 {
     QAction* action = new QAction("Choose topic and field");
     connect(action, &QAction::triggered, this,
-            &StateViewerModule::onConfigureClicked);
+            &PayloadStateViewerModule::onConfigureClicked);
 
     addActionToMenu(action);
 }
 
-void StateViewerModule::onConfigureClicked()
+void PayloadStateViewerModule::onConfigureClicked()
 {
     FilterSelector::selectFilter(
         filter, [this](const Filter& newFilter) { setFilter(newFilter); });
 }
 
-void StateViewerModule::setFilter(const Filter& newFilter)
+void PayloadStateViewerModule::setFilter(const Filter& newFilter)
 {
     getCore()->getMessageBroker()->unsubscribe(filter, this);
     getCore()->getMessageBroker()->subscribe(
@@ -95,23 +95,20 @@ void StateViewerModule::setFilter(const Filter& newFilter)
     filter = newFilter;
 }
 
-void StateViewerModule::onMsgReceived(const Message& msg)
+void PayloadStateViewerModule::onMsgReceived(const Message& msg)
 {
     Field field = msg.getField("fmm_state");
 
-    StatesList::State state =
-        static_cast<StatesList::State>(field.getUnsignedInteger());
+    PayloadStatesList::State state =
+        static_cast<PayloadStatesList::State>(field.getUnsignedInteger());
 
     // Skip invalid and macro states
-    if (state == StatesList::State::INVALID ||
-        state == StatesList::State::ON_GROUND ||
-        state == StatesList::State::IGNITION ||
-        state == StatesList::State::FLYING)
+    if (state == PayloadStatesList::State::INVALID)
         return;
 
     if (state != currentState)
     {
-        currentState = static_cast<StatesList::State>(state);
+        currentState = static_cast<PayloadStatesList::State>(state);
 
         QString baseStyle =
             "border-bottom-width:1px;border-left-width:1px;border-top-width:"
@@ -121,10 +118,10 @@ void StateViewerModule::onMsgReceived(const Message& msg)
         QString completedStyle = "background-color:green;" + baseStyle;
         QString errorStyle     = "background-color:red;" + baseStyle;
 
-        int index  = StatesList::statesIndexes[currentState];
+        int index  = PayloadStatesList::statesIndexes[currentState];
         auto label = outerLayout->itemAt(index)->widget();
 
-        if (currentState == StatesList::State::INIT_ERROR)
+        if (currentState == PayloadStatesList::State::INIT_ERROR)
             label->setStyleSheet(errorStyle);
         else
             label->setStyleSheet(currentStateStyle);
@@ -134,13 +131,13 @@ void StateViewerModule::onMsgReceived(const Message& msg)
             outerLayout->itemAt(i)->widget()->setStyleSheet(completedStyle);
 
         // Reset every state after the current
-        for (int i = index + 1; i < StatesList::statesLabels.count(); i++)
+        for (int i = index + 1; i < PayloadStatesList::statesLabels.count(); i++)
             outerLayout->itemAt(i)->widget()->setStyleSheet(baseStyle);
 
-        auto tmp = outerLayout->itemAt(StatesList::statesLabels.count() - 1)
+        auto tmp = outerLayout->itemAt(PayloadStatesList::statesLabels.count() - 1)
                        ->widget()
                        ->styleSheet();
-        outerLayout->itemAt(StatesList::statesLabels.count() - 1)
+        outerLayout->itemAt(PayloadStatesList::statesLabels.count() - 1)
             ->widget()
             ->setStyleSheet(tmp + "border-right-width:1px;");
     }
diff --git a/src/shared/Modules/PayloadStateViewer/PayloadStateViewer.h b/src/shared/Modules/PayloadStateViewer/PayloadStateViewer.h
new file mode 100644
index 00000000..790387f9
--- /dev/null
+++ b/src/shared/Modules/PayloadStateViewer/PayloadStateViewer.h
@@ -0,0 +1,54 @@
+/*
+ * This file is part of Skyward Hub.
+ *
+ * Skyward Hub is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * Skyward Hub is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Skyward Hub. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <Core/Message/Filter.h>
+#include <Core/Message/Message.h>
+#include <Modules/DefaultModule/DefaultModule.h>
+
+#include <QLabel>
+#include <QWidget>
+
+#include "PayloadStatesList.h"
+
+class PayloadStateViewerModule : public DefaultModule
+{
+    Q_OBJECT
+
+public:
+    explicit PayloadStateViewerModule(QWidget* parent = nullptr);
+    ~PayloadStateViewerModule();
+
+    QWidget* toWidget() override;
+
+    XmlObject toXmlObject() override;
+    void fromXmlObject(const XmlObject& xmlObject) override;
+
+private:
+    void setupUi();
+    void addCustomActionsToMenu() override;
+    void onConfigureClicked();
+    void setFilter(const Filter& filter);
+    void onMsgReceived(const Message& msg);
+
+    QHBoxLayout* outerLayout;
+
+    Filter filter;
+    PayloadStatesList::State currentState;
+};
diff --git a/src/shared/Modules/PayloadStateViewer/PayloadStatesList.h b/src/shared/Modules/PayloadStateViewer/PayloadStatesList.h
new file mode 100644
index 00000000..9a45a210
--- /dev/null
+++ b/src/shared/Modules/PayloadStateViewer/PayloadStatesList.h
@@ -0,0 +1,77 @@
+/*
+ * This file is part of Skyward Hub.
+ *
+ * Skyward Hub is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * Skyward Hub is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Skyward Hub. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <QList>
+#include <QMap>
+#include <QString>
+
+namespace PayloadStatesList
+{
+
+// Rockets states
+enum class State : int
+{
+    INVALID = 0,
+    INIT,
+    INIT_ERROR,
+    INIT_DONE,
+    SENSORS_CALIBRATION,
+    ALGOS_CALIBRATION,
+    DISARMED,
+    TEST_MODE,
+    ARMED,
+    ASCENDING,
+    DROGUE_DESCENT,
+    WING_DESCENT,
+    LANDED,
+};
+
+// Groundstation labels
+static const QList<QString> statesLabels{
+    "INIT",
+    "CALIBRATE\nSENSORS",
+    "CALIBRATE\nALGORITHMS",
+    "DISARMED",
+    "TEST\nMODE",
+    "ARMED",
+    "ASCENDING",
+    "DROGUE\nDESCENT",
+    "WING\nDESCENT",
+    "LANDED",
+};
+
+// Map from rocket states to groundstation labels
+static const QMap<State, int> statesIndexes{
+    {State::INVALID, -1},
+    {State::INIT, 0},
+    {State::INIT_ERROR, 0},
+    {State::INIT_DONE, 0},
+    {State::SENSORS_CALIBRATION, 1},
+    {State::ALGOS_CALIBRATION, 2},
+    {State::DISARMED, 3},
+    {State::TEST_MODE, 4},
+    {State::ARMED, 5},
+    {State::ASCENDING, 6},
+    {State::DROGUE_DESCENT, 7},
+    {State::WING_DESCENT, 8},
+    {State::LANDED, 9}
+};
+
+}  // namespace StatesList
\ No newline at end of file
-- 
GitLab


From cdca25c2b62d8e69548513cc171dc6deb9e03207 Mon Sep 17 00:00:00 2001
From: Davide Mor <davide.mor@skywarder.eu>
Date: Sun, 17 Sep 2023 09:26:49 +0200
Subject: [PATCH 4/6] [StateViewer] Updated gs tester with fmm_state

---
 scripts/udp_gs_tester.py | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/scripts/udp_gs_tester.py b/scripts/udp_gs_tester.py
index 68c9afe0..87fb0a14 100755
--- a/scripts/udp_gs_tester.py
+++ b/scripts/udp_gs_tester.py
@@ -47,7 +47,7 @@ def fake_data(i):
     return MAVLink_rocket_flight_tm_message(
         get_timestamp(), # timestamp
         0, # ada_state
-        0, # fmm_state
+        i % 15, # fmm_state
         0, # dpl_state
         0, # abk_state
         0, # nas_state
@@ -87,6 +87,7 @@ def fake_data(i):
         0.0, # nas_bias_x
         0.0, # nas_bias_y
         0.0, # nas_bias_z
+        0, # pin_quick_connector
         0, # pin_launch
         0, # pin_nosecone
         0, # pin_expulsion
@@ -96,6 +97,7 @@ def fake_data(i):
         0.0, # cam_battery_voltage
         0.0, # temperature
         0, # logger_error
+        
     )
 
 def build_ack(msg):
-- 
GitLab


From 17af97a5abec86511ed9568e811b0880aecfb292 Mon Sep 17 00:00:00 2001
From: Davide Mor <davide.mor@skywarder.eu>
Date: Sun, 17 Sep 2023 09:30:08 +0200
Subject: [PATCH 5/6] [StateViewer] Fixed formatting

---
 .../MainStateViewer/MainStateViewer.cpp       |  3 +-
 .../Modules/MainStateViewer/MainStatesList.h  | 38 ++++++++---------
 .../PayloadStateViewer/PayloadStateViewer.cpp | 13 +++---
 .../PayloadStateViewer/PayloadStatesList.h    | 42 ++++++++-----------
 4 files changed, 45 insertions(+), 51 deletions(-)

diff --git a/src/shared/Modules/MainStateViewer/MainStateViewer.cpp b/src/shared/Modules/MainStateViewer/MainStateViewer.cpp
index 4776e98f..c9648a23 100644
--- a/src/shared/Modules/MainStateViewer/MainStateViewer.cpp
+++ b/src/shared/Modules/MainStateViewer/MainStateViewer.cpp
@@ -21,7 +21,8 @@
 #include <Components/FilterSelector/FilterSelector.h>
 #include <Core/MessageBroker/MessageBroker.h>
 
-MainStateViewerModule::MainStateViewerModule(QWidget* parent) : DefaultModule(parent)
+MainStateViewerModule::MainStateViewerModule(QWidget* parent)
+    : DefaultModule(parent)
 {
     setupUi();
     defaultContextMenuSetup();
diff --git a/src/shared/Modules/MainStateViewer/MainStatesList.h b/src/shared/Modules/MainStateViewer/MainStatesList.h
index afbf389a..d5ec9a4e 100644
--- a/src/shared/Modules/MainStateViewer/MainStatesList.h
+++ b/src/shared/Modules/MainStateViewer/MainStatesList.h
@@ -63,24 +63,22 @@ static const QList<QString> statesLabels{
 };
 
 // Map from rocket states to groundstation labels
-static const QMap<State, int> statesIndexes{
-    {State::INVALID, -1},
-    {State::ON_GROUND, -1},
-    {State::IGNITION, -1},
-    {State::FLYING, -1},
-    {State::INIT, 0},
-    {State::INIT_ERROR, 0},
-    {State::INIT_DONE, 0},
-    {State::CALIBRATE_SENSORS, 1},
-    {State::CALIBRATE_ALGORITHMS, 2},
-    {State::DISARMED, 3},
-    {State::TEST_MODE, 4},
-    {State::ARMED, 5},
-    {State::POWERED_ASCENT, 6},
-    {State::UNPOWERED_ASCENT, 7},
-    {State::DROGUE_DESCENT, 8},
-    {State::TERMINAL_DESCENT, 9},
-    {State::LANDED, 10}
-};
+static const QMap<State, int> statesIndexes{{State::INVALID, -1},
+                                            {State::ON_GROUND, -1},
+                                            {State::IGNITION, -1},
+                                            {State::FLYING, -1},
+                                            {State::INIT, 0},
+                                            {State::INIT_ERROR, 0},
+                                            {State::INIT_DONE, 0},
+                                            {State::CALIBRATE_SENSORS, 1},
+                                            {State::CALIBRATE_ALGORITHMS, 2},
+                                            {State::DISARMED, 3},
+                                            {State::TEST_MODE, 4},
+                                            {State::ARMED, 5},
+                                            {State::POWERED_ASCENT, 6},
+                                            {State::UNPOWERED_ASCENT, 7},
+                                            {State::DROGUE_DESCENT, 8},
+                                            {State::TERMINAL_DESCENT, 9},
+                                            {State::LANDED, 10}};
 
-}  // namespace StatesList
\ No newline at end of file
+}  // namespace MainStatesList
\ No newline at end of file
diff --git a/src/shared/Modules/PayloadStateViewer/PayloadStateViewer.cpp b/src/shared/Modules/PayloadStateViewer/PayloadStateViewer.cpp
index d05eacee..8202a497 100644
--- a/src/shared/Modules/PayloadStateViewer/PayloadStateViewer.cpp
+++ b/src/shared/Modules/PayloadStateViewer/PayloadStateViewer.cpp
@@ -21,7 +21,8 @@
 #include <Components/FilterSelector/FilterSelector.h>
 #include <Core/MessageBroker/MessageBroker.h>
 
-PayloadStateViewerModule::PayloadStateViewerModule(QWidget* parent) : DefaultModule(parent)
+PayloadStateViewerModule::PayloadStateViewerModule(QWidget* parent)
+    : DefaultModule(parent)
 {
     setupUi();
     defaultContextMenuSetup();
@@ -131,12 +132,14 @@ void PayloadStateViewerModule::onMsgReceived(const Message& msg)
             outerLayout->itemAt(i)->widget()->setStyleSheet(completedStyle);
 
         // Reset every state after the current
-        for (int i = index + 1; i < PayloadStatesList::statesLabels.count(); i++)
+        for (int i = index + 1; i < PayloadStatesList::statesLabels.count();
+             i++)
             outerLayout->itemAt(i)->widget()->setStyleSheet(baseStyle);
 
-        auto tmp = outerLayout->itemAt(PayloadStatesList::statesLabels.count() - 1)
-                       ->widget()
-                       ->styleSheet();
+        auto tmp =
+            outerLayout->itemAt(PayloadStatesList::statesLabels.count() - 1)
+                ->widget()
+                ->styleSheet();
         outerLayout->itemAt(PayloadStatesList::statesLabels.count() - 1)
             ->widget()
             ->setStyleSheet(tmp + "border-right-width:1px;");
diff --git a/src/shared/Modules/PayloadStateViewer/PayloadStatesList.h b/src/shared/Modules/PayloadStateViewer/PayloadStatesList.h
index 9a45a210..a822eefd 100644
--- a/src/shared/Modules/PayloadStateViewer/PayloadStatesList.h
+++ b/src/shared/Modules/PayloadStateViewer/PayloadStatesList.h
@@ -45,33 +45,25 @@ enum class State : int
 
 // Groundstation labels
 static const QList<QString> statesLabels{
-    "INIT",
-    "CALIBRATE\nSENSORS",
-    "CALIBRATE\nALGORITHMS",
-    "DISARMED",
-    "TEST\nMODE",
-    "ARMED",
-    "ASCENDING",
-    "DROGUE\nDESCENT",
-    "WING\nDESCENT",
+    "INIT",      "CALIBRATE\nSENSORS", "CALIBRATE\nALGORITHMS",
+    "DISARMED",  "TEST\nMODE",         "ARMED",
+    "ASCENDING", "DROGUE\nDESCENT",    "WING\nDESCENT",
     "LANDED",
 };
 
 // Map from rocket states to groundstation labels
-static const QMap<State, int> statesIndexes{
-    {State::INVALID, -1},
-    {State::INIT, 0},
-    {State::INIT_ERROR, 0},
-    {State::INIT_DONE, 0},
-    {State::SENSORS_CALIBRATION, 1},
-    {State::ALGOS_CALIBRATION, 2},
-    {State::DISARMED, 3},
-    {State::TEST_MODE, 4},
-    {State::ARMED, 5},
-    {State::ASCENDING, 6},
-    {State::DROGUE_DESCENT, 7},
-    {State::WING_DESCENT, 8},
-    {State::LANDED, 9}
-};
+static const QMap<State, int> statesIndexes{{State::INVALID, -1},
+                                            {State::INIT, 0},
+                                            {State::INIT_ERROR, 0},
+                                            {State::INIT_DONE, 0},
+                                            {State::SENSORS_CALIBRATION, 1},
+                                            {State::ALGOS_CALIBRATION, 2},
+                                            {State::DISARMED, 3},
+                                            {State::TEST_MODE, 4},
+                                            {State::ARMED, 5},
+                                            {State::ASCENDING, 6},
+                                            {State::DROGUE_DESCENT, 7},
+                                            {State::WING_DESCENT, 8},
+                                            {State::LANDED, 9}};
 
-}  // namespace StatesList
\ No newline at end of file
+}  // namespace PayloadStatesList
\ No newline at end of file
-- 
GitLab


From 321bc8cee006b108b82fea8d3cdafe030b6c3381 Mon Sep 17 00:00:00 2001
From: Davide Mor <davide.mor@skywarder.eu>
Date: Sun, 17 Sep 2023 09:42:53 +0200
Subject: [PATCH 6/6] [StateViewer] Fixed windows compilation

---
 SkywardHub.pro | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/SkywardHub.pro b/SkywardHub.pro
index e6877463..75586e3a 100644
--- a/SkywardHub.pro
+++ b/SkywardHub.pro
@@ -83,8 +83,10 @@ HEADERS += \
     src/shared/Modules/TimerController/TimerControllerModule.h \
     src/shared/Modules/ModuleInfo.h \
     src/shared/Modules/OrientationVisualizer/OrientationVisualizer.h \
-    src/shared/Modules/StateViewer/StatesList.h \
-    src/shared/Modules/StateViewer/StateViewer.h \
+    src/shared/Modules/MainStateViewer/MainStatesList.h \
+    src/shared/Modules/MainStateViewer/MainStateViewer.h \
+    src/shared/Modules/PayloadStateViewer/PayloadStatesList.h \
+    src/shared/Modules/PayloadStateViewer/PayloadStateViewer.h \
     src/shared/Modules/FileStream/FileStreamModule.h \
     src/shared/Modules/Graph/Graph.h \
     src/shared/Modules/Test/TestModule.h \
-- 
GitLab