9#include <QtCore/QThread>
10#include <QtQml/QQmlEngine>
15 constexpr int WORKER_SHUTDOWN_TIMEOUT_MS = 3000;
22 QQmlEngine::setObjectOwnership(
this, QQmlEngine::CppOwnership);
27 if (_vehicleReferenceCount != 0) {
28 qCWarning(LinkInterfaceLog) <<
"still have vehicle references:" << _vehicleReferenceCount;
41 if (thread->isCurrentThread()) {
42 qCCritical(category) <<
"Shutdown called from worker thread itself, orphaning";
44 _orphanWorkerThread(thread);
49 if (thread->wait(WORKER_SHUTDOWN_TIMEOUT_MS)) {
54 qCWarning(category) <<
"Worker thread did not stop within timeout, terminating";
56 if (thread->wait(WORKER_SHUTDOWN_TIMEOUT_MS)) {
62 qCCritical(category) <<
"Worker thread could not be stopped, leaking it to avoid abort";
63 _orphanWorkerThread(thread);
66void LinkInterface::_orphanWorkerThread(QThread *thread)
68 thread->setParent(
nullptr);
72 (void) QObject::connect(thread, &QThread::finished, thread, [
config =
_config]() { Q_UNUSED(
config); });
77 (void) QObject::connect(thread, &QThread::finished, thread, &QObject::deleteLater);
83 qCWarning(LinkInterfaceLog) <<
"mavlinkChannelIsSet() == false";
86 return _mavlinkChannel;
99 qCWarning(LinkInterfaceLog) <<
"already have" << _mavlinkChannel;
106 qCWarning(LinkInterfaceLog) <<
"failed";
110 qCDebug(LinkInterfaceLog) <<
"_allocateMavlinkChannel" << _mavlinkChannel;
112 mavlink_set_proto_version(_mavlinkChannel, MAVLINK_VERSION);
114 _signingController = std::make_unique<SigningController>(
static_cast<mavlink_channel_t>(_mavlinkChannel));
115 _signingController->clearSigning();
117 qCDebug(LinkInterfaceLog) <<
"SigningController created for channel" << _mavlinkChannel
125 qCDebug(LinkInterfaceLog) << _mavlinkChannel;
132 _signingController.reset();
136 status->signing =
nullptr;
137 status->signing_streams =
nullptr;
138 mavlink_reset_channel_status(_mavlinkChannel);
146 const QByteArray data(bytes, length);
147 (void) QMetaObject::invokeMethod(
this,
"_writeBytes", Qt::AutoConnection, data);
155 if (_signingController) {
156 (void) _signingController->signOutgoing(message);
159 uint8_t buffer[MAVLINK_MAX_PACKET_LEN];
160 const int len = mavlink_msg_to_send_buffer(buffer, &message);
166 if (_vehicleReferenceCount != 0) {
167 _vehicleReferenceCount--;
170 qCWarning(LinkInterfaceLog) <<
"called with no vehicle references";
176 if (_vehicleReferenceCount == 0) {
186 if (!_radioStatusSeen) {
187 _radioStatusSeen =
true;
188 qCDebug(LinkInterfaceLog) <<
"RADIO_STATUS seen, treating link as radio link:" <<
_config->name();
194 if (_mavlinkV1TrafficReported || _mavlinkV2TrafficSeen) {
200 if (!_mavlinkV1FirstSeenTimer.isValid()) {
201 _mavlinkV1FirstSeenTimer.start();
203 if (_mavlinkV1FirstSeenTimer.elapsed() < _mavlinkV1TrafficGraceMsecs) {
207 _mavlinkV1TrafficReported =
true;
210 const QString linkName = linkConfig ? linkConfig->name() : QStringLiteral(
"unknown");
211 qCWarning(LinkInterfaceLog) <<
"MAVLink v1 traffic detected on link" << linkName;
212 const QString message = tr(
"MAVLink v1 traffic detected on link '%1'. "
213 "%2 only supports MAVLink v2. "
214 "Please ensure your vehicle is configured to use MAVLink v2.")
215 .arg(linkName).arg(
qgcApp()->applicationName());
std::shared_ptr< LinkConfiguration > SharedLinkConfigurationPtr
mavlink_status_t * mavlink_get_channel_status(uint8_t chan)
struct __mavlink_message mavlink_message_t
#define QGC_LOGGING_CATEGORY(name, categoryStr)
uint8_t mavlinkChannel() const
void _shutdownWorkerThread(QThread *thread, const QLoggingCategory &category, bool allowTerminate=true)
virtual void _freeMavlinkChannel()
LinkInterface(SharedLinkConfigurationPtr &config, QObject *parent=nullptr)
Links are only created by LinkManager so constructor is not public.
virtual Q_INVOKABLE void disconnect()=0
void sendMessageThreadSafe(mavlink_message_t &message)
void reportMavlinkV1Traffic()
void _connectionRemoved()
bool mavlinkChannelIsSet() const
virtual bool _allocateMavlinkChannel()
void removeVehicleReference()
virtual bool isSecureConnection() const
void writeBytesThreadSafe(const char *bytes, int length)
SharedLinkConfigurationPtr linkConfiguration()
SharedLinkConfigurationPtr _config
void reportRadioStatusReceived()
uint8_t allocateMavlinkChannel()
static LinkManager * instance()
void freeMavlinkChannel(uint8_t channel)
static constexpr uint8_t invalidMavlinkChannel()
void showAppMessage(const QString &message, const QString &title)
Modal application message. Queued if the UI isn't ready yet.