QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
LinkInterface.cc
Go to the documentation of this file.
1#include "LinkInterface.h"
2#include "MAVLinkLib.h"
3#include "LinkManager.h"
4#include "AppMessages.h"
5#include "QGCApplication.h"
7#include "SigningController.h"
8
9#include <QtQml/QQmlEngine>
10
11QGC_LOGGING_CATEGORY(LinkInterfaceLog, "Comms.LinkInterface")
12
14 : QObject(parent)
15 , _config(config)
16{
17 QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
18}
19
21{
22 if (_vehicleReferenceCount != 0) {
23 qCWarning(LinkInterfaceLog) << "still have vehicle references:" << _vehicleReferenceCount;
24 }
25
26 _config.reset();
27}
28
30{
31 if (!mavlinkChannelIsSet()) {
32 qCWarning(LinkInterfaceLog) << "mavlinkChannelIsSet() == false";
33 }
34
35 return _mavlinkChannel;
36}
37
39{
40 return (LinkManager::invalidMavlinkChannel() != _mavlinkChannel);
41}
42
44{
45 Q_ASSERT(!mavlinkChannelIsSet());
46
47 if (mavlinkChannelIsSet()) {
48 qCWarning(LinkInterfaceLog) << "already have" << _mavlinkChannel;
49 return true;
50 }
51
52 _mavlinkChannel = LinkManager::instance()->allocateMavlinkChannel();
53
54 if (!mavlinkChannelIsSet()) {
55 qCWarning(LinkInterfaceLog) << "failed";
56 return false;
57 }
58
59 qCDebug(LinkInterfaceLog) << "_allocateMavlinkChannel" << _mavlinkChannel;
60
61 mavlink_set_proto_version(_mavlinkChannel, MAVLINK_VERSION); // We only support v2 protcol
62
63 _signingController = std::make_unique<SigningController>(static_cast<mavlink_channel_t>(_mavlinkChannel));
64 _signingController->clearSigning();
65
66 qCDebug(LinkInterfaceLog) << "SigningController created for channel" << _mavlinkChannel
67 << (isSecureConnection() ? "(secure)" : "(will auto-detect)");
68
69 return true;
70}
71
73{
74 qCDebug(LinkInterfaceLog) << _mavlinkChannel;
75
76 if (!mavlinkChannelIsSet()) {
77 return;
78 }
79
80 // Destroy the controller before freeing the channel so it can flush the final timestamp.
81 _signingController.reset();
82
83 // mavlink_reset_channel_status only resets parse_state — null signing/streams explicitly to avoid dangling derefs.
84 mavlink_status_t* const status = mavlink_get_channel_status(_mavlinkChannel);
85 status->signing = nullptr;
86 status->signing_streams = nullptr;
87 mavlink_reset_channel_status(_mavlinkChannel);
88
89 LinkManager::instance()->freeMavlinkChannel(_mavlinkChannel);
90 _mavlinkChannel = LinkManager::invalidMavlinkChannel();
91}
92
93void LinkInterface::writeBytesThreadSafe(const char *bytes, int length)
94{
95 const QByteArray data(bytes, length);
96 (void) QMetaObject::invokeMethod(this, "_writeBytes", Qt::AutoConnection, data);
97}
98
100{
101 // Re-sign with a current timestamp; the cached-resend path (Vehicle::sendMessageMultiple) otherwise ships frozen
102 // signed bytes whose timestamp drifts behind wall clock and gets OLD_TIMESTAMP-rejected. No-op when signing is
103 // disabled or the message isn't outgoing-signed. The secret key stays in the signing layer.
104 if (_signingController) {
105 (void) _signingController->signOutgoing(message);
106 }
107
108 uint8_t buffer[MAVLINK_MAX_PACKET_LEN];
109 const int len = mavlink_msg_to_send_buffer(buffer, &message);
110 writeBytesThreadSafe(reinterpret_cast<const char *>(buffer), len);
111}
112
114{
115 if (_vehicleReferenceCount != 0) {
116 _vehicleReferenceCount--;
118 } else {
119 qCWarning(LinkInterfaceLog) << "called with no vehicle references";
120 }
121}
122
124{
125 if (_vehicleReferenceCount == 0) {
126 // Since there are no vehicles on the link we can disconnect it right now
127 disconnect();
128 } else {
129 // If there are still vehicles on this link we allow communication lost to trigger and don't automatically disconect until all the vehicles go away
130 }
131}
132
134{
135 if (!_mavlinkV1TrafficReported) {
136 _mavlinkV1TrafficReported = true;
137
139 const QString linkName = linkConfig ? linkConfig->name() : QStringLiteral("unknown");
140 qCWarning(LinkInterfaceLog) << "MAVLink v1 traffic detected on link" << linkName;
141 const QString message = tr("MAVLink v1 traffic detected on link '%1'. "
142 "%2 only supports MAVLink v2. "
143 "Please ensure your vehicle is configured to use MAVLink v2.")
144 .arg(linkName).arg(qgcApp()->applicationName());
145 QGC::showAppMessage(message);
146 }
147}
Config config
std::shared_ptr< LinkConfiguration > SharedLinkConfigurationPtr
mavlink_channel_t
mavlink_status_t * mavlink_get_channel_status(uint8_t chan)
Definition QGCMAVLink.cc:53
#define qgcApp()
struct __mavlink_message mavlink_message_t
#define QGC_LOGGING_CATEGORY(name, categoryStr)
The link interface defines the interface for all links used to communicate with the ground station ap...
virtual ~LinkInterface()
uint8_t mavlinkChannel() const
virtual void _freeMavlinkChannel()
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
Returns true if the connection is secure (e.g. USB, wired ethernet)
void writeBytesThreadSafe(const char *bytes, int length)
SharedLinkConfigurationPtr linkConfiguration()
SharedLinkConfigurationPtr _config
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.
Definition AppMessages.cc:9