From d2e69df355b55e701b3fe71462ecc8d667cacf15 Mon Sep 17 00:00:00 2001
From: Pos <pierpaolo.mancini@mail.polimi.it>
Date: Wed, 26 May 2021 18:05:15 +0200
Subject: [PATCH] Small fix

---
 Modules/CommandPad/commandpadmodule.ui |  75 +++++----
 Modules/Mavlink/mavlinkmodule.cpp      | 220 ++++++++++++++-----------
 Modules/Mavlink/mavlinkmodule.h        |  16 +-
 Modules/Mavlink/mavlinkmodule.ui       |  43 +++--
 Modules/Mavlink/mavlinkreader.cpp      |  49 +++---
 Modules/Mavlink/mavlinkreader.h        |   2 +-
 Modules/Test/testmodule.cpp            |  13 +-
 Modules/Test/testmodule.h              |   3 +
 Modules/Test/testmodule.ui             |  52 ++++--
 Modules/skywardhubstrings.cpp          |   1 +
 Modules/skywardhubstrings.h            |   2 +-
 SkywardHub.pro.user                    |   2 +-
 12 files changed, 282 insertions(+), 196 deletions(-)

diff --git a/Modules/CommandPad/commandpadmodule.ui b/Modules/CommandPad/commandpadmodule.ui
index 081f7101..a46c463e 100644
--- a/Modules/CommandPad/commandpadmodule.ui
+++ b/Modules/CommandPad/commandpadmodule.ui
@@ -13,7 +13,7 @@
   <property name="windowTitle">
    <string>Form</string>
   </property>
-  <layout class="QVBoxLayout" name="verticalLayout_3" stretch="1,1,0,0,2,2,2,2">
+  <layout class="QVBoxLayout" name="verticalLayout_3" stretch="1,1,0,0,0,2,2,2,2">
    <item>
     <widget class="QGroupBox" name="groupBox">
      <property name="title">
@@ -115,65 +115,60 @@
    <item>
     <widget class="QGroupBox" name="groupBox_7">
      <property name="title">
-      <string>Test</string>
+      <string>Deployment</string>
      </property>
      <property name="alignment">
       <set>Qt::AlignCenter</set>
      </property>
      <layout class="QGridLayout" name="gridLayout">
       <item row="1" column="0">
-       <widget class="QPushButton" name="wiggleDPLServo_button">
-        <property name="text">
-         <string>WIGGLE DPL SERVO</string>
-        </property>
-       </widget>
-      </item>
-      <item row="2" column="2">
-       <widget class="QPushButton" name="testBackupCut_button">
+       <widget class="QPushButton" name="resetDPLServo_button">
         <property name="text">
-         <string>TEST BACKUP CUT</string>
+         <string>RESET DPL SERVO</string>
         </property>
        </widget>
       </item>
       <item row="0" column="0">
-       <widget class="QPushButton" name="wiggleARBServo_button">
-        <property name="text">
-         <string>WIGGLE ARB SERVO</string>
-        </property>
-       </widget>
-      </item>
-      <item row="0" column="2">
-       <widget class="QPushButton" name="testPrimaryCut_button">
+       <widget class="QPushButton" name="wiggleDPLServo_button">
         <property name="text">
-         <string>TEST PRIMARY  CUT</string>
+         <string>WIGGLE DPL SERVO</string>
         </property>
        </widget>
       </item>
-      <item row="2" column="0">
-       <widget class="QPushButton" name="resetARBServo_button">
+      <item row="0" column="1">
+       <widget class="QPushButton" name="testMode_button">
         <property name="text">
-         <string>RESET ARB SERVO</string>
+         <string>TEST MODE</string>
         </property>
        </widget>
       </item>
-      <item row="3" column="0">
-       <widget class="QPushButton" name="resetDPLServo_button">
+      <item row="1" column="1">
+       <widget class="QPushButton" name="boardReset_button">
         <property name="text">
-         <string>RESET DPL SERVO</string>
+         <string>BOARD RESET</string>
         </property>
        </widget>
       </item>
-      <item row="3" column="2">
-       <widget class="QPushButton" name="boardReset_button">
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="groupBox_9">
+     <property name="title">
+      <string>Cutter</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout_5">
+      <item>
+       <widget class="QPushButton" name="testBackupCut_button">
         <property name="text">
-         <string>BOARD RESET</string>
+         <string>TEST BACKUP CUT</string>
         </property>
        </widget>
       </item>
-      <item row="1" column="2">
-       <widget class="QPushButton" name="testMode_button">
+      <item>
+       <widget class="QPushButton" name="testPrimaryCut_button">
         <property name="text">
-         <string>TEST MODE</string>
+         <string>TEST PRIMARY  CUT</string>
         </property>
        </widget>
       </item>
@@ -196,6 +191,20 @@
         </property>
        </widget>
       </item>
+      <item>
+       <widget class="QPushButton" name="resetARBServo_button">
+        <property name="text">
+         <string>RESET ARB SERVO</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QPushButton" name="wiggleARBServo_button">
+        <property name="text">
+         <string>WIGGLE ARB SERVO</string>
+        </property>
+       </widget>
+      </item>
       <item>
        <widget class="QPushButton" name="disableAerobrakes_button">
         <property name="text">
@@ -515,7 +524,7 @@
    <item>
     <widget class="QGroupBox" name="groupBox_6">
      <property name="title">
-      <string>Drogue</string>
+      <string>Flight</string>
      </property>
      <property name="alignment">
       <set>Qt::AlignCenter</set>
diff --git a/Modules/Mavlink/mavlinkmodule.cpp b/Modules/Mavlink/mavlinkmodule.cpp
index e09071a9..820e35f4 100644
--- a/Modules/Mavlink/mavlinkmodule.cpp
+++ b/Modules/Mavlink/mavlinkmodule.cpp
@@ -12,18 +12,21 @@ MavlinkModule::MavlinkModule(QWidget *parent) : DefaultModule(parent), ui(new Ui
     defaultContextMenuSetup();
 
     initializeSerialPortView();
-    buildCentralGraphView();
+//    buildCentralGraphView();
     connectUiSlots();
     qRegisterMetaType<ModuleMessage>();
     connect(&mavlinkReader,&MavlinkReader::msgReceived, this, &MavlinkModule::onMsgReceived);
     connect(&mavlinkCommandAdapter,&MavlinkCommandAdapter::publishRequested, this, &MavlinkModule::publish);
+    connect(&linkQualityTimer, &QTimer::timeout, this, &MavlinkModule::onLinkQualityTimerTick);
     mavlinkCommandAdapter.setSerialPort(&serialPort);
     subscribe();
 }
 
 MavlinkModule::~MavlinkModule()
 {
+    mavlinkReader.stopReading();
     delete ui;
+    closePort();
 }
 
 QWidget* MavlinkModule::toWidget()
@@ -64,22 +67,29 @@ void MavlinkModule::publish(const ModuleMessage &msg)
     getCore()->getModuleMessagesBroker()->publish(msg);
 }
 
-void MavlinkModule::replotAll()
+void MavlinkModule::closePort()
 {
-    if(ui->groupBox_2->isChecked()){
-        if(ui->checkBox_follow->isChecked() && linkGraph != nullptr && !linkGraph->data()->isEmpty()){
-            // Center the view to the last sample in the graph
-            double lastKey = (linkGraph->data()->constEnd()-1)->key;
-            double lastValue = (linkGraph->data()->constEnd()-1)->value;
-            double size_x = graphCentralView.xAxis->range().size();
-            double size_y = graphCentralView.yAxis->range().size();
-            graphCentralView.xAxis->setRange(lastKey, size_x, Qt::AlignmentFlag::AlignCenter);
-            graphCentralView.yAxis->setRange(lastValue, size_y, Qt::AlignmentFlag::AlignCenter);
-        }
-        graphCentralView.replot();
+    if(serialPort.isOpen()){
+        serialPort.close();
     }
 }
 
+//void MavlinkModule::replotAll()
+//{
+//    if(ui->linkQuality_groupBox->isChecked()){
+//        if(ui->checkBox_follow->isChecked() && linkGraph != nullptr && !linkGraph->data()->isEmpty()){
+//            // Center the view to the last sample in the graph
+//            double lastKey = (linkGraph->data()->constEnd()-1)->key;
+//            double lastValue = (linkGraph->data()->constEnd()-1)->value;
+//            double size_x = graphCentralView.xAxis->range().size();
+//            double size_y = graphCentralView.yAxis->range().size();
+//            graphCentralView.xAxis->setRange(lastKey, size_x, Qt::AlignmentFlag::AlignCenter);
+//            graphCentralView.yAxis->setRange(lastValue, size_y, Qt::AlignmentFlag::AlignCenter);
+//        }
+//        graphCentralView.replot();
+//    }
+//}
+
 void MavlinkModule::initializeSerialPortView()
 {
     //fill the baud rate combo box
@@ -94,6 +104,7 @@ void MavlinkModule::initializeSerialPortView()
     ui->comboBox_baudRate->addItem(baudPrefix + "1200", QSerialPort::Baud1200);
 
 
+    bool first = true;
     //Check available port
     const auto serialPortInfos = QSerialPortInfo::availablePorts();
     for (const QSerialPortInfo &serialPortInfo : serialPortInfos) {
@@ -101,59 +112,64 @@ void MavlinkModule::initializeSerialPortView()
 //        QVariant data = (!serialNumber.isEmpty() ? serialNumber : "N/A");
         QVariant data(serialPortInfo.portName());
         ui->comboBox_serialPort->addItem(serialPortInfo.portName(), data);
+
+        if(first){
+            ui->lineEdit_serialPort->setText(serialPortInfo.portName());
+            first = false;
+        }
     }
 }
 
 
-void MavlinkModule::buildCentralGraphView()
-{
-    ui->graphLayout->addWidget(&graphCentralView);
-    linkGraph = graphCentralView.addGraph();
+//void MavlinkModule::buildCentralGraphView()
+//{
+//    ui->graphLayout->addWidget(&graphCentralView);
+//    linkGraph = graphCentralView.addGraph();
 
-    // Set graph style
-    linkGraph->setPen(QPen(Qt::green)); // line color
-    linkGraph->setBrush(QBrush(QColor(0, 128, 0, 40))); // first graph will be filled with this color
+//    // Set graph style
+//    linkGraph->setPen(QPen(Qt::green)); // line color
+//    linkGraph->setBrush(QBrush(QColor(0, 128, 0, 40))); // first graph will be filled with this color
 
 
-    // int maxPackets = ui->spinBox_maxPackets->value();
-    // graphCentralView.yAxis->setRange(0, maxPackets);
+//    // int maxPackets = ui->spinBox_maxPackets->value();
+//    // graphCentralView.yAxis->setRange(0, maxPackets);
 
-    graphCentralView.yAxis2->setVisible(false);
-    // graphCentralView.yAxis2->setTicks(true);
-    // graphCentralView.yAxis2->setTickLabels(true);
+//    graphCentralView.yAxis2->setVisible(false);
+//    // graphCentralView.yAxis2->setTicks(true);
+//    // graphCentralView.yAxis2->setTickLabels(true);
 
-    //graphCentralView.xAxis2->setVisible(true);
-    //textTicker = QSharedPointer<QCPAxisTickerText>(new QCPAxisTickerText());
-    //cPlot.xAxis2->setTicker(textTicker);
-    //graphCentralView.xAxis2->setTickLabels(true);
+//    //graphCentralView.xAxis2->setVisible(true);
+//    //textTicker = QSharedPointer<QCPAxisTickerText>(new QCPAxisTickerText());
+//    //cPlot.xAxis2->setTicker(textTicker);
+//    //graphCentralView.xAxis2->setTickLabels(true);
 
-    QSharedPointer<QCPAxisTickerDateTime> dateTimeTicker(new QCPAxisTickerDateTime);
-    graphCentralView.xAxis->setTicker(dateTimeTicker);
-    //QDateTime rangeLowerBound = QDateTime::currentDateTime().addDays(-2);
-    double now = QDateTime::currentDateTime().toTime_t();
-    QDateTime rangeUpperBound = QDateTime::currentDateTime().addDays(+2);
-    graphCentralView.xAxis->setRange(now, QCPAxisTickerDateTime::dateTimeToKey(rangeUpperBound));
-    dateTimeTicker->setDateTimeFormat(dateFormat);
+//    QSharedPointer<QCPAxisTickerDateTime> dateTimeTicker(new QCPAxisTickerDateTime);
+//    graphCentralView.xAxis->setTicker(dateTimeTicker);
+//    //QDateTime rangeLowerBound = QDateTime::currentDateTime().addDays(-2);
+//    double now = QDateTime::currentDateTime().toTime_t();
+//    QDateTime rangeUpperBound = QDateTime::currentDateTime().addDays(+2);
+//    graphCentralView.xAxis->setRange(now, QCPAxisTickerDateTime::dateTimeToKey(rangeUpperBound));
+//    dateTimeTicker->setDateTimeFormat(dateFormat);
 
-    graphCentralView.legend->setVisible(false);
+//    graphCentralView.legend->setVisible(false);
 
-    // make left and bottom axes always transfer their ranges to right and top axes:
-    connect(graphCentralView.xAxis, SIGNAL(rangeChanged(QCPRange)), graphCentralView.xAxis2, SLOT(setRange(QCPRange)));
-    connect(graphCentralView.yAxis, SIGNAL(rangeChanged(QCPRange)), graphCentralView.yAxis2, SLOT(setRange(QCPRange)));
+//    // make left and bottom axes always transfer their ranges to right and top axes:
+//    connect(graphCentralView.xAxis, SIGNAL(rangeChanged(QCPRange)), graphCentralView.xAxis2, SLOT(setRange(QCPRange)));
+//    connect(graphCentralView.yAxis, SIGNAL(rangeChanged(QCPRange)), graphCentralView.yAxis2, SLOT(setRange(QCPRange)));
 
-    // Allow user to drag axis ranges with mouse, zoom with mouse wheel and select graphs by clicking:
-    graphCentralView.setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
+//    // Allow user to drag axis ranges with mouse, zoom with mouse wheel and select graphs by clicking:
+//    graphCentralView.setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
 
-    // Disable  drag and zoom on y axe
-    // graphCentralView.axisRects().at(0)->setRangeDrag(Qt::Horizontal);
-    // graphCentralView.axisRects().at(0)->setRangeZoom(Qt::Horizontal);
+//    // Disable  drag and zoom on y axe
+//    // graphCentralView.axisRects().at(0)->setRangeDrag(Qt::Horizontal);
+//    // graphCentralView.axisRects().at(0)->setRangeZoom(Qt::Horizontal);
 
-    // Enable context menu
-    graphCentralView.setContextMenuPolicy(Qt::CustomContextMenu);
-    // connect(&graphCentralView,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(onCustomContextMenuRequested(QPoint)));
-    connect(&graphCentralView, &QCustomPlot::customContextMenuRequested, this, &MavlinkModule::onCustomContextMenuRequested);
-    //connect(customPlot,SIGNAL(selectionChangedByUser()),this,SLOT(selectedGraphChange()));
-}
+//    // Enable context menu
+//    graphCentralView.setContextMenuPolicy(Qt::CustomContextMenu);
+//    // connect(&graphCentralView,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(onCustomContextMenuRequested(QPoint)));
+//    connect(&graphCentralView, &QCustomPlot::customContextMenuRequested, this, &MavlinkModule::onCustomContextMenuRequested);
+//    //connect(customPlot,SIGNAL(selectionChangedByUser()),this,SLOT(selectedGraphChange()));
+//}
 
 void MavlinkModule::onStartClicked()
 {
@@ -168,15 +184,73 @@ bool MavlinkModule::startReadingOnSerialPort()
     QString portName = ui->lineEdit_serialPort->text().trimmed();
     bool ok;
     int baudRate = ui->comboBox_baudRate->currentData().toInt(&ok);
-    if(ok && portName != ""){
+    if(ok && portName != "" && !serialPort.isOpen()){
         QSerialPortInfo port(portName);
         serialPort.setPort(port);
         serialPort.setBaudRate(baudRate);
+//        serialPort.setDataBits(QSerialPort::Data8);
+//        serialPort.setParity(QSerialPort::NoParity);
+//        serialPort.setStopBits(QSerialPort::TwoStop);
         return serialPort.open(QIODevice::ReadWrite);
     }
     return false;
 }
 
+
+
+void MavlinkModule::onStopClicked()
+{
+    mavlinkReader.stopReading();
+    closePort();
+}
+
+void MavlinkModule::onMsgReceived(const ModuleMessage &msg)
+{
+    msgArrived++;
+    publish(msg);
+}
+
+void MavlinkModule::onLinkQualityIndicatorClicked(bool checked)
+{
+    if(checked && !linkQualityTimer.isActive()){
+        linkQualityTimer.start(linkQualityPeriod);
+    }
+    else if(!checked && linkQualityTimer.isActive()){
+        linkQualityTimer.stop();
+    }
+}
+
+void MavlinkModule::onLinkQualityTimerTick()
+{
+    float ratio = msgArrived/ui->spinBox_maxPackets->value();
+    updateLinkSignalIndicator(msgArrived, ratio);
+    msgArrived = 0;
+}
+
+void MavlinkModule::updateLinkSignalIndicator(int msgArrived, float ratio)
+{
+    ModuleMessage linkQualityMsgNumber(SkywardHubStrings::mavlink_quality_link_topic + "/ReceivedMsgNumber", QString::number(msgArrived));
+    ModuleMessage linkQualityMsgRatio(SkywardHubStrings::mavlink_quality_link_topic + "/ReceivedRatio", QString::number(ratio));
+
+    publish(linkQualityMsgNumber);
+    publish(linkQualityMsgRatio);
+}
+
+void MavlinkModule::connectUiSlots()
+{
+    connect(ui->button_start,&QPushButton::clicked,this, &MavlinkModule::onStartClicked);
+    connect(ui->button_stop,&QPushButton::clicked,this, &MavlinkModule::onStopClicked);
+//    connect(ui->spinBox_maxPackets,SIGNAL(valueChanged(int)),this,SLOT(onMaxPackedValueChanged(int)));
+    connect(ui->comboBox_serialPort, SIGNAL(currentIndexChanged(int)), this, SLOT(onSerialPortIndexChanged(int)));
+    connect(ui->linkQuality_groupBox, &QGroupBox::clicked, this, &MavlinkModule::onLinkQualityIndicatorClicked);
+}
+
+void MavlinkModule::onSerialPortIndexChanged(int index)
+{
+    QVariant data = ui->comboBox_serialPort->itemData(index);
+    ui->lineEdit_serialPort->setText(data.toString());
+}
+
 void MavlinkModule::onCommandReceived(const ModuleMessage &msg)
 {
     QString arg = msg.originalTopic().replace(SkywardHubStrings::commandsTopic+"/","");
@@ -383,45 +457,3 @@ void MavlinkModule::onTelemetryRequestReceived(const ModuleMessage &msg)
 
     mavlinkCommandAdapter.send(encoded_mvl_msg);
 }
-
-void MavlinkModule::onStopClicked()
-{
-    mavlinkReader.close();
-}
-
-void MavlinkModule::onMaxPackedValueChanged(int val)
-{
-    graphCentralView.yAxis->setRange(0, val);
-    replotAll();
-}
-
-void MavlinkModule::onMsgReceived(const ModuleMessage &msg)
-{
-    publish(msg);
-//    if(linkGraph != nullptr){
-//        double x = 0,y = 0;
-//        x = msg.timestamp().toTime_t();
-//        bool ok;
-//        y = msg.payload().toDouble(&ok);
-//        if(ok){
-//            linkGraph->addData(x,y);
-//            //Da rimuovere per performance
-//            replotAll();
-//        }
-    //    }
-}
-
-void MavlinkModule::connectUiSlots()
-{
-    connect(ui->button_start,&QPushButton::clicked,this, &MavlinkModule::onStartClicked);
-    connect(ui->button_stop,&QPushButton::clicked,this, &MavlinkModule::onStopClicked);
-    connect(ui->spinBox_maxPackets,SIGNAL(valueChanged(int)),this,SLOT(onMaxPackedValueChanged(int)));
-    connect(ui->comboBox_serialPort, SIGNAL(currentIndexChanged(int)), this, SLOT(onSerialPortIndexChanged(int)));
-}
-
-void MavlinkModule::onSerialPortIndexChanged(int index)
-{
-    QVariant data = ui->comboBox_serialPort->itemData(index);
-    ui->lineEdit_serialPort->setText(data.toString());
-}
-
diff --git a/Modules/Mavlink/mavlinkmodule.h b/Modules/Mavlink/mavlinkmodule.h
index 80a8820b..8102aa80 100644
--- a/Modules/Mavlink/mavlinkmodule.h
+++ b/Modules/Mavlink/mavlinkmodule.h
@@ -27,7 +27,7 @@ public:
     QWidget * toWidget() override;
     XmlObject toXmlObject() override;
     void fromXmlObject(const XmlObject &xmlObject) override;
-    void replotAll();
+//    void replotAll();
 
     void onCommandReceived(const ModuleMessage &msg);
     void onTelemetryRequestReceived(const ModuleMessage &msg);
@@ -35,18 +35,24 @@ public:
 public slots:
     void onStartClicked();
     void onStopClicked();
-    void onMaxPackedValueChanged(int val);
     void onMsgReceived(const ModuleMessage &msg);
+    void onLinkQualityIndicatorClicked(bool checked);
+    void onLinkQualityTimerTick();
 
 protected:
     void connectUiSlots();
     void initializeSerialPortView();
-    void buildCentralGraphView();
+//    void buildCentralGraphView();
     mavlink_message_t parseMavlinkMsg(char *buffer, int readCount);
 
     void subscribe();
     void publish(const ModuleMessage &msg);
 
+    void closePort();
+    void updateLinkSignalIndicator();
+
+    void updateLinkSignalIndicator(int msgArrived, float ratio);
+
 private slots:
     void onSerialPortIndexChanged(int index);
     bool startReadingOnSerialPort();
@@ -62,6 +68,10 @@ private:
     MavlinkCommandAdapter mavlinkCommandAdapter;
     QSerialPort serialPort;
 
+    QTimer linkQualityTimer;
+    int linkQualityPeriod = 1000; // [ms]
+    int msgArrived = 0;
+
 };
 
 #endif // MAVLINKMODULE_H
diff --git a/Modules/Mavlink/mavlinkmodule.ui b/Modules/Mavlink/mavlinkmodule.ui
index 2a6ca0f7..32df5018 100644
--- a/Modules/Mavlink/mavlinkmodule.ui
+++ b/Modules/Mavlink/mavlinkmodule.ui
@@ -7,13 +7,13 @@
     <x>0</x>
     <y>0</y>
     <width>401</width>
-    <height>309</height>
+    <height>541</height>
    </rect>
   </property>
   <property name="windowTitle">
    <string>Form</string>
   </property>
-  <layout class="QVBoxLayout" name="verticalLayout" stretch="0,1,0">
+  <layout class="QVBoxLayout" name="verticalLayout" stretch="0,1,0,1">
    <item>
     <widget class="QLabel" name="module_title">
      <property name="text">
@@ -25,7 +25,7 @@
     </widget>
    </item>
    <item>
-    <widget class="QGroupBox" name="groupBox_2">
+    <widget class="QGroupBox" name="linkQuality_groupBox">
      <property name="title">
       <string>Link quality</string>
      </property>
@@ -38,25 +38,9 @@
      <property name="checkable">
       <bool>true</bool>
      </property>
-     <layout class="QVBoxLayout" name="verticalLayout_3" stretch="0,1">
+     <layout class="QVBoxLayout" name="verticalLayout_3" stretch="0">
       <item>
-       <layout class="QHBoxLayout" name="horizontalLayout_4" stretch="1,0,0,0">
-        <item>
-         <widget class="QCheckBox" name="checkBox_follow">
-          <property name="sizePolicy">
-           <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-            <horstretch>0</horstretch>
-            <verstretch>0</verstretch>
-           </sizepolicy>
-          </property>
-          <property name="text">
-           <string>Follow</string>
-          </property>
-          <property name="checked">
-           <bool>true</bool>
-          </property>
-         </widget>
-        </item>
+       <layout class="QHBoxLayout" name="horizontalLayout_4" stretch="0,0,0">
         <item>
          <spacer name="horizontalSpacer">
           <property name="orientation">
@@ -98,8 +82,21 @@
         </item>
        </layout>
       </item>
-      <item>
-       <layout class="QVBoxLayout" name="graphLayout"/>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="groupBox_2">
+     <property name="title">
+      <string>Setup</string>
+     </property>
+     <layout class="QGridLayout" name="gridLayout">
+      <item row="0" column="0">
+       <widget class="QLabel" name="label_2">
+        <property name="text">
+         <string>TextLabel</string>
+        </property>
+       </widget>
       </item>
      </layout>
     </widget>
diff --git a/Modules/Mavlink/mavlinkreader.cpp b/Modules/Mavlink/mavlinkreader.cpp
index 5d3355bb..d908f4bf 100644
--- a/Modules/Mavlink/mavlinkreader.cpp
+++ b/Modules/Mavlink/mavlinkreader.cpp
@@ -3,6 +3,8 @@
 #include <QFile>
 #include <QTextStream>
 
+#include "windows.h"
+
 MavlinkReader::MavlinkReader()
 {
     //loadMsgMapping();
@@ -10,21 +12,15 @@ MavlinkReader::MavlinkReader()
 
 MavlinkReader::~MavlinkReader()
 {
-    close();
-}
 
-
-void MavlinkReader::close()
-{
-    if(serial != nullptr && serial->isOpen() ){
-        serial->close();
-    }
 }
 
 void MavlinkReader::startAsyncReading(QSerialPort *port)
 {
+    stop = false;
     serial = port;
     this->start(); // Chiama run()
+
 }
 
 //void MavlinkReader::loadMsgMapping()
@@ -50,20 +46,27 @@ void MavlinkReader::run()
     }
 }
 
+void MavlinkReader::stopReading()
+{
+    stop = true;
+}
+
 mavlink_message_t MavlinkReader::waitForMavlinkMsg()
 {
     mavlink_message_t msg;
     mavlink_status_t status;
+    int waitingTimeout = 1000;
 
     int numRead = 0;
-    char buffer[1];
+
     unsigned char byte;
 
-    while (!stop && serial != nullptr) {
-        numRead  = serial->read(buffer, 1);
+    while (!stop && serial != nullptr && serial->waitForReadyRead(waitingTimeout)) {
+        QByteArray dataRead = serial->readAll();
+        numRead = dataRead.size();
 
-        if(numRead == 1){
-            byte = buffer[0];
+        for(int i = 0; i < dataRead.count(); i++){
+            byte = dataRead.at(i);
             if(mavlink_parse_char(MAVLINK_COMM_0, byte, &msg, &status)){
                 // if the parser has found a message, return it
                 return msg;
@@ -74,15 +77,11 @@ mavlink_message_t MavlinkReader::waitForMavlinkMsg()
             //An error occurred
             stop = true;
         }
-
-        if (numRead == 0 && !serial->waitForReadyRead())
-            break;
     }
 
     return msg;
 }
 
-
 QList<ModuleMessage> MavlinkReader::parseMavlinkMsg(mavlink_message_t *msg)
 {
     if(msg == nullptr)
@@ -130,14 +129,18 @@ QString MavlinkReader::extractFields(mavlink_message_t *msg, const mavlink_field
 QList<ModuleMessage> MavlinkReader::translateToGsMessage(mavlink_message_t *msg, const QString &msgName, const QMap<QString,QString> &payloads)
 {
     QDateTime timestamp;
+    bool timeOK = false;
+    double t;
     if(payloads.contains("timestamp")){
-        bool ok;
-        unsigned long t = payloads["timestamp"].toLong(&ok);
-        timestamp.fromTime_t(t);
+        t = payloads["timestamp"].toDouble(&timeOK);
     }
-    else{
+
+    if(!timeOK){
         timestamp = timestamp.currentDateTime();
     }
+    else{
+        timestamp.setTime_t(t);
+    }
 
     QList<ModuleMessage> messagesReceived;
 
@@ -222,7 +225,9 @@ QString MavlinkReader::extractOneField(mavlink_message_t *msg, const mavlink_fie
         {
         //printf(PRINT_FORMAT(f, "%f"), (double)_MAV_RETURN_float(msg, f->wire_offset+idx*4));
         double val_double = (double)_MAV_RETURN_float(msg, f->wire_offset+idx*4);
-        payload = QString::number(val_double);
+        QTextStream out(&payload);
+        out.setRealNumberNotation(QTextStream::FixedNotation);
+        out << val_double;
 
         } break;
         case MAVLINK_TYPE_DOUBLE:
diff --git a/Modules/Mavlink/mavlinkreader.h b/Modules/Mavlink/mavlinkreader.h
index 9a43a237..c7085253 100644
--- a/Modules/Mavlink/mavlinkreader.h
+++ b/Modules/Mavlink/mavlinkreader.h
@@ -17,9 +17,9 @@ public:
     MavlinkReader();
     ~MavlinkReader();
 
-    void close();
     void startAsyncReading(QSerialPort *port);
     QList<ModuleMessage> parseMavlinkMsg(mavlink_message_t *msg);
+    void stopReading();
 
 signals:
     //void receivedMsg(const QString &topic,const QString &payload,const QDateTime &timestamp);
diff --git a/Modules/Test/testmodule.cpp b/Modules/Test/testmodule.cpp
index 4bef5de0..5a1969c7 100644
--- a/Modules/Test/testmodule.cpp
+++ b/Modules/Test/testmodule.cpp
@@ -9,6 +9,9 @@ TestModule::TestModule(QWidget *parent) : DefaultModule(parent), ui(new Ui::Test
 {
     ui->setupUi(this);
     defaultContextMenuSetup();
+
+    maxChar = ui->maxChar_spinBox->value();
+    connect(ui->maxChar_spinBox,SIGNAL(valueChanged(int)),this,SLOT(onMaxCharChanged(int)));
 }
 
 TestModule::~TestModule()
@@ -45,11 +48,12 @@ void TestModule::on_subscribe_button_clicked()
         QString oldText = ui->textArea->toPlainText();
         QString line = QDateTime::currentDateTime().toString("hh.mm.ss (zzz): ") + "(Topic) " + msg.originalTopic() + " -> " + msg.payload() + " (payload)";
         auto i = msg.getOptions().attributesIterator();
-        while(i.hasNext()){
+        while(i.hasNext() && line.count() < maxChar){
             i.next();
             line = line + ", " + i.value() + " ("+i.key()+")";
         }
-        ui->textArea->setPlainText(line + '\n' + oldText);
+        QString newText(line + '\n' + oldText);
+        ui->textArea->setPlainText(newText.mid(0, maxChar));
     });
 }
 
@@ -57,3 +61,8 @@ void TestModule::on_unsubscribe_button_clicked()
 {
     getCore()->getModuleMessagesBroker()->unsubscribe(ui->subscribe_lineEdit->text().trimmed(),this);
 }
+
+void TestModule::onMaxCharChanged(int value)
+{
+    maxChar = value;
+}
diff --git a/Modules/Test/testmodule.h b/Modules/Test/testmodule.h
index ea7b1149..377f3c4f 100644
--- a/Modules/Test/testmodule.h
+++ b/Modules/Test/testmodule.h
@@ -26,9 +26,12 @@ private slots:
     void on_subscribe_button_clicked();
 
     void on_unsubscribe_button_clicked();
+    void onMaxCharChanged(int value);
 
 private:
     Ui::TestModule *ui;
+
+    int maxChar = 2000;
 };
 
 #endif // TESTMODULE_H
diff --git a/Modules/Test/testmodule.ui b/Modules/Test/testmodule.ui
index df1fad0d..d14ad0ca 100644
--- a/Modules/Test/testmodule.ui
+++ b/Modules/Test/testmodule.ui
@@ -7,7 +7,7 @@
     <x>0</x>
     <y>0</y>
     <width>373</width>
-    <height>150</height>
+    <height>163</height>
    </rect>
   </property>
   <property name="sizePolicy">
@@ -75,8 +75,8 @@
    </item>
    <item>
     <layout class="QGridLayout" name="gridLayout">
-     <item row="1" column="1">
-      <widget class="QLineEdit" name="payload_lineEdit">
+     <item row="1" column="0">
+      <widget class="QLineEdit" name="topic_lineEdit">
        <property name="sizePolicy">
         <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
          <horstretch>0</horstretch>
@@ -84,33 +84,33 @@
         </sizepolicy>
        </property>
        <property name="text">
-        <string>Prova</string>
+        <string>Test/Prova1</string>
        </property>
       </widget>
      </item>
-     <item row="1" column="0">
-      <widget class="QLineEdit" name="topic_lineEdit">
+     <item row="0" column="0">
+      <widget class="QLabel" name="label_3">
        <property name="sizePolicy">
-        <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+        <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
          <horstretch>0</horstretch>
          <verstretch>0</verstretch>
         </sizepolicy>
        </property>
        <property name="text">
-        <string>Test/Prova1</string>
+        <string>Topic</string>
        </property>
       </widget>
      </item>
-     <item row="1" column="2">
-      <widget class="QPushButton" name="publish_button">
+     <item row="1" column="1">
+      <widget class="QLineEdit" name="payload_lineEdit">
        <property name="sizePolicy">
-        <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+        <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
          <horstretch>0</horstretch>
          <verstretch>0</verstretch>
         </sizepolicy>
        </property>
        <property name="text">
-        <string>Publish</string>
+        <string>Prova</string>
        </property>
       </widget>
      </item>
@@ -127,16 +127,36 @@
        </property>
       </widget>
      </item>
-     <item row="0" column="0">
-      <widget class="QLabel" name="label_3">
+     <item row="1" column="2">
+      <widget class="QPushButton" name="publish_button">
        <property name="sizePolicy">
-        <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+        <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
          <horstretch>0</horstretch>
          <verstretch>0</verstretch>
         </sizepolicy>
        </property>
        <property name="text">
-        <string>Topic</string>
+        <string>Publish</string>
+       </property>
+      </widget>
+     </item>
+     <item row="2" column="2">
+      <widget class="QSpinBox" name="maxChar_spinBox">
+       <property name="maximum">
+        <number>99999</number>
+       </property>
+       <property name="value">
+        <number>2000</number>
+       </property>
+      </widget>
+     </item>
+     <item row="2" column="1">
+      <widget class="QLabel" name="label_4">
+       <property name="text">
+        <string>Max char</string>
+       </property>
+       <property name="alignment">
+        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
        </property>
       </widget>
      </item>
diff --git a/Modules/skywardhubstrings.cpp b/Modules/skywardhubstrings.cpp
index fdc7f72d..7f6e8e63 100644
--- a/Modules/skywardhubstrings.cpp
+++ b/Modules/skywardhubstrings.cpp
@@ -37,6 +37,7 @@ const QString SkywardHubStrings::mavlink_orientation_tc_pitch_name = "pitch";
 const QString SkywardHubStrings::mavlink_orientation_tc_roll_name = "roll";
 const QString SkywardHubStrings::msgIdField = "id";
 const QString SkywardHubStrings::msgSequenceNumberField = "sequenceNumber";
+const QString SkywardHubStrings::mavlink_quality_link_topic = "MavlinkLinkQuality";
 
 
 SkywardHubStrings::SkywardHubStrings()
diff --git a/Modules/skywardhubstrings.h b/Modules/skywardhubstrings.h
index 89acb851..6d6271ea 100644
--- a/Modules/skywardhubstrings.h
+++ b/Modules/skywardhubstrings.h
@@ -45,7 +45,7 @@ public:
     static const QString msgIdField;
     static const QString msgSequenceNumberField;
 
-    static const QString mavlink_tester_publish_topic;
+    static const QString mavlink_quality_link_topic;
 };
 
 
diff --git a/SkywardHub.pro.user b/SkywardHub.pro.user
index 8ba22efb..46b0555c 100644
--- a/SkywardHub.pro.user
+++ b/SkywardHub.pro.user
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE QtCreatorProject>
-<!-- Written by QtCreator 4.14.2, 2021-05-25T15:26:01. -->
+<!-- Written by QtCreator 4.14.2, 2021-05-26T12:01:02. -->
 <qtcreator>
  <data>
   <variable>EnvironmentId</variable>
-- 
GitLab