QGIS API Documentation  3.8.0-Zanzibar (11aff65)
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 "qgslogger.h"
20 #include "qgsgpsconnection.h"
21 #include "qgsnmeaconnection.h"
22 #include "qgsgpsdconnection.h"
23 
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 #if defined( HAVE_QT5SERIALPORT )
34 #include <QSerialPortInfo>
35 #include <QSerialPort>
36 #endif
37 
38 QList< QPair<QString, QString> > QgsGpsDetector::availablePorts()
39 {
40  QList< QPair<QString, QString> > devs;
41 
42  // try local QtLocation first
43 #if defined(HAVE_QT_MOBILITY_LOCATION ) || defined(QT_POSITIONING_LIB)
44  devs << QPair<QString, QString>( QStringLiteral( "internalGPS" ), tr( "internal GPS" ) );
45 #endif
46 
47  // try local gpsd first
48  devs << QPair<QString, QString>( QStringLiteral( "localhost:2947:" ), tr( "local gpsd" ) );
49 
50  // try serial ports
51 #if defined( HAVE_QT5SERIALPORT )
52  for ( auto p : QSerialPortInfo::availablePorts() )
53  {
54  devs << QPair<QString, QString>( p.portName(), tr( "%1: %2" ).arg( p.portName(), p.description() ) );
55  }
56 #endif
57 
58  return devs;
59 }
60 
61 QgsGpsDetector::QgsGpsDetector( const QString &portName )
62 {
63  mConn = nullptr;
64 
65 #if defined( HAVE_QT5SERIALPORT )
66  mBaudList << QSerialPort::Baud4800 << QSerialPort::Baud9600 << QSerialPort::Baud38400 << QSerialPort::Baud57600 << QSerialPort::Baud115200; //add 57600 for SXBlueII GPS unit
67 #endif
68 
69  if ( portName.isEmpty() )
70  {
71  mPortList = availablePorts();
72  }
73  else
74  {
75  mPortList << QPair<QString, QString>( portName, portName );
76  }
77 
78  mPortIndex = 0;
79  mBaudIndex = -1;
80 }
81 
83 {
84  delete mConn;
85 }
86 
88 {
89  delete mConn;
90 
91  mConn = nullptr;
92 
93  while ( !mConn )
94  {
95  mBaudIndex++;
96  if ( mBaudIndex == mBaudList.size() )
97  {
98  mBaudIndex = 0;
99  mPortIndex++;
100  }
101 
102  if ( mPortIndex == mPortList.size() )
103  {
104  emit detectionFailed();
105  deleteLater();
106  return;
107  }
108 
109  if ( mPortList.at( mPortIndex ).first.contains( ':' ) )
110  {
111  mBaudIndex = mBaudList.size() - 1;
112 
113  QStringList gpsParams = mPortList.at( mPortIndex ).first.split( ':' );
114 
115  Q_ASSERT( gpsParams.size() >= 3 );
116 
117  mConn = new QgsGpsdConnection( gpsParams[0], gpsParams[1].toShort(), gpsParams[2] );
118  }
119  else if ( mPortList.at( mPortIndex ).first.contains( QLatin1String( "internalGPS" ) ) )
120  {
121 #if defined(HAVE_QT_MOBILITY_LOCATION ) || defined(QT_POSITIONING_LIB)
122  mConn = new QgsQtLocationConnection();
123 #else
124  qWarning( "QT_MOBILITY_LOCATION not found and mPortList matches internalGPS, this should never happen" );
125 #endif
126  }
127  else
128  {
129 #if defined( HAVE_QT5SERIALPORT )
130  QSerialPort *serial = new QSerialPort( mPortList.at( mPortIndex ).first );
131 
132  serial->setBaudRate( mBaudList[ mBaudIndex ] );
133  serial->setFlowControl( QSerialPort::NoFlowControl );
134  serial->setParity( QSerialPort::NoParity );
135  serial->setDataBits( QSerialPort::Data8 );
136  serial->setStopBits( QSerialPort::OneStop );
137 
138  if ( serial->open( QIODevice::ReadOnly ) )
139  {
140  mConn = new QgsNmeaConnection( serial );
141  }
142  else
143  {
144  delete serial;
145  }
146 #else
147  qWarning( "QT5SERIALPORT not found and mPortList matches serial port, this should never happen" );
148 #endif
149  }
150  }
151 
152  connect( mConn, &QgsGpsConnection::stateChanged, this, static_cast < void ( QgsGpsDetector::* )( const QgsGpsInformation & ) >( &QgsGpsDetector::detected ) );
153  connect( mConn, &QObject::destroyed, this, &QgsGpsDetector::connDestroyed );
154 
155  // leave 2s to pickup a valid string
156  QTimer::singleShot( 2000, this, &QgsGpsDetector::advance );
157 }
158 
160 {
161  Q_UNUSED( info )
162 
163  if ( !mConn )
164  {
165  // advance if connection was destroyed
166  advance();
167  }
168  else if ( mConn->status() == QgsGpsConnection::GPSDataReceived )
169  {
170  // signal detection
171  QgsGpsConnection *conn = mConn;
172  mConn = nullptr;
173  emit detected( conn );
174  deleteLater();
175  }
176 }
177 
178 void QgsGpsDetector::connDestroyed( QObject *obj )
179 {
180  if ( obj == mConn )
181  {
182  mConn = nullptr;
183  }
184 }
Evaluates NMEA sentences coming from gpsd.
Class to detect the GPS port.
void detected(const QgsGpsInformation &)
~QgsGpsDetector() override
void connDestroyed(QObject *)
void stateChanged(const QgsGpsInformation &info)
void detectionFailed()
Evaluates NMEA sentences coming from a GPS device.
Status status() const
Returns the status. Possible state are not connected, connected, data received.
static QList< QPair< QString, QString > > availablePorts()
QgsGpsDetector(const QString &portName)
Abstract base class for connection to a GPS device.