1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
#include "location.h"
#include "interfaces.h"
#include "legato.h"
#include "util.h"
le_posCtrl_ActivationRef_t posCtrlRef;
double lat, lon, horizAccuracy;
uint64_t lastReadingDatetime = 0;
le_timer_Ref_t pollingTimer;
/**
* Determine if we have a reading
*
* (other things make factor in here down the road)
*/
bool hasReading() {
return lastReadingDatetime != 0;
}
/**
* Determine if we can provide an IPC caller
* with a location
*/
bool canGetLocation() {
return hasReading() && posCtrlRef != NULL;
}
/**
* IPC function to get location
*/
le_result_t brnkl_gps_getCurrentLocation(double* latitude,
double* longitude,
double* horizontalAccuracy,
uint64_t* lastReading) {
if (!canGetLocation()) {
return LE_UNAVAILABLE;
}
*latitude = lat;
*longitude = lon;
*horizontalAccuracy = horizAccuracy;
*lastReading = lastReadingDatetime;
return LE_OK;
}
/**
* Main polling function
*
* Change MIN_REQUIRED_HORIZ_ACCURACY_METRES if
* a more/less accurate fix is required
*/
void getLocation(le_timer_Ref_t timerRef) {
le_timer_Stop(timerRef);
LE_DEBUG("Checking GPS position");
int32_t rawLat, rawLon, rawHoriz;
le_result_t result = le_pos_Get2DLocation(&rawLat, &rawLon, &rawHoriz);
bool isAccurate = rawHoriz <= MIN_REQUIRED_HORIZ_ACCURACY_METRES;
bool resOk = result == LE_OK;
if (resOk && isAccurate) {
double denom = powf(10, GPS_DECIMAL_SHIFT); // divide by this
lat = ((double)rawLat) / denom;
lon = ((double)rawLon) / denom;
// no conversion required for horizontal accuracy
horizAccuracy = (double)rawHoriz;
lastReadingDatetime = GetCurrentTimestamp();
LE_INFO("Got reading...");
LE_INFO("lat: %f, long: %f, horiz: %f", lat, lon, horizAccuracy);
le_timer_SetMsInterval(timerRef, POLL_PERIOD_SEC * 1000);
} else {
if (!isAccurate && resOk) {
LE_INFO("Rejected for accuracy (%d m)", rawHoriz);
}
LE_INFO("Failed to get reading... retrying in %d seconds",
RETRY_PERIOD_SEC);
le_timer_SetMsInterval(timerRef, RETRY_PERIOD_SEC * 1000);
}
le_timer_Start(timerRef);
}
/**
* Perform all required setup
*
* Note that we run this on a timer to avoid
* blocking up the main (only) thread. If this
* was run in a while(true) that sleeps,
* the IPC caller would be blocked indefinitely
*/
le_result_t gps_init() {
pollingTimer = le_timer_Create("GPS polling timer");
le_timer_SetHandler(pollingTimer, getLocation);
le_timer_SetRepeat(pollingTimer, 1);
le_timer_SetMsInterval(pollingTimer, 0);
posCtrlRef = le_posCtrl_Request();
le_timer_Start(pollingTimer);
return posCtrlRef != NULL ? LE_OK : LE_UNAVAILABLE;
}
COMPONENT_INIT {
gps_init();
}
|