16
16
#include " controller.h"
17
17
18
18
/* !
19
- * @brief Constructor
19
+ * @brief Constructor for GPSController.
20
20
*/
21
- GPSController::GPSController () {
22
- _gps_model = new GPSModel ();
23
- _iface_type = GPS_IFACE_NONE;
24
- _driver_type = GPS_DRV_NONE;
25
- }
21
+ GPSController::GPSController () { _gps_model = new GPSModel (); }
26
22
27
23
/* !
28
- * @brief Destructor
24
+ * @brief Destructor for GPSController.
29
25
*/
30
26
GPSController::~GPSController () {
31
27
// Clean up model
32
28
if (_gps_model) {
33
29
delete _gps_model;
34
30
_gps_model = nullptr ;
35
31
}
36
-
37
- // Clean up GPS instance
38
- if (_ada_gps) {
39
- delete _ada_gps;
40
- _ada_gps = nullptr ;
41
- }
42
32
}
43
33
44
34
/* !
45
- * @brief Handles a GPSConfig message from the protobuf stream .
46
- * @param stream
47
- * Pointer to a pb_istream_t object .
48
- * @returns True if the message was handled successfully, False otherwise.
35
+ * @brief Adds a GPS hardware instance to the controller .
36
+ * @param serial Pointer to the HardwareSerial instance for GPS communication.
37
+ * @param gps_config Pointer to the GPS configuration message .
38
+ * @return True if the GPS was added successfully, false otherwise.
49
39
*/
50
- bool GPSController::Handle_GPSConfig (wippersnapper_gps_GPSConfig *gps_config) {
51
- // Attempt to decode the GPSConfig message
52
- if (_driver_type == GPS_DRV_MTK) {
53
- WS_DEBUG_PRINTLN (" [gps] Handling GPSConfig for MediaTek driver..." );
54
- if (gps_config == nullptr ) {
55
- WS_DEBUG_PRINTLN (" [gps] ERROR: No GPSConfig message found!" );
56
- return false ;
57
- }
58
- // Iterate through the command sentences and send them to the GPS module
59
- // TODO: We may want to break this out into a generic function that supports
60
- // MTK, Ublox, etc...
61
- for (size_t i = 0 ; i < gps_config->commands_count ; i++) {
62
- WS_DEBUG_PRINT (" [gps] Sending command to MediaTek GPS: " );
63
- WS_DEBUG_PRINTLN (gps_config->commands [i]);
64
- // Send the command to the GPS module
65
- _hw_serial->flush (); // Flush the serial buffer before sending
66
- _ada_gps->sendCommand (gps_config->commands [i]);
67
- // and wait for the corresponding response from the GPS module
68
- char msg_resp[MAX_NEMA_SENTENCE_LEN];
69
- if (!BuildPmtkAck (gps_config->commands [i], msg_resp)) {
70
- WS_DEBUG_PRINTLN (" [gps] ERROR: Failed to build PMTK ACK response!" );
71
- return false ;
72
- }
73
- if (!_ada_gps->waitForSentence (msg_resp)) {
74
- WS_DEBUG_PRINT (" [gps] ERROR: Failed to get response | cmd:" );
75
- WS_DEBUG_PRINTLN (gps_config->commands [i]);
76
- return false ;
77
- }
78
- }
79
- } else {
80
- WS_DEBUG_PRINTLN (" [gps] ERROR: Unsupported GPS driver type!" );
81
- return false ;
82
- }
40
+ bool GPSController::AddGPS (HardwareSerial *serial,
41
+ wippersnapper_gps_GPSConfig *gps_config) {
42
+ GPSHardware *gps_hw = new GPSHardware ();
83
43
84
- return true ;
85
- }
86
-
87
- /* !
88
- * @brief Sets a UART hardware interface for the GPS controller.
89
- * @param serial
90
- * Pointer to a HardwareSerial instance.
91
- * @returns True if the interface was set successfully, False otherwise.
92
- */
93
- bool GPSController::SetInterface (HardwareSerial *serial) {
94
- if (serial == nullptr )
95
- return false ;
96
- // Set the hardware serial interface
97
- _hw_serial = serial;
98
- _iface_type = GPS_IFACE_UART_HW;
99
- return true ;
100
- }
101
-
102
- /* !
103
- * @brief Attempts to initialize the GPS device based on the configured
104
- * interface type.
105
- * @returns True if the GPS device was initialized successfully, False
106
- * otherwise.
107
- */
108
- bool GPSController::begin () {
109
- // Validate if the interface type is set
110
- if (_iface_type == GPS_IFACE_NONE) {
111
- WS_DEBUG_PRINTLN (" [gps] ERROR: No interface type configured!" );
44
+ if (!gps_hw->SetInterface (serial)) {
45
+ WS_DEBUG_PRINTLN (" [gps] ERROR: Failed to set GPS interface!" );
46
+ delete gps_hw;
112
47
return false ;
113
48
}
114
49
115
- // Attempt to set the GPS interface type based on the hardware
116
- if (! QueryModuleType ()) {
117
- WS_DEBUG_PRINTLN ( " [gps] ERROR: Failed to query GPS module type! " ) ;
50
+ if (!gps_hw-> begin ()) {
51
+ WS_DEBUG_PRINTLN ( " [gps] ERROR: Failed to initialize GPS hardware! " );
52
+ delete gps_hw ;
118
53
return false ;
119
54
}
120
55
121
- WS_DEBUG_PRINTLN (
122
- " [gps] GPS module type detected successfully and ready for commands!" );
123
- return true ;
124
- }
125
-
126
- /* !
127
- * @brief Queries the GPS driver type by attempting to detect MediaTek or u-blox
128
- * GPS modules.
129
- * @returns True if the driver type was detected successfully, False otherwise.
130
- */
131
- bool GPSController::QueryModuleType () {
132
- // Validate if the interface is set
133
- if (_iface_type == GPS_IFACE_NONE) {
134
- WS_DEBUG_PRINTLN (" [gps] ERROR: No interface configured for GPS!" );
56
+ if (!gps_hw->Handle_GPSConfig (gps_config)) {
57
+ WS_DEBUG_PRINTLN (" [gps] ERROR: Failed to configure GPS!" );
58
+ delete gps_hw;
135
59
return false ;
136
60
}
137
- WS_DEBUG_PRINTLN (" [gps] Attempting to detect GPS module type..." );
138
-
139
- // Try to detect MediaTek GPS module
140
- if (DetectMediatek ()) {
141
- WS_DEBUG_PRINTLN (" [gps] Using MediaTek GPS driver!" );
142
- return true ;
143
- }
144
-
145
- WS_DEBUG_PRINTLN (" [gps] Failed to detect MTK GPS, attempting to detect "
146
- " u-blox GPS module..." );
147
- // TODO: Implement u-blox detection here
148
- // if (DetectUblox()) {
149
- // return true;
150
- // }
151
-
152
- WS_DEBUG_PRINTLN (" [gps] ERROR: Failed to detect GPS driver type, attempting "
153
- " to use generic driver!" );
154
- // TODO: Implement generic NMEA GPS driver detection
155
61
156
- // No responses from the GPS module over the defined iface, so we bail out
157
- WS_DEBUG_PRINTLN (" [gps] ERROR: No GPS driver type detected!" );
158
- return false ;
159
- }
160
-
161
- /* !
162
- * @brief Detects if the GPS module is a MediaTek GPS module by querying its
163
- * firmware version.
164
- * @returns True if a MediaTek GPS module was detected, False otherwise.
165
- */
166
- bool GPSController::DetectMediatek () {
167
- if (_iface_type != GPS_IFACE_UART_HW) {
168
- WS_DEBUG_PRINTLN (" [gps] ERROR: MediaTek GPS module only supports Hardware "
169
- " Serial interface!" );
170
- return false ;
171
- }
172
-
173
- // Query MediaTek firmware version
174
- _hw_serial->flush ();
175
- _hw_serial->println (CMD_MTK_QUERY_FW);
176
- // Wait for response
177
- uint16_t timeout = 2000 ; // 1 second timeout
178
- while (_hw_serial->available () < MAX_NEMA_SENTENCE_LEN && timeout--) {
179
- delay (1 );
180
- }
181
-
182
- if (timeout == 0 )
183
- return false ;
184
-
185
- // We found a response, let's verify that it's the expected PMTK_DK_RELEASE
186
- // command by reading out the NMEA sentence string into a buffer
187
- size_t buf_len = MAX_NEMA_SENTENCE_LEN * 4 ; // +3 for \r\n and null terminator
188
- char buffer[buf_len];
189
- size_t available = _hw_serial->available ();
190
- size_t bytes_to_read = min (available, buf_len - 1 );
191
- // Print the two out
192
- WS_DEBUG_PRINT (" [gps] Reading MediaTek GPS response: " );
193
- WS_DEBUG_PRINT (available);
194
- WS_DEBUG_PRINT (" bytes, reading " );
195
- WS_DEBUG_PRINTLN (bytes_to_read);
196
- for (size_t i = 0 ; i < bytes_to_read; i++) {
197
- buffer[i] = _hw_serial->read ();
198
- }
199
- buffer[bytes_to_read] = ' \0 ' ;
200
- WS_DEBUG_PRINT (" [gps] MediaTek GPS response: " );
201
- WS_DEBUG_PRINTLN (buffer);
202
- // did we get the expected PMTK705 string?
203
- if (strncmp (buffer, CMD_MTK_QUERY_FW_RESP, 8 ) != 0 ) {
204
- return false ;
205
- }
206
-
207
- // Attempt to use Adafruit_GPS
208
- if (_ada_gps != nullptr ) {
209
- delete _ada_gps; // Clean up previous instance if it exists
210
- }
211
- _ada_gps = new Adafruit_GPS (_hw_serial);
212
- if (!_ada_gps->begin (_hw_serial->baudRate ())) {
213
- WS_DEBUG_PRINTLN (" [gps] ERROR: Failed to initialize Mediatek!" );
214
- return false ;
215
- }
216
- _driver_type = GPS_DRV_MTK;
217
- return true ;
218
- }
219
-
220
- /* !
221
- * @brief Builds a PMTK acknowledgment message for the provided command.
222
- * @param msg_cmd
223
- * Pointer to a command string.
224
- * @param msg_resp
225
- * Pointer to a response string.
226
- * @returns True if the acknowledgment was built successfully, False otherwise.
227
- */
228
- bool GPSController::BuildPmtkAck (char *msg_cmd, char *msg_resp) {
229
- int cmd_num = 0 ;
230
- if (sscanf (msg_cmd, " $PMTK%d" , &cmd_num) != 1 )
231
- return false ;
232
- snprintf (msg_resp, MAX_NEMA_SENTENCE_LEN, " $PMTK001,%d,3" , cmd_num);
233
- _ada_gps->addChecksum (msg_resp);
62
+ _gps_hardware.push_back (gps_hw);
63
+ WS_DEBUG_PRINTLN (" [gps] GPS hardware added successfully!" );
234
64
return true ;
235
65
}
0 commit comments