From 4545d87670bb1cd4131b8560d0104cc0c893106b Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Sun, 5 May 2024 02:15:54 -0500 Subject: [PATCH] Create an NMEA position source if configured to do so --- .../scwx/qt/manager/position_manager.cpp | 149 +++++++++++++++--- 1 file changed, 124 insertions(+), 25 deletions(-) diff --git a/scwx-qt/source/scwx/qt/manager/position_manager.cpp b/scwx-qt/source/scwx/qt/manager/position_manager.cpp index 23357444..a6d1e2f1 100644 --- a/scwx-qt/source/scwx/qt/manager/position_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/position_manager.cpp @@ -1,7 +1,10 @@ #include +#include +#include #include #include +#include #include #include @@ -23,37 +26,37 @@ public: explicit Impl(PositionManager* self) : self_ {self}, trackingUuid_ {boost::uuids::random_generator()()} { - // TODO: macOS requires permission - geoPositionInfoSource_ = - QGeoPositionInfoSource::createDefaultSource(self); + auto& generalSettings = settings::GeneralSettings::Instance(); - if (geoPositionInfoSource_ != nullptr) - { - logger_->debug("Using position source: {}", - geoPositionInfoSource_->sourceName().toStdString()); + logger_->debug( + "Available sources: {}", + QGeoPositionInfoSource::availableSources().join(", ").toStdString()); - QObject::connect(geoPositionInfoSource_, - &QGeoPositionInfoSource::positionUpdated, - self_, - [this](const QGeoPositionInfo& info) - { - auto coordinate = info.coordinate(); + CreatePositionSource(); - if (coordinate != position_.coordinate()) - { - logger_->debug("Position updated: {}, {}", - coordinate.latitude(), - coordinate.longitude()); - } + positioningPluginCallbackUuid_ = + generalSettings.positioning_plugin().RegisterValueChangedCallback( + [this](const std::string&) { CreatePositionSource(); }); + nmeaBaudRateCallbackUuid_ = + generalSettings.nmea_baud_rate().RegisterValueChangedCallback( + [this](const std::int64_t&) { CreatePositionSource(); }); + nmeaSourceCallbackUuid_ = + generalSettings.nmea_source().RegisterValueChangedCallback( + [this](const std::string&) { CreatePositionSource(); }); + } + ~Impl() + { + auto& generalSettings = settings::GeneralSettings::Instance(); - position_ = info; - - Q_EMIT self_->PositionUpdated(info); - }); - } + generalSettings.positioning_plugin().UnregisterValueChangedCallback( + positioningPluginCallbackUuid_); + generalSettings.nmea_baud_rate().UnregisterValueChangedCallback( + nmeaBaudRateCallbackUuid_); + generalSettings.nmea_source().UnregisterValueChangedCallback( + nmeaSourceCallbackUuid_); } - ~Impl() {} + void CreatePositionSource(); PositionManager* self_; @@ -62,8 +65,19 @@ public: std::set uuids_ {}; + std::mutex positionSourceMutex_ {}; + QGeoPositionInfoSource* geoPositionInfoSource_ {}; QGeoPositionInfo position_ {}; + + types::PositioningPlugin lastPositioningPlugin_ { + types::PositioningPlugin::Unknown}; + std::int64_t lastNmeaBaudRate_ {-1}; + std::string lastNmeaSource_ {"?"}; + + boost::uuids::uuid positioningPluginCallbackUuid_ {}; + boost::uuids::uuid nmeaBaudRateCallbackUuid_ {}; + boost::uuids::uuid nmeaSourceCallbackUuid_ {}; }; PositionManager::PositionManager() : p(std::make_unique(this)) {} @@ -79,9 +93,94 @@ bool PositionManager::IsLocationTracked() return p->trackingEnabled_; } +void PositionManager::Impl::CreatePositionSource() +{ + auto& generalSettings = settings::GeneralSettings::Instance(); + + types::PositioningPlugin positioningPlugin = types::GetPositioningPlugin( + generalSettings.positioning_plugin().GetValue()); + std::int64_t nmeaBaudRate = generalSettings.nmea_baud_rate().GetValue(); + std::string nmeaSource = generalSettings.nmea_source().GetValue(); + + if (positioningPlugin == lastPositioningPlugin_ && + nmeaBaudRate == lastNmeaBaudRate_ && nmeaSource == lastNmeaSource_) + { + return; + } + + QGeoPositionInfoSource* positionSource = nullptr; + + // TODO: macOS requires permission + if (positioningPlugin == types::PositioningPlugin::Default) + { + positionSource = QGeoPositionInfoSource::createDefaultSource(self_); + } + else if (positioningPlugin == types::PositioningPlugin::Nmea) + { + QVariantMap params {}; + params["nmea.source"] = QString::fromStdString(nmeaSource); + params["nmea.baudrate"] = static_cast(nmeaBaudRate); + + positionSource = + QGeoPositionInfoSource::createSource("nmea", params, self_); + } + + if (positionSource != nullptr) + { + logger_->debug("Using position source: {}", + positionSource->sourceName().toStdString()); + + QObject::connect(positionSource, + &QGeoPositionInfoSource::positionUpdated, + self_, + [this](const QGeoPositionInfo& info) + { + auto coordinate = info.coordinate(); + + if (coordinate != position_.coordinate()) + { + logger_->debug("Position updated: {}, {}", + coordinate.latitude(), + coordinate.longitude()); + } + + position_ = info; + + Q_EMIT self_->PositionUpdated(info); + }); + } + else + { + logger_->error("Unable to create position source for plugin: {}", + types::GetPositioningPluginName(positioningPlugin)); + return; + } + + lastPositioningPlugin_ = positioningPlugin; + lastNmeaBaudRate_ = nmeaBaudRate; + lastNmeaSource_ = nmeaSource; + + std::unique_lock lock {positionSourceMutex_}; + + if (geoPositionInfoSource_ != nullptr) + { + geoPositionInfoSource_->stopUpdates(); + delete geoPositionInfoSource_; + } + + geoPositionInfoSource_ = positionSource; + + if (!uuids_.empty()) + { + positionSource->startUpdates(); + } +} + void PositionManager::EnablePositionUpdates(boost::uuids::uuid uuid, bool enabled) { + std::unique_lock lock {p->positionSourceMutex_}; + if (p->geoPositionInfoSource_ == nullptr) { return;