QGIS API Documentation  2.99.0-Master (19b062c)
qgsgpsdetector.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsgpsdetector.cpp - description
3  --------------------
4  begin : January 13th, 2009
5  copyright : (C) 2009 by Juergen E. Fischer
6  email : jef at norbit dot de
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 #include "qgsgpsdetector.h"
19 #include "qextserialenumerator.h"
20 #include "qgslogger.h"
21 #include "qgsgpsconnection.h"
22 #include "qgsnmeaconnection.h"
23 #include "qgsgpsdconnection.h"
24 
25 #if defined(HAVE_QT_MOBILITY_LOCATION ) || defined(QT_POSITIONING_LIB)
27 #endif
28 
29 #include <QStringList>
30 #include <QFileInfo>
31 #include <QTimer>
32 
33 QList< QPair<QString, QString> > QgsGPSDetector::availablePorts()
34 {
35  QList< QPair<QString, QString> > devs;
36 
37  // try local QtLocation first
38 #if defined(HAVE_QT_MOBILITY_LOCATION ) || defined(QT_POSITIONING_LIB)
39  devs << QPair<QString, QString>( QStringLiteral( "internalGPS" ), tr( "internal GPS" ) );
40 #endif
41 
42  // try local gpsd first
43  devs << QPair<QString, QString>( QStringLiteral( "localhost:2947:" ), tr( "local gpsd" ) );
44 
45 #ifdef Q_OS_LINUX
46  // look for linux serial devices
47  const QStringList devices { QStringLiteral( "/dev/ttyS%1" ),
48  QStringLiteral( "/dev/ttyUSB%1" ),
49  QStringLiteral( "/dev/rfcomm%1" ), QStringLiteral( "/dev/ttyACM%1" ) };
50  for ( const QString &linuxDev : devices )
51  {
52  for ( int i = 0; i < 10; ++i )
53  {
54  if ( QFileInfo::exists( linuxDev.arg( i ) ) )
55  {
56  devs << QPair<QString, QString>( linuxDev.arg( i ), linuxDev.arg( i ) );
57  }
58  }
59  }
60 #endif
61 
62 #ifdef Q_OS_FREEBSD
63  // and freebsd devices (untested)
64  Q_FOREACH ( const QString &freebsdDev, QStringList() << "/dev/cuaa%1" << "/dev/ucom%1" )
65  {
66  for ( int i = 0; i < 10; ++i )
67  {
68  if ( QFileInfo( freebsdDev.arg( i ) ).exists() )
69  {
70  devs << QPair<QString, QString>( freebsdDev.arg( i ), freebsdDev.arg( i ) );
71  }
72  }
73  }
74 #endif
75 
76 #ifdef Q_OS_SOLARIS
77  // and solaris devices (also untested)
78  QString solarisDev( "/dev/cua/%1" );
79  for ( char i = 'a'; i < 'k'; ++i )
80  {
81  if ( QFileInfo( solarisDev.arg( i ) ).exists() )
82  {
83  devs << QPair<QString, QString>( solarisDev.arg( i ), solarisDev.arg( i ) );
84  }
85  }
86 #endif
87 
88 #if defined(Q_OS_WIN) || defined(Q_OS_MAC)
89  QList<QextPortInfo> ports = QextSerialEnumerator::getPorts();
90  Q_FOREACH ( QextPortInfo port, ports )
91  {
92  devs << QPair<QString, QString>( port.portName, port.friendName );
93  }
94 #endif
95 
96  // OpenBSD, NetBSD etc? Anyone?
97 
98  return devs;
99 }
100 
101 QgsGPSDetector::QgsGPSDetector( const QString &portName )
102 {
103  mConn = nullptr;
104  mBaudList << BAUD4800 << BAUD9600 << BAUD38400 << BAUD57600 << BAUD115200; //add 57600 for SXBlueII GPS unit
105 
106  if ( portName.isEmpty() )
107  {
108  mPortList = availablePorts();
109  }
110  else
111  {
112  mPortList << QPair<QString, QString>( portName, portName );
113  }
114 
115  mPortIndex = 0;
116  mBaudIndex = -1;
117 }
118 
120 {
121  if ( mConn )
122  delete mConn;
123 }
124 
126 {
127  if ( mConn )
128  {
129  delete mConn;
130  }
131 
132  mConn = nullptr;
133 
134  while ( !mConn )
135  {
136  mBaudIndex++;
137  if ( mBaudIndex == mBaudList.size() )
138  {
139  mBaudIndex = 0;
140  mPortIndex++;
141  }
142 
143  if ( mPortIndex == mPortList.size() )
144  {
145  emit detectionFailed();
146  deleteLater();
147  return;
148  }
149 
150  if ( mPortList.at( mPortIndex ).first.contains( ':' ) )
151  {
152  mBaudIndex = mBaudList.size() - 1;
153 
154  QStringList gpsParams = mPortList.at( mPortIndex ).first.split( ':' );
155 
156  Q_ASSERT( gpsParams.size() >= 3 );
157 
158  mConn = new QgsGpsdConnection( gpsParams[0], gpsParams[1].toShort(), gpsParams[2] );
159  }
160  else if ( mPortList.at( mPortIndex ).first.contains( QLatin1String( "internalGPS" ) ) )
161  {
162 #if defined(HAVE_QT_MOBILITY_LOCATION ) || defined(QT_POSITIONING_LIB)
163  mConn = new QgsQtLocationConnection();
164 #else
165  qWarning( "QT_MOBILITY_LOCATION not found and mPortList matches internalGPS, this should never happen" );
166 #endif
167  }
168  else
169  {
170  QextSerialPort *serial = new QextSerialPort( mPortList.at( mPortIndex ).first, QextSerialPort::EventDriven );
171 
172  serial->setBaudRate( mBaudList[ mBaudIndex ] );
173  serial->setFlowControl( FLOW_OFF );
174  serial->setParity( PAR_NONE );
175  serial->setDataBits( DATA_8 );
176  serial->setStopBits( STOP_1 );
177 
178  if ( serial->open( QIODevice::ReadOnly | QIODevice::Unbuffered ) )
179  {
180  mConn = new QgsNMEAConnection( serial );
181  }
182  else
183  {
184  delete serial;
185  }
186  }
187  }
188 
189  connect( mConn, &QgsGPSConnection::stateChanged, this, static_cast < void ( QgsGPSDetector::* )( const QgsGPSInformation & ) >( &QgsGPSDetector::detected ) );
190  connect( mConn, &QObject::destroyed, this, &QgsGPSDetector::connDestroyed );
191 
192  // leave 2s to pickup a valid string
193  QTimer::singleShot( 2000, this, &QgsGPSDetector::advance );
194 }
195 
197 {
198  Q_UNUSED( info );
199 
200  if ( !mConn )
201  {
202  // advance if connection was destroyed
203  advance();
204  }
205  else if ( mConn->status() == QgsGPSConnection::GPSDataReceived )
206  {
207  // signal detection
208  QgsGPSConnection *conn = mConn;
209  mConn = nullptr;
210  emit detected( conn );
211  deleteLater();
212  }
213 }
214 
215 void QgsGPSDetector::connDestroyed( QObject *obj )
216 {
217  if ( obj == mConn )
218  {
219  mConn = nullptr;
220  }
221 }
Evaluates NMEA sentences coming from gpsd.
void detectionFailed()
Abstract base class for connection to a GPS device.
QgsGPSDetector(const QString &portName)
Evaluates NMEA sentences coming from a GPS device.
Class to detect the GPS port.
void connDestroyed(QObject *)
void detected(const QgsGPSInformation &)
void stateChanged(const QgsGPSInformation &info)
static QList< QPair< QString, QString > > availablePorts()
Status status() const
Returns the status. Possible state are not connected, connected, data received.