// Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include #include #include #include #include QT_USE_NAMESPACE using namespace Qt::StringLiterals; class SatelliteSource : public QGeoSatelliteInfoSource { Q_OBJECT public: SatelliteSource(const QVariantMap ¶meters, QObject *parent=0); ~SatelliteSource(); void startUpdates() override; void stopUpdates() override; void requestUpdate(int timeout = 5000) override; void setUpdateInterval(int msec) override; int minimumUpdateInterval() const override; Error error() const override; bool setBackendProperty(const QString &name, const QVariant &value) override; QVariant backendProperty(const QString &name) const override; private slots: void doTimeout(); void updateSatelliteInfo(); private: QTimer *timer; QTimer *timeoutTimer; QTimer *singleUpdateTimer; Error lastError = QGeoSatelliteInfoSource::NoError; QList satellitesInView; QList satellitesInUse; qsizetype desiredInViewCount = 5; qsizetype desiredInUseCount = 3; bool useElevation = false; bool useAzimuth = false; QGeoSatelliteInfo::SatelliteSystem desiredSystem = QGeoSatelliteInfo::GPS; }; SatelliteSource::SatelliteSource(const QVariantMap ¶meters, QObject *parent) : QGeoSatelliteInfoSource(parent), timer(new QTimer(this)), timeoutTimer(new QTimer(this)), singleUpdateTimer(new QTimer(this)) { QVariant systemType = parameters.value("satellitesystem"_L1, QVariant()); if (systemType.isValid()) desiredSystem = systemType.value(); timer->setInterval(200); connect(timer, &QTimer::timeout, this, &SatelliteSource::updateSatelliteInfo); connect(singleUpdateTimer, &QTimer::timeout, this, &SatelliteSource::updateSatelliteInfo); connect(timeoutTimer, &QTimer::timeout, this, &SatelliteSource::doTimeout); } SatelliteSource::~SatelliteSource() { } QGeoSatelliteInfoSource::Error SatelliteSource::error() const { return lastError; } bool SatelliteSource::setBackendProperty(const QString &name, const QVariant &value) { if (name == "desiredInViewCount"_L1) desiredInViewCount = value.value(); else if (name == "desiredInUseCount"_L1) desiredInUseCount = value.value(); else if (name == "useElevation"_L1) useElevation = value.toBool(); else if (name == "useAzimuth"_L1) useAzimuth = value.toBool(); else return false; return true; } QVariant SatelliteSource::backendProperty(const QString &name) const { if (name == "desiredInViewCount"_L1) return desiredInViewCount; else if (name == "desiredInUseCount"_L1) return desiredInUseCount; else if (name == "useElevation"_L1) return useElevation; else if (name == "useAzimuth"_L1) return useAzimuth; return {}; } void SatelliteSource::setUpdateInterval(int msec) { const int minInterval = minimumUpdateInterval(); if (msec == 0) { timer->setInterval(minInterval); } else if (msec < minInterval) { msec = minInterval; timer->setInterval(msec); } else { timer->setInterval(msec); } QGeoSatelliteInfoSource::setUpdateInterval(msec); } int SatelliteSource::minimumUpdateInterval() const { return 200; } void SatelliteSource::startUpdates() { lastError = QGeoSatelliteInfoSource::NoError; timer->start(); } void SatelliteSource::stopUpdates() { timer->stop(); } void SatelliteSource::requestUpdate(int timeout) { if (timeoutTimer->isActive()) return; // already requested an update lastError = QGeoSatelliteInfoSource::NoError; // Such logic for timeout handling is needed for tst_qgeosatelliteinfosource. // It expects an immediate error in case of negative timeout. if (timeout == 0) timeout = 5000; if (timeout < 0) timeout = 0; timeoutTimer->setInterval(timeout); timeoutTimer->start(); if (timer->isActive()) { timer->stop(); timer->start(); } singleUpdateTimer->start(minimumUpdateInterval()); } void SatelliteSource::doTimeout() { timeoutTimer->stop(); singleUpdateTimer->stop(); lastError = QGeoSatelliteInfoSource::UpdateTimeoutError; emit errorOccurred(lastError); } void SatelliteSource::updateSatelliteInfo() { timeoutTimer->stop(); singleUpdateTimer->stop(); if (desiredInUseCount > desiredInViewCount) desiredInUseCount = desiredInViewCount; satellitesInView.clear(); satellitesInUse.clear(); for (qsizetype i = 0; i < desiredInViewCount; ++i) { QGeoSatelliteInfo si; si.setSatelliteSystem(desiredSystem); si.setSatelliteIdentifier(i + 1); si.setSignalStrength(5 * (i + 1)); if (useElevation) si.setAttribute(QGeoSatelliteInfo::Elevation, 3.0 * (i + 1)); if (useAzimuth) si.setAttribute(QGeoSatelliteInfo::Azimuth, 0.5 * (i + 1)); satellitesInView.push_back(si); if (i < desiredInUseCount) satellitesInUse.push_back(si); } emit satellitesInViewUpdated(satellitesInView); emit satellitesInUseUpdated(satellitesInUse); } class QGeoPositionInfoSourceFactoryTest : public QObject, public QGeoPositionInfoSourceFactory { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.qt.position.sourcefactory/6.0" FILE "plugin.json") Q_INTERFACES(QGeoPositionInfoSourceFactory) public: QGeoPositionInfoSource *positionInfoSource(QObject *parent, const QVariantMap ¶meters) override; QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent, const QVariantMap ¶meters) override; QGeoAreaMonitorSource *areaMonitor(QObject *parent, const QVariantMap ¶meters) override; }; QGeoPositionInfoSource * QGeoPositionInfoSourceFactoryTest::positionInfoSource(QObject *parent, const QVariantMap ¶meters) { Q_UNUSED(parent); Q_UNUSED(parameters); return nullptr; } QGeoSatelliteInfoSource * QGeoPositionInfoSourceFactoryTest::satelliteInfoSource(QObject *parent, const QVariantMap ¶meters) { return new SatelliteSource(parameters, parent); } QGeoAreaMonitorSource * QGeoPositionInfoSourceFactoryTest::areaMonitor(QObject *parent, const QVariantMap ¶meters) { Q_UNUSED(parent); Q_UNUSED(parameters); return nullptr; } #include "plugin.moc"