Skip to content

Commit 0376181

Browse files
committed
GPS - Fully refactor out common HAL to hardware and parsing to model
1 parent 5ccb7c7 commit 0376181

File tree

4 files changed

+255
-58
lines changed

4 files changed

+255
-58
lines changed

src/components/gps/controller.cpp

Lines changed: 27 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -165,65 +165,39 @@ void GPSController::update() {
165165
_gps_model->CreateGPSEvent();
166166
char nmea_sentence[MAX_LEN_NMEA_SENTENCE];
167167
bool has_gps_event = false;
168-
// TODO: You were here
169-
// Thoughts:
170-
// 1. Split out the parsing into the hardware HAL API
171-
// 2. Return the sentence back to the controller func, here
172-
// 3. Controller will then the sentence to the model for parsing/inclusion
173-
// into a GPSEvent
174-
// 4. controller sends it
175168
while (drv->NmeaBufPop(nmea_sentence) != -1) {
176-
// Parse the NMEA sentence
169+
// Let the driver parse the NMEA sentence
177170
WS_DEBUG_PRINT("[gps] Parsing NMEA sentence: ");
178171
WS_DEBUG_PRINTLN(nmea_sentence);
179-
if (!drv->ParseNMEASentence(nmea_sentence)) {
172+
if (!drv->ParseNMEASentence(nmea_sentence))
180173
continue; // Skip this sentence if parsing failed
181-
}
182-
has_gps_event = true;
183-
// Build a GPSEvent message from the sentence
184-
wippersnapper_gps_GPSDateTime datetime = _gps_model->CreateGpsDatetime(
185-
ada_gps->hour, ada_gps->minute, ada_gps->seconds,
186-
ada_gps->milliseconds, ada_gps->day, ada_gps->month, ada_gps->year);
187-
if (strncmp(nmea_sentence, "$GPRMC", 6) == 0 ||
188-
strncmp(nmea_sentence, "$GNRMC", 6) == 0) {
189-
_gps_model->AddGpsEventRMC(
190-
datetime, ada_gps->fix, ada_gps->latitude, &ada_gps->lat,
191-
ada_gps->longitude, &ada_gps->lon, ada_gps->speed, ada_gps->angle);
192-
} else if (strncmp(nmea_sentence, "$GPGGA", 6) == 0 ||
193-
strncmp(nmea_sentence, "$GNGGA", 6) == 0) {
194-
_gps_model->AddGpsEventGGA(
195-
datetime, ada_gps->fix, ada_gps->latitude, &ada_gps->lat,
196-
ada_gps->longitude, &ada_gps->lon, ada_gps->satellites,
197-
ada_gps->HDOP, ada_gps->altitude, ada_gps->geoidheight);
198-
} else {
199-
WS_DEBUG_PRINTLN(
200-
"[gps] WARNING - Parsed sentence is not type RMC or GGA!");
201-
}
202-
}
174+
else
175+
has_gps_event = true; // We have a valid NMEA sentence
203176

204-
// We did not create a GPSEvent because the NMEA sentences were not
205-
// GGA/RMC or parsed correctly
206-
if (!has_gps_event) {
207-
WS_DEBUG_PRINTLN(
208-
"[gps] No GPSEvent created from NMEA sentences!"); // TODO: Remove
209-
// this in prod
210-
continue;
211-
}
177+
// Using the Model, process the NMEA sentence into a GPSEvent
178+
WS_DEBUG_PRINTLN("[gps] Processing NMEA sentence...");
179+
_gps_model->ProcessNMEASentence(nmea_sentence, drv);
212180

213-
// Encode and publish to IO
214-
WS_DEBUG_PRINT("[gps] Encoding and publishing GPSEvent to IO...");
215-
bool did_encode = _gps_model->EncodeGPSEvent();
216-
if (!did_encode) {
217-
WS_DEBUG_PRINTLN("[gps] ERROR: Failed to encode GPSEvent!");
218-
} else {
219-
// Publish the GPSEvent to IO
220-
if (!WsV2.PublishSignal(wippersnapper_signal_DeviceToBroker_gps_event_tag,
221-
_gps_model->GetGPSEvent())) {
222-
WS_DEBUG_PRINTLN("[gps] ERROR: Failed to publish GPSEvent!");
181+
// We did not create a GPSEvent because the NMEA sentences were not
182+
// GGA/RMC or parsed correctly
183+
if (!has_gps_event)
184+
continue;
185+
186+
// Encode and publish to IO
187+
WS_DEBUG_PRINT("[gps] Encoding and publishing GPSEvent to IO...");
188+
bool did_encode = _gps_model->EncodeGPSEvent();
189+
if (!did_encode) {
190+
WS_DEBUG_PRINTLN("[gps] ERROR: Failed to encode GPSEvent!");
223191
} else {
224-
WS_DEBUG_PRINTLN("...ok!");
192+
// Publish the GPSEvent to IO
193+
if (!WsV2.PublishSignal(
194+
wippersnapper_signal_DeviceToBroker_gps_event_tag,
195+
_gps_model->GetGPSEvent())) {
196+
WS_DEBUG_PRINTLN("[gps] ERROR: Failed to publish GPSEvent!");
197+
} else {
198+
WS_DEBUG_PRINTLN("...ok!");
199+
}
225200
}
201+
drv->SetPollPeriodPrv(cur_time);
226202
}
227-
drv->SetPollPeriodPrv(cur_time);
228-
}
229-
}
203+
}

src/components/gps/hardware.cpp

Lines changed: 188 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,10 @@ bool GPSHardware::ParseNMEASentence(char *sentence) {
632632
return false;
633633
}
634634

635+
/*!
636+
* @brief Gets the hours from the GPS module.
637+
* @returns The hours (0-23), or 0 if the GPS driver type is not set.
638+
*/
635639
uint8_t GPSHardware::GetHour() {
636640
if (_driver_type == GPS_DRV_MTK) {
637641
return _ada_gps->hour;
@@ -641,6 +645,10 @@ uint8_t GPSHardware::GetHour() {
641645
return 0;
642646
}
643647

648+
/*!
649+
* @brief Gets the minute from the GPS module.
650+
* @returns The minute (0-59), or 0 if the GPS driver type is not set.
651+
*/
644652
uint8_t GPSHardware::GetMinute() {
645653
if (_driver_type == GPS_DRV_MTK) {
646654
return _ada_gps->minute;
@@ -650,6 +658,10 @@ uint8_t GPSHardware::GetMinute() {
650658
return 0;
651659
}
652660

661+
/*!
662+
* @brief Gets the seconds from the GPS module.
663+
* @returns The seconds (0-59), or 0 if the GPS driver type is not set.
664+
*/
653665
uint8_t GPSHardware::GetSeconds() {
654666
if (_driver_type == GPS_DRV_MTK) {
655667
return _ada_gps->seconds;
@@ -659,6 +671,11 @@ uint8_t GPSHardware::GetSeconds() {
659671
return 0;
660672
}
661673

674+
/*!
675+
* @brief Gets the milliseconds from the GPS module.
676+
* @returns The milliseconds part of the current time, or 0 if the GPS driver
677+
* type is not set.
678+
*/
662679
uint16_t GPSHardware::GetMilliseconds() {
663680
if (_driver_type == GPS_DRV_MTK) {
664681
return _ada_gps->milliseconds;
@@ -668,6 +685,10 @@ uint16_t GPSHardware::GetMilliseconds() {
668685
return 0;
669686
}
670687

688+
/*!
689+
* @brief Gets the day from the GPS module.
690+
* @returns The day of the month (1-31), or 0 if the GPS driver type is not set.
691+
*/
671692
uint8_t GPSHardware::GetDay() {
672693
if (_driver_type == GPS_DRV_MTK) {
673694
return _ada_gps->day;
@@ -677,6 +698,11 @@ uint8_t GPSHardware::GetDay() {
677698
return 0;
678699
}
679700

701+
/*!
702+
* @brief Gets the month from the GPS module.
703+
* @returns The month as a number (1-12), or 0 if the GPS driver type is not
704+
* set.
705+
*/
680706
uint8_t GPSHardware::GetMonth() {
681707
if (_driver_type == GPS_DRV_MTK) {
682708
return _ada_gps->month;
@@ -686,11 +712,172 @@ uint8_t GPSHardware::GetMonth() {
686712
return 0;
687713
}
688714

715+
/*!
716+
* @brief Gets the year from the GPS module.
717+
* @returns The year as a 2-digit number (e.g., 23 for 2023), or 0 if the GPS
718+
* driver type is not set.
719+
*/
689720
uint8_t GPSHardware::GetYear() {
690721
if (_driver_type == GPS_DRV_MTK) {
691722
return _ada_gps->year;
692723
} else if (_driver_type == GPS_DRV_UBLOX) {
693724
// TODO: Implement for UBLOX
694725
}
695726
return 0;
696-
}
727+
}
728+
729+
/*!
730+
* @brief Gets the GPS fix status.
731+
* @returns True if the GPS has a fix, False otherwise.
732+
*/
733+
bool GPSHardware::GetFix() {
734+
if (_driver_type == GPS_DRV_MTK) {
735+
return _ada_gps->fix;
736+
} else if (_driver_type == GPS_DRV_UBLOX) {
737+
// TODO: Implement for UBLOX
738+
}
739+
return false;
740+
}
741+
742+
/*!
743+
* @brief Gets the GPS latitude.
744+
* @returns The latitude in degrees, or 0.0 if the GPS driver type is not set.
745+
*/
746+
float GPSHardware::GetLat() {
747+
if (_driver_type == GPS_DRV_MTK) {
748+
return _ada_gps->latitude;
749+
} else if (_driver_type == GPS_DRV_UBLOX) {
750+
// TODO: Implement for UBLOX
751+
}
752+
return 0.0f;
753+
}
754+
755+
/*!
756+
* @brief Gets the GPS latitude direction.
757+
* @returns The latitude direction as a character ('N' or 'S'), or '\0' if the
758+
* GPS driver type is not set.
759+
*/
760+
char GPSHardware::GetLatDir() {
761+
if (_driver_type == GPS_DRV_MTK) {
762+
return _ada_gps->lat;
763+
} else if (_driver_type == GPS_DRV_UBLOX) {
764+
// TODO: Implement for UBLOX
765+
}
766+
return '\0';
767+
}
768+
769+
/*!
770+
* @brief Gets the GPS longitude.
771+
* @returns The longitude in degrees, or 0.0 if the GPS driver type is not set.
772+
*/
773+
float GPSHardware::GetLon() {
774+
if (_driver_type == GPS_DRV_MTK) {
775+
return _ada_gps->longitude;
776+
} else if (_driver_type == GPS_DRV_UBLOX) {
777+
// TODO: Implement for UBLOX
778+
}
779+
780+
return 0.0f;
781+
}
782+
783+
/*!
784+
* @brief Gets the GPS longitude direction.
785+
* @returns The longitude direction as a character ('E' or 'W'), or '\0' if the
786+
* GPS driver type is not set.
787+
*/
788+
char GPSHardware::GetLonDir() {
789+
if (_driver_type == GPS_DRV_MTK) {
790+
return _ada_gps->lon;
791+
} else if (_driver_type == GPS_DRV_UBLOX) {
792+
// TODO: Implement for UBLOX
793+
}
794+
795+
return '\0';
796+
}
797+
798+
/*!
799+
* @brief Gets the number of satellites in view.
800+
* @returns The number of satellites in view, or 0 if the GPS driver type is
801+
* not set.
802+
*/
803+
uint8_t GPSHardware::GetNumSats() {
804+
if (_driver_type == GPS_DRV_MTK) {
805+
return _ada_gps->satellites;
806+
} else if (_driver_type == GPS_DRV_UBLOX) {
807+
// TODO: Implement for UBLOX
808+
}
809+
810+
return 0;
811+
}
812+
813+
/*!
814+
* @brief Gets the horizontal dilution of precision (HDOP).
815+
* @returns The HDOP value, or 0.0 if the GPS driver type is not set.
816+
*/
817+
float GPSHardware::GetHDOP() {
818+
if (_driver_type == GPS_DRV_MTK) {
819+
return _ada_gps->HDOP;
820+
} else if (_driver_type == GPS_DRV_UBLOX) {
821+
// TODO: Implement for UBLOX
822+
}
823+
824+
return 0.0f;
825+
}
826+
827+
/*!
828+
* @brief Gets the altitude from the GPS module.
829+
* @returns The altitude in meters, or 0.0 if the GPS driver type is not set.
830+
*/
831+
float GPSHardware::GetAltitude() {
832+
if (_driver_type == GPS_DRV_MTK) {
833+
return _ada_gps->altitude;
834+
} else if (_driver_type == GPS_DRV_UBLOX) {
835+
// TODO: Implement for UBLOX
836+
}
837+
838+
return 0.0f;
839+
}
840+
841+
/*!
842+
* @brief Gets the speed from the GPS module.
843+
* @returns The speed in meters per second, or 0.0 if the GPS driver type is
844+
* not set.
845+
*/
846+
float GPSHardware::GetSpeed() {
847+
if (_driver_type == GPS_DRV_MTK) {
848+
return _ada_gps->speed;
849+
} else if (_driver_type == GPS_DRV_UBLOX) {
850+
// TODO: Implement for UBLOX
851+
}
852+
853+
return 0.0f;
854+
}
855+
856+
/*!
857+
* @brief Gets the angle from the GPS module.
858+
* @returns The angle in degrees, or 0.0 if the GPS driver type is not set.
859+
*/
860+
float GPSHardware::GetAngle() {
861+
if (_driver_type == GPS_DRV_MTK) {
862+
return _ada_gps->angle;
863+
} else if (_driver_type == GPS_DRV_UBLOX) {
864+
// TODO: Implement for UBLOX
865+
}
866+
867+
return 0.0f;
868+
}
869+
870+
/*!
871+
* @brief Gets the geoid height from the GPS module.
872+
* @returns The geoid height in meters, or 0.0 if the GPS driver type is not
873+
* set.
874+
*/
875+
float GPSHardware::GetGeoidHeight() {
876+
if (_driver_type == GPS_DRV_MTK) {
877+
return _ada_gps->fix;
878+
} else if (_driver_type == GPS_DRV_UBLOX) {
879+
// TODO: Implement for UBLOX
880+
}
881+
882+
return 0.0f;
883+
}

src/components/gps/hardware.h

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,19 +87,33 @@ class GPSHardware {
8787
GpsDriverType GetDriverType();
8888
GpsInterfaceType GetIfaceType();
8989
int NmeaBufPop(char *sentence);
90-
// HAL Abstraction for GPS driver commands
91-
// Used to abstract the Adafruit_GPS and SFE_UBLOX_GNSS libraries
92-
// and intelligently handle the differences between them
90+
// "Helpers" for GPS Drivers
91+
// Used to abstract common parsing functions from GPS driver libraries (i.e:
92+
// Adafruit_GPS, SFE_UBLOX_GNSS, anything in the future) and intelligently
93+
// handle the differences between them
9394
void ReadDiscardBuffer();
9495
void PollStoreSentences();
9596
bool ParseNMEASentence(char *sentence);
97+
// Datetime getters
9698
uint8_t GetHour();
9799
uint8_t GetMinute();
98100
uint8_t GetSeconds();
99101
uint16_t GetMilliseconds();
100102
uint8_t GetDay();
101103
uint8_t GetMonth();
102104
uint8_t GetYear();
105+
// RMC/GGA getters
106+
bool GetFix();
107+
float GetLat();
108+
char GetLatDir();
109+
float GetLon();
110+
char GetLonDir();
111+
uint8_t GetNumSats();
112+
float GetHDOP();
113+
float GetAltitude();
114+
float GetSpeed();
115+
float GetAngle();
116+
float GetGeoidHeight();
103117

104118
private:
105119
bool QueryModuleType();

0 commit comments

Comments
 (0)