QGIS API Documentation  2.8.2-Wien
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 #ifdef HAVE_QT_MOBILITY_LOCATION
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 #ifdef HAVE_QT_MOBILITY_LOCATION
39  devs << QPair<QString, QString>( "internalGPS", tr( "internal GPS" ) );
40 #endif
41  // try local gpsd first
42  devs << QPair<QString, QString>( "localhost:2947:", tr( "local gpsd" ) );
43 
44 #ifdef linux
45  // look for linux serial devices
46  foreach ( QString linuxDev, QStringList() << "/dev/ttyS%1" << "/dev/ttyUSB%1" << "/dev/rfcomm%1" << "/dev/ttyACM%1" )
47  {
48  for ( int i = 0; i < 10; ++i )
49  {
50  if ( QFileInfo( linuxDev.arg( i ) ).exists() )
51  {
52  devs << QPair<QString, QString>( linuxDev.arg( i ), linuxDev.arg( i ) );
53  }
54  }
55  }
56 #endif
57 
58 #ifdef __FreeBSD__ // freebsd
59  // and freebsd devices (untested)
60  foreach ( QString freebsdDev, QStringList() << "/dev/cuaa%1" << "/dev/ucom%1" )
61  {
62  for ( int i = 0; i < 10; ++i )
63  {
64  if ( QFileInfo( freebsdDev.arg( i ) ).exists() )
65  {
66  devs << QPair<QString, QString>( freebsdDev.arg( i ), freebsdDev.arg( i ) );
67  }
68  }
69  }
70 #endif
71 
72 #ifdef sparc
73  // and solaris devices (also untested)
74  QString solarisDev( "/dev/cua/%1" );
75  for ( char i = 'a'; i < 'k'; ++i )
76  {
77  if ( QFileInfo( solarisDev.arg( i ) ).exists() )
78  {
79  devs << QPair<QString, QString>( solarisDev.arg( i ), solarisDev.arg( i ) );
80  }
81  }
82 #endif
83 
84 #if defined(Q_OS_WIN) || defined(Q_OS_MAC)
85  QList<QextPortInfo> ports = QextSerialEnumerator::getPorts();
86  foreach ( QextPortInfo port, ports )
87  {
88  devs << QPair<QString, QString>( port.portName, port.friendName );
89  }
90 #endif
91 
92  // OpenBSD, NetBSD etc? Anyone?
93 
94  return devs;
95 }
96 
97 QgsGPSDetector::QgsGPSDetector( QString portName )
98 {
99  mConn = 0;
100  mBaudList << BAUD4800 << BAUD9600 << BAUD38400 << BAUD57600 << BAUD115200; //add 57600 for SXBlueII GPS unit
101 
102  if ( portName.isEmpty() )
103  {
104  mPortList = availablePorts();
105  }
106  else
107  {
108  mPortList << QPair<QString, QString>( portName, portName );
109  }
110 
111  mPortIndex = 0;
112  mBaudIndex = -1;
113 }
114 
116 {
117  if ( mConn )
118  delete mConn;
119 }
120 
122 {
123  if ( mConn )
124  {
125  delete mConn;
126  }
127 
128  mConn = 0;
129 
130  while ( !mConn )
131  {
132  mBaudIndex++;
133  if ( mBaudIndex == mBaudList.size() )
134  {
135  mBaudIndex = 0;
136  mPortIndex++;
137  }
138 
139  if ( mPortIndex == mPortList.size() )
140  {
141  emit detectionFailed();
142  deleteLater();
143  return;
144  }
145 
146  if ( mPortList[ mPortIndex ].first.contains( ":" ) )
147  {
148  mBaudIndex = mBaudList.size() - 1;
149 
150  QStringList gpsParams = mPortList[ mPortIndex ].first.split( ":" );
151 
152  Q_ASSERT( gpsParams.size() >= 3 );
153 
154  mConn = new QgsGpsdConnection( gpsParams[0], gpsParams[1].toShort(), gpsParams[2] );
155  }
156  else if ( mPortList[ mPortIndex ].first.contains( "internalGPS" ) )
157  {
158 #ifdef HAVE_QT_MOBILITY_LOCATION
159  mConn = new QgsQtLocationConnection();
160 #else
161  qWarning( "QT_MOBILITY_LOCATION not found and mPortList matches internalGPS, this should never happen" );
162 #endif
163  }
164 
165  else
166  {
167  QextSerialPort *serial = new QextSerialPort( mPortList[ mPortIndex ].first, QextSerialPort::EventDriven );
168 
169  serial->setBaudRate( mBaudList[ mBaudIndex ] );
170  serial->setFlowControl( FLOW_OFF );
171  serial->setParity( PAR_NONE );
172  serial->setDataBits( DATA_8 );
173  serial->setStopBits( STOP_1 );
174 
175  if ( serial->open( QIODevice::ReadOnly | QIODevice::Unbuffered ) )
176  {
177  mConn = new QgsNMEAConnection( serial );
178  }
179  else
180  {
181  delete serial;
182  }
183  }
184  }
185 
186  connect( mConn, SIGNAL( stateChanged( const QgsGPSInformation & ) ), this, SLOT( detected( const QgsGPSInformation & ) ) );
187  connect( mConn, SIGNAL( destroyed( QObject * ) ), this, SLOT( connDestroyed( QObject * ) ) );
188 
189  // leave 2s to pickup a valid string
190  QTimer::singleShot( 2000, this, SLOT( advance() ) );
191 }
192 
194 {
195  Q_UNUSED( info );
196 
197  if ( !mConn )
198  {
199  // advance if connection was destroyed
200  advance();
201  }
202  else if ( mConn->status() == QgsGPSConnection::GPSDataReceived )
203  {
204  // signal detection
205  QgsGPSConnection *conn = mConn;
206  mConn = 0;
207  emit detected( conn );
208  deleteLater();
209  }
210 }
211 
212 void QgsGPSDetector::connDestroyed( QObject *obj )
213 {
214  if ( obj == mConn )
215  {
216  mConn = 0;
217  }
218 }