File indexing completed on 2024-04-28 03:50:07

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2009 Eckhart Wörner <ewoerner@kde.org>
0004 // SPDX-FileCopyrightText: 2011 Bastian Holst <bastianholst@gmx.de>
0005 //
0006 
0007 #include "GpsdConnection.h"
0008 
0009 #include "MarbleDebug.h"
0010 
0011 #include <QTime>
0012 
0013 #include <cerrno>
0014 #include <clocale>
0015 
0016 using namespace Marble;
0017 /* TRANSLATOR Marble::GpsdConnection */
0018 
0019 const int gpsUpdateInterval = 1000; // ms
0020 const int gpsWaitTimeout = 200; // ms
0021 
0022 GpsdConnection::GpsdConnection( QObject* parent )
0023     : QObject( parent ),
0024 #if defined( GPSD_API_MAJOR_VERSION ) && ( GPSD_API_MAJOR_VERSION >= 5 )
0025       m_gpsd( "localhost", DEFAULT_GPSD_PORT ),
0026 #endif
0027       m_timer( nullptr )
0028 {
0029     m_oldLocale = setlocale( LC_NUMERIC, nullptr );
0030     setlocale( LC_NUMERIC, "C" );
0031     connect( &m_timer, SIGNAL(timeout()), this, SLOT(update()) );
0032 }
0033 
0034 GpsdConnection::~GpsdConnection()
0035 {
0036     setlocale( LC_NUMERIC, m_oldLocale );
0037 }
0038 
0039 void GpsdConnection::initialize()
0040 {
0041     m_timer.stop();
0042     bool success = false;
0043 #if defined( GPSD_API_MAJOR_VERSION ) && ( GPSD_API_MAJOR_VERSION >= 5 )
0044     success = true;
0045 #else
0046     gps_data_t* data = m_gpsd.open();
0047     success = ( data != 0 );
0048 #endif
0049 #if defined( GPSD_API_MAJOR_VERSION ) && ( GPSD_API_MAJOR_VERSION >= 3 ) && defined( WATCH_ENABLE )
0050     if ( success ) {
0051         success = (m_gpsd.stream( WATCH_ENABLE ) != nullptr);
0052     }
0053 #endif
0054     if ( success ) {
0055         m_status = PositionProviderStatusAcquiring;
0056         emit statusChanged( m_status );
0057         m_timer.start( gpsUpdateInterval );
0058     }
0059     else {
0060         // There is also gps_errstr() for libgps version >= 2.90,
0061         // but it doesn't return a sensible error description
0062         switch ( errno ) {
0063             case NL_NOSERVICE:
0064                 m_error = tr("Internal gpsd error (cannot get service entry)");
0065                 break;
0066             case NL_NOHOST:
0067                 m_error = tr("Internal gpsd error (cannot get host entry)");
0068                 break;
0069             case NL_NOPROTO:
0070                 m_error = tr("Internal gpsd error (cannot get protocol entry)");
0071                 break;
0072             case NL_NOSOCK:
0073                 m_error = tr("Internal gpsd error (unable to create socket)");
0074                 break;
0075             case NL_NOSOCKOPT:
0076                 m_error = tr("Internal gpsd error (unable to set socket option)");
0077                 break;
0078             case NL_NOCONNECT:
0079                 m_error = tr("No GPS device found by gpsd.");
0080                 break;
0081             default:
0082                 m_error = tr("Unknown error when opening gpsd connection");
0083                 break;
0084         }
0085 
0086         m_status = PositionProviderStatusError;
0087         emit statusChanged( m_status );
0088 
0089         mDebug() << "Connection to gpsd failed, no position info available: " << m_error;
0090     }
0091 }
0092 
0093 void GpsdConnection::update()
0094 {
0095 #if defined( GPSD_API_MAJOR_VERSION ) && ( GPSD_API_MAJOR_VERSION >= 12 ) && defined( PACKET_SET )
0096     gps_data_t* data = nullptr;
0097 
0098     if ( m_gpsd.waiting(gpsUpdateInterval * 1000) )
0099     {
0100         gps_data_t *currentData = m_gpsd.read();
0101 
0102         if( currentData && currentData->set & PACKET_SET ) {
0103             data = currentData;
0104         }
0105     }
0106 
0107     if ( data ) {
0108         emit gpsdInfo( *data );
0109     }
0110 #else
0111 #if defined( GPSD_API_MAJOR_VERSION ) && ( GPSD_API_MAJOR_VERSION >= 4 ) && defined( PACKET_SET )
0112     gps_data_t *data = nullptr;
0113 
0114     QTime watchdog;
0115     watchdog.start();
0116 
0117 #if defined( GPSD_API_MAJOR_VERSION ) && ( GPSD_API_MAJOR_VERSION >= 5 )
0118     while ( m_gpsd.waiting( 0 ) && watchdog.elapsed() < gpsWaitTimeout ) {
0119         gps_data_t *currentData = m_gpsd.read();
0120 #else
0121     while ( m_gpsd.waiting() && watchdog.elapsed() < gpsWaitTimeout ) {
0122         gps_data_t *currentData = m_gpsd.poll();
0123 #endif
0124 
0125         if( currentData && currentData->set & PACKET_SET ) {
0126             data = currentData;
0127         }
0128     }
0129 
0130     if ( data ) {
0131         emit gpsdInfo( *data );
0132     }
0133 #else
0134 #if defined( GPSD_API_MAJOR_VERSION ) && ( GPSD_API_MAJOR_VERSION == 3 ) && defined( PACKET_SET )
0135     gps_data_t *data = m_gpsd.poll();
0136 #else
0137     gps_data_t* data = m_gpsd.query( "o" );
0138 #endif
0139 
0140     if ( data ) {
0141         emit gpsdInfo( *data );
0142     }
0143     else if ( m_status != PositionProviderStatusAcquiring ) {
0144         mDebug() << "Lost connection to gpsd, trying to re-open.";
0145         initialize();
0146     }
0147 #endif
0148 #endif
0149 }
0150 
0151 QString GpsdConnection::error() const
0152 {
0153     return m_error;
0154 }
0155 
0156 #include "moc_GpsdConnection.cpp"