Added signal strength indicator to detail screen. Changed speed treshold to change...
[jspeed] / src / location.cpp
1 /*
2  * This file is part of jSpeed.
3  *
4  * jSpeed is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * jSpeed is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
16  *
17  */
18
19 #include <QtCore/QDebug>
20 #include "location.h"
21
22 namespace
23 {
24     static const double KM_MULTIPLIER = 1.0;
25     static const double MILE_MULTIPLIER = 0.621371192;
26 }
27
28 Location::Unit Location::unit_ = Location::KM;
29
30 Location::Location(QObject* parent): QObject(parent), started_(false),
31 control_(0), device_(0)
32 {
33     g_type_init();
34 }
35
36 Location::~Location()
37 {
38     end();
39 }
40
41 void Location::start()
42 {
43     control_ = location_gpsd_control_get_default();
44     device_ = (LocationGPSDevice*) g_object_new(LOCATION_TYPE_GPS_DEVICE, NULL);
45
46     g_object_set(G_OBJECT(control_),
47                  "preferred-method", LOCATION_METHOD_USER_SELECTED,
48                  "preferred-interval", LOCATION_INTERVAL_DEFAULT,
49                  NULL);
50
51     g_signal_connect(control_, "error-verbose", G_CALLBACK(onError), this);
52     g_signal_connect(device_, "changed", G_CALLBACK(onChanged), this);
53
54     location_gpsd_control_start(control_);
55
56     started_ = true;
57 }
58
59 void Location::end()
60 {
61     if(!started_)
62     {
63         return;
64     }
65
66     location_gpsd_control_stop(control_);
67
68     g_object_unref(device_);
69     device_ = 0;
70     g_object_unref(control_);
71     control_ = 0;
72
73     started_ = false;
74 }
75
76 bool Location::hasFix() const
77 {
78     if(!started_)
79     {
80         return false;
81     }
82
83     return (device_->status == LOCATION_GPS_DEVICE_STATUS_FIX);
84 }
85
86 double Location::getSignalStrength() const
87 {
88     if(!hasFix())
89     {
90         qDebug() << "No fix";
91         return 0.0;
92     }
93
94     if(device_->satellites_in_view == 0)
95     {
96         return 0.0;
97     }
98
99     double val = (device_->satellites_in_use / static_cast<double>(device_->satellites_in_view)) * 100.0;
100
101     if(val > 100.0)
102     {
103         val = 100.0;
104     }
105
106     return val;
107 }
108
109 void Location::setUnit(Location::Unit unit)
110 {
111     unit_ = unit;
112 }
113
114 Location::Unit Location::getUnit()
115 {
116     return unit_;
117 }
118
119 double Location::getUnitMultiplier()
120 {
121     if(unit_ == MILE)
122     {
123         return MILE_MULTIPLIER;
124     }
125
126     return KM_MULTIPLIER;
127 }
128
129 void Location::onChanged(LocationGPSDevice *device, gpointer data)
130 {
131     if(device && device->fix &&
132        !(device->fix->fields & LOCATION_GPS_DEVICE_NONE_SET))
133     {
134
135         Fix fix;
136         fix.unit = unit_;
137         fix.time = device->fix->time;
138         fix.ept = device->fix->ept;
139
140         if (device->fix->fields & LOCATION_GPS_DEVICE_LATLONG_SET)
141         {
142             fix.latitude = device->fix->latitude;
143             fix.longitude = device->fix->longitude;
144             fix.eph = device->fix->eph;
145         }
146
147         if(device->fix->fields & LOCATION_GPS_DEVICE_ALTITUDE_SET)
148         {
149             fix.altitude = device->fix->altitude;
150             fix.epv = device->fix->epv;
151         }
152
153         if(device->fix->fields & LOCATION_GPS_DEVICE_SPEED_SET)
154         {
155             fix.kmSpeed = device->fix->speed;
156             fix.speed = device->fix->speed * getUnitMultiplier();
157             fix.eps = device->fix->eps;
158         }
159
160         if(device->fix->fields & LOCATION_GPS_DEVICE_TRACK_SET)
161         {
162             fix.track = device->fix->track;
163             fix.epd = device->fix->epd;
164         }
165
166         if(device->fix->fields & LOCATION_GPS_DEVICE_CLIMB_SET)
167         {
168             fix.climb = device->fix->climb;
169             fix.epc = device->fix->epc;
170         }
171
172         Location* meh = (Location*) data;
173         meh->emit locationChanged(fix);
174     }
175 }
176
177 void Location::onError(LocationGPSDControl *control, LocationGPSDControlError error, gpointer data)
178 {
179     Q_UNUSED(control);
180
181     Error err = SYSTEM_ERROR;
182
183     switch(error)
184     {
185     case LOCATION_ERROR_USER_REJECTED_DIALOG:
186         err = USER_REJECTED_DIALOG;
187         break;
188     case LOCATION_ERROR_USER_REJECTED_SETTINGS:
189         err = USER_REJECTED_SETTINGS;
190         break;
191     case LOCATION_ERROR_BT_GPS_NOT_AVAILABLE:
192         err = GPS_NOT_AVAILABLE;
193         break;
194     case LOCATION_ERROR_METHOD_NOT_ALLOWED_IN_OFFLINE_MODE:
195         err = NOT_ALLOWED_IN_OFFLINE_MODE;
196         break;
197     case LOCATION_ERROR_SYSTEM:
198         err = SYSTEM_ERROR;
199         break;
200     }
201
202     Location* meh = (Location*) data;
203     meh->emit locationError(err);
204 }
205
206 Location::Fix::Fix()
207 {
208     unit = KM;
209     kmSpeed = 0.0;
210     time = 0.0;
211     ept = 0.0;
212     latitude = 0.0;
213     longitude = 0.0;
214     eph = 0.0;
215     altitude = 0.0;
216     epv = 0.0;
217     track = 0.0;
218     epd = 0.0;
219     speed = 0.0;
220     eps = 0.0;
221     climb = 0.0;
222     epc = 0.0;
223 }