summaryrefslogtreecommitdiff
path: root/location
diff options
context:
space:
mode:
Diffstat (limited to 'location')
-rw-r--r--location/Component.cdef28
-rw-r--r--location/location.c101
-rw-r--r--location/location.h13
3 files changed, 142 insertions, 0 deletions
diff --git a/location/Component.cdef b/location/Component.cdef
new file mode 100644
index 0000000..7907352
--- /dev/null
+++ b/location/Component.cdef
@@ -0,0 +1,28 @@
+cflags:
+{
+ -std=c99
+ -I$BRNKL_ROOT/apps/util
+}
+
+requires:
+{
+ api:
+ {
+ le_posCtrl = ${LEGATO_ROOT}/interfaces/positioning/le_posCtrl.api
+ le_pos = ${LEGATO_ROOT}/interfaces/positioning/le_pos.api
+ }
+}
+
+provides:
+{
+ api:
+ {
+ $CURDIR/../brnkl_gps.api
+ }
+}
+
+sources:
+{
+ location.c
+ $BRNKL_ROOT/apps/util/util.c
+}
diff --git a/location/location.c b/location/location.c
new file mode 100644
index 0000000..69b934c
--- /dev/null
+++ b/location/location.c
@@ -0,0 +1,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();
+}
diff --git a/location/location.h b/location/location.h
new file mode 100644
index 0000000..8ffa3ed
--- /dev/null
+++ b/location/location.h
@@ -0,0 +1,13 @@
+#ifndef LOCATION_H
+#define LOCATION_H
+
+#include "legato.h"
+
+// Used to convert GPS int to double
+#define GPS_DECIMAL_SHIFT 6
+// Used for distance calculations
+#define MIN_REQUIRED_HORIZ_ACCURACY_METRES 10 // TODO validate this
+#define POLL_PERIOD_SEC 2 * 60
+#define RETRY_PERIOD_SEC 1
+
+#endif // LOCATION_H