Commit 76677481 authored by Don Gagne's avatar Don Gagne

Reference counting for LinkInterface, LinkConfiguration

Prevent shutdown ordering crashes
parent 5040e3d9
...@@ -641,6 +641,7 @@ SOURCES += \ ...@@ -641,6 +641,7 @@ SOURCES += \
src/VehicleSetup/JoystickConfigController.cc \ src/VehicleSetup/JoystickConfigController.cc \
src/audio/QGCAudioWorker.cpp \ src/audio/QGCAudioWorker.cpp \
src/comm/LinkConfiguration.cc \ src/comm/LinkConfiguration.cc \
src/comm/LinkInterface.cc \
src/comm/LinkManager.cc \ src/comm/LinkManager.cc \
src/comm/MAVLinkProtocol.cc \ src/comm/MAVLinkProtocol.cc \
src/comm/QGCMAVLink.cc \ src/comm/QGCMAVLink.cc \
......
...@@ -155,8 +155,8 @@ void QGroundControlQmlGlobal::stopAllMockLinks(void) ...@@ -155,8 +155,8 @@ void QGroundControlQmlGlobal::stopAllMockLinks(void)
#ifdef QT_DEBUG #ifdef QT_DEBUG
LinkManager* linkManager = qgcApp()->toolbox()->linkManager(); LinkManager* linkManager = qgcApp()->toolbox()->linkManager();
for (int i=0; i<linkManager->links()->count(); i++) { for (int i=0; i<linkManager->links().count(); i++) {
LinkInterface* link = linkManager->links()->value<LinkInterface*>(i); LinkInterface* link = linkManager->links()[i];
MockLink* mockLink = qobject_cast<MockLink*>(link); MockLink* mockLink = qobject_cast<MockLink*>(link);
if (mockLink) { if (mockLink) {
......
...@@ -306,9 +306,9 @@ void MultiVehicleManager::setGcsHeartbeatEnabled(bool gcsHeartBeatEnabled) ...@@ -306,9 +306,9 @@ void MultiVehicleManager::setGcsHeartbeatEnabled(bool gcsHeartBeatEnabled)
void MultiVehicleManager::_sendGCSHeartbeat(void) void MultiVehicleManager::_sendGCSHeartbeat(void)
{ {
// Send a heartbeat out on each link // Send a heartbeat out on each link
QmlObjectListModel* links = _toolbox->linkManager()->links(); LinkManager* linkMgr = _toolbox->linkManager();
for (int i=0; i<links->count(); i++) { for (int i=0; i<linkMgr->links().count(); i++) {
LinkInterface* link = links->value<LinkInterface*>(i); LinkInterface* link = linkMgr->links()[i];
if (link->isConnected()) { if (link->isConnected()) {
mavlink_message_t message; mavlink_message_t message;
mavlink_msg_heartbeat_pack_chan(_mavlinkProtocol->getSystemId(), mavlink_msg_heartbeat_pack_chan(_mavlinkProtocol->getSystemId(),
......
...@@ -926,8 +926,9 @@ bool Vehicle::_containsLink(LinkInterface* link) ...@@ -926,8 +926,9 @@ bool Vehicle::_containsLink(LinkInterface* link)
void Vehicle::_addLink(LinkInterface* link) void Vehicle::_addLink(LinkInterface* link)
{ {
if (!_containsLink(link)) { if (!_containsLink(link)) {
_links += link;
qCDebug(VehicleLog) << "_addLink:" << QString("%1").arg((ulong)link, 0, 16); qCDebug(VehicleLog) << "_addLink:" << QString("%1").arg((ulong)link, 0, 16);
_links += link;
_updatePriorityLink();
connect(qgcApp()->toolbox()->linkManager(), &LinkManager::linkInactive, this, &Vehicle::_linkInactiveOrDeleted); connect(qgcApp()->toolbox()->linkManager(), &LinkManager::linkInactive, this, &Vehicle::_linkInactiveOrDeleted);
connect(qgcApp()->toolbox()->linkManager(), &LinkManager::linkDeleted, this, &Vehicle::_linkInactiveOrDeleted); connect(qgcApp()->toolbox()->linkManager(), &LinkManager::linkDeleted, this, &Vehicle::_linkInactiveOrDeleted);
} }
...@@ -938,6 +939,7 @@ void Vehicle::_linkInactiveOrDeleted(LinkInterface* link) ...@@ -938,6 +939,7 @@ void Vehicle::_linkInactiveOrDeleted(LinkInterface* link)
qCDebug(VehicleLog) << "_linkInactiveOrDeleted linkCount" << _links.count(); qCDebug(VehicleLog) << "_linkInactiveOrDeleted linkCount" << _links.count();
_links.removeOne(link); _links.removeOne(link);
_updatePriorityLink();
if (_links.count() == 0 && !_allLinksInactiveSent) { if (_links.count() == 0 && !_allLinksInactiveSent) {
qCDebug(VehicleLog) << "All links inactive"; qCDebug(VehicleLog) << "All links inactive";
...@@ -983,26 +985,42 @@ void Vehicle::_sendMessageOnLink(LinkInterface* link, mavlink_message_t message) ...@@ -983,26 +985,42 @@ void Vehicle::_sendMessageOnLink(LinkInterface* link, mavlink_message_t message)
emit messagesSentChanged(); emit messagesSentChanged();
} }
/// @return Direct usb connection link to board if one, NULL if none void Vehicle::_updatePriorityLink(void)
LinkInterface* Vehicle::priorityLink(void)
{ {
#ifndef NO_SERIAL_LINK #ifndef NO_SERIAL_LINK
foreach (LinkInterface* link, _links) { LinkInterface* newPriorityLink = NULL;
// Note that this routine specificallty does not clear _priorityLink when there are no links remaining.
// By doing this we hold a reference on the last link as the Vehicle shuts down. Thus preventing shutdown
// ordering NULL pointer crashes where priorityLink() is still called during shutdown sequence.
for (int i=0; i<_links.count(); i++) {
LinkInterface* link = _links[i];
if (link->isConnected()) { if (link->isConnected()) {
SerialLink* pSerialLink = qobject_cast<SerialLink*>(link); SerialLink* pSerialLink = qobject_cast<SerialLink*>(link);
if (pSerialLink) { if (pSerialLink) {
LinkConfiguration* pLinkConfig = pSerialLink->getLinkConfiguration(); LinkConfiguration* config = pSerialLink->getLinkConfiguration();
if (pLinkConfig) { if (config) {
SerialConfiguration* pSerialConfig = qobject_cast<SerialConfiguration*>(pLinkConfig); SerialConfiguration* pSerialConfig = qobject_cast<SerialConfiguration*>(config);
if (pSerialConfig && pSerialConfig->usbDirect()) { if (pSerialConfig && pSerialConfig->usbDirect()) {
return link; if (_priorityLink.data() != link) {
newPriorityLink = link;
break;
}
return;
} }
} }
} }
} }
} }
if (!newPriorityLink && !_priorityLink.data() && _links.count()) {
newPriorityLink = _links[0];
}
if (newPriorityLink) {
_priorityLink = qgcApp()->toolbox()->linkManager()->sharedLinkInterfacePointerForLink(newPriorityLink);
}
#endif #endif
return _links.count() ? _links[0] : NULL;
} }
void Vehicle::setLatitude(double latitude) void Vehicle::setLatitude(double latitude)
......
...@@ -416,8 +416,9 @@ public: ...@@ -416,8 +416,9 @@ public:
MAV_TYPE vehicleType(void) const { return _vehicleType; } MAV_TYPE vehicleType(void) const { return _vehicleType; }
Q_INVOKABLE QString vehicleTypeName(void) const; Q_INVOKABLE QString vehicleTypeName(void) const;
/// Returns the highest quality link available to the Vehicle /// Returns the highest quality link available to the Vehicle. If you need to hold a refernce to this link use
LinkInterface* priorityLink(void); /// LinkManager::sharedLinkInterfaceForGet to get QSharedPointer for link.
LinkInterface* priorityLink(void) { return _priorityLink.data(); }
/// Sends a message to the specified link /// Sends a message to the specified link
/// @return true: message sent, false: Link no longer connected /// @return true: message sent, false: Link no longer connected
...@@ -720,6 +721,7 @@ private: ...@@ -720,6 +721,7 @@ private:
void _handleMavlinkLoggingDataAcked(mavlink_message_t& message); void _handleMavlinkLoggingDataAcked(mavlink_message_t& message);
void _ackMavlinkLogData(uint16_t sequence); void _ackMavlinkLogData(uint16_t sequence);
void _sendNextQueuedMavCommand(void); void _sendNextQueuedMavCommand(void);
void _updatePriorityLink(void);
private: private:
int _id; ///< Mavlink system id int _id; ///< Mavlink system id
...@@ -851,6 +853,8 @@ private: ...@@ -851,6 +853,8 @@ private:
static const int _lowBatteryAnnounceRepeatMSecs; // Amount of time in between each low battery announcement static const int _lowBatteryAnnounceRepeatMSecs; // Amount of time in between each low battery announcement
QElapsedTimer _lowBatteryAnnounceTimer; QElapsedTimer _lowBatteryAnnounceTimer;
SharedLinkInterfacePointer _priorityLink; // We always keep a reference to the priority link to manage shutdown ordering
// FactGroup facts // FactGroup facts
Fact _rollFact; Fact _rollFact;
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
* *
****************************************************************************/ ****************************************************************************/
#ifndef LINKCONFIGURATION_H #ifndef LINKCONFIGURATION_H
#define LINKCONFIGURATION_H #define LINKCONFIGURATION_H
...@@ -37,7 +36,7 @@ public: ...@@ -37,7 +36,7 @@ public:
// Property accessors // Property accessors
const QString name(void) { return _name; } QString name(void) const { return _name; }
LinkInterface* link(void) { return _link; } LinkInterface* link(void) { return _link; }
void setName(const QString name); void setName(const QString name);
...@@ -190,4 +189,6 @@ private: ...@@ -190,4 +189,6 @@ private:
bool _autoConnect; ///< This connection is started automatically at boot bool _autoConnect; ///< This connection is started automatically at boot
}; };
typedef QSharedPointer<LinkConfiguration> SharedLinkConfigurationPointer;
#endif // LINKCONFIGURATION_H #endif // LINKCONFIGURATION_H
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#include "LinkInterface.h"
#include "QGCApplication.h"
/// mavlink channel to use for this link, as used by mavlink_parse_char. The mavlink channel is only
/// set into the link when it is added to LinkManager
uint8_t LinkInterface::mavlinkChannel(void) const
{
if (!_mavlinkChannelSet) {
qWarning() << "Call to LinkInterface::mavlinkChannel with _mavlinkChannelSet == false";
}
return _mavlinkChannel;
}
// Links are only created by LinkManager so constructor is not public
LinkInterface::LinkInterface(SharedLinkConfigurationPointer& config)
: QThread(0)
, _config(config)
, _mavlinkChannelSet(false)
, _active(false)
, _enableRateCollection(false)
{
_config->setLink(this);
// Initialize everything for the data rate calculation buffers.
_inDataIndex = 0;
_outDataIndex = 0;
// Initialize our data rate buffers.
memset(_inDataWriteAmounts, 0, sizeof(_inDataWriteAmounts));
memset(_inDataWriteTimes, 0, sizeof(_inDataWriteTimes));
memset(_outDataWriteAmounts,0, sizeof(_outDataWriteAmounts));
memset(_outDataWriteTimes, 0, sizeof(_outDataWriteTimes));
QObject::connect(this, &LinkInterface::_invokeWriteBytes, this, &LinkInterface::_writeBytes);
qRegisterMetaType<LinkInterface*>("LinkInterface*");
}
/// This function logs the send times and amounts of datas for input. Data is used for calculating
/// the transmission rate.
/// @param byteCount Number of bytes received
/// @param time Time in ms send occurred
void LinkInterface::_logInputDataRate(quint64 byteCount, qint64 time) {
if(_enableRateCollection)
_logDataRateToBuffer(_inDataWriteAmounts, _inDataWriteTimes, &_inDataIndex, byteCount, time);
}
/// This function logs the send times and amounts of datas for output. Data is used for calculating
/// the transmission rate.
/// @param byteCount Number of bytes sent
/// @param time Time in ms receive occurred
void LinkInterface::_logOutputDataRate(quint64 byteCount, qint64 time) {
if(_enableRateCollection)
_logDataRateToBuffer(_outDataWriteAmounts, _outDataWriteTimes, &_outDataIndex, byteCount, time);
}
/**
* @brief logDataRateToBuffer Stores transmission times/amounts for statistics
*
* This function logs the send times and amounts of datas to the given circular buffers.
* This data is used for calculating the transmission rate.
*
* @param bytesBuffer[out] The buffer to write the bytes value into.
* @param timeBuffer[out] The buffer to write the time value into
* @param writeIndex[out] The write index used for this buffer.
* @param bytes The amount of bytes transmit.
* @param time The time (in ms) this transmission occurred.
*/
void LinkInterface::_logDataRateToBuffer(quint64 *bytesBuffer, qint64 *timeBuffer, int *writeIndex, quint64 bytes, qint64 time)
{
QMutexLocker dataRateLocker(&_dataRateMutex);
int i = *writeIndex;
// Now write into the buffer, if there's no room, we just overwrite the first data point.
bytesBuffer[i] = bytes;
timeBuffer[i] = time;
// Increment and wrap the write index
++i;
if (i == _dataRateBufferSize)
{
i = 0;
}
*writeIndex = i;
}
/**
* @brief getCurrentDataRate Get the current data rate given a data rate buffer.
*
* This function attempts to use the times and number of bytes transmit into a current data rate
* estimation. Since it needs to use timestamps to get the timeperiods over when the data was sent,
* this is effectively a global data rate over the last _dataRateBufferSize - 1 data points. Also note
* that data points older than NOW - dataRateCurrentTimespan are ignored.
*
* @param index The first valid sample in the data rate buffer. Refers to the oldest time sample.
* @param dataWriteTimes The time, in ms since epoch, that each data sample took place.
* @param dataWriteAmounts The amount of data (in bits) that was transferred.
* @return The bits per second of data transferrence of the interface over the last [-statsCurrentTimespan, 0] timespan.
*/
qint64 LinkInterface::_getCurrentDataRate(int index, const qint64 dataWriteTimes[], const quint64 dataWriteAmounts[]) const
{
const qint64 now = QDateTime::currentMSecsSinceEpoch();
// Limit the time we calculate to the recent past
const qint64 cutoff = now - _dataRateCurrentTimespan;
// Grab the mutex for working with the stats variables
QMutexLocker dataRateLocker(&_dataRateMutex);
// Now iterate through the buffer of all received data packets adding up all values
// within now and our cutof.
qint64 totalBytes = 0;
qint64 totalTime = 0;
qint64 lastTime = 0;
int size = _dataRateBufferSize;
while (size-- > 0)
{
// If this data is within our cutoff time, include it in our calculations.
// This also accounts for when the buffer is empty and filled with 0-times.
if (dataWriteTimes[index] > cutoff && lastTime > 0) {
// Track the total time, using the previous time as our timeperiod.
totalTime += dataWriteTimes[index] - lastTime;
totalBytes += dataWriteAmounts[index];
}
// Track the last time sample for doing timespan calculations
lastTime = dataWriteTimes[index];
// Increment and wrap the index if necessary.
if (++index == _dataRateBufferSize)
{
index = 0;
}
}
// Return the final calculated value in bits / s, converted from bytes/ms.
qint64 dataRate = (totalTime != 0)?(qint64)((float)totalBytes * 8.0f / ((float)totalTime / 1000.0f)):0;
// Finally return our calculated data rate.
return dataRate;
}
/// Sets the mavlink channel to use for this link
void LinkInterface::_setMavlinkChannel(uint8_t channel)
{
Q_ASSERT(!_mavlinkChannelSet);
_mavlinkChannelSet = true;
_mavlinkChannel = channel;
}
...@@ -19,9 +19,9 @@ ...@@ -19,9 +19,9 @@
#include <QDebug> #include <QDebug>
#include "QGCMAVLink.h" #include "QGCMAVLink.h"
#include "LinkConfiguration.h"
class LinkManager; class LinkManager;
class LinkConfiguration;
/** /**
* The link interface defines the interface for all links used to communicate * The link interface defines the interface for all links used to communicate
...@@ -35,18 +35,16 @@ class LinkInterface : public QThread ...@@ -35,18 +35,16 @@ class LinkInterface : public QThread
// Only LinkManager is allowed to create/delete or _connect/_disconnect a link // Only LinkManager is allowed to create/delete or _connect/_disconnect a link
friend class LinkManager; friend class LinkManager;
public: public:
~LinkInterface() { _config->setLink(NULL); }
Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged) Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged)
// Property accessors // Property accessors
bool active(void) { return _active; } bool active(void) { return _active; }
void setActive(bool active) { _active = active; emit activeChanged(active); } void setActive(bool active) { _active = active; emit activeChanged(active); }
/** LinkConfiguration* getLinkConfiguration(void) { return _config.data(); }
* @brief Get link configuration
* @return A pointer to the instance of LinkConfiguration
**/
virtual LinkConfiguration* getLinkConfiguration() = 0;
/* Connection management */ /* Connection management */
...@@ -116,13 +114,7 @@ public: ...@@ -116,13 +114,7 @@ public:
/// mavlink channel to use for this link, as used by mavlink_parse_char. The mavlink channel is only /// mavlink channel to use for this link, as used by mavlink_parse_char. The mavlink channel is only
/// set into the link when it is added to LinkManager /// set into the link when it is added to LinkManager
uint8_t mavlinkChannel(void) const uint8_t mavlinkChannel(void) const;
{
if (!_mavlinkChannelSet) {
qWarning() << "Call to LinkInterface::mavlinkChannel with _mavlinkChannelSet == false";
}
return _mavlinkChannel;
}
// These are left unimplemented in order to cause linker errors which indicate incorrect usage of // These are left unimplemented in order to cause linker errors which indicate incorrect usage of
// connect/disconnect on link directly. All connect/disconnect calls should be made through LinkManager. // connect/disconnect on link directly. All connect/disconnect calls should be made through LinkManager.
...@@ -192,43 +184,21 @@ signals: ...@@ -192,43 +184,21 @@ signals:
protected: protected:
// Links are only created by LinkManager so constructor is not public // Links are only created by LinkManager so constructor is not public
LinkInterface() : LinkInterface(SharedLinkConfigurationPointer& config);
QThread(0)
, _mavlinkChannelSet(false)
, _active(false)
, _enableRateCollection(false)
{
// Initialize everything for the data rate calculation buffers.
_inDataIndex = 0;
_outDataIndex = 0;
// Initialize our data rate buffers.
memset(_inDataWriteAmounts, 0, sizeof(_inDataWriteAmounts));
memset(_inDataWriteTimes, 0, sizeof(_inDataWriteTimes));
memset(_outDataWriteAmounts,0, sizeof(_outDataWriteAmounts));
memset(_outDataWriteTimes, 0, sizeof(_outDataWriteTimes));
QObject::connect(this, &LinkInterface::_invokeWriteBytes, this, &LinkInterface::_writeBytes);
qRegisterMetaType<LinkInterface*>("LinkInterface*");
}
/// This function logs the send times and amounts of datas for input. Data is used for calculating /// This function logs the send times and amounts of datas for input. Data is used for calculating
/// the transmission rate. /// the transmission rate.
/// @param byteCount Number of bytes received /// @param byteCount Number of bytes received
/// @param time Time in ms send occurred /// @param time Time in ms send occurred
void _logInputDataRate(quint64 byteCount, qint64 time) { void _logInputDataRate(quint64 byteCount, qint64 time);
if(_enableRateCollection)
_logDataRateToBuffer(_inDataWriteAmounts, _inDataWriteTimes, &_inDataIndex, byteCount, time);
}
/// This function logs the send times and amounts of datas for output. Data is used for calculating /// This function logs the send times and amounts of datas for output. Data is used for calculating
/// the transmission rate. /// the transmission rate.
/// @param byteCount Number of bytes sent /// @param byteCount Number of bytes sent
/// @param time Time in ms receive occurred /// @param time Time in ms receive occurred
void _logOutputDataRate(quint64 byteCount, qint64 time) { void _logOutputDataRate(quint64 byteCount, qint64 time);
if(_enableRateCollection)
_logDataRateToBuffer(_outDataWriteAmounts, _outDataWriteTimes, &_outDataIndex, byteCount, time); SharedLinkConfigurationPointer _config;
}
private: private:
/** /**
...@@ -243,24 +213,7 @@ private: ...@@ -243,24 +213,7 @@ private:
* @param bytes The amount of bytes transmit. * @param bytes The amount of bytes transmit.
* @param time The time (in ms) this transmission occurred. * @param time The time (in ms) this transmission occurred.
*/ */
void _logDataRateToBuffer(quint64 *bytesBuffer, qint64 *timeBuffer, int *writeIndex, quint64 bytes, qint64 time) void _logDataRateToBuffer(quint64 *bytesBuffer, qint64 *timeBuffer, int *writeIndex, quint64 bytes, qint64 time);
{
QMutexLocker dataRateLocker(&_dataRateMutex);
int i = *writeIndex;
// Now write into the buffer, if there's no room, we just overwrite the first data point.
bytesBuffer[i] = bytes;
timeBuffer[i] = time;
// Increment and wrap the write index
++i;
if (i == _dataRateBufferSize)
{
i = 0;
}
*writeIndex = i;
}
/** /**
* @brief getCurrentDataRate Get the current data rate given a data rate buffer. * @brief getCurrentDataRate Get the current data rate given a data rate buffer.
...@@ -275,48 +228,7 @@ private: ...@@ -275,48 +228,7 @@ private:
* @param dataWriteAmounts The amount of data (in bits) that was transferred. * @param dataWriteAmounts The amount of data (in bits) that was transferred.
* @return The bits per second of data transferrence of the interface over the last [-statsCurrentTimespan, 0] timespan. * @return The bits per second of data transferrence of the interface over the last [-statsCurrentTimespan, 0] timespan.
*/ */
qint64 _getCurrentDataRate(int index, const qint64 dataWriteTimes[], const quint64 dataWriteAmounts[]) const qint64 _getCurrentDataRate(int index, const qint64 dataWriteTimes[], const quint64 dataWriteAmounts[]) const;
{
const qint64 now = QDateTime::currentMSecsSinceEpoch();
// Limit the time we calculate to the recent past
const qint64 cutoff = now - _dataRateCurrentTimespan;
// Grab the mutex for working with the stats variables
QMutexLocker dataRateLocker(&_dataRateMutex);
// Now iterate through the buffer of all received data packets adding up all values
// within now and our cutof.
qint64 totalBytes = 0;
qint64 totalTime = 0;
qint64 lastTime = 0;
int size = _dataRateBufferSize;
while (size-- > 0)
{
// If this data is within our cutoff time, include it in our calculations.
// This also accounts for when the buffer is empty and filled with 0-times.
if (dataWriteTimes[index] > cutoff && lastTime > 0) {
// Track the total time, using the previous time as our timeperiod.
totalTime += dataWriteTimes[index] - lastTime;
totalBytes += dataWriteAmounts[index];
}
// Track the last time sample for doing timespan calculations
lastTime = dataWriteTimes[index];
// Increment and wrap the index if necessary.
if (++index == _dataRateBufferSize)
{
index = 0;
}
}
// Return the final calculated value in bits / s, converted from bytes/ms.
qint64 dataRate = (totalTime != 0)?(qint64)((float)totalBytes * 8.0f / ((float)totalTime / 1000.0f)):0;
// Finally return our calculated data rate.
return dataRate;
}
/** /**
* @brief Connect this interface logically * @brief Connect this interface logically
...@@ -328,7 +240,7 @@ private: ...@@ -328,7 +240,7 @@ private:
virtual void _disconnect(void) = 0; virtual void _disconnect(void) = 0;
/// Sets the mavlink channel to use for this link /// Sets the mavlink channel to use for this link
void _setMavlinkChannel(uint8_t channel) { Q_ASSERT(!_mavlinkChannelSet); _mavlinkChannelSet = true; _mavlinkChannel = channel; } void _setMavlinkChannel(uint8_t channel);
bool _mavlinkChannelSet; ///< true: _mavlinkChannel has been set bool _mavlinkChannelSet; ///< true: _mavlinkChannel has been set
uint8_t _mavlinkChannel; ///< mavlink channel to use for this link, as used by mavlink_parse_char uint8_t _mavlinkChannel; ///< mavlink channel to use for this link, as used by mavlink_parse_char
...@@ -355,6 +267,6 @@ private: ...@@ -355,6 +267,6 @@ private:
bool _enableRateCollection; bool _enableRateCollection;
}; };
typedef QSharedPointer<LinkInterface> SharedLinkInterface; typedef QSharedPointer<LinkInterface> SharedLinkInterfacePointer;
#endif // _LINKINTERFACE_H_ #endif // _LINKINTERFACE_H_
This diff is collapsed.
...@@ -67,19 +67,12 @@ public: ...@@ -67,19 +67,12 @@ public:
Q_PROPERTY(bool autoconnectPX4Flow READ autoconnectPX4Flow WRITE setAutoconnectPX4Flow NOTIFY autoconnectPX4FlowChanged) Q_PROPERTY(bool autoconnectPX4Flow READ autoconnectPX4Flow WRITE setAutoconnectPX4Flow NOTIFY autoconnectPX4FlowChanged)
Q_PROPERTY(bool autoconnectRTKGPS READ autoconnectRTKGPS WRITE setAutoconnectRTKGPS NOTIFY autoconnectRTKGPSChanged) Q_PROPERTY(bool autoconnectRTKGPS READ autoconnectRTKGPS WRITE setAutoconnectRTKGPS NOTIFY autoconnectRTKGPSChanged)
Q_PROPERTY(bool autoconnectLibrePilot READ autoconnectLibrePilot WRITE setAutoconnectLibrePilot NOTIFY autoconnectLibrePilotChanged) Q_PROPERTY(bool autoconnectLibrePilot READ autoconnectLibrePilot WRITE setAutoconnectLibrePilot NOTIFY autoconnectLibrePilotChanged)
Q_PROPERTY(bool isBluetoothAvailable READ isBluetoothAvailable CONSTANT) Q_PROPERTY(bool isBluetoothAvailable READ isBluetoothAvailable CONSTANT)
/// LinkInterface Accessor Q_PROPERTY(QmlObjectListModel* linkConfigurations READ _qmlLinkConfigurations NOTIFY linkConfigurationsChanged)
Q_PROPERTY(QmlObjectListModel* links READ links CONSTANT) Q_PROPERTY(QStringList linkTypeStrings READ linkTypeStrings CONSTANT)
/// LinkConfiguration Accessor Q_PROPERTY(QStringList serialBaudRates READ serialBaudRates CONSTANT)
Q_PROPERTY(QmlObjectListModel* linkConfigurations READ linkConfigurations NOTIFY linkConfigurationsChanged)
/// List of comm type strings
Q_PROPERTY(QStringList linkTypeStrings READ linkTypeStrings CONSTANT)
/// List of supported baud rates for serial links
Q_PROPERTY(QStringList serialBaudRates READ serialBaudRates CONSTANT)
/// List of comm ports display names
Q_PROPERTY(QStringList serialPortStrings READ serialPortStrings NOTIFY commPortStringsChanged) Q_PROPERTY(QStringList serialPortStrings READ serialPortStrings NOTIFY commPortStringsChanged)
/// List of comm ports
Q_PROPERTY(QStringList serialPorts READ serialPorts NOTIFY commPortsChanged) Q_PROPERTY(QStringList serialPorts READ serialPorts NOTIFY commPortsChanged)
// Create/Edit Link Configuration // Create/Edit Link Configuration
...@@ -100,12 +93,11 @@ public: ...@@ -100,12 +93,11 @@ public:
bool autoconnectLibrePilot (void) { return _autoconnectLibrePilot; } bool autoconnectLibrePilot (void) { return _autoconnectLibrePilot; }
bool isBluetoothAvailable (void); bool isBluetoothAvailable (void);
QmlObjectListModel* links (void) { return &_links; } QList<LinkInterface*> links (void);
QmlObjectListModel* linkConfigurations (void) { return &_linkConfigurations; } QStringList linkTypeStrings (void) const;
QStringList linkTypeStrings (void) const; QStringList serialBaudRates (void);
QStringList serialBaudRates (void); QStringList serialPortStrings (void);
QStringList serialPortStrings (void); QStringList serialPorts (void);
QStringList serialPorts (void);
void setAutoconnectUDP (bool autoconnect); void setAutoconnectUDP (bool autoconnect);
void setAutoconnectPixhawk (bool autoconnect); void setAutoconnectPixhawk (bool autoconnect);
...@@ -132,7 +124,7 @@ public: ...@@ -132,7 +124,7 @@ public:
/// Creates, connects (and adds) a link based on the given configuration instance. /// Creates, connects (and adds) a link based on the given configuration instance.
/// Link takes ownership of config. /// Link takes ownership of config.
Q_INVOKABLE LinkInterface* createConnectedLink(LinkConfiguration* config); Q_INVOKABLE LinkInterface* createConnectedLink(SharedLinkConfigurationPointer& config);
/// Creates, connects (and adds) a link based on the given configuration name. /// Creates, connects (and adds) a link based on the given configuration name.
LinkInterface* createConnectedLink(const QString& name); LinkInterface* createConnectedLink(const QString& name);
...@@ -165,6 +157,17 @@ public: ...@@ -165,6 +157,17 @@ public:
// Override from QGCTool // Override from QGCTool
virtual void setToolbox(QGCToolbox *toolbox); virtual void setToolbox(QGCToolbox *toolbox);
/// @return This mavlink channel is never assigned to a vehicle.
uint8_t reservedMavlinkChannel(void) { return 0; }
/// If you are going to hold a reference to a LinkInterface* in your object you must reference count it
/// by using this method to get access to the shared pointer.
SharedLinkInterfacePointer sharedLinkInterfacePointerForLink(LinkInterface* link);
bool containsLink(LinkInterface* link);
SharedLinkConfigurationPointer addConfiguration(LinkConfiguration* config);
signals: signals:
void autoconnectUDPChanged (bool autoconnect); void autoconnectUDPChanged (bool autoconnect);
void autoconnectPixhawkChanged (bool autoconnect); void autoconnectPixhawkChanged (bool autoconnect);
...@@ -204,11 +207,13 @@ private slots: ...@@ -204,11 +207,13 @@ private slots:
#endif #endif
private: private:
QmlObjectListModel* _qmlLinkConfigurations (void) { return &_qmlConfigurations; }
bool _connectionsSuspendedMsg(void); bool _connectionsSuspendedMsg(void);
void _updateAutoConnectLinks(void); void _updateAutoConnectLinks(void);
void _updateSerialPorts(); void _updateSerialPorts();
void _fixUnnamed(LinkConfiguration* config); void _fixUnnamed(LinkConfiguration* config);
bool _setAutoconnectWorker(bool& currentAutoconnect, bool newAutoconnect, const char* autoconnectKey); bool _setAutoconnectWorker(bool& currentAutoconnect, bool newAutoconnect, const char* autoconnectKey);
void _removeConfiguration(LinkConfiguration* config);
#ifndef NO_SERIAL_LINK #ifndef NO_SERIAL_LINK
SerialConfiguration* _autoconnectConfigurationsContainsPort(const QString& portName); SerialConfiguration* _autoconnectConfigurationsContainsPort(const QString& portName);
...@@ -223,9 +228,11 @@ private: ...@@ -223,9 +228,11 @@ private:
MAVLinkProtocol* _mavlinkProtocol; MAVLinkProtocol* _mavlinkProtocol;