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
7#include "qohosjsutils.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/qohoslogger_p.h>
12#include <QtCore/qset.h>
13#include <QtCore/qmath.h>
14#include <QtPositioning/qgeosatelliteinfo.h>
15#include <algorithm>
16#include <chrono>
17#include <memory>
18#include <optional>
19#include <utility>
20#include <vector>
21
22QT_BEGIN_NAMESPACE
23
24namespace {
25
27
39
49
52 QOhosJsState &jsState, QNapi::Object satelliteStatusInfoObject)
53{
54 auto satelliteConstellationArray = QNapi::getOptionalPropOrEmpty<QNapi::Array>(
55 satelliteStatusInfoObject, "satelliteConstellation");
56
57 return !satelliteConstellationArray.IsEmpty()
58 ? std::make_optional(
59 QNapi::getArrayElements<std::vector<SatelliteConstellationCategory>, QNapi::Number>(
60 satelliteConstellationArray,
61 [&](auto satelliteConstellation) {
62 return jsState.mapOhosEnumFromJs<SatelliteConstellationCategory>(satelliteConstellation);
63 }))
64 : std::nullopt;
65}
66
68 QOhosJsState &, QNapi::Object satelliteStatusInfoObject)
69{
70 auto satelliteAdditionalInfoArray = QNapi::getOptionalPropOrEmpty<QNapi::Array>(
71 satelliteStatusInfoObject, "satelliteAdditionalInfo");
72
73 return !satelliteAdditionalInfoArray.IsEmpty()
74 ? std::make_optional(
75 QNapi::getArrayElements<std::vector<int>, QNapi::Number>(satelliteAdditionalInfoArray))
76 : std::nullopt;
77}
78
79bool isSatelliteUsedInFix(QOhosJsState &jsState, int satelliteAdditionalInfo)
80{
81 int satelliteUsedInValueFlag = jsState.eval<QNapi::Number>(
82 "@ohos.geoLocationManager.SatelliteAdditionalInfo.SATELLITES_ADDITIONAL_INFO_USED_IN_FIX");
83
84 return (satelliteAdditionalInfo & satelliteUsedInValueFlag) != 0;
85}
86
88 QOhosJsState &jsState, QNapi::Object satelliteStatusInfoObject)
89{
90 int satellitesNumber = satelliteStatusInfoObject.get<QNapi::Number>("satellitesNumber");
91 auto satelliteIds = QNapi::getArrayElements<std::vector<int>, QNapi::Number>(
92 satelliteStatusInfoObject.get<QNapi::Array>("satelliteIds"));
93 auto carrierToNoiseDensities = QNapi::getArrayElements<std::vector<double>, QNapi::Number>(
94 satelliteStatusInfoObject.get<QNapi::Array>("carrierToNoiseDensitys"));
95 auto altitudes = QNapi::getArrayElements<std::vector<double>, QNapi::Number>(
96 satelliteStatusInfoObject.get<QNapi::Array>("altitudes"));
97 auto azimuths = QNapi::getArrayElements<std::vector<double>, QNapi::Number>(
98 satelliteStatusInfoObject.get<QNapi::Array>("azimuths"));
99 auto satelliteConstellations = tryGetSatelliteConstelationCategoriesFromSatelliteStatusInfoObject(
100 jsState, satelliteStatusInfoObject);
101 auto satelliteAdditionalInfos = tryGetSatelliteAdditionalInfosFromSatelliteStatusInfoObject(
102 jsState, satelliteStatusInfoObject);
103
104 std::vector<SatelliteInfo> satelliteInfos;
105 satelliteInfos.reserve(satellitesNumber);
106
107 for (int i = 0; i < satellitesNumber; i++) {
108 satelliteInfos.push_back(SatelliteInfo{
109 .id = satelliteIds[i],
110 .carrierToNoiseDensity = carrierToNoiseDensities[i],
111 .altitude = altitudes[i],
112 .azimuth = azimuths[i],
113 .optConstellationCategory = satelliteConstellations.has_value()
114 ? std::make_optional(satelliteConstellations.value()[i])
115 : std::nullopt,
116 .usedInFix = satelliteAdditionalInfos.has_value()
117 ? isSatelliteUsedInFix(jsState, satelliteAdditionalInfos.value()[i])
118 : false
119 });
120 }
121
122 return satelliteInfos;
123}
124
126 SatelliteConstellationCategory constellationCategory)
127{
128 switch (constellationCategory) {
129 case SatelliteConstellationCategory::CONSTELLATION_CATEGORY_UNKNOWN:
130 return QGeoSatelliteInfo::Undefined;
131 case SatelliteConstellationCategory::CONSTELLATION_CATEGORY_GPS:
132 return QGeoSatelliteInfo::GPS;
133 case SatelliteConstellationCategory::CONSTELLATION_CATEGORY_GLONASS:
134 return QGeoSatelliteInfo::GLONASS;
135 case SatelliteConstellationCategory::CONSTELLATION_CATEGORY_SBAS:
136 return QGeoSatelliteInfo::SBAS;
137 case SatelliteConstellationCategory::CONSTELLATION_CATEGORY_QZSS:
138 return QGeoSatelliteInfo::QZSS;
139 case SatelliteConstellationCategory::CONSTELLATION_CATEGORY_BEIDOU:
140 return QGeoSatelliteInfo::BEIDOU;
141 case SatelliteConstellationCategory::CONSTELLATION_CATEGORY_GALILEO:
142 return QGeoSatelliteInfo::GALILEO;
143 case SatelliteConstellationCategory::CONSTELLATION_CATEGORY_IRNSS:
144 return QGeoSatelliteInfo::IRNSS;
145 }
146
147 qOhosReportFatalErrorAndAbort(
148 "%s Received an unknown SatelliteConstellationCategory: %d",
149 Q_FUNC_INFO, constellationCategory);
150}
151
153 QObject *contextObject, QOhosConsumer<std::vector<SatelliteInfo>> satelliteStatusInfoConsumer)
154{
155 qOhosDebug(QtForOhos) << Q_FUNC_INFO << contextObject;
156
157 auto contextObjectRef = QtOhos::makeQThreadSafeRef(contextObject);
158 auto sharedSatelliteStatusInfoConsumer =
159 QtOhos::moveToSharedPtr(std::move(satelliteStatusInfoConsumer));
160 auto weakSatelliteStatusInfoConsumer = QtOhos::makeWeakPtr(sharedSatelliteStatusInfoConsumer);
161
162 auto registrationHandle = QOhosJsThreadGateway::eval(
163 [&](QOhosJsState &jsState) {
164 return QtOhos::registerOnOffMethodsBasedEventHandler(
165 getGeoLocationManagerObject(jsState), "satelliteStatusChange",
166 [contextObjectRef, weakSatelliteStatusInfoConsumer](const QOhosCallbackInfo &cbInfo) {
167 auto satelliteStatusInfo = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
168 auto satelliteInfos = convertJsSatelliteStatusInfoObjectToQGeoSatelliteInfos(
169 cbInfo.jsState(), satelliteStatusInfo);
170 contextObjectRef.visitInQtThreadIfAlive(
171 [weakSatelliteStatusInfoConsumer, satelliteInfos](auto &) {
172 auto sharedSatelliteStatusInfoConsumer = weakSatelliteStatusInfoConsumer.lock();
173 if (sharedSatelliteStatusInfoConsumer)
174 (*sharedSatelliteStatusInfoConsumer)(satelliteInfos);
175 });
176 });
177 });
178
179 return QtOhos::moveToSharedPtr(
180 std::make_pair(registrationHandle, sharedSatelliteStatusInfoConsumer));
181}
182
184{
185public:
188
191 Error error() const override;
192
193public:
196
197 void requestUpdate(int timeout) override;
198
199private:
200 enum UpdateType
201 {
202 SingleUpdate,
203 ContinuousUpdate,
204 };
205
206 void startUpdatesHelper();
207 void setErrorHelper(Error error);
208
209 void handleSatelliteStatusInfoUpdate(std::vector<SatelliteInfo> updatedSatelliteStatusInfo);
210 void handleSingleUpdateFinished();
211 void handleUpdateFinished();
212
213 QSet<UpdateType> m_updateTypes;
214 std::shared_ptr<void> m_updateSatelliteStatusInfoProducerHandle;
215 std::unique_ptr<QGeoPositionInfoSource> m_positionInfoSource;
216
217 std::unique_ptr<QTimer> m_singleUpdateTimeoutTimer;
218
219 std::optional<QList<QGeoSatelliteInfo>> m_lastUpdatedSatellitesInView;
220 std::optional<QList<QGeoSatelliteInfo>> m_lastUpdatedSatellitesInUse;
221
222 QGeoSatelliteInfoSource::Error m_error = QGeoSatelliteInfoSource::NoError;
223};
224
227{
228 qOhosDebug(QtForOhos) << Q_FUNC_INFO;
229}
230
232
234{
235 qOhosDebug(QtForOhos) << Q_FUNC_INFO << msec;
236
237 if (msec != updateAsOftenAsNecessaryInterval)
238 qOhosWarning(QtForOhos) << Q_FUNC_INFO << "Specific update intervals are not supported";
239}
240
242{
243 qOhosDebug(QtForOhos) << Q_FUNC_INFO;
244
246}
247
249{
250 qOhosDebug(QtForOhos) << Q_FUNC_INFO;
251
252 return m_error;
253}
254
256{
257 qOhosDebug(QtForOhos) << Q_FUNC_INFO;
258
260 qOhosWarning(QtForOhos) << Q_FUNC_INFO << "Location permission not granted. Can't start updates";
261 setErrorHelper(QGeoSatelliteInfoSource::AccessError);
262 return;
263 }
264
265 if (m_updateTypes.contains(UpdateType::ContinuousUpdate))
266 return;
267
268 m_updateTypes.insert(UpdateType::ContinuousUpdate);
269
270 if (!m_updateSatelliteStatusInfoProducerHandle && !m_positionInfoSource)
271 startUpdatesHelper();
272}
273
275{
276 qOhosDebug(QtForOhos) << Q_FUNC_INFO;
277
278 m_updateTypes.remove(UpdateType::ContinuousUpdate);
279
280 handleUpdateFinished();
281}
282
284{
285 qOhosDebug(QtForOhos) << Q_FUNC_INFO << timeout;
286
288 qOhosWarning(QtForOhos) << Q_FUNC_INFO << "Location permission not granted. Can't request update";
289 setErrorHelper(QGeoSatelliteInfoSource::AccessError);
290 return;
291 }
292
293 if (m_updateTypes.contains(UpdateType::SingleUpdate))
294 return;
295
296 m_updateTypes.insert(UpdateType::SingleUpdate);
297
298 if (!m_updateSatelliteStatusInfoProducerHandle && !m_positionInfoSource)
299 startUpdatesHelper();
300
301 m_singleUpdateTimeoutTimer = makeSingleShotUpdateTimeoutTimer(
302 timeout, [this]() {
303 if (m_lastUpdatedSatellitesInUse.has_value() && m_lastUpdatedSatellitesInView.has_value()) {
304 Q_EMIT satellitesInUseUpdated(m_lastUpdatedSatellitesInUse.value());
305 Q_EMIT satellitesInViewUpdated(m_lastUpdatedSatellitesInView.value());
306 } else {
307 Q_EMIT errorOccurred(QGeoSatelliteInfoSource::UpdateTimeoutError);
308 }
309
310 handleSingleUpdateFinished();
311 });
312}
313
314void QOhosGeoSatelliteInfoSource::startUpdatesHelper()
315{
316 qOhosDebug(QtForOhos) << Q_FUNC_INFO;
317
318 m_updateSatelliteStatusInfoProducerHandle =
319 registerSatelliteStatusInfoProducerConsumer(
320 this, [this](auto updatedSatelliteInfos) {
321 handleSatelliteStatusInfoUpdate(updatedSatelliteInfos);
322 });
323
324 m_positionInfoSource = std::unique_ptr<QGeoPositionInfoSource>(tryMakeQOhosGeoPositionInfoSource());
325 if (!m_positionInfoSource)
326 qOhosReportFatalErrorAndAbort("%s positionInfoSource is invalid", Q_FUNC_INFO);
327
328 m_positionInfoSource->setPreferredPositioningMethods(QGeoPositionInfoSource::SatellitePositioningMethods);
329 m_positionInfoSource->startUpdates();
330}
331
332void QOhosGeoSatelliteInfoSource::setErrorHelper(Error error)
333{
334 qOhosWarning(QtForOhos) << Q_FUNC_INFO << error;
335
336 if (m_error == error)
337 return;
338
339 m_error = error;
340
341 if (error != QGeoSatelliteInfoSource::NoError)
342 Q_EMIT QGeoSatelliteInfoSource::errorOccurred(m_error);
343}
344
345void QOhosGeoSatelliteInfoSource::handleSatelliteStatusInfoUpdate(
346 std::vector<SatelliteInfo> updatedSatellites)
347{
348 qOhosDebug(QtForOhos) << Q_FUNC_INFO << "found" << updatedSatellites.size() << "satellites";
349
350 QList<QGeoSatelliteInfo> satellitesInView;
351 QList<QGeoSatelliteInfo> satellitesInUse;
352
353 for (const auto &updatedSatellite : updatedSatellites) {
354 if (qFuzzyIsNull(updatedSatellite.carrierToNoiseDensity))
355 continue;
356
357 QGeoSatelliteInfo satelliteInfo;
358 satelliteInfo.setSatelliteIdentifier(updatedSatellite.id);
359 satelliteInfo.setSatelliteSystem(
360 updatedSatellite.optConstellationCategory.has_value()
361 ? convertSatelliteConstellationCategoryToQt(updatedSatellite.optConstellationCategory.value())
362 : QGeoSatelliteInfo::SatelliteSystem::Undefined);
363 satelliteInfo.setSignalStrength(updatedSatellite.carrierToNoiseDensity);
364 satelliteInfo.setAttribute(QGeoSatelliteInfo::Azimuth, updatedSatellite.azimuth);
365 satelliteInfo.setAttribute(QGeoSatelliteInfo::Elevation, updatedSatellite.altitude);
366
367 satellitesInView.append(satelliteInfo);
368 if (updatedSatellite.usedInFix)
369 satellitesInUse.append(satelliteInfo);
370 }
371
372 Q_EMIT satellitesInUseUpdated(satellitesInUse);
373 Q_EMIT satellitesInViewUpdated(satellitesInView);
374
375 m_lastUpdatedSatellitesInView = satellitesInView;
376 m_lastUpdatedSatellitesInUse = satellitesInUse;
377
378 if (m_updateTypes.contains(UpdateType::SingleUpdate))
379 handleSingleUpdateFinished();
380}
381
382void QOhosGeoSatelliteInfoSource::handleSingleUpdateFinished()
383{
384 m_updateTypes.remove(UpdateType::SingleUpdate);
385
386 m_singleUpdateTimeoutTimer.reset();
387
388 handleUpdateFinished();
389}
390
391void QOhosGeoSatelliteInfoSource::handleUpdateFinished()
392{
393 if (m_updateTypes.empty()) {
394 m_positionInfoSource.reset();
395 m_updateSatelliteStatusInfoProducerHandle.reset();
396 m_lastUpdatedSatellitesInView.reset();
397 m_lastUpdatedSatellitesInUse.reset();
398 }
399}
400
401}
402
407
408namespace QtOhos {
409
410template<>
412{
413 static constexpr const char *fullTypeName = "@ohos.geoLocationManager.SatelliteConstellationCategory";
414 static constexpr std::array<std::pair<SatelliteConstellationCategory, const char *>, 8> enumeratorsNames = {{
415 {SatelliteConstellationCategory::CONSTELLATION_CATEGORY_UNKNOWN, "CONSTELLATION_CATEGORY_UNKNOWN"},
418 {SatelliteConstellationCategory::CONSTELLATION_CATEGORY_GLONASS, "CONSTELLATION_CATEGORY_GLONASS"},
420 {SatelliteConstellationCategory::CONSTELLATION_CATEGORY_BEIDOU, "CONSTELLATION_CATEGORY_BEIDOU"},
421 {SatelliteConstellationCategory::CONSTELLATION_CATEGORY_GALILEO, "CONSTELLATION_CATEGORY_GALILEO"},
422 {SatelliteConstellationCategory::CONSTELLATION_CATEGORY_IRNSS, "CONSTELLATION_CATEGORY_IRNSS"},
423 }};
424};
425
426}
427
428QT_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)
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
static constexpr std::array< std::pair< SatelliteConstellationCategory, const char * >, 8 > enumeratorsNames