summaryrefslogtreecommitdiff
path: root/location/location.c
blob: 69b934c678046300cc006c413b13ef74ba57732f (plain)
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
100
101
#include "location.h"
#include "interfaces.h"
#include "legato.h"
#include "util.h"

le_posCtrl_ActivationRef_t posCtrlRef;
double lat, lon, horizAccuracy;
// we initially set these pointers to null
// so we can tell if there has never been a reading
double *latPtr = NULL, *lonPtr = NULL, *horizAccuracyPtr = NULL;
uint64_t lastReadingDatetime = 0;
le_timer_Ref_t pollingTimer;

bool hasReading() {
  return latPtr != NULL && lonPtr != NULL && horizAccuracyPtr != NULL;
}

bool canGetLocation() {
  return hasReading() && posCtrlRef != NULL;
}

void setLocationPtrs() {
  horizAccuracyPtr = &horizAccuracy;
  latPtr = ⪫
  lonPtr = &lon;
}

le_result_t brnkl_gps_getCurrentLocation(double* latitude,
                                         double* longitude,
                                         double* horizontalAccuracy,
                                         uint64_t* lastReading) {
  if (!canGetLocation()) {
    return LE_UNAVAILABLE;
  }
  *latitude = *latPtr;
  *longitude = *lonPtr;
  *horizontalAccuracy = *horizAccuracyPtr;
  *lastReading = lastReadingDatetime;
  return LE_OK;
}

/**
  * Attempts to use the GPS to find the current latitude, longitude and
 * horizontal accuracy within
  * the given timeout constraints.
  *
  * @return
  *      - LE_OK on success
  *      - LE_UNAVAILABLE if positioning services are unavailable
  *      - LE_TIMEOUT if the timeout expires before successfully acquiring the
 * location
  *
  * @note
  *      Blocks until the location has been identified or the timeout has
 * occurred.
  */
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;
    // set these so we know there is a reading
    lastReadingDatetime = GetCurrentTimestamp();
    if (!hasReading()) {
      setLocationPtrs();
    }
    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);
}

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();
}