1 /***************************************************************************
2                           qgsgpsconnection.h  -  description
3                           -------------------
4     begin                : November 30th, 2009
5     copyright            : (C) 2009 by Marco Hugentobler
6     email                : marco at hugis dot net
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #ifndef QGSGPSCONNECTION_H
19 #define QGSGPSCONNECTION_H
20 
21 #include <QDateTime>
22 #include "qgis.h"
23 #include <QObject>
24 #include <QString>
25 
26 #include "qgis_core.h"
27 
28 class QIODevice;
29 
30 #ifdef SIP_RUN
31 % ModuleHeaderCode
32 #include "qgsgpsconnection.h"
33 % End
34 #endif
35 
36 /**
37  * \ingroup core
38  * \class QgsSatelliteInfo
39  * \brief Encapsulates information relating to a GPS satellite.
40 */
41 class CORE_EXPORT QgsSatelliteInfo
42 {
43   public:
44 
45     /**
46      * Contains the satellite identifier number.
47      *
48      * The satellite identifier number can be used to identify a satellite inside the satellite system.
49      * For satellite system GPS the satellite identifier number represents the PRN (Pseudo-random noise)
50      * number. For satellite system GLONASS the satellite identifier number represents the slot number.
51      */
52     int id = 0;
53 
54     /**
55      * TRUE if satellite was used in obtaining the position fix.
56      */
57     bool inUse = false;
58 
59 #ifndef SIP_RUN
60 
61     /**
62      * Elevation of the satellite, in degrees.
63      */
64     double elevation = std::numeric_limits< double >::quiet_NaN();
65 #else
66 
67     /**
68      * Elevation of the satellite, in degrees.
69      */
70     double elevation;
71 #endif
72 
73 #ifndef SIP_RUN
74 
75     /**
76      * The azimuth of the satellite to true north, in degrees.
77      */
78     double azimuth = std::numeric_limits< double >::quiet_NaN();
79 #else
80 
81     /**
82      * The azimuth of the satellite to true north, in degrees.
83      */
84     double azimuth;
85 #endif
86 
87     /**
88      * Signal strength (0-99dB), or -1 if not available.
89      */
90     int signal = -1;
91 };
92 
93 /**
94  * \ingroup core
95  * \class QgsGpsInformation
96  * \brief Encapsulates information relating to a GPS position fix.
97 */
98 class CORE_EXPORT QgsGpsInformation
99 {
100   public:
101 
102     /**
103      * GPS fix status
104      * \since QGIS 3.10
105      */
106     enum FixStatus
107     {
108       NoData,
109       NoFix,
110       Fix2D,
111       Fix3D
112     };
113 
114     /**
115      * Latitude in decimal degrees, using the WGS84 datum. A positive value indicates the Northern Hemisphere, and
116      * a negative value indicates the Southern Hemisphere.
117      */
118     double latitude = 0;
119 
120     /**
121      * Longitude in decimal degrees, using the WGS84 datum. A positive value indicates the Eastern Hemisphere, and
122      * a negative value indicates the Western Hemisphere.
123      */
124     double longitude = 0;
125 
126     /**
127      * Altitude (in meters) above or below the mean sea level.
128      */
129     double elevation = 0;
130 
131     /**
132      * Geoidal separation (Diff. between WGS-84 earth ellipsoid and
133      * mean sea level.
134      *
135      * \since QGIS 3.18
136      */
137     double elevation_diff = 0;
138 
139     /**
140      * Ground speed, in km/h.
141      */
142     double speed = 0;
143 
144 #ifndef SIP_RUN
145 
146     /**
147      * The bearing measured in degrees clockwise from true north to the direction of travel.
148      */
149     double direction = std::numeric_limits< double >::quiet_NaN();
150 #else
151 
152     /**
153      * The bearing measured in degrees clockwise from true north to the direction of travel.
154      */
155     double direction;
156 #endif
157 
158     /**
159      * Contains a list of information relating to the current satellites in view.
160      */
161     QList<QgsSatelliteInfo> satellitesInView;
162 
163     /**
164      * Dilution of precision.
165      */
166     double pdop = 0;
167 
168     /**
169      * Horizontal dilution of precision.
170      */
171     double hdop = 0;
172 
173     /**
174      * Vertical dilution of precision.
175      */
176     double vdop = 0;
177 
178 #ifndef SIP_RUN
179     //! Horizontal accuracy in meters
180     double hacc = std::numeric_limits< double >::quiet_NaN();
181     //! Vertical accuracy in meters
182     double vacc = std::numeric_limits< double >::quiet_NaN();
183 
184     /**
185      * 3D RMS
186      * \since QGIS 3.18
187      */
188     double hvacc = std::numeric_limits< double >::quiet_NaN();
189 #else
190     //! Horizontal accuracy in meters
191     double hacc;
192     //! Vertical accuracy in meters
193     double vacc;
194 
195     /**
196      * 3D RMS
197      * \since QGIS 3.18
198      */
199     double hvacc;
200 #endif
201 
202     /**
203      * The date and time at which this position was reported, in UTC time.
204      */
205     QDateTime utcDateTime;
206 
207     /**
208      * Fix mode (where M = Manual, forced to operate in 2D or 3D or A = Automatic, 3D/2D)
209      */
210     QChar fixMode;
211 
212     /**
213      * Contains the fix type, where 1 = no fix, 2 = 2d fix, 3 = 3d fix
214      */
215     int fixType = 0;
216 
217     /**
218      * GPS quality indicator (0 = Invalid; 1 = Fix; 2 = Differential, 3 = Sensitive)
219      */
220     int quality = -1;
221 
222     /**
223      * Count of satellites used in obtaining the fix.
224      */
225     int satellitesUsed = 0;
226 
227     /**
228      * Status (A = active or V = void)
229      */
230     QChar status;
231 
232     /**
233      * IDs of satellites used in the position fix.
234      */
235     QList<int> satPrn;
236 
237     /**
238      * TRUE if satellite information is complete.
239      */
240     bool satInfoComplete = false;
241 
242     /**
243      * Returns whether the connection information is valid
244      * \since QGIS 3.10
245      */
246     bool isValid() const;
247 
248     /**
249      * Returns the fix status
250      * \since QGIS 3.10
251      */
252     FixStatus fixStatus() const;
253 
254     /**
255      * Returns a descriptive string for the signal quality.
256      *
257      * \since QGIS 3.16
258      */
259     QString qualityDescription() const;
260 };
261 
262 /**
263  * \ingroup core
264  * \brief Abstract base class for connection to a GPS device
265 */
266 class CORE_EXPORT QgsGpsConnection : public QObject
267 {
268 #ifdef SIP_RUN
269 #include <qgsgpsdconnection.h>
270 #include <qgsnmeaconnection.h>
271 #endif
272 
273 
274 #ifdef SIP_RUN
275     SIP_CONVERT_TO_SUBCLASS_CODE
276     if ( sipCpp->inherits( "QgsGpsdConnection" ) )
277       sipType = sipType_QgsGpsdConnection;
278     else if ( sipCpp->inherits( "QgsNmeaConnection" ) )
279       sipType = sipType_QgsNmeaConnection;
280     else
281       sipType = NULL;
282     SIP_END
283 #endif
284 
285     Q_OBJECT
286   public:
287 
288     enum Status
289     {
290       NotConnected,
291       Connected,
292       DataReceived,
293       GPSDataReceived
294     };
295 
296     /**
297      * Constructor
298      * \param dev input device for the connection (e.g. serial device). The class takes ownership of the object
299      */
300     QgsGpsConnection( QIODevice *dev SIP_TRANSFER );
301     ~QgsGpsConnection() override;
302     //! Opens connection to device
303     bool connect();
304     //! Closes connection to device
305     bool close();
306 
307     //! Sets the GPS source. The class takes ownership of the device class
308     void setSource( QIODevice *source SIP_TRANSFER );
309 
310     //! Returns the status. Possible state are not connected, connected, data received
status()311     Status status() const { return mStatus; }
312 
313     //! Returns the current gps information (lat, lon, etc.)
currentGPSInformation()314     QgsGpsInformation currentGPSInformation() const { return mLastGPSInformation; }
315 
316   signals:
317     void stateChanged( const QgsGpsInformation &info );
318     void nmeaSentenceReceived( const QString &substring ); // added to capture 'raw' data
319 
320   protected:
321     //! Data source (e.g. serial device, socket, file,...)
322     std::unique_ptr< QIODevice > mSource;
323     //! Last state of the gps related variables (e.g. position, time, ...)
324     QgsGpsInformation mLastGPSInformation;
325     //! Connection status
326     Status mStatus = NotConnected;
327 
328   private:
329     //! Closes and deletes mSource
330     void cleanupSource();
331     void clearLastGPSInformation();
332 
333   protected slots:
334     //! Parse available data source content
335     virtual void parseData() = 0;
336 };
337 
338 #endif // QGSGPSCONNECTION_H
339