From 3dd49e19e72a5304d733a49f01ebdb4060ea545d Mon Sep 17 00:00:00 2001 From: Holden Date: Thu, 13 Feb 2025 01:19:11 -0500 Subject: [PATCH] Comms: Update MockLink Threading --- src/Comms/MockLink/CMakeLists.txt | 2 + src/Comms/MockLink/MockLink.cc | 68 +++++++++------------------ src/Comms/MockLink/MockLink.h | 21 +++++---- src/Comms/MockLink/MockLinkWorker.cc | 70 ++++++++++++++++++++++++++++ src/Comms/MockLink/MockLinkWorker.h | 42 +++++++++++++++++ 5 files changed, 150 insertions(+), 53 deletions(-) create mode 100644 src/Comms/MockLink/MockLinkWorker.cc create mode 100644 src/Comms/MockLink/MockLinkWorker.h diff --git a/src/Comms/MockLink/CMakeLists.txt b/src/Comms/MockLink/CMakeLists.txt index 6c845453718..7ebe421f9d1 100644 --- a/src/Comms/MockLink/CMakeLists.txt +++ b/src/Comms/MockLink/CMakeLists.txt @@ -13,6 +13,8 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug") MockLink.h MockLinkFTP.cc MockLinkFTP.h + MockLinkWorker.cc + MockLinkWorker.h MockLinkMissionItemHandler.cc MockLinkMissionItemHandler.h ) diff --git a/src/Comms/MockLink/MockLink.cc b/src/Comms/MockLink/MockLink.cc index 27d4957559c..a55453736d9 100644 --- a/src/Comms/MockLink/MockLink.cc +++ b/src/Comms/MockLink/MockLink.cc @@ -8,9 +8,9 @@ ****************************************************************************/ #include "MockLink.h" - #include "LinkManager.h" #include "MockLinkFTP.h" +#include "MockLinkWorker.h" #include "QGCApplication.h" #include "QGCLoggingCategory.h" @@ -61,10 +61,15 @@ MockLink::MockLink(SharedLinkConfigurationPtr &config, QObject *parent) (void) QObject::connect(this, &MockLink::writeBytesQueuedSignal, this, &MockLink::_writeBytesQueued, Qt::QueuedConnection); - (void) moveToThread(this); - _loadParams(); _runningTime.start(); + + _workerThread = new QThread(this); + _worker = new MockLinkWorker(this); + _worker->moveToThread(_workerThread); + (void) connect(_workerThread, &QThread::started, _worker, &MockLinkWorker::startWork); + (void) connect(_workerThread, &QThread::finished, _worker, &QObject::deleteLater); + _workerThread->start(); } MockLink::~MockLink() @@ -75,6 +80,11 @@ MockLink::~MockLink() QFile::remove(_logDownloadFilename); } + if (_workerThread) { + _workerThread->quit(); + _workerThread->wait(); + } + // qCDebug(MockLinkLog) << Q_FUNC_INFO << this; } @@ -86,7 +96,6 @@ bool MockLink::_connect() mavlinkStatus->flags &= ~MAVLINK_STATUS_FLAG_OUT_MAVLINK1; mavlink_status_t *const auxStatus = mavlink_get_channel_status(_getMavlinkAuxChannel()); auxStatus->flags &= ~MAVLINK_STATUS_FLAG_OUT_MAVLINK1; - start(); emit connected(); } @@ -95,51 +104,15 @@ bool MockLink::_connect() void MockLink::disconnect() { + _missionItemHandler->shutdown(); + if (_connected) { _connected = false; - quit(); - wait(); emit disconnected(); } } -void MockLink::run() -{ - QTimer timer1HzTasks; - QTimer timer10HzTasks; - QTimer timer500HzTasks; - QTimer timerStatusText; - - (void) QObject::connect(&timer1HzTasks, &QTimer::timeout, this, &MockLink::_run1HzTasks); - (void) QObject::connect(&timer10HzTasks, &QTimer::timeout, this, &MockLink::_run10HzTasks); - (void) QObject::connect(&timer500HzTasks, &QTimer::timeout, this, &MockLink::_run500HzTasks); - (void) QObject::connect(&timerStatusText, &QTimer::timeout, this, &MockLink::_sendStatusTextMessages); - - timer1HzTasks.start(1000); - timer10HzTasks.start(100); - timer500HzTasks.start(2); - - // Wait a little bit for the ui to finish loading up before sending out status text messages - if (_sendStatusText) { - timerStatusText.setSingleShot(true); - timerStatusText.start(10000); - } - - // Send first set right away - _run1HzTasks(); - _run10HzTasks(); - _run500HzTasks(); - - exec(); - - (void) QObject::disconnect(&timer1HzTasks, &QTimer::timeout, this, &MockLink::_run1HzTasks); - (void) QObject::disconnect(&timer10HzTasks, &QTimer::timeout, this, &MockLink::_run10HzTasks); - (void) QObject::disconnect(&timer500HzTasks, &QTimer::timeout, this, &MockLink::_run500HzTasks); - - _missionItemHandler->shutdown(); -} - -void MockLink::_run1HzTasks() +void MockLink::run1HzTasks() { if (!_mavlinkStarted || !_connected) { return; @@ -168,7 +141,7 @@ void MockLink::_run1HzTasks() } } -void MockLink::_run10HzTasks() +void MockLink::run10HzTasks() { if (linkConfiguration()->isHighLatency()) { return; @@ -187,7 +160,7 @@ void MockLink::_run10HzTasks() } } -void MockLink::_run500HzTasks() +void MockLink::run500HzTasks() { if (linkConfiguration()->isHighLatency()) { return; @@ -199,6 +172,11 @@ void MockLink::_run500HzTasks() } } +void MockLink::sendStatusTextMessages() +{ + _sendStatusTextMessages(); +} + bool MockLink::_allocateMavlinkChannel() { // should only be called by the LinkManager during setup diff --git a/src/Comms/MockLink/MockLink.h b/src/Comms/MockLink/MockLink.h index c8b5d6c8792..fee54d3c711 100644 --- a/src/Comms/MockLink/MockLink.h +++ b/src/Comms/MockLink/MockLink.h @@ -22,6 +22,8 @@ #include class MockLinkFTP; +class MockLinkWorker; +class QThread; Q_DECLARE_LOGGING_CATEGORY(MockLinkLog) Q_DECLARE_LOGGING_CATEGORY(MockLinkVerboseLog) @@ -34,6 +36,13 @@ class MockLink : public LinkInterface explicit MockLink(SharedLinkConfigurationPtr &config, QObject *parent = nullptr); virtual ~MockLink(); + void run1HzTasks(); + void run10HzTasks(); + void run500HzTasks(); + void sendStatusTextMessages(); + + bool shouldSendStatusText() const { return _sendStatusText; } + bool isConnected() const final { return _connected; } void disconnect() final; @@ -109,20 +118,13 @@ class MockLink : public LinkInterface private slots: /// Called when QGC wants to write bytes to the MAV void _writeBytes(const QByteArray &bytes) final; - void _writeBytesQueued(const QByteArray &bytes); - void _run1HzTasks(); - void _run10HzTasks(); - void _run500HzTasks(); - void _sendStatusTextMessages(); private: bool _connect() final; bool _allocateMavlinkChannel() final; void _freeMavlinkChannel() final; - void run() final; - uint8_t _getMavlinkAuxChannel() const { return _mavlinkAuxChannel; } bool _mavlinkAuxChannelIsSet() const; @@ -163,6 +165,7 @@ private slots: void _sendSysStatus(); void _sendBatteryStatus(); void _sendChunkedStatusText(uint16_t chunkId, bool missingChunks); + void _sendStatusTextMessages(); void _respondWithAutopilotVersion(); void _sendRCChannels(); /// Sends the next parameter to the vehicle @@ -181,6 +184,9 @@ private slots: /// @return Fully qualified path to created file static QString _createRandomFile(uint32_t byteCount); + QThread *_workerThread = nullptr; + MockLinkWorker *_worker = nullptr; + const MockConfiguration *_mockConfig = nullptr; const MAV_AUTOPILOT _firmwareType = MAV_AUTOPILOT_PX4; const MAV_TYPE _vehicleType = MAV_TYPE_QUADROTOR; @@ -263,4 +269,3 @@ private slots: static constexpr bool _mavlinkStarted = true; }; - diff --git a/src/Comms/MockLink/MockLinkWorker.cc b/src/Comms/MockLink/MockLinkWorker.cc new file mode 100644 index 00000000000..5fe22d2fea2 --- /dev/null +++ b/src/Comms/MockLink/MockLinkWorker.cc @@ -0,0 +1,70 @@ +/**************************************************************************** + * + * (c) 2009-2024 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#include "MockLinkWorker.h" +#include "MockLink.h" + +MockLinkWorker::MockLinkWorker(MockLink *link, QObject *parent) + : QObject(parent) + , _mockLink(link) +{ + (void) connect(&_timer1Hz, &QTimer::timeout, this, &MockLinkWorker::run1HzTasks); + (void) connect(&_timer10Hz, &QTimer::timeout, this, &MockLinkWorker::run10HzTasks); + (void) connect(&_timer500Hz, &QTimer::timeout, this, &MockLinkWorker::run500HzTasks); + (void) connect(&_timerStatusText, &QTimer::timeout, this, &MockLinkWorker::sendStatusTextMessages); +} + +MockLinkWorker::~MockLinkWorker() +{ + stopWork(); +} + +void MockLinkWorker::startWork() +{ + _timer1Hz.start(1000); + _timer10Hz.start(100); + _timer500Hz.start(2); + + if (_mockLink->shouldSendStatusText()) { + _timerStatusText.setSingleShot(true); + _timerStatusText.start(10000); + } + + run1HzTasks(); + run10HzTasks(); + run500HzTasks(); +} + +void MockLinkWorker::stopWork() +{ + _timer1Hz.stop(); + _timer10Hz.stop(); + _timer500Hz.stop(); + _timerStatusText.stop(); +} + +void MockLinkWorker::run1HzTasks() +{ + _mockLink->run1HzTasks(); +} + +void MockLinkWorker::run10HzTasks() +{ + _mockLink->run10HzTasks(); +} + +void MockLinkWorker::run500HzTasks() +{ + _mockLink->run500HzTasks(); +} + +void MockLinkWorker::sendStatusTextMessages() +{ + _mockLink->sendStatusTextMessages(); +} diff --git a/src/Comms/MockLink/MockLinkWorker.h b/src/Comms/MockLink/MockLinkWorker.h new file mode 100644 index 00000000000..41bc341ff81 --- /dev/null +++ b/src/Comms/MockLink/MockLinkWorker.h @@ -0,0 +1,42 @@ +/**************************************************************************** + * + * (c) 2009-2024 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#pragma once + +#include +#include + +class MockLink; + +class MockLinkWorker : public QObject +{ + Q_OBJECT + +public: + explicit MockLinkWorker(MockLink *link, QObject *parent = nullptr); + ~MockLinkWorker(); + +public slots: + void startWork(); + void stopWork(); + +private slots: + void run1HzTasks(); + void run10HzTasks(); + void run500HzTasks(); + + void sendStatusTextMessages(); + +private: + MockLink *_mockLink = nullptr; + QTimer _timer1Hz; + QTimer _timer10Hz; + QTimer _timer500Hz; + QTimer _timerStatusText; +};