QGIS API Documentation  2.14.0-Essen
qgsqtlocationconnection.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  QgsQtLocationConnection.cpp - description
3  ---------------------
4  begin : December 7th, 2011
5  copyright : (C) 2011 by Marco Bernasocchi, Bernawebdesign.ch
6  email : marco at bernawebdesign dot ch
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 
19 #include "qgslogger.h"
20 
21 #include <QLocalSocket>
22 #include <QTimer>
23 #include <QMetaType>
24 
26 {
27  //needed to fix https://sourceforge.net/p/necessitas/tickets/146/
28  qRegisterMetaType< QList<QGeoSatelliteInfo> >( "QList<QGeoSatelliteInfo>" );
29 
30  startSatelliteMonitor();
31  startGPS();
32 
33  //HACK to signal the gpsinformationwidget that we have a QtLocationConnection
34  QTimer::singleShot( 500, this, SLOT( broadcastConnectionAvailable() ) );
35 }
36 
38 {
39  //connection will be closed by base class
40  QgsDebugMsg( "entered." );
41 }
42 
43 //Needed to make connection detectable (half HACK)
44 //this signals that the device has started the GPS sucessfully,
45 //not that it has a fix yet.
47 {
48  if ( locationDataSource )
49  {
52  }
53 }
54 
55 //TODO: Temporarely needed to workaround https://sourceforge.net/p/necessitas/tickets/147/
56 void QgsQtLocationConnection::positionUpdated( const QGeoPositionInfo &info )
57 {
58  mInfo = info;
59  parseData();
60 }
61 
63 {
64  if ( locationDataSource )
65  {
67  //const QGeoPositionInfo &info = locationDataSource->lastKnownPosition();
68  if ( mInfo.isValid() )
69  {
70  // mInfo.HorizontalAccuracy;
71  mLastGPSInformation.latitude = mInfo.coordinate().latitude();
72  mLastGPSInformation.longitude = mInfo.coordinate().longitude();
73  mLastGPSInformation.elevation = mInfo.coordinate().altitude();
74  mLastGPSInformation.speed = mInfo.attribute( QGeoPositionInfo::GroundSpeed ) * 3.6; // m/s to km/h
75  mLastGPSInformation.direction = mInfo.attribute( QGeoPositionInfo::Direction );
76  mLastGPSInformation.utcDateTime = mInfo.timestamp();
77  mLastGPSInformation.fixType = mInfo.coordinate().type() + 1;
78  //< fixType, used for navigation (1 = Fix not available; 2 = 2D; 3 = 3D)
79  //< coordinate().type(), returns 0 = Fix not available; 1 = 2D; 2 = 3D)
80  mLastGPSInformation.hacc = mInfo.attribute( QGeoPositionInfo::HorizontalAccuracy ); //< Horizontal dilution of precision
81  mLastGPSInformation.vacc = mInfo.attribute( QGeoPositionInfo::VerticalAccuracy ); //< Vertical dilution of precision
82 
83  //TODO implement dop maybe by getting a
84  //http://developer.android.com/reference/android/location/GpsStatus.NmeaListener.html
85  //http://doc.qt.nokia.com/qtmobility-1.1/qnmeapositioninfosource.html
86  //into QtLocation and subclass QgsNMEAConnection directly?
87  mLastGPSInformation.pdop; //< Dilution of precision
88  mLastGPSInformation.hdop; //< Horizontal dilution of precision
89  mLastGPSInformation.vdop; //< Vertical dilution of precision
90 
91  mLastGPSInformation.fixMode; //< Mode (M = Manual, forced to operate in 2D or 3D; A = Automatic, 3D/2D)
92  mLastGPSInformation.quality; //< GPS quality indicator (0 = Invalid; 1 = Fix; 2 = Differential, 3 = Sensitive)
93  mLastGPSInformation.status; //< Status (A = active or V = void)
94 
96  QgsDebugMsg( "Valid QGeoPositionInfo, positionUpdated" );
97  }
98  }
99 }
100 
102  const QList<QGeoSatelliteInfo>& satellites )
103 {
104  // The number of satellites in view is updated
106  for ( int i = 0; i < satellites.size(); ++i )
107  {
108  QGeoSatelliteInfo currentSatellite = satellites.at( i );
109  QgsSatelliteInfo satelliteInfo;
110  satelliteInfo.azimuth = currentSatellite.attribute( QGeoSatelliteInfo::Azimuth );
111  satelliteInfo.elevation = currentSatellite.attribute( QGeoSatelliteInfo::Elevation );
112 #if defined(HAVE_QT_MOBILITY_LOCATION )
113  satelliteInfo.id = currentSatellite.prnNumber();
114 #else // QtPositioning
115  satelliteInfo.id = currentSatellite.satelliteIdentifier();
116 #endif
117  satelliteInfo.signal = currentSatellite.signalStrength();
119  }
120  mLastGPSInformation.satInfoComplete = true; //to be used to determine when to graph signal and satellite position
122  QgsDebugMsg( "satellitesInViewUpdated" );
123 }
124 
126  const QList<QGeoSatelliteInfo>& satellites )
127 {
128  // The number of satellites in use is updated
129  mLastGPSInformation.satellitesUsed = QString::number( satellites.count() ).toInt();
130 
132  for ( int i = 0; i < satellites.size(); ++i )
133  {
134  QGeoSatelliteInfo currentSatellite = satellites.at( i );
135  //add pnr to mLastGPSInformation.satPrn
136 #if defined(HAVE_QT_MOBILITY_LOCATION )
137  mLastGPSInformation.satPrn.append( currentSatellite.prnNumber() );
138 #else // QtPositioning
139  mLastGPSInformation.satPrn.append( currentSatellite.satelliteIdentifier() );
140 #endif
141 
142  //set QgsSatelliteInfo.inuse to true for the satellites in use
143  for ( int i = 0; i < mLastGPSInformation.satellitesInView.size(); ++i )
144  {
146 #if defined(HAVE_QT_MOBILITY_LOCATION )
147  if ( satInView.id == currentSatellite.prnNumber() )
148 #else // QtPositioning
149  if ( satInView.id == currentSatellite.satelliteIdentifier() )
150 #endif
151  {
152  satInView.inUse = true;
153  break;
154  }
155  }
156  }
157  mLastGPSInformation.satInfoComplete = true; //to be used to determine when to graph signal and satellite position
159  QgsDebugMsg( "satellitesInUseUpdated" );
160 }
161 
162 void QgsQtLocationConnection::startGPS()
163 {
164  QgsDebugMsg( "Starting GPS QtLocation connection" );
165  // Obtain the location data source if it is not obtained already
166  if ( !locationDataSource )
167  {
168  locationDataSource = QGeoPositionInfoSource::createDefaultSource( this );
169  if ( locationDataSource )
170  {
171  locationDataSource->setPreferredPositioningMethods( QGeoPositionInfoSource::SatellitePositioningMethods ); //QGeoPositionInfoSource::AllPositioningMethods
172  locationDataSource->setUpdateInterval( 1000 );
173  // Whenever the location data source signals that the current
174  // position is updated, the positionUpdated function is called.
175  QObject::connect( locationDataSource,
176  SIGNAL( positionUpdated( QGeoPositionInfo ) ),
177  this,
178  SLOT( positionUpdated( QGeoPositionInfo ) ) );
179  // Start listening for position updates
180  locationDataSource->startUpdates();
181  }
182  else
183  {
184  // Not able to obtain the location data source
185  QgsDebugMsg( "No QtLocation Position Source" );
186  }
187  }
188  else
189  {
190  // Start listening for position updates
191  locationDataSource->startUpdates();
192  }
193 }
194 
195 void QgsQtLocationConnection::startSatelliteMonitor()
196 {
197  QgsDebugMsg( "Starting GPS QtLocation satellite monitor" );
198 
199  if ( !satelliteInfoSource )
200  {
201  satelliteInfoSource = QGeoSatelliteInfoSource::createDefaultSource( this );
202  if ( satelliteInfoSource )
203  {
204  QgsDebugMsg( "satelliteMonitor started" );
205  // Whenever the satellite info source signals that the number of
206  // satellites in use is updated, the satellitesInUseUpdated function
207  // is called
208  QObject::connect( satelliteInfoSource,
209  SIGNAL( satellitesInUseUpdated(
210  const QList<QGeoSatelliteInfo>& ) ),
211  this,
213  const QList<QGeoSatelliteInfo>& ) ) );
214 
215  // Whenever the satellite info source signals that the number of
216  // satellites in view is updated, the satellitesInViewUpdated function
217  // is called
218  QObject::connect( satelliteInfoSource,
219  SIGNAL( satellitesInViewUpdated(
220  const QList<QGeoSatelliteInfo>& ) ),
221  this,
223  const QList<QGeoSatelliteInfo>& ) ) );
224 
225  // Start listening for satellite updates
226  satelliteInfoSource->startUpdates();
227  }
228  else
229  {
230  // Not able to obtain the Satellite data source
231  QgsDebugMsg( "No QtLocation Satellite Source" );
232  }
233  }
234  else
235  {
236  // Start listening for position updates
237  satelliteInfoSource->startUpdates();
238  }
239 }
void clear()
void satellitesInUseUpdated(const QList< QGeoSatelliteInfo > &satellites)
Called when the number of satellites in use is updated.
Status mStatus
Connection status.
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
void positionUpdated(const QGeoPositionInfo &info)
Called when the position updated.
const T & at(int i) const
QList< QgsSatelliteInfo > satellitesInView
int size() const
QList< int > satPrn
QString number(int n, int base)
int count(const T &value) const
void append(const T &value)
Abstract base class for connection to a GPS device.
void satellitesInViewUpdated(const QList< QGeoSatelliteInfo > &satellites)
Called when the number of satellites in view is updated.
QgsGPSInformation mLastGPSInformation
Last state of the gps related variables (e.g.
void broadcastConnectionAvailable()
Needed to make QtLocation detected.
void stateChanged(const QgsGPSInformation &info)
void parseData()
Parse available data source content.
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)