diff --git a/src/Comms/LinkManager.cc b/src/Comms/LinkManager.cc index 076fc04cbb42..222c614b542a 100644 --- a/src/Comms/LinkManager.cc +++ b/src/Comms/LinkManager.cc @@ -509,7 +509,8 @@ void LinkManager::_updateAutoConnectLinks() _reconnectAutoConnectLinks(); // check to see if nmea gps is configured for UDP input, if so, set it up to connect - if (_autoConnectSettings->autoConnectNmeaPort()->cookedValueString() == "UDP Port") { + const QString nmeaPortValue = _autoConnectSettings->autoConnectNmeaPort()->cookedValueString(); + if (nmeaPortValue == "UDP Port") { if ((_nmeaSocket->localPort() != _autoConnectSettings->nmeaUdpPort()->rawValue().toUInt()) || (_nmeaSocket->state() != UdpIODevice::BoundState)) { qCDebug(LinkManagerLog) << "Changing port for UDP NMEA stream"; _nmeaSocket->close(); @@ -526,6 +527,22 @@ void LinkManager::_updateAutoConnectLinks() #endif } else { _nmeaSocket->close(); + + // Only tear things down when NMEA is switched off entirely ("Disabled"). Any other + // value is a serial NMEA port, which is set up by _addSerialAutoConnectLink() below; + // touching _nmeaPort / the position source here would break it on every tick. + if (nmeaPortValue == "Disabled") { +#ifndef QGC_NO_SERIAL_LINK + if (_nmeaPort) { + _nmeaPort->close(); + delete _nmeaPort; + _nmeaPort = nullptr; + _nmeaDeviceName = ""; + } +#endif + // Revert QGCPositionManager to the integrated GPS if it was using an NMEA source + QGCPositionManager::instance()->resetNmeaSourceDevice(); + } } #ifndef QGC_NO_SERIAL_LINK diff --git a/src/PositionManager/PositionManager.cpp b/src/PositionManager/PositionManager.cpp index 17ee71614375..b2c1b8c7904f 100644 --- a/src/PositionManager/PositionManager.cpp +++ b/src/PositionManager/PositionManager.cpp @@ -101,6 +101,26 @@ void QGCPositionManager::setNmeaSourceDevice(QIODevice *device) _setPositionSource(QGCPositionManager::NmeaGPS); } +void QGCPositionManager::resetNmeaSourceDevice() +{ + if (!_nmeaSource) { + return; + } + + if (_currentSource == _nmeaSource) { + // Switch away while the NMEA source is still valid so _setPositionSource() can run its + // usual cleanup (stop updates, disconnect, and reset the stale GCS position/accuracy) + // before we delete it. Falls back to the platform's default source (e.g. integrated GPS). + _setPositionSource(QGCPositionManager::InternalGPS); + } else { + _nmeaSource->stopUpdates(); + (void) disconnect(_nmeaSource); + } + + delete _nmeaSource; + _nmeaSource = nullptr; +} + void QGCPositionManager::_positionUpdated(const QGeoPositionInfo &update) { _geoPositionInfo = update; diff --git a/src/PositionManager/PositionManager.h b/src/PositionManager/PositionManager.h index 13c75b90c62d..7bc4c749a9dd 100644 --- a/src/PositionManager/PositionManager.h +++ b/src/PositionManager/PositionManager.h @@ -37,6 +37,9 @@ class QGCPositionManager : public QObject int updateInterval() const { return _updateInterval; } void setNmeaSourceDevice(QIODevice *device); + /// Tears down any active NMEA source and falls back to the platform's default + /// position source (e.g. the integrated Android GPS). + void resetNmeaSourceDevice(); signals: void gcsPositionChanged(QGeoCoordinate gcsPosition);