Skip to content
LinkManager.cc 34.8 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"
#include "SettingsManager.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__
DonLakeFlyer's avatar
DonLakeFlyer committed
#include "GPSManager.h"
#include "PositionManager.h"
Don Gagne's avatar
Don Gagne committed
#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")

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, QGCToolbox* toolbox)
    : QGCTool(app, toolbox)
    , _configUpdateSuspended(false)
    , _configurationsLoaded(false)
    , _connectionsSuspended(false)
    , _mavlinkChannelsUsedBitMask(1)    // We never use channel 0 to avoid sequence numbering problems
    , _autoConnectSettings(NULL)
    , _mavlinkProtocol(NULL)
#ifndef __mobile__
    , _nmeaPort(NULL)
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");

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()
{
#ifndef __mobile__
    delete _nmeaPort;
pixhawk's avatar
pixhawk committed
}

void LinkManager::setToolbox(QGCToolbox *toolbox)
{
DonLakeFlyer's avatar
DonLakeFlyer committed
    QGCTool::setToolbox(toolbox);
DonLakeFlyer's avatar
DonLakeFlyer committed
    _autoConnectSettings = toolbox->settingsManager()->autoConnectSettings();
    _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
Don Gagne's avatar
Don Gagne committed
// This should only be used by Qml code
void LinkManager::createConnectedLink(LinkConfiguration* config)
{
    for(int i = 0; i < _sharedConfigurations.count(); i++) {
        SharedLinkConfigurationPointer& sharedConf = _sharedConfigurations[i];
        if (sharedConf->name() == config->name())
            createConnectedLink(sharedConf);
    }
}

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
DonLakeFlyer's avatar
DonLakeFlyer committed
    case LinkConfiguration::TypeSerial:
    {
        SerialConfiguration* serialConfig = dynamic_cast<SerialConfiguration*>(config.data());
        if (serialConfig) {
            pLink = new SerialLink(config);
            if (serialConfig->usbDirect()) {
                _activeLinkCheckList.append((SerialLink*)pLink);
                if (!_activeLinkCheckTimer.isActive()) {
                    _activeLinkCheckTimer.start();
DonLakeFlyer's avatar
DonLakeFlyer committed
    }
Don Gagne's avatar
Don Gagne committed
        break;
dogmaphobic's avatar
dogmaphobic committed
#endif
DonLakeFlyer's avatar
DonLakeFlyer committed
    case LinkConfiguration::TypeUdp:
        pLink = new UDPLink(config);
        break;
    case LinkConfiguration::TypeTcp:
        pLink = new TCPLink(config);
        break;
dogmaphobic's avatar
dogmaphobic committed
#ifdef QGC_ENABLE_BLUETOOTH
DonLakeFlyer's avatar
DonLakeFlyer committed
    case LinkConfiguration::TypeBluetooth:
        pLink = new BluetoothLink(config);
        break;
dogmaphobic's avatar
dogmaphobic committed
#endif
dogmaphobic's avatar
dogmaphobic committed
#ifndef __mobile__
DonLakeFlyer's avatar
DonLakeFlyer committed
    case LinkConfiguration::TypeLogReplay:
        pLink = new LogReplayLink(config);
        break;
dogmaphobic's avatar
dogmaphobic committed
#endif
#ifdef QT_DEBUG
DonLakeFlyer's avatar
DonLakeFlyer committed
    case LinkConfiguration::TypeMock:
        pLink = new MockLink(config);
        break;
DonLakeFlyer's avatar
DonLakeFlyer committed
    case LinkConfiguration::TypeLast:
    default:
        break;
        _addLink(pLink);
        connectLink(pLink);
Don Gagne's avatar
Don Gagne committed
LinkInterface* LinkManager::createConnectedLink(const QString& name)
DonLakeFlyer's avatar
DonLakeFlyer committed
    if (name.isEmpty()) {
        qWarning() << "Internal error";
    } else {
        for(int i = 0; i < _sharedConfigurations.count(); i++) {
            SharedLinkConfigurationPointer& conf = _sharedConfigurations[i];
            if (conf->name() == name) {
                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)) {
        int mavlinkChannel = _reserveMavlinkChannel();
        if (mavlinkChannel != 0) {
            link->_setMavlinkChannel(mavlinkChannel);
        } else {
            qWarning() << "Ran out of mavlink channels";
            return;
        _sharedLinks.append(SharedLinkInterfacePointer(link));
Don Gagne's avatar
Don Gagne committed
    connect(link, &LinkInterface::communicationError,   _app,               &QGCApplication::criticalMessageBoxOnMainThread);
    connect(link, &LinkInterface::bytesReceived,        _mavlinkProtocol,   &MAVLinkProtocol::receiveBytes);
    _mavlinkProtocol->resetMetadataForLink(link);
    _mavlinkProtocol->setVersion(_mavlinkProtocol->getCurrentVersion());
Loading
Loading full blame...