Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qgeosatelliteinfosource_gypsy.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 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
5
6#ifdef Q_LOCATION_GYPSY_DEBUG
7#include <QDebug>
8#endif
9#include <QFile>
10#include <QVariantMap>
11
13
14#define UPDATE_TIMEOUT_COLD_START 120000
15
16static const auto deviceNameParameter = "deviceName";
17static const auto gconfKeyParameter = "gconfKey";
18static const auto defaultGconfKey = "/apps/geoclue/master/org.freedesktop.Geoclue.GPSDevice";
19
20// Callback function for 'satellites-changed' -signal
21static void satellites_changed (GypsySatellite *satellite,
22 GPtrArray *satellites,
23 gpointer userdata)
24{
25#ifdef Q_LOCATION_GYPSY_DEBUG
26 qDebug() << "QGeoSatelliteInfoSourceGypsy Gypsy satellites-changed -signal received.";
27#endif
28 ((QGeoSatelliteInfoSourceGypsy *)userdata)->satellitesChanged(satellite, satellites);
29}
30
38
39// Glib symbols
41 const gchar *detailed_signal,
42 GCallback c_handler,
43 gpointer data)
44{
45 return ::g_signal_connect(instance, detailed_signal, c_handler, data);
46}
48 gpointer func,
49 gpointer data)
50{
51 return ::g_signal_handlers_disconnect_by_func(instance, func, data);
52}
53
55{
56 return ::g_free(mem);
57}
58// Gypsy symbols
60{
61 return ::gypsy_control_get_default();
62}
63char *SatelliteGypsyEngine::eng_gypsy_control_create (GypsyControl *control, const char *device_name, GError **error)
64{
65 return ::gypsy_control_create(control, device_name, error);
66}
67GypsyDevice *SatelliteGypsyEngine::eng_gypsy_device_new (const char *object_path)
68{
69 return ::gypsy_device_new(object_path);
70}
71GypsySatellite *SatelliteGypsyEngine::eng_gypsy_satellite_new (const char *object_path)
72{
73 return ::gypsy_satellite_new (object_path);
74}
76{
77 return ::gypsy_device_start(device, error);
78}
80{
81 // Unfortunately this cannot be done; calling this will stop the GPS device
82 // (basically makes gypsy-daemon unusable for anyone), regardless of applications
83 // using it (see bug http://bugs.meego.com/show_bug.cgi?id=11707).
86 return true;
87 //return ::gypsy_device_stop (device, error);
88}
89GypsyDeviceFixStatus SatelliteGypsyEngine::eng_gypsy_device_get_fix_status (GypsyDevice *device, GError **error)
90{
91 return ::gypsy_device_get_fix_status (device, error);
92}
93GPtrArray *SatelliteGypsyEngine::eng_gypsy_satellite_get_satellites (GypsySatellite *satellite, GError **error)
94{
95 return ::gypsy_satellite_get_satellites (satellite, error);
96}
98{
99 return ::gypsy_satellite_free_satellite_array(satellites);
100}
101// GConf symbols (mockability due to X11 requirement)
103{
104 return ::gconf_client_get_default();
105}
106gchar *SatelliteGypsyEngine::eng_gconf_client_get_string(GConfClient *client, const gchar *key, GError** err)
107{
108 return ::gconf_client_get_string(client, key, err);
109}
110
112 : QGeoSatelliteInfoSource(parent), m_engine(0), m_satellite(0), m_device(0),
113 m_requestTimer(this), m_updatesOngoing(false), m_requestOngoing(false)
114{
115 m_requestTimer.setSingleShot(true);
116 QObject::connect(&m_requestTimer, SIGNAL(timeout()), this, SLOT(requestUpdateTimeout()));
117}
118
124
126{
127 GError *error = NULL;
128 if (m_device) {
130 g_object_unref(m_device);
131 }
132 if (m_satellite)
133 g_object_unref(m_satellite);
134 if (m_control)
135 g_object_unref(m_control);
136 if (error)
137 g_error_free(error);
138 delete m_engine;
139}
140
142{
143 if (prn >= 1 && prn <= 32)
145 else if (prn >= 65 && prn <= 96)
147 else if (prn >= 193 && prn <= 200)
149 else if ((prn >= 201 && prn <= 235) || (prn >= 401 && prn <= 437))
151 else if (prn >= 301 && prn <= 336)
154}
155
157 GPtrArray *satellites)
158{
159 if (!satellite || !satellites)
160 return;
161 // We have satellite data and assume it is valid.
162 // If a single updateRequest was active, send signals right away.
163 // If a periodic timer was running (meaning that the client wishes
164 // to have updates at defined intervals), store the data for later sending.
165 QList<QGeoSatelliteInfo> lastSatellitesInView;
166 QList<QGeoSatelliteInfo> lastSatellitesInUse;
167
168 unsigned int i;
169 for (i = 0; i < satellites->len; i++) {
170 GypsySatelliteDetails *details = (GypsySatelliteDetails *)satellites->pdata[i];
172 info.setSatelliteIdentifier(details->satellite_id);
173 info.setSatelliteSystem(idToSystem(details->satellite_id));
174 info.setAttribute(QGeoSatelliteInfo::Elevation, details->elevation);
175 info.setAttribute(QGeoSatelliteInfo::Azimuth, details->azimuth);
176 info.setSignalStrength(details->snr);
177 if (details->in_use)
178 lastSatellitesInUse.append(info);
179 lastSatellitesInView.append(info);
180 }
181 bool sendUpdates(false);
182 // If a single updateRequest() has been issued:
183 if (m_requestOngoing) {
184 sendUpdates = true;
185 m_requestTimer.stop();
186 m_requestOngoing = false;
187 // If there is no regular updates ongoing, disconnect now.
188 if (!m_updatesOngoing) {
189 m_engine->eng_g_signal_handlers_disconnect_by_func(G_OBJECT(m_satellite), (void *)satellites_changed, this);
190 }
191 }
192 // If regular updates are to be delivered as they come:
193 if (m_updatesOngoing)
194 sendUpdates = true;
195
196 if (sendUpdates) {
197 emit satellitesInUseUpdated(lastSatellitesInUse);
198 emit satellitesInViewUpdated(lastSatellitesInView);
199 }
200}
201
202QString QGeoSatelliteInfoSourceGypsy::extractDeviceNameFromParameters(const QVariantMap &parameters) const
203{
204 // The logic is as follows:
205 // 1. If the deviceNameParameter is specified, its value is used to get the
206 // device name.
207 // 2. If the gconfKeyParameter is specified, its value is used as a key to
208 // extract the device name from GConf.
209 // 3. If nothing is specified, defaultGconfKey is used as a key to extract
210 // the device name from GConf.
211 if (parameters.contains(deviceNameParameter))
212 return parameters.value(deviceNameParameter).toString();
213
214 QString gconfKey = parameters.value(gconfKeyParameter).toString();
215 if (gconfKey.isEmpty())
216 gconfKey = defaultGconfKey;
217
218 if (!m_engine)
219 return QString();
220
221 GConfClient *client = m_engine->eng_gconf_client_get_default();
222 if (!client)
223 return QString();
224
225 gchar *device_name = m_engine->eng_gconf_client_get_string(client,
226 gconfKey.toLatin1().constData(),
227 nullptr);
228 g_object_unref(client);
229
230 const QString deviceName = QString::fromLatin1(device_name);
231 m_engine->eng_g_free(device_name);
232
233 return deviceName;
234}
235
237{
238 GError *error = NULL;
239 char *path;
240
241#if !GLIB_CHECK_VERSION(2, 36, 0)
242 g_type_init (); // this function was deprecated in glib 2.36
243#endif
244 createEngine();
245
246 const QString deviceName = extractDeviceNameFromParameters(parameters);
247
248 if (deviceName.isEmpty() ||
249 (deviceName.trimmed().at(0) == '/' && !QFile::exists(deviceName.trimmed()))) {
250 qWarning ("QGeoSatelliteInfoSourceGypsy Empty/nonexistent GPS device name detected.");
251 qWarning("Use '%s' plugin parameter to specify device name directly", deviceNameParameter);
252 qWarning("or use '%s' plugin parameter to specify a GConf key to extract the device name.",
254 qWarning ("If the GConf key is used, the gconftool-2 tool can be used to set device name "
255 "for the selected key, e.g. on terminal:");
256 qWarning ("gconftool-2 -t string -s %s /dev/ttyUSB0", gconfKeyParameter);
257 return -1;
258 }
260 if (!m_control) {
261 qWarning("QGeoSatelliteInfoSourceGypsy unable to create Gypsy control.");
262 return -1;
263 }
264 // (path is the DBus path)
265 path = m_engine->eng_gypsy_control_create(m_control, deviceName.toLatin1().constData(), &error);
266 if (!path) {
267 qWarning ("QGeoSatelliteInfoSourceGypsy error creating client.");
268 if (error) {
269 qWarning ("error message: %s", error->message);
270 g_error_free (error);
271 }
272 return -1;
273 }
274 m_device = m_engine->eng_gypsy_device_new (path);
275 m_satellite = m_engine->eng_gypsy_satellite_new (path);
277 if (!m_device || !m_satellite) {
278 qWarning ("QGeoSatelliteInfoSourceGypsy error creating satellite device.");
279 qWarning ("Please check that the GPS device is specified correctly.");
280 qWarning("Use '%s' plugin parameter to specify device name directly", deviceNameParameter);
281 qWarning("or use '%s' plugin parameter to specify a GConf key to extract the device name.",
283 qWarning ("If the GConf key is used, the gconftool-2 tool can be used to set device name "
284 "for the selected key, e.g. on terminal:");
285 qWarning ("gconftool-2 -t string -s %s /dev/ttyUSB0", gconfKeyParameter);
286 if (m_device)
287 g_object_unref(m_device);
288 if (m_satellite)
289 g_object_unref(m_satellite);
290 return -1;
291 }
293 if (error) {
294 qWarning ("QGeoSatelliteInfoSourceGypsy error starting device: %s ",
295 error->message);
296 g_error_free(error);
297 g_object_unref(m_device);
298 g_object_unref(m_satellite);
299 return -1;
300 }
301 return 0;
302}
303
305{
306 return 1;
307}
308
313
315{
316 if (m_updatesOngoing)
317 return;
318
320
321 // If there is a request timer ongoing, we've connected to the signal already
322 if (!m_requestTimer.isActive()) {
323 m_engine->eng_g_signal_connect (m_satellite, "satellites-changed",
324 G_CALLBACK (satellites_changed), this);
325 }
326 m_updatesOngoing = true;
327}
328
330{
331 if (!m_updatesOngoing)
332 return;
333 m_updatesOngoing = false;
334 // Disconnect only if there is no single update request ongoing. Once single update request
335 // is completed and it notices that there is no active update ongoing, it will disconnect
336 // the signal.
337 if (!m_requestTimer.isActive())
338 m_engine->eng_g_signal_handlers_disconnect_by_func(G_OBJECT(m_satellite), (void *)satellites_changed, this);
339}
340
342{
343 if (m_requestOngoing)
344 return;
345
347
348 if (timeout < 0) {
350 return;
351 }
352 m_requestOngoing = true;
353 GError *error = 0;
354 // If GPS has a fix a already, request current data.
355 GypsyDeviceFixStatus fixStatus = m_engine->eng_gypsy_device_get_fix_status(m_device, &error);
356 if (!error && (fixStatus != GYPSY_DEVICE_FIX_STATUS_INVALID &&
357 fixStatus != GYPSY_DEVICE_FIX_STATUS_NONE)) {
358#ifdef Q_LOCATION_GYPSY_DEBUG
359 qDebug() << "QGeoSatelliteInfoSourceGypsy fix available, requesting current satellite data";
360#endif
361 GPtrArray *satelliteData = m_engine->eng_gypsy_satellite_get_satellites(m_satellite, &error);
362 if (!error) {
363 // The fix was available and we have satellite data to deliver right away.
364 satellitesChanged(m_satellite, satelliteData);
366 return;
367 }
368 }
369 // No fix is available. If updates are not ongoing already, start them.
371 if (!m_updatesOngoing) {
372 m_engine->eng_g_signal_connect (m_satellite, "satellites-changed",
373 G_CALLBACK (satellites_changed), this);
374 }
375 m_requestTimer.start();
376 if (error) {
377#ifdef Q_LOCATION_GYPSY_DEBUG
378 qDebug() << "QGeoSatelliteInfoSourceGypsy error asking fix status or satellite data: " << error->message;
379#endif
380 g_error_free(error);
381 }
382}
383
384void QGeoSatelliteInfoSourceGypsy::requestUpdateTimeout()
385{
386#ifdef Q_LOCATION_GYPSY_DEBUG
387 qDebug("QGeoSatelliteInfoSourceGypsy request update timeout occurred.");
388#endif
389 // If we end up here, there has not been valid satellite update.
390 // Emit timeout and disconnect from signal if regular updates are not
391 // ongoing (as we were listening just for one single requestUpdate).
392 if (!m_updatesOngoing) {
393 m_engine->eng_g_signal_handlers_disconnect_by_func(G_OBJECT(m_satellite), (void *)satellites_changed, this);
394 }
395 m_requestOngoing = false;
397}
398
399void QGeoSatelliteInfoSourceGypsy::setError(QGeoSatelliteInfoSource::Error error)
400{
401 m_error = error;
404}
405
IOBluetoothDevice * device
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:124
bool exists() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qfile.cpp:351
void satellitesChanged(GypsySatellite *satellite, GPtrArray *satellites)
void requestUpdate(int timeout=5000) override
int init(const QVariantMap parameters)
Error error() const override
Returns the last error that occurred.
\inmodule QtPositioning
Error
The Error enumeration represents the errors which can occur.
void satellitesInViewUpdated(const QList< QGeoSatelliteInfo > &satellites)
If startUpdates() or requestUpdate() is called, this signal is emitted when an update is available on...
void satellitesInUseUpdated(const QList< QGeoSatelliteInfo > &satellites)
If startUpdates() or requestUpdate() is called, this signal is emitted when an update is available on...
void errorOccurred(QGeoSatelliteInfoSource::Error)
This signal is emitted after an error occurred.
\inmodule QtPositioning
SatelliteSystem
Defines the GNSS system of the satellite.
T value(const Key &key, const T &defaultValue=T()) const
Definition qmap.h:357
bool contains(const Key &key) const
Definition qmap.h:341
\inmodule QtCore
Definition qobject.h:103
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QByteArray toLatin1() const &
Definition qstring.h:630
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
Definition qstring.h:1226
QString trimmed() const &
Definition qstring.h:447
void setSingleShot(bool singleShot)
Definition qtimer.cpp:552
void start(int msec)
Starts or restarts the timer with a timeout interval of msec milliseconds.
Definition qtimer.cpp:241
void setInterval(int msec)
Definition qtimer.cpp:579
bool isActive() const
Returns true if the timer is running (pending); otherwise returns false.
Definition qtimer.cpp:167
void stop()
Stops the timer.
Definition qtimer.cpp:267
QString toString() const
Returns the variant as a QString if the variant has a userType() including, but not limited to:
virtual void eng_g_free(gpointer mem)
virtual gboolean eng_gypsy_device_stop(GypsyDevice *device, GError **error)
virtual gchar * eng_gconf_client_get_string(GConfClient *client, const gchar *key, GError **err)
SatelliteGypsyEngine(QGeoSatelliteInfoSource *parent=0)
virtual guint eng_g_signal_handlers_disconnect_by_func(gpointer instance, gpointer func, gpointer data)
virtual GypsyControl * eng_gypsy_control_get_default(void)
virtual GConfClient * eng_gconf_client_get_default(void)
virtual gulong eng_g_signal_connect(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data)
virtual gboolean eng_gypsy_device_start(GypsyDevice *device, GError **error)
virtual void eng_gypsy_satellite_free_satellite_array(GPtrArray *satellites)
virtual GPtrArray * eng_gypsy_satellite_get_satellites(GypsySatellite *satellite, GError **error)
virtual GypsyDevice * eng_gypsy_device_new(const char *object_path)
virtual char * eng_gypsy_control_create(GypsyControl *control, const char *device_name, GError **error)
virtual GypsySatellite * eng_gypsy_satellite_new(const char *object_path)
virtual GypsyDeviceFixStatus eng_gypsy_device_get_fix_status(GypsyDevice *device, GError **error)
#define this
Definition dialogs.cpp:9
Combined button and popup list for selecting options.
DBusConnection const char DBusError * error
static const auto defaultGconfKey
static const auto gconfKeyParameter
static const auto deviceNameParameter
static void satellites_changed(GypsySatellite *satellite, GPtrArray *satellites, gpointer userdata)
static QGeoSatelliteInfo::SatelliteSystem idToSystem(int prn)
#define UPDATE_TIMEOUT_COLD_START
#define qDebug
[1]
Definition qlogging.h:164
#define qWarning
Definition qlogging.h:166
#define SLOT(a)
Definition qobjectdefs.h:52
#define SIGNAL(a)
Definition qobjectdefs.h:53
GLuint64 key
GLbitfield GLuint64 timeout
[4]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum func
Definition qopenglext.h:663
GLsizei const GLchar *const * path
#define emit
#define Q_UNUSED(x)
QHostInfo info
[0]