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