Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qohosgeosatelliteinfosource.cpp
Go to the documentation of this file.
1// Copyright (C) 2025 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
6#include "qohosenums.h"
8#include <QtCore/private/qcore_ohos_p.h>
9#include <QtCore/private/qnapi_p.h>
10#include <QtCore/private/qohoscommon_p.h>
11#include <QtCore/private/qohosjstools_p.h>
12#include <QtCore/private/qohoslogger_p.h>
13#include <QtCore/qset.h>
14#include <QtCore/qmath.h>
15#include <QtPositioning/qgeosatelliteinfo.h>
16#include <algorithm>
17#include <chrono>
18#include <memory>
19#include <optional>
20#include <utility>
21#include <vector>
22
23QT_BEGIN_NAMESPACE
24
25namespace {
26
28
31
41
44 QOhosJsState &jsState, QNapi::Object satelliteStatusInfoObject)
45{
46 auto satelliteConstellationArray = QNapi::getOptionalPropOrEmpty<QNapi::Array>(
47 satelliteStatusInfoObject, "satelliteConstellation");
48
49 return !satelliteConstellationArray.IsEmpty()
50 ? std::make_optional(
51 QNapi::getArrayElements<std::vector<SatelliteConstellationCategory>, QNapi::Number>(
52 satelliteConstellationArray,
53 [&](auto satelliteConstellation) {
54 return jsState.mapOhosEnumFromJs<SatelliteConstellationCategory>(satelliteConstellation);
55 }))
56 : std::nullopt;
57}
58
60 QOhosJsState &, QNapi::Object satelliteStatusInfoObject)
61{
62 auto satelliteAdditionalInfoArray = QNapi::getOptionalPropOrEmpty<QNapi::Array>(
63 satelliteStatusInfoObject, "satelliteAdditionalInfo");
64
65 return !satelliteAdditionalInfoArray.IsEmpty()
66 ? std::make_optional(
67 QNapi::getArrayElements<std::vector<int>, QNapi::Number>(satelliteAdditionalInfoArray))
68 : std::nullopt;
69}
70
71bool isSatelliteUsedInFix(QOhosJsState &jsState, int satelliteAdditionalInfo)
72{
73 int satelliteUsedInValueFlag = jsState.eval<QNapi::Number>(
74 "@ohos.geoLocationManager.SatelliteAdditionalInfo.SATELLITES_ADDITIONAL_INFO_USED_IN_FIX");
75
76 return (satelliteAdditionalInfo & satelliteUsedInValueFlag) != 0;
77}
78
80 QOhosJsState &jsState, QNapi::Object satelliteStatusInfoObject)
81{
82 int satellitesNumber = satelliteStatusInfoObject.get<QNapi::Number>("satellitesNumber");
83 auto satelliteIds = QNapi::getArrayElements<std::vector<int>, QNapi::Number>(
84 satelliteStatusInfoObject.get<QNapi::Array>("satelliteIds"));
85 auto carrierToNoiseDensities = QNapi::getArrayElements<std::vector<double>, QNapi::Number>(
86 satelliteStatusInfoObject.get<QNapi::Array>("carrierToNoiseDensitys"));
87 auto altitudes = QNapi::getArrayElements<std::vector<double>, QNapi::Number>(
88 satelliteStatusInfoObject.get<QNapi::Array>("altitudes"));
89 auto azimuths = QNapi::getArrayElements<std::vector<double>, QNapi::Number>(
90 satelliteStatusInfoObject.get<QNapi::Array>("azimuths"));
91 auto satelliteConstellations = tryGetSatelliteConstelationCategoriesFromSatelliteStatusInfoObject(
92 jsState, satelliteStatusInfoObject);
93 auto satelliteAdditionalInfos = tryGetSatelliteAdditionalInfosFromSatelliteStatusInfoObject(
94 jsState, satelliteStatusInfoObject);
95
96 std::vector<SatelliteInfo> satelliteInfos;
97 satelliteInfos.reserve(satellitesNumber);
98
99 for (int i = 0; i < satellitesNumber; i++) {
100 satelliteInfos.push_back(SatelliteInfo{
101 .id = satelliteIds[i],
102 .carrierToNoiseDensity = carrierToNoiseDensities[i],
103 .altitude = altitudes[i],
104 .azimuth = azimuths[i],
105 .optConstellationCategory = satelliteConstellations.has_value()
106 ? std::make_optional(satelliteConstellations.value()[i])
107 : std::nullopt,
108 .usedInFix = satelliteAdditionalInfos.has_value()
109 ? isSatelliteUsedInFix(jsState, satelliteAdditionalInfos.value()[i])
110 : false
111 });
112 }
113
114 return satelliteInfos;
115}
116
118 SatelliteConstellationCategory constellationCategory)
119{
120 switch (constellationCategory) {
121 case SatelliteConstellationCategory::CONSTELLATION_CATEGORY_UNKNOWN:
122 return QGeoSatelliteInfo::Undefined;
123 case SatelliteConstellationCategory::CONSTELLATION_CATEGORY_GPS:
124 return QGeoSatelliteInfo::GPS;
125 case SatelliteConstellationCategory::CONSTELLATION_CATEGORY_GLONASS:
126 return QGeoSatelliteInfo::GLONASS;
127 case SatelliteConstellationCategory::CONSTELLATION_CATEGORY_SBAS:
128 return QGeoSatelliteInfo::SBAS;
129 case SatelliteConstellationCategory::CONSTELLATION_CATEGORY_QZSS:
130 return QGeoSatelliteInfo::QZSS;
131 case SatelliteConstellationCategory::CONSTELLATION_CATEGORY_BEIDOU:
132 return QGeoSatelliteInfo::BEIDOU;
133 case SatelliteConstellationCategory::CONSTELLATION_CATEGORY_GALILEO:
134 return QGeoSatelliteInfo::GALILEO;
135 case SatelliteConstellationCategory::CONSTELLATION_CATEGORY_IRNSS:
136 return QGeoSatelliteInfo::IRNSS;
137 }
138
139 qOhosReportFatalErrorAndAbort(
140 "%s Received an unknown SatelliteConstellationCategory: %d",
141 Q_FUNC_INFO, constellationCategory);
142}
143
145 QObject *contextObject, QOhosConsumer<std::vector<SatelliteInfo>> satelliteStatusInfoConsumer)
146{
147 qOhosDebug(QtForOhos) << Q_FUNC_INFO << contextObject;
148
149 auto contextObjectRef = QtOhos::makeQThreadSafeRef(contextObject);
150 auto sharedSatelliteStatusInfoConsumer =
151 QtOhos::moveToSharedPtr(std::move(satelliteStatusInfoConsumer));
152 auto weakSatelliteStatusInfoConsumer = QtOhos::makeWeakPtr(sharedSatelliteStatusInfoConsumer);
153
154 auto registrationHandle = QOhosJsThreadGateway::eval(
155 [&](QOhosJsState &jsState) {
156 return QtOhos::makeProxyWithJsThreadDeleter(
157 registerQOhosOnOffMethodsBasedEventHandler(
158 getGeoLocationManagerObject(jsState), "satelliteStatusChange",
159 [contextObjectRef, weakSatelliteStatusInfoConsumer](const QOhosCallbackInfo &cbInfo) {
160 auto satelliteStatusInfo = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
161 auto satelliteInfos = convertJsSatelliteStatusInfoObjectToQGeoSatelliteInfos(
162 cbInfo.jsState(), satelliteStatusInfo);
163 contextObjectRef.visitInQtThreadIfAlive(
164 [weakSatelliteStatusInfoConsumer, satelliteInfos](auto &) {
165 auto sharedSatelliteStatusInfoConsumer = weakSatelliteStatusInfoConsumer.lock();
166 if (sharedSatelliteStatusInfoConsumer)
167 (*sharedSatelliteStatusInfoConsumer)(satelliteInfos);
168 });
169 }));
170 });
171
172 return QtOhos::moveToSharedPtr(
173 std::make_pair(registrationHandle, sharedSatelliteStatusInfoConsumer));
174}
175
177{
178public:
181
184 Error error() const override;
185
186public:
189
190 void requestUpdate(int timeout) override;
191
192private:
193 enum UpdateType
194 {
195 SingleUpdate,
196 ContinuousUpdate,
197 };
198
199 void startUpdatesHelper();
200 void setErrorHelper(Error error);
201
202 void handleSatelliteStatusInfoUpdate(std::vector<SatelliteInfo> updatedSatelliteStatusInfo);
203 void handleSingleUpdateFinished();
204 void handleUpdateFinished();
205
206 QSet<UpdateType> m_updateTypes;
207 std::shared_ptr<void> m_updateSatelliteStatusInfoProducerHandle;
208 std::unique_ptr<QGeoPositionInfoSource> m_positionInfoSource;
209
210 std::unique_ptr<QTimer> m_singleUpdateTimeoutTimer;
211
212 std::optional<QList<QGeoSatelliteInfo>> m_lastUpdatedSatellitesInView;
213 std::optional<QList<QGeoSatelliteInfo>> m_lastUpdatedSatellitesInUse;
214
215 QGeoSatelliteInfoSource::Error m_error = QGeoSatelliteInfoSource::NoError;
216};
217
220{
221 qOhosDebug(QtForOhos) << Q_FUNC_INFO;
222}
223
225
227{
228 qOhosDebug(QtForOhos) << Q_FUNC_INFO << msec;
229
230 if (msec != updateAsOftenAsNecessaryInterval)
231 qOhosWarning(QtForOhos) << Q_FUNC_INFO << "Specific update intervals are not supported";
232}
233
235{
236 qOhosDebug(QtForOhos) << Q_FUNC_INFO;
237
239}
240
242{
243 qOhosDebug(QtForOhos) << Q_FUNC_INFO;
244
245 return m_error;
246}
247
249{
250 qOhosDebug(QtForOhos) << Q_FUNC_INFO;
251
253 qOhosWarning(QtForOhos) << Q_FUNC_INFO << "Location permission not granted. Can't start updates";
254 setErrorHelper(QGeoSatelliteInfoSource::AccessError);
255 return;
256 }
257
258 if (m_updateTypes.contains(UpdateType::ContinuousUpdate))
259 return;
260
261 m_updateTypes.insert(UpdateType::ContinuousUpdate);
262
263 if (!m_updateSatelliteStatusInfoProducerHandle && !m_positionInfoSource)
264 startUpdatesHelper();
265}
266
268{
269 qOhosDebug(QtForOhos) << Q_FUNC_INFO;
270
271 m_updateTypes.remove(UpdateType::ContinuousUpdate);
272
273 handleUpdateFinished();
274}
275
277{
278 qOhosDebug(QtForOhos) << Q_FUNC_INFO << timeout;
279
281 qOhosWarning(QtForOhos) << Q_FUNC_INFO << "Location permission not granted. Can't request update";
282 setErrorHelper(QGeoSatelliteInfoSource::AccessError);
283 return;
284 }
285
286 if (m_updateTypes.contains(UpdateType::SingleUpdate))
287 return;
288
289 m_updateTypes.insert(UpdateType::SingleUpdate);
290
291 if (!m_updateSatelliteStatusInfoProducerHandle && !m_positionInfoSource)
292 startUpdatesHelper();
293
294 m_singleUpdateTimeoutTimer = makeSingleShotUpdateTimeoutTimer(
295 timeout, [this]() {
296 if (m_lastUpdatedSatellitesInUse.has_value() && m_lastUpdatedSatellitesInView.has_value()) {
297 Q_EMIT satellitesInUseUpdated(m_lastUpdatedSatellitesInUse.value());
298 Q_EMIT satellitesInViewUpdated(m_lastUpdatedSatellitesInView.value());
299 } else {
300 Q_EMIT errorOccurred(QGeoSatelliteInfoSource::UpdateTimeoutError);
301 }
302
303 handleSingleUpdateFinished();
304 });
305}
306
307void QOhosGeoSatelliteInfoSource::startUpdatesHelper()
308{
309 qOhosDebug(QtForOhos) << Q_FUNC_INFO;
310
311 m_updateSatelliteStatusInfoProducerHandle =
312 registerSatelliteStatusInfoProducerConsumer(
313 this, [this](auto updatedSatelliteInfos) {
314 handleSatelliteStatusInfoUpdate(updatedSatelliteInfos);
315 });
316
317 m_positionInfoSource = std::unique_ptr<QGeoPositionInfoSource>(tryMakeQOhosGeoPositionInfoSource());
318 if (!m_positionInfoSource)
319 qOhosReportFatalErrorAndAbort("%s positionInfoSource is invalid", Q_FUNC_INFO);
320
321 m_positionInfoSource->setPreferredPositioningMethods(QGeoPositionInfoSource::SatellitePositioningMethods);
322 m_positionInfoSource->startUpdates();
323}
324
325void QOhosGeoSatelliteInfoSource::setErrorHelper(Error error)
326{
327 qOhosWarning(QtForOhos) << Q_FUNC_INFO << error;
328
329 if (m_error == error)
330 return;
331
332 m_error = error;
333
334 if (error != QGeoSatelliteInfoSource::NoError)
335 Q_EMIT QGeoSatelliteInfoSource::errorOccurred(m_error);
336}
337
338void QOhosGeoSatelliteInfoSource::handleSatelliteStatusInfoUpdate(
339 std::vector<SatelliteInfo> updatedSatellites)
340{
341 qOhosDebug(QtForOhos) << Q_FUNC_INFO << "found" << updatedSatellites.size() << "satellites";
342
343 QList<QGeoSatelliteInfo> satellitesInView;
344 QList<QGeoSatelliteInfo> satellitesInUse;
345
346 QSet<std::pair<int, int>> seenIds;
347
348 for (const auto &updatedSatellite : updatedSatellites) {
349 if (qFuzzyIsNull(updatedSatellite.carrierToNoiseDensity))
350 continue;
351
352 QGeoSatelliteInfo satelliteInfo;
353 satelliteInfo.setSatelliteIdentifier(updatedSatellite.id);
354 satelliteInfo.setSatelliteSystem(
355 updatedSatellite.optConstellationCategory.has_value()
356 ? convertSatelliteConstellationCategoryToQt(updatedSatellite.optConstellationCategory.value())
357 : QGeoSatelliteInfo::SatelliteSystem::Undefined);
358 satelliteInfo.setSignalStrength(updatedSatellite.carrierToNoiseDensity);
359 satelliteInfo.setAttribute(QGeoSatelliteInfo::Azimuth, updatedSatellite.azimuth);
360 satelliteInfo.setAttribute(QGeoSatelliteInfo::Elevation, updatedSatellite.altitude);
361
362 const auto uid = std::make_pair(static_cast<int>(satelliteInfo.satelliteSystem()),
363 satelliteInfo.satelliteIdentifier());
364 if (seenIds.contains(uid))
365 continue;
366 seenIds.insert(uid);
367
368 satellitesInView.append(satelliteInfo);
369 if (updatedSatellite.usedInFix)
370 satellitesInUse.append(satelliteInfo);
371 }
372
373 Q_EMIT satellitesInUseUpdated(satellitesInUse);
374 Q_EMIT satellitesInViewUpdated(satellitesInView);
375
376 m_lastUpdatedSatellitesInView = satellitesInView;
377 m_lastUpdatedSatellitesInUse = satellitesInUse;
378
379 if (m_updateTypes.contains(UpdateType::SingleUpdate))
380 handleSingleUpdateFinished();
381}
382
383void QOhosGeoSatelliteInfoSource::handleSingleUpdateFinished()
384{
385 m_updateTypes.remove(UpdateType::SingleUpdate);
386
387 m_singleUpdateTimeoutTimer.reset();
388
389 handleUpdateFinished();
390}
391
392void QOhosGeoSatelliteInfoSource::handleUpdateFinished()
393{
394 if (m_updateTypes.empty()) {
395 m_positionInfoSource.reset();
396 m_updateSatelliteStatusInfoProducerHandle.reset();
397 m_lastUpdatedSatellitesInView.reset();
398 m_lastUpdatedSatellitesInUse.reset();
399 }
400}
401
402}
403
408
409QT_END_NAMESPACE
Error error() const override
Returns the last error that occurred.
void requestUpdate(int timeout) override
Attempts to get the current satellite information and emit satellitesInViewUpdated() and satellitesIn...
void startUpdates() override
Starts emitting updates at regular intervals.
void stopUpdates() override
Stops emitting updates at regular intervals.
bool isSatelliteUsedInFix(QOhosJsState &jsState, int satelliteAdditionalInfo)
QGeoSatelliteInfo::SatelliteSystem convertSatelliteConstellationCategoryToQt(SatelliteConstellationCategory constellationCategory)
std::shared_ptr< void > registerSatelliteStatusInfoProducerConsumer(QObject *contextObject, QOhosConsumer< std::vector< SatelliteInfo > > satelliteStatusInfoConsumer)
std::optional< std::vector< int > > tryGetSatelliteAdditionalInfosFromSatelliteStatusInfoObject(QOhosJsState &, QNapi::Object satelliteStatusInfoObject)
QtOhos::enums::ohos::geoLocationManager::SatelliteConstellationCategory SatelliteConstellationCategory
std::vector< SatelliteInfo > convertJsSatelliteStatusInfoObjectToQGeoSatelliteInfos(QOhosJsState &jsState, QNapi::Object satelliteStatusInfoObject)
std::optional< std::vector< SatelliteConstellationCategory > > tryGetSatelliteConstelationCategoriesFromSatelliteStatusInfoObject(QOhosJsState &jsState, QNapi::Object satelliteStatusInfoObject)
QGeoSatelliteInfoSource * makeQOhosGeoSatelliteInfoSource(QObject *parent)
bool checkLocationOrApproximatelyLocationPermissionGranted()
std::optional< SatelliteConstellationCategory > optConstellationCategory