From b5f30ae40b9cc40aa3b263d44f0d411c8a78c36b Mon Sep 17 00:00:00 2001 From: Gus Grubba Date: Tue, 4 Sep 2018 13:10:58 -0400 Subject: [PATCH] MAVLink message receive status Fixed the core MAVLink receiver. Among other things, it wasn't accounting for fragmented messages. Fixed code that monitors messages received (and lost) Added a section within the MAVLink panel to show the current status (for the current vehicle) Remove some old, unused exposed interfaces --- src/Vehicle/Vehicle.cc | 14 +- src/Vehicle/Vehicle.h | 16 ++ src/comm/MAVLinkProtocol.cc | 209 ++++++++++++------------- src/comm/MAVLinkProtocol.h | 51 ++---- src/comm/ProtocolInterface.h | 33 +--- src/ui/preferences/MavlinkSettings.qml | 87 ++++++++++ 6 files changed, 238 insertions(+), 172 deletions(-) diff --git a/src/Vehicle/Vehicle.cc b/src/Vehicle/Vehicle.cc index f9ea0b742..7fac40971 100644 --- a/src/Vehicle/Vehicle.cc +++ b/src/Vehicle/Vehicle.cc @@ -202,7 +202,8 @@ Vehicle::Vehicle(LinkInterface* link, _mavlink = _toolbox->mavlinkProtocol(); - connect(_mavlink, &MAVLinkProtocol::messageReceived, this, &Vehicle::_mavlinkMessageReceived); + connect(_mavlink, &MAVLinkProtocol::messageReceived, this, &Vehicle::_mavlinkMessageReceived); + connect(_mavlink, &MAVLinkProtocol::mavlinkMessageStatus, this, &Vehicle::_mavlinkMessageStatus); _addLink(link); @@ -3594,6 +3595,17 @@ void Vehicle::_updateHighLatencyLink(bool sendCommand) } } +void Vehicle::_mavlinkMessageStatus(int uasId, uint64_t totalSent, uint64_t totalReceived, uint64_t totalLoss, float lossPercent) +{ + if(uasId == _id) { + _mavlinkSentCount = totalSent; + _mavlinkReceivedCount = totalReceived; + _mavlinkLossCount = totalLoss; + _mavlinkLossPercent = lossPercent; + emit mavlinkStatusChanged(); + } +} + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- diff --git a/src/Vehicle/Vehicle.h b/src/Vehicle/Vehicle.h index d261171f3..7b684dc65 100644 --- a/src/Vehicle/Vehicle.h +++ b/src/Vehicle/Vehicle.h @@ -622,6 +622,10 @@ public: Q_PROPERTY(QString priorityLinkName READ priorityLinkName WRITE setPriorityLinkByName NOTIFY priorityLinkNameChanged) Q_PROPERTY(QVariantList links READ links NOTIFY linksChanged) Q_PROPERTY(LinkInterface* priorityLink READ priorityLink NOTIFY priorityLinkNameChanged) + Q_PROPERTY(quint64 mavlinkSentCount READ mavlinkSentCount NOTIFY mavlinkStatusChanged) + Q_PROPERTY(quint64 mavlinkReceivedCount READ mavlinkReceivedCount NOTIFY mavlinkStatusChanged) + Q_PROPERTY(quint64 mavlinkLossCount READ mavlinkLossCount NOTIFY mavlinkStatusChanged) + Q_PROPERTY(float mavlinkLossPercent READ mavlinkLossPercent NOTIFY mavlinkStatusChanged) // Vehicle state used for guided control Q_PROPERTY(bool flying READ flying NOTIFY flyingChanged) ///< Vehicle is flying @@ -1044,6 +1048,11 @@ public: /// Vehicle is about to be deleted void prepareDelete(); + quint64 mavlinkSentCount () { return _mavlinkSentCount; } /// Calculated total number of messages sent to us + quint64 mavlinkReceivedCount () { return _mavlinkReceivedCount; } /// Total number of sucessful messages received + quint64 mavlinkLossCount () { return _mavlinkLossCount; } /// Total number of lost messages + float mavlinkLossPercent () { return _mavlinkLossPercent; } /// Running loss rate + signals: void allLinksInactive(Vehicle* vehicle); void coordinateChanged(QGeoCoordinate coordinate); @@ -1147,6 +1156,7 @@ signals: // MAVLink protocol version void requestProtocolVersion(unsigned version); + void mavlinkStatusChanged(); private slots: void _mavlinkMessageReceived(LinkInterface* link, mavlink_message_t message); @@ -1179,6 +1189,7 @@ private slots: void _updateHobbsMeter(void); void _vehicleParamLoaded(bool ready); void _sendQGCTimeToVehicle(void); + void _mavlinkMessageStatus(int uasId, uint64_t totalSent, uint64_t totalReceived, uint64_t totalLoss, float lossPercent); private: bool _containsLink(LinkInterface* link); @@ -1405,6 +1416,11 @@ private: SharedLinkInterfacePointer _priorityLink; // We always keep a reference to the priority link to manage shutdown ordering bool _priorityLinkCommanded; + uint64_t _mavlinkSentCount = 0; + uint64_t _mavlinkReceivedCount = 0; + uint64_t _mavlinkLossCount = 0; + float _mavlinkLossPercent = 0.0f; + // FactGroup facts Fact _rollFact; diff --git a/src/comm/MAVLinkProtocol.cc b/src/comm/MAVLinkProtocol.cc index d517a9a67..b96092d56 100644 --- a/src/comm/MAVLinkProtocol.cc +++ b/src/comm/MAVLinkProtocol.cc @@ -61,14 +61,14 @@ MAVLinkProtocol::MAVLinkProtocol(QGCApplication* app, QGCToolbox* toolbox) , _logSuspendReplay(false) , _vehicleWasArmed(false) , _tempLogFile(QString("%2.%3").arg(_tempLogFileTemplate).arg(_logFileExtension)) - , _linkMgr(NULL) - , _multiVehicleManager(NULL) + , _linkMgr(nullptr) + , _multiVehicleManager(nullptr) { - memset(&totalReceiveCounter, 0, sizeof(totalReceiveCounter)); - memset(&totalLossCounter, 0, sizeof(totalLossCounter)); - memset(&totalErrorCounter, 0, sizeof(totalErrorCounter)); - memset(&currReceiveCounter, 0, sizeof(currReceiveCounter)); - memset(&currLossCounter, 0, sizeof(currLossCounter)); + memset(totalReceiveCounter, 0, sizeof(totalReceiveCounter)); + memset(totalSentCounter, 0, sizeof(totalSentCounter)); + memset(totalLossCounter, 0, sizeof(totalLossCounter)); + memset(runningLossPercent, 0, sizeof(runningLossPercent)); + memset(firstMessage, 1, sizeof(firstMessage)); } MAVLinkProtocol::~MAVLinkProtocol() @@ -109,15 +109,6 @@ void MAVLinkProtocol::setToolbox(QGCToolbox *toolbox) // All the *Counter variables are not initialized here, as they should be initialized // on a per-link basis before those links are used. @see resetMetadataForLink(). - // Initialize the list for tracking dropped messages to invalid. - for (int i = 0; i < 256; i++) - { - for (int j = 0; j < 256; j++) - { - lastIndex[i][j] = -1; - } - } - connect(this, &MAVLinkProtocol::protocolStatusMessage, _app, &QGCApplication::criticalMessageBoxOnMainThread); connect(this, &MAVLinkProtocol::saveTelemetryLog, _app, &QGCApplication::saveTelemetryLogOnMainThread); connect(this, &MAVLinkProtocol::checkTelemetrySavePath, _app, &QGCApplication::checkTelemetrySavePathOnMainThread); @@ -157,10 +148,12 @@ void MAVLinkProtocol::resetMetadataForLink(LinkInterface *link) { int channel = link->mavlinkChannel(); totalReceiveCounter[channel] = 0; - totalLossCounter[channel] = 0; - totalErrorCounter[channel] = 0; - currReceiveCounter[channel] = 0; - currLossCounter[channel] = 0; + totalLossCounter[channel] = 0; + totalSentCounter[channel] = 0; + runningLossPercent[channel] = 0.0f; + for(int i = 0; i < 256; i++) { + firstMessage[channel][i] = 1; + } link->setDecodedFirstMavlinkPacket(false); } @@ -171,6 +164,7 @@ void MAVLinkProtocol::resetMetadataForLink(LinkInterface *link) * @param link The interface to read from * @see LinkInterface **/ + void MAVLinkProtocol::receiveBytes(LinkInterface* link, QByteArray b) { // Since receiveBytes signals cross threads we can end up with signals in the queue @@ -180,56 +174,70 @@ void MAVLinkProtocol::receiveBytes(LinkInterface* link, QByteArray b) return; } -// receiveMutex.lock(); - mavlink_message_t message; - mavlink_status_t status; + uint8_t mavlinkChannel = link->mavlinkChannel(); - int mavlinkChannel = link->mavlinkChannel(); - - static int nonmavlinkCount = 0; + static int nonmavlinkCount = 0; static bool checkedUserNonMavlink = false; - static bool warnedUserNonMavlink = false; + static bool warnedUserNonMavlink = false; for (int position = 0; position < b.size(); position++) { - unsigned int decodeState = mavlink_parse_char(mavlinkChannel, (uint8_t)(b[position]), &message, &status); - - if (decodeState == 0 && !link->decodedFirstMavlinkPacket()) - { - nonmavlinkCount++; - if (nonmavlinkCount > 1000 && !warnedUserNonMavlink) - { - // 500 bytes with no mavlink message. Are we connected to a mavlink capable device? - if (!checkedUserNonMavlink) - { - link->requestReset(); - checkedUserNonMavlink = true; - } - else - { - warnedUserNonMavlink = true; - // Disconnect the link since its some other device and - // QGC clinging on to it and feeding it data might have unintended - // side effects (e.g. if its a modem) - qDebug() << "disconnected link" << link->getName() << "as it contained no MAVLink data"; - QMetaObject::invokeMethod(_linkMgr, "disconnectLink", Q_ARG( LinkInterface*, link ) ); - return; - } - } - } - if (decodeState == 1) - { + if (mavlink_parse_char(mavlinkChannel, static_cast(b[position]), &_message, &_status)) { + // Got a valid message if (!link->decodedFirstMavlinkPacket()) { link->setDecodedFirstMavlinkPacket(true); mavlink_status_t* mavlinkStatus = mavlink_get_channel_status(mavlinkChannel); if (!(mavlinkStatus->flags & MAVLINK_STATUS_FLAG_IN_MAVLINK1) && (mavlinkStatus->flags & MAVLINK_STATUS_FLAG_OUT_MAVLINK1)) { qDebug() << "Switching outbound to mavlink 2.0 due to incoming mavlink 2.0 packet:" << mavlinkStatus << mavlinkChannel << mavlinkStatus->flags; mavlinkStatus->flags &= ~MAVLINK_STATUS_FLAG_OUT_MAVLINK1; - // Set all links to v2 setVersion(200); } } + //----------------------------------------------------------------- + // MAVLink Status + uint8_t lastSeq = lastIndex[_message.sysid][_message.compid]; + uint8_t expectedSeq = lastSeq + 1; + // Increase receive counter + totalReceiveCounter[mavlinkChannel]++; + // Determine what the next expected sequence number is, accounting for + // never having seen a message for this system/component pair. + if(firstMessage[_message.sysid][_message.compid]) { + firstMessage[_message.sysid][_message.compid] = 0; + lastSeq = _message.seq; + expectedSeq = _message.seq; + } + // And if we didn't encounter that sequence number, record the error + //int foo = 0; + if (_message.seq != expectedSeq) + { + //foo = 1; + int lostMessages = 0; + //-- Account for overflow during packet loss + if(_message.seq < expectedSeq) { + lostMessages = (_message.seq + 255) - expectedSeq; + } else { + lostMessages = _message.seq - expectedSeq; + } + // Log how many were lost + totalLossCounter[mavlinkChannel] += static_cast(lostMessages); + // Compute actual count of sent messages + totalSentCounter[mavlinkChannel] += static_cast(lostMessages); + } else { + totalSentCounter[mavlinkChannel]++; + } + + // And update the last sequence number for this system/component pair + lastIndex[_message.sysid][_message.compid] = _message.seq;; + // Calculate new loss ratio + float receiveLossPercent = static_cast(totalLossCounter[mavlinkChannel]) / static_cast(totalSentCounter[mavlinkChannel]); + receiveLossPercent *= 100.0f; + receiveLossPercent = (receiveLossPercent * 0.5f) + (runningLossPercent[mavlinkChannel] * 0.5f); + runningLossPercent[mavlinkChannel] = receiveLossPercent; + + //qDebug() << foo << _message.seq << expectedSeq << lastSeq << totalLossCounter[mavlinkChannel] << totalReceiveCounter[mavlinkChannel] << totalSentCounter[mavlinkChannel] << "(" << _message.sysid << _message.compid << ")"; + + //----------------------------------------------------------------- // Log data if (!_logSuspendError && !_logSuspendReplay && _tempLogFile.isOpen()) { uint8_t buf[MAVLINK_MAX_PACKET_LEN+sizeof(quint64)]; @@ -237,17 +245,17 @@ void MAVLinkProtocol::receiveBytes(LinkInterface* link, QByteArray b) // Write the uint64 time in microseconds in big endian format before the message. // This timestamp is saved in UTC time. We are only saving in ms precision because // getting more than this isn't possible with Qt without a ton of extra code. - quint64 time = (quint64)QDateTime::currentMSecsSinceEpoch() * 1000; + quint64 time = static_cast(QDateTime::currentMSecsSinceEpoch() * 1000); qToBigEndian(time, buf); // Then write the message to the buffer - int len = mavlink_msg_to_send_buffer(buf + sizeof(quint64), &message); + int len = mavlink_msg_to_send_buffer(buf + sizeof(quint64), &_message); // Determine how many bytes were written by adding the timestamp size to the message size len += sizeof(quint64); // Now write this timestamp/message pair to the log. - QByteArray b((const char*)buf, len); + QByteArray b(reinterpret_cast(buf), len); if(_tempLogFile.write(b) != len) { // If there's an error logging data, raise an alert and stop logging. @@ -257,32 +265,32 @@ void MAVLinkProtocol::receiveBytes(LinkInterface* link, QByteArray b) } // Check for the vehicle arming going by. This is used to trigger log save. - if (!_vehicleWasArmed && message.msgid == MAVLINK_MSG_ID_HEARTBEAT) { + if (!_vehicleWasArmed && _message.msgid == MAVLINK_MSG_ID_HEARTBEAT) { mavlink_heartbeat_t state; - mavlink_msg_heartbeat_decode(&message, &state); + mavlink_msg_heartbeat_decode(&_message, &state); if (state.base_mode & MAV_MODE_FLAG_DECODE_POSITION_SAFETY) { _vehicleWasArmed = true; } } } - if (message.msgid == MAVLINK_MSG_ID_HEARTBEAT) { + if (_message.msgid == MAVLINK_MSG_ID_HEARTBEAT) { _startLogging(); mavlink_heartbeat_t heartbeat; - mavlink_msg_heartbeat_decode(&message, &heartbeat); - emit vehicleHeartbeatInfo(link, message.sysid, message.compid, heartbeat.autopilot, heartbeat.type); + mavlink_msg_heartbeat_decode(&_message, &heartbeat); + emit vehicleHeartbeatInfo(link, _message.sysid, _message.compid, heartbeat.autopilot, heartbeat.type); } - if (message.msgid == MAVLINK_MSG_ID_HIGH_LATENCY2) { + if (_message.msgid == MAVLINK_MSG_ID_HIGH_LATENCY2) { _startLogging(); mavlink_high_latency2_t highLatency2; - mavlink_msg_high_latency2_decode(&message, &highLatency2); - emit vehicleHeartbeatInfo(link, message.sysid, message.compid, highLatency2.autopilot, highLatency2.type); + mavlink_msg_high_latency2_decode(&_message, &highLatency2); + emit vehicleHeartbeatInfo(link, _message.sysid, _message.compid, highLatency2.autopilot, highLatency2.type); } // Detect if we are talking to an old radio not supporting v2 mavlink_status_t* mavlinkStatus = mavlink_get_channel_status(mavlinkChannel); - if (message.msgid == MAVLINK_MSG_ID_RADIO_STATUS) { + if (_message.msgid == MAVLINK_MSG_ID_RADIO_STATUS) { if ((mavlinkStatus->flags & MAVLINK_STATUS_FLAG_IN_MAVLINK1) && !(mavlinkStatus->flags & MAVLINK_STATUS_FLAG_OUT_MAVLINK1)) { @@ -300,53 +308,36 @@ void MAVLinkProtocol::receiveBytes(LinkInterface* link, QByteArray b) mavlinkStatus->flags |= MAVLINK_STATUS_FLAG_OUT_MAVLINK1; } - // Increase receive counter - totalReceiveCounter[mavlinkChannel]++; - currReceiveCounter[mavlinkChannel]++; - - // Determine what the next expected sequence number is, accounting for - // never having seen a message for this system/component pair. - int lastSeq = lastIndex[message.sysid][message.compid]; - int expectedSeq = (lastSeq == -1) ? message.seq : (lastSeq + 1); - - // And if we didn't encounter that sequence number, record the error - if (message.seq != expectedSeq) - { - - // Determine how many messages were skipped - int lostMessages = message.seq - expectedSeq; - - // Out of order messages or wraparound can cause this, but we just ignore these conditions for simplicity - if (lostMessages < 0) - { - lostMessages = 0; - } - - // And log how many were lost for all time and just this timestep - totalLossCounter[mavlinkChannel] += lostMessages; - currLossCounter[mavlinkChannel] += lostMessages; - } - - // And update the last sequence number for this system/component pair - lastIndex[message.sysid][message.compid] = expectedSeq; - - // Update on every 32th packet - if ((totalReceiveCounter[mavlinkChannel] & 0x1F) == 0) - { - // Calculate new loss ratio - // Receive loss - float receiveLossPercent = (double)currLossCounter[mavlinkChannel]/(double)(currReceiveCounter[mavlinkChannel]+currLossCounter[mavlinkChannel]); - receiveLossPercent *= 100.0f; - currLossCounter[mavlinkChannel] = 0; - currReceiveCounter[mavlinkChannel] = 0; - emit receiveLossPercentChanged(message.sysid, receiveLossPercent); - emit receiveLossTotalChanged(message.sysid, totalLossCounter[mavlinkChannel]); + // Update MAVLink status on every 32th packet + if ((totalReceiveCounter[mavlinkChannel] & 0x1F) == 0) { + emit mavlinkMessageStatus(_message.sysid, totalSentCounter[mavlinkChannel], totalReceiveCounter[mavlinkChannel], totalLossCounter[mavlinkChannel], receiveLossPercent); } // The packet is emitted as a whole, as it is only 255 - 261 bytes short // kind of inefficient, but no issue for a groundstation pc. // It buys as reentrancy for the whole code over all threads - emit messageReceived(link, message); + emit messageReceived(link, _message); + // Reset message parsing + memset(&_status, 0, sizeof(_status)); + memset(&_message, 0, sizeof(_message)); + } else if (!link->decodedFirstMavlinkPacket()) { + // No formed message yet + nonmavlinkCount++; + if (nonmavlinkCount > 1000 && !warnedUserNonMavlink) { + // 1000 bytes with no mavlink message. Are we connected to a mavlink capable device? + if (!checkedUserNonMavlink) { + link->requestReset(); + checkedUserNonMavlink = true; + } else { + warnedUserNonMavlink = true; + // Disconnect the link since it's some other device and + // QGC clinging on to it and feeding it data might have unintended + // side effects (e.g. if its a modem) + qDebug() << "disconnected link" << link->getName() << "as it contained no MAVLink data"; + QMetaObject::invokeMethod(_linkMgr, "disconnectLink", Q_ARG( LinkInterface*, link ) ); + return; + } + } } } } diff --git a/src/comm/MAVLinkProtocol.h b/src/comm/MAVLinkProtocol.h index 4d6ae9f79..01be94c52 100644 --- a/src/comm/MAVLinkProtocol.h +++ b/src/comm/MAVLinkProtocol.h @@ -65,27 +65,6 @@ public: unsigned getCurrentVersion() { return _current_version; } - /** - * Retrieve a total of all successfully parsed packets for the specified link. - * @returns -1 if this is not available for this protocol, # of packets otherwise. - */ - qint32 getReceivedPacketCount(const LinkInterface *link) const { - return totalReceiveCounter[link->mavlinkChannel()]; - } - /** - * Retrieve a total of all parsing errors for the specified link. - * @returns -1 if this is not available for this protocol, # of errors otherwise. - */ - qint32 getParsingErrorCount(const LinkInterface *link) const { - return totalErrorCounter[link->mavlinkChannel()]; - } - /** - * Retrieve a total of all dropped packets for the specified link. - * @returns -1 if this is not available for this protocol, # of packets otherwise. - */ - qint32 getDroppedPacketCount(const LinkInterface *link) const { - return totalLossCounter[link->mavlinkChannel()]; - } /** * Reset the counters for all metadata for this link. */ @@ -122,18 +101,21 @@ public slots: void checkForLostLogFiles(void); protected: - bool m_enable_version_check; ///< Enable checking of version match of MAV and QGC - QMutex receiveMutex; ///< Mutex to protect receiveBytes function - int lastIndex[256][256]; ///< Store the last received sequence ID for each system/componenet pair - int totalReceiveCounter[MAVLINK_COMM_NUM_BUFFERS]; ///< The total number of successfully received messages - int totalLossCounter[MAVLINK_COMM_NUM_BUFFERS]; ///< Total messages lost during transmission. - int totalErrorCounter[MAVLINK_COMM_NUM_BUFFERS]; ///< Total count of all parsing errors. Generally <= totalLossCounter. - int currReceiveCounter[MAVLINK_COMM_NUM_BUFFERS]; ///< Received messages during this sample time window. Used for calculating loss %. - int currLossCounter[MAVLINK_COMM_NUM_BUFFERS]; ///< Lost messages during this sample time window. Used for calculating loss %. - bool versionMismatchIgnore; - int systemId; - unsigned _current_version; - unsigned _radio_version_mismatch_count; + bool m_enable_version_check; ///< Enable checking of version match of MAV and QGC + uint8_t lastIndex[256][256]; ///< Store the last received sequence ID for each system/componenet pair + uint8_t firstMessage[256][256]; ///< First message flag + uint64_t totalReceiveCounter[MAVLINK_COMM_NUM_BUFFERS]; ///< The total number of successfully received messages + uint64_t totalSentCounter[MAVLINK_COMM_NUM_BUFFERS]; ///< The calculated total number of messages sent to us + uint64_t totalLossCounter[MAVLINK_COMM_NUM_BUFFERS]; ///< Total messages lost during transmission. + float runningLossPercent[MAVLINK_COMM_NUM_BUFFERS]; ///< Loss rate + + mavlink_message_t _message = {}; + mavlink_status_t _status = {}; + + bool versionMismatchIgnore; + int systemId; + unsigned _current_version; + unsigned _radio_version_mismatch_count; signals: /// Heartbeat received on link @@ -148,8 +130,7 @@ signals: /** @brief Emitted if a new system ID was set */ void systemIdChanged(int systemId); - void receiveLossPercentChanged(int uasId, float lossPercent); - void receiveLossTotalChanged(int uasId, int totalLoss); + void mavlinkMessageStatus(int uasId, uint64_t totalSent, uint64_t totalReceived, uint64_t totalLoss, float lossPercent); /** * @brief Emitted if a new radio status packet received diff --git a/src/comm/ProtocolInterface.h b/src/comm/ProtocolInterface.h index b5cc9704d..ad37c07e8 100644 --- a/src/comm/ProtocolInterface.h +++ b/src/comm/ProtocolInterface.h @@ -16,8 +16,7 @@ * */ -#ifndef _PROTOCOLINTERFACE_H_ -#define _PROTOCOLINTERFACE_H_ +#pragma once #include #include @@ -37,26 +36,8 @@ class ProtocolInterface : public QThread { Q_OBJECT public: - virtual ~ProtocolInterface () {} - virtual QString getName() = 0; - /** - * Retrieve a total of all successfully parsed packets for the specified link. - * @param link The link to return metadata about. - * @returns -1 if this is not available for this protocol, # of packets otherwise. - */ - virtual qint32 getReceivedPacketCount(const LinkInterface *link) const = 0; - /** - * Retrieve a total of all parsing errors for the specified link. - * @param link The link to return metadata about. - * @returns -1 if this is not available for this protocol, # of errors otherwise. - */ - virtual qint32 getParsingErrorCount(const LinkInterface *link) const = 0; - /** - * Retrieve a total of all dropped packets for the specified link. - * @param link The link to return metadata about. - * @returns -1 if this is not available for this protocol, # of packets otherwise. - */ - virtual qint32 getDroppedPacketCount(const LinkInterface *link) const = 0; + virtual ~ProtocolInterface () {} + virtual QString getName () = 0; /** * Reset the received, error, and dropped counts for the given link. Useful for * when reconnecting a link. @@ -65,13 +46,11 @@ public: virtual void resetMetadataForLink(LinkInterface *link) = 0; public slots: - virtual void receiveBytes(LinkInterface *link, QByteArray b) = 0; - virtual void linkStatusChanged(bool connected) = 0; + virtual void receiveBytes (LinkInterface *link, QByteArray b) = 0; + virtual void linkStatusChanged (bool connected) = 0; signals: /** @brief Update the packet loss from one system */ - void receiveLossChanged(int uasId, float loss); + void receiveLossChanged (int uasId, float loss); }; - -#endif // _PROTOCOLINTERFACE_H_ diff --git a/src/ui/preferences/MavlinkSettings.qml b/src/ui/preferences/MavlinkSettings.qml index 75b9af075..5e33a0849 100644 --- a/src/ui/preferences/MavlinkSettings.qml +++ b/src/ui/preferences/MavlinkSettings.qml @@ -30,6 +30,7 @@ Rectangle { property int _selectedCount: 0 property real _columnSpacing: ScreenTools.defaultFontPixelHeight * 0.25 property bool _uploadedSelected: false + property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle QGCPalette { id: qgcPal } @@ -152,6 +153,92 @@ Rectangle { } } //----------------------------------------------------------------- + //-- Mavlink Status + Item { + width: __mavlinkRoot.width * 0.8 + height: mavStatusLabel.height + anchors.margins: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + QGCLabel { + id: mavStatusLabel + text: qsTr("MAVLink Link Status (Current Vehicle)") + font.family: ScreenTools.demiboldFontFamily + } + } + Rectangle { + height: mavStatusColumn.height + (ScreenTools.defaultFontPixelHeight * 2) + width: __mavlinkRoot.width * 0.8 + color: qgcPal.windowShade + anchors.margins: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + Column { + id: mavStatusColumn + width: gcsColumn.width + spacing: _columnSpacing + anchors.centerIn: parent + //----------------------------------------------------------------- + Row { + spacing: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + QGCLabel { + width: _labelWidth + text: qsTr("Total messages sent (computed):") + anchors.verticalCenter: parent.verticalCenter + } + QGCLabel { + width: _valueWidth + text: _activeVehicle ? _activeVehicle.mavlinkSentCount : qsTr("Not Connected") + anchors.verticalCenter: parent.verticalCenter + } + } + //----------------------------------------------------------------- + Row { + spacing: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + QGCLabel { + width: _labelWidth + text: qsTr("Total messages received:") + anchors.verticalCenter: parent.verticalCenter + } + QGCLabel { + width: _valueWidth + text: _activeVehicle ? _activeVehicle.mavlinkReceivedCount : qsTr("Not Connected") + anchors.verticalCenter: parent.verticalCenter + } + } + //----------------------------------------------------------------- + Row { + spacing: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + QGCLabel { + width: _labelWidth + text: qsTr("Total message loss:") + anchors.verticalCenter: parent.verticalCenter + } + QGCLabel { + width: _valueWidth + text: _activeVehicle ? _activeVehicle.mavlinkLossCount : qsTr("Not Connected") + anchors.verticalCenter: parent.verticalCenter + } + } + //----------------------------------------------------------------- + Row { + spacing: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + QGCLabel { + width: _labelWidth + text: qsTr("Loss rate:") + anchors.verticalCenter: parent.verticalCenter + } + QGCLabel { + width: _valueWidth + text: _activeVehicle ? _activeVehicle.mavlinkLossPercent.toFixed(0) + '%' : qsTr("Not Connected") + anchors.verticalCenter: parent.verticalCenter + } + } + } + } + //----------------------------------------------------------------- //-- Mavlink Logging Item { width: __mavlinkRoot.width * 0.8 -- 2.22.0