1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2009 Eckhart Wörner <ewoerner@kde.org>
4 //
5 
6 #include "GpsdPositionProviderPlugin.h"
7 
8 #include "GpsdThread.h"
9 #include "MarbleDebug.h"
10 
11 #include <QIcon>
12 
13 #include <cmath>
14 
15 using namespace Marble;
16 /* TRANSLATOR Marble::GpsdPositionProviderPlugin */
17 
name() const18 QString GpsdPositionProviderPlugin::name() const
19 {
20     return tr( "Gpsd position provider Plugin" );
21 }
22 
nameId() const23 QString GpsdPositionProviderPlugin::nameId() const
24 {
25     return QStringLiteral("Gpsd");
26 }
27 
guiString() const28 QString GpsdPositionProviderPlugin::guiString() const
29 {
30     return tr( "gpsd" );
31 }
32 
version() const33 QString GpsdPositionProviderPlugin::version() const
34 {
35     return QStringLiteral("1.0");
36 }
37 
description() const38 QString GpsdPositionProviderPlugin::description() const
39 {
40     return tr( "Reports the position of a GPS device." );
41 }
42 
copyrightYears() const43 QString GpsdPositionProviderPlugin::copyrightYears() const
44 {
45     return QStringLiteral("2009");
46 }
47 
pluginAuthors() const48 QVector<PluginAuthor> GpsdPositionProviderPlugin::pluginAuthors() const
49 {
50     return QVector<PluginAuthor>()
51             << PluginAuthor(QStringLiteral("Eckhart Wörner"), QStringLiteral("ewoerner@kde.org"));
52 
53 }
54 
icon() const55 QIcon GpsdPositionProviderPlugin::icon() const
56 {
57     return QIcon();
58 }
59 
initialize()60 void GpsdPositionProviderPlugin::initialize()
61 {
62     m_status = PositionProviderStatusAcquiring;
63     emit statusChanged( m_status );
64 
65     m_thread = new GpsdThread;
66     connect( m_thread, SIGNAL(gpsdInfo(gps_data_t)),
67              this, SLOT(update(gps_data_t)) );
68     connect( m_thread, SIGNAL(statusChanged(PositionProviderStatus)),
69              this, SIGNAL(statusChanged(PositionProviderStatus)) );
70     m_thread->start();
71 }
72 
update(gps_data_t data)73 void GpsdPositionProviderPlugin::update( gps_data_t data )
74 {
75     PositionProviderStatus oldStatus = m_status;
76     GeoDataCoordinates oldPosition = m_position;
77 #if defined(STATUS_UNK) // STATUS_NO_FIX was renamed to STATUS_UNK without bumping API version
78     if ( data.fix.status == STATUS_UNK || std::isnan( data.fix.longitude ) || std::isnan( data.fix.latitude ) )
79 #elif defined( GPSD_API_MAJOR_VERSION ) && ( GPSD_API_MAJOR_VERSION >= 10 )
80     if ( data.fix.status == STATUS_NO_FIX || std::isnan( data.fix.longitude ) || std::isnan( data.fix.latitude ) )
81 #else
82     if ( data.status == STATUS_NO_FIX || std::isnan( data.fix.longitude ) || std::isnan( data.fix.latitude ) )
83 #endif
84         m_status = PositionProviderStatusAcquiring;
85     else {
86         m_status = PositionProviderStatusAvailable;
87         m_position.set( data.fix.longitude, data.fix.latitude,
88                         data.fix.altitude, GeoDataCoordinates::Degree );
89         if (data.fix.mode == MODE_2D) {
90             m_position.setAltitude(0);
91         }
92 
93         m_accuracy.level = GeoDataAccuracy::Detailed;
94 #if defined( GPSD_API_MAJOR_VERSION ) && ( GPSD_API_MAJOR_VERSION >= 3 )
95         if ( !std::isnan( data.fix.epx ) && !std::isnan( data.fix.epy ) ) {
96             m_accuracy.horizontal = qMax( data.fix.epx, data.fix.epy );
97         }
98 #else
99         if ( !std::isnan( data.fix.eph ) ) {
100             m_accuracy.horizontal = data.fix.eph;
101         }
102 #endif
103         if ( !std::isnan( data.fix.epv ) ) {
104             m_accuracy.vertical = data.fix.epv;
105         }
106 
107         if( !std::isnan(data.fix.speed ) )
108         {
109             m_speed = data.fix.speed;
110         }
111 
112         if( !std::isnan( data.fix.track ) )
113         {
114             m_track = data.fix.track;
115         }
116 
117 #if defined( GPSD_API_MAJOR_VERSION ) && ( GPSD_API_MAJOR_VERSION >= 9 )
118         if ( !std::isnan( data.fix.time.tv_sec ) )
119 #else
120         if ( !std::isnan( data.fix.time ) )
121 #endif
122         {
123 #if defined( GPSD_API_MAJOR_VERSION ) && ( GPSD_API_MAJOR_VERSION >= 9 )
124             m_timestamp = QDateTime::fromMSecsSinceEpoch( data.fix.time.tv_sec * 1000 + data.fix.time.tv_nsec / 1000000 );
125 #else
126             m_timestamp = QDateTime::fromMSecsSinceEpoch( data.fix.time * 1000 );
127 #endif
128         }
129     }
130     if (m_status != oldStatus)
131         emit statusChanged( m_status );
132     if (!(oldPosition == m_position)) {
133         emit positionChanged( m_position, m_accuracy );
134     }
135 }
136 
isInitialized() const137 bool GpsdPositionProviderPlugin::isInitialized() const
138 {
139     return m_thread;
140 }
141 
newInstance() const142 PositionProviderPlugin* GpsdPositionProviderPlugin::newInstance() const
143 {
144     return new GpsdPositionProviderPlugin;
145 }
146 
status() const147 PositionProviderStatus GpsdPositionProviderPlugin::status() const
148 {
149     return m_status;
150 }
151 
position() const152 GeoDataCoordinates GpsdPositionProviderPlugin::position() const
153 {
154     return m_position;
155 }
156 
accuracy() const157 GeoDataAccuracy GpsdPositionProviderPlugin::accuracy() const
158 {
159     return m_accuracy;
160 }
161 
GpsdPositionProviderPlugin()162 GpsdPositionProviderPlugin::GpsdPositionProviderPlugin() : m_thread( nullptr ),
163     m_speed( 0.0 ),
164     m_track( 0.0 )
165 {
166 }
167 
~GpsdPositionProviderPlugin()168 GpsdPositionProviderPlugin::~GpsdPositionProviderPlugin()
169 {
170     if ( m_thread ) {
171         m_thread->exit();
172 
173         if ( !m_thread->wait( 5000 ) ) {
174             mDebug() << "Failed to stop GpsdThread";
175         }
176         else {
177             delete m_thread;
178         }
179     }
180 }
181 
speed() const182 qreal GpsdPositionProviderPlugin::speed() const
183 {
184     return m_speed;
185 }
186 
direction() const187 qreal GpsdPositionProviderPlugin::direction() const
188 {
189     return m_track;
190 }
191 
timestamp() const192 QDateTime GpsdPositionProviderPlugin::timestamp() const
193 {
194     return m_timestamp;
195 }
196 
197 
error() const198 QString GpsdPositionProviderPlugin::error() const
199 {
200     return m_thread->error();
201 }
202 
203 #include "moc_GpsdPositionProviderPlugin.cpp"
204