From cf1e49f08d0cfef61d94105cf03f1a8abdaba75a Mon Sep 17 00:00:00 2001
From: Starbeamrainbowlabs <sbrl@starbeamrainbowlabs.com>
Date: Mon, 15 Jul 2019 15:25:51 +0100
Subject: [PATCH] Implement GPS delta checking

---
 iot/main/gps.cpp     | 26 +++++++++++++++++++++++++-
 iot/main/settings.h  |  9 ++++++++-
 iot/main/storage.cpp | 10 ++++++++++
 iot/main/storage.h   | 13 +++++++++++++
 4 files changed, 56 insertions(+), 2 deletions(-)

diff --git a/iot/main/gps.cpp b/iot/main/gps.cpp
index acb3483..f2ef746 100644
--- a/iot/main/gps.cpp
+++ b/iot/main/gps.cpp
@@ -1,7 +1,10 @@
+#include <TinyGPS.h>
+
 #include "gps.h"
 #include "settings.h"
+#include "power.h"
+#include "storage.h"
 
-#include <TinyGPS.h>
 
 SoftwareSerial gps_begin() {
 	// FUTURE: If this doesn't work as expected, we may want to find a more reliable SoftwareSerial library
@@ -67,6 +70,27 @@ GPSLocation gps_fetch() {
 		
 		// gps.f_get_position pushes the values into result directly
 		
+		#ifdef GPS_DELTA_CHECK
+		float last_reading_lat = store_eeprom_float_retrieve(sizeof(uint32_t) * 2);
+		float last_reading_lng = store_eeprom_float_retrieve(sizeof(uint32_t) * 2 + sizeof(float));
+		// Serial.println(last_reading_lat);
+		// Serial.println(last_reading_lng);
+		// Serial.println(result.lat);
+		// Serial.println(result.lng);
+		if(abs(last_reading_lat - result.lat) < GPS_DELTA_MIN_LAT &&
+			abs(last_reading_lng - result.lng) < GPS_DELTA_MIN_LNG &&
+			last_reading_lat == last_reading_lat && // Ensure that the last readings aren't NaN
+			last_reading_lng == last_reading_lng) {
+			Serial.println(F("[gps] No movement detected"));
+			power_off();
+		}
+		
+		// Save this location to EEPROM
+		store_eeprom_float_save(sizeof(uint32_t) * 2, result.lat);
+		store_eeprom_float_save(sizeof(uint32_t) * 2 + sizeof(float), result.lng);
+		#endif
+		
+		// TODO: Don't send a message at night
 		#ifdef SD_DEBUG_ENABLED
 		int year;
 		byte month, day, hour, minute, second, _hundredths;
diff --git a/iot/main/settings.h b/iot/main/settings.h
index 8850bf7..9dba02a 100644
--- a/iot/main/settings.h
+++ b/iot/main/settings.h
@@ -51,7 +51,7 @@
 // the RX pin, and the GPS device transmits messages on the TX.
 #define PIN_GPS_RX	5
 // The *RX* pin on the GPS device.
-// This is swapped because where the GPs device is receiving, we aresending and 
+// This is swapped because where the GPS device is receiving, we aresending and 
 // vice versa.
 // The TX / RX here are according to *our* side, not the GPS device's side.
 #define PIN_GPS_TX	4
@@ -61,6 +61,13 @@
 // 9600 is the correct speed for a NEO-6M.
 #define BAUD_GPS	9600
 
+// Uncomment to cause the system to check the newest GPS value against the last one, and only transmit a reading if they differ by more than (0.0003, 0.0002) - ~(20m, 14m).
+// Unhelpful for debugging, but useful in production to reduce the number of messages sent when stationary.
+#define GPS_DELTA_CHECK
+
+#define GPS_DELTA_MIN_LAT	0.0003
+#define GPS_DELTA_MIN_LNG	0.0002
+
 //////////////////////////////////
 ////////// microSD Card //////////
 //////////////////////////////////
diff --git a/iot/main/storage.cpp b/iot/main/storage.cpp
index 0fc1539..5acabbe 100644
--- a/iot/main/storage.cpp
+++ b/iot/main/storage.cpp
@@ -61,3 +61,13 @@ uint32_t store_eeprom_uint32_retrieve(uint8_t offset) {
 	EEPROM.get(offset, result);
 	return result;
 }
+
+void store_eeprom_float_save(uint8_t offset, float value) {
+	EEPROM.put(offset, value);
+}
+
+float store_eeprom_float_retrieve(uint8_t offset) {
+	float result;
+	EEPROM.get(offset, result);
+	return result;
+}
diff --git a/iot/main/storage.h b/iot/main/storage.h
index 195d3b7..a3136f5 100644
--- a/iot/main/storage.h
+++ b/iot/main/storage.h
@@ -35,5 +35,18 @@ void store_eeprom_uint32_save(uint8_t offset, uint32_t value);
  */
 uint32_t store_eeprom_uint32_retrieve(uint8_t offset);
 
+/**
+ * The same as store_eeprom_uint32_save, but for floats
+ * @param	offset	The offset to save the value to.
+ * @param	value	The value to save
+ */
+void store_eeprom_float_save(uint8_t offset, float value);
+
+/**
+ * The same as store_eeprom_uint32_retrieve, but for floats
+ * @param	offset	The offset to retrieve from
+ * @return	The retreived value
+ */
+float store_eeprom_float_retrieve(uint8_t offset);
 
 // void store_end();
