Skip to content
LinkManager.cc 35.7 KiB
Newer Older
/****************************************************************************
 *
 *   (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.
 *
 ****************************************************************************/
pixhawk's avatar
pixhawk committed
#include <QList>
#include <QApplication>
#include <QSignalSpy>
Gus Grubba's avatar
Gus Grubba committed
#ifndef NO_SERIAL_LINK
Don Gagne's avatar
Don Gagne committed
#include "QGCSerialPortInfo.h"
dogmaphobic's avatar
dogmaphobic committed
#endif
#include "LinkManager.h"
#include "QGCApplication.h"
Don Gagne's avatar
Don Gagne committed
#include "UDPLink.h"
#include "TCPLink.h"
dogmaphobic's avatar
dogmaphobic committed
#ifdef QGC_ENABLE_BLUETOOTH
dogmaphobic's avatar
dogmaphobic committed
#include "BluetoothLink.h"
#endif
Don Gagne's avatar
Don Gagne committed
#ifndef __mobile__
    #include "GPSManager.h"
#endif

Don Gagne's avatar
Don Gagne committed
QGC_LOGGING_CATEGORY(LinkManagerLog, "LinkManagerLog")
Don Gagne's avatar
Don Gagne committed
QGC_LOGGING_CATEGORY(LinkManagerVerboseLog, "LinkManagerVerboseLog")

const char* LinkManager::_settingsGroup =            "LinkManager";
const char* LinkManager::_autoconnectUDPKey =        "AutoconnectUDP";
const char* LinkManager::_autoconnectPixhawkKey =    "AutoconnectPixhawk";
const char* LinkManager::_autoconnect3DRRadioKey =   "Autoconnect3DRRadio";
const char* LinkManager::_autoconnectPX4FlowKey =    "AutoconnectPX4Flow";
const char* LinkManager::_autoconnectRTKGPSKey =     "AutoconnectRTKGPS";
const char* LinkManager::_autoconnectLibrePilotKey = "AutoconnectLibrePilot";
Don Gagne's avatar
Don Gagne committed
const char* LinkManager::_defaultUPDLinkName =       "UDP Link (AutoConnect)";
const int LinkManager::_autoconnectUpdateTimerMSecs =   1000;
#ifdef Q_OS_WIN
// Have to manually let the bootloader go by on Windows to get a working connect
const int LinkManager::_autoconnectConnectDelayMSecs =  6000;
#else
const int LinkManager::_autoconnectConnectDelayMSecs =  1000;
#endif

LinkManager::LinkManager(QGCApplication* app)
    : QGCTool(app)
    , _configUpdateSuspended(false)
    , _configurationsLoaded(false)
    , _connectionsSuspended(false)
    , _mavlinkChannelsUsedBitMask(1)    // We never use channel 0 to avoid sequence numbering problems
    , _mavlinkProtocol(NULL)
Don Gagne's avatar
Don Gagne committed
    , _autoconnectUDP(true)
    , _autoconnectPixhawk(true)
    , _autoconnect3DRRadio(true)
    , _autoconnectPX4Flow(true)
Don Gagne's avatar
Don Gagne committed
    , _autoconnectRTKGPS(true)
    , _autoconnectLibrePilot(true)
pixhawk's avatar
pixhawk committed
{
Don Gagne's avatar
Don Gagne committed
    qmlRegisterUncreatableType<LinkManager>         ("QGroundControl", 1, 0, "LinkManager",         "Reference only");
    qmlRegisterUncreatableType<LinkConfiguration>   ("QGroundControl", 1, 0, "LinkConfiguration",   "Reference only");
    qmlRegisterUncreatableType<LinkInterface>       ("QGroundControl", 1, 0, "LinkInterface",       "Reference only");

    QSettings settings;
Don Gagne's avatar
Don Gagne committed
    settings.beginGroup(_settingsGroup);
    _autoconnectUDP =        settings.value(_autoconnectUDPKey, true).toBool();
    _autoconnectPixhawk =    settings.value(_autoconnectPixhawkKey, true).toBool();
    _autoconnect3DRRadio =   settings.value(_autoconnect3DRRadioKey, true).toBool();
    _autoconnectPX4Flow =    settings.value(_autoconnectPX4FlowKey, true).toBool();
    _autoconnectRTKGPS =     settings.value(_autoconnectRTKGPSKey, true).toBool();
    _autoconnectLibrePilot = settings.value(_autoconnectLibrePilotKey, true).toBool();
Gus Grubba's avatar
Gus Grubba committed
#ifndef NO_SERIAL_LINK
Don Gagne's avatar
Don Gagne committed
    _activeLinkCheckTimer.setInterval(_activeLinkCheckTimeoutMSecs);
    _activeLinkCheckTimer.setSingleShot(false);
    connect(&_activeLinkCheckTimer, &QTimer::timeout, this, &LinkManager::_activeLinkCheck);
Don Gagne's avatar
Don Gagne committed
#endif
pixhawk's avatar
pixhawk committed
}

LinkManager::~LinkManager()
{
pixhawk's avatar
pixhawk committed
}

void LinkManager::setToolbox(QGCToolbox *toolbox)
{
   QGCTool::setToolbox(toolbox);

   _mavlinkProtocol = _toolbox->mavlinkProtocol();

Don Gagne's avatar
Don Gagne committed
    connect(&_portListTimer, &QTimer::timeout, this, &LinkManager::_updateAutoConnectLinks);
    _portListTimer.start(_autoconnectUpdateTimerMSecs); // timeout must be long enough to get past bootloader on second pass
LinkInterface* LinkManager::createConnectedLink(SharedLinkConfigurationPointer& config)
    if (!config) {
        qWarning() << "LinkManager::createConnectedLink called with NULL config";
        return NULL;
    }

    LinkInterface* pLink = NULL;
    switch(config->type()) {
Gus Grubba's avatar
Gus Grubba committed
#ifndef NO_SERIAL_LINK
Don Gagne's avatar
Don Gagne committed
        {
            SerialConfiguration* serialConfig = dynamic_cast<SerialConfiguration*>(config.data());
Don Gagne's avatar
Don Gagne committed
            if (serialConfig) {
                pLink = new SerialLink(config);
Don Gagne's avatar
Don Gagne committed
                if (serialConfig->usbDirect()) {
                    _activeLinkCheckList.append((SerialLink*)pLink);
Don Gagne's avatar
Don Gagne committed
                    if (!_activeLinkCheckTimer.isActive()) {
                        _activeLinkCheckTimer.start();
                    }
                }
            }
        }
        break;
dogmaphobic's avatar
dogmaphobic committed
#endif
            pLink = new UDPLink(config);
        case LinkConfiguration::TypeTcp:
            pLink = new TCPLink(config);
dogmaphobic's avatar
dogmaphobic committed
#ifdef QGC_ENABLE_BLUETOOTH
dogmaphobic's avatar
dogmaphobic committed
        case LinkConfiguration::TypeBluetooth:
            pLink = new BluetoothLink(config);
dogmaphobic's avatar
dogmaphobic committed
            break;
#endif
dogmaphobic's avatar
dogmaphobic committed
#ifndef __mobile__
Don Gagne's avatar
Don Gagne committed
        case LinkConfiguration::TypeLogReplay:
            pLink = new LogReplayLink(config);
Don Gagne's avatar
Don Gagne committed
            break;
dogmaphobic's avatar
dogmaphobic committed
#endif
#ifdef QT_DEBUG
            pLink = new MockLink(config);
        case LinkConfiguration::TypeLast:
        default:
            break;
        _addLink(pLink);
        connectLink(pLink);
Don Gagne's avatar
Don Gagne committed
LinkInterface* LinkManager::createConnectedLink(const QString& name)
    for(int i = 0; i < _sharedConfigurations.count(); i++) {
        SharedLinkConfigurationPointer& conf = _sharedConfigurations[i];
        if (conf->name() == name)
Don Gagne's avatar
Don Gagne committed
            return createConnectedLink(conf);
void LinkManager::_addLink(LinkInterface* link)
pixhawk's avatar
pixhawk committed
{
Don Gagne's avatar
Don Gagne committed
    if (thread() != QThread::currentThread()) {
        qWarning() << "_deleteLink called from incorrect thread";
        return;
    }
Don Gagne's avatar
Don Gagne committed
    if (!link) {
        return;
    }
    if (!containsLink(link)) {
        bool channelSet = false;

        // Find a mavlink channel to use for this link, Channel 0 is reserved for internal use.
        for (int i=1; i<32; i++) {
            if (!(_mavlinkChannelsUsedBitMask & 1 << i)) {
                mavlink_reset_channel_status(i);
                link->_setMavlinkChannel(i);
Don Gagne's avatar
Don Gagne committed
                // Start the channel on Mav 1 protocol
                mavlink_status_t* mavlinkStatus = mavlink_get_channel_status(i);
                mavlinkStatus->flags = mavlink_get_channel_status(i)->flags | MAVLINK_STATUS_FLAG_OUT_MAVLINK1;
                qDebug() << "LinkManager mavlinkStatus" << mavlinkStatus << i << mavlinkStatus->flags;
Don Gagne's avatar
Don Gagne committed
                _mavlinkChannelsUsedBitMask |= 1 << i;
                channelSet = true;
Loading
Loading full blame...