QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
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#include "qgssettings.h"
24
25#if 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
38QList< QPair<QString, QString> > QgsGpsDetector::availablePorts()
39{
40 QList< QPair<QString, QString> > devs;
41
42 // try local QtLocation first
43#if 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 ( const QSerialPortInfo &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
61QgsGpsDetector::QgsGpsDetector( const QString &portName )
62{
63#if defined( HAVE_QT5SERIALPORT )
64 mBaudList << QSerialPort::Baud4800 << QSerialPort::Baud9600 << QSerialPort::Baud38400 << QSerialPort::Baud57600 << QSerialPort::Baud115200; //add 57600 for SXBlueII GPS unit
65#endif
66
67 if ( portName.isEmpty() )
68 {
69 mPortList = availablePorts();
70 }
71 else
72 {
73 mPortList << QPair<QString, QString>( portName, portName );
74 }
75}
76
78
80{
81 mConn.reset();
82
83 QgsSettings settings;
84
85 while ( !mConn )
86 {
87 mBaudIndex++;
88 if ( mBaudIndex == mBaudList.size() )
89 {
90 mBaudIndex = 0;
91 mPortIndex++;
92 }
93
94 if ( mPortIndex == mPortList.size() )
95 {
96 emit detectionFailed();
97 deleteLater();
98 return;
99 }
100
101 if ( mPortList.at( mPortIndex ).first.contains( ':' ) )
102 {
103 mBaudIndex = mBaudList.size() - 1;
104
105 QStringList gpsParams = mPortList.at( mPortIndex ).first.split( ':' );
106
107 Q_ASSERT( gpsParams.size() >= 3 );
108
109 mConn = std::make_unique< QgsGpsdConnection >( gpsParams[0], gpsParams[1].toShort(), gpsParams[2] );
110 }
111 else if ( mPortList.at( mPortIndex ).first.contains( QLatin1String( "internalGPS" ) ) )
112 {
113#if defined(QT_POSITIONING_LIB)
114 mConn = std::make_unique< QgsQtLocationConnection >();
115#else
116 qWarning( "QT_POSITIONING_LIB not found and mPortList matches internalGPS, this should never happen" );
117#endif
118 }
119 else
120 {
121#if defined( HAVE_QT5SERIALPORT )
122 std::unique_ptr< QSerialPort > serial = std::make_unique< QSerialPort >( mPortList.at( mPortIndex ).first );
123
124 serial->setBaudRate( mBaudList[ mBaudIndex ] );
125
126 serial->setFlowControl( settings.enumValue( QStringLiteral( "gps/flow_control" ), QSerialPort::NoFlowControl, QgsSettings::Core ) );
127 serial->setParity( settings.enumValue( QStringLiteral( "gps/parity" ), QSerialPort::NoParity, QgsSettings::Core ) );
128 serial->setDataBits( settings.enumValue( QStringLiteral( "gps/data_bits" ), QSerialPort::Data8, QgsSettings::Core ) );
129 serial->setStopBits( settings.enumValue( QStringLiteral( "gps/stop_bits" ), QSerialPort::OneStop, QgsSettings::Core ) );
130
131 if ( serial->open( QIODevice::ReadOnly ) )
132 {
133 mConn = std::make_unique< QgsNmeaConnection >( serial.release() );
134 }
135#else
136 qWarning( "QT5SERIALPORT not found and mPortList matches serial port, this should never happen" );
137#endif
138 }
139 }
140
141 connect( mConn.get(), &QgsGpsConnection::stateChanged, this, static_cast < void ( QgsGpsDetector::* )( const QgsGpsInformation & ) >( &QgsGpsDetector::detected ) );
142 connect( mConn.get(), &QObject::destroyed, this, &QgsGpsDetector::connDestroyed );
143
144 // leave 2s to pickup a valid string
145 QTimer::singleShot( 2000, this, &QgsGpsDetector::advance );
146}
147
149{
150 Q_UNUSED( info )
151
152 if ( !mConn )
153 {
154 // advance if connection was destroyed
155 advance();
156 }
157 else if ( mConn->status() == QgsGpsConnection::GPSDataReceived )
158 {
159 // signal detected
160
161 // let's hope there's a single, unique connection to this signal... otherwise... boom
162 emit detected( mConn.release() );
163
164 deleteLater();
165 }
166}
167
169{
170 // WTF? This whole class needs re-writing...
171 if ( obj == mConn.get() )
172 {
173 mConn.release();
174 }
175}
void stateChanged(const QgsGpsInformation &info)
Class to detect the GPS port.
~QgsGpsDetector() override
void connDestroyed(QObject *)
void detected(const QgsGpsInformation &)
static QList< QPair< QString, QString > > availablePorts()
QgsGpsDetector(const QString &portName)
void detectionFailed()
Encapsulates information relating to a GPS position fix.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:62
T enumValue(const QString &key, const T &defaultValue, const Section section=NoSection)
Returns the setting value for a setting based on an enum.
Definition: qgssettings.h:284