OpenCPN Partial API docs
Loading...
Searching...
No Matches
garmin_wrapper.cpp
1/*
2 Garmin Jeeps - OpenCPN Interface Wrapper.
3
4 Copyright (C) 2010 David S Register
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA
19
20 */
21
22#include "config.h"
23
24#include "garmin_wrapper.h"
25
26#include "gpsapp.h"
27#include "garmin_gps.h"
28#include "gpsserial.h"
29#include "route.h"
30
31#ifndef CLIAPP
32#include "gui_lib.h"
33#endif
34
35#define GPS_DEBUG
36
37extern char last_error[];
38
39gpsdevh *my_gps_devh;
40
41wxString GetLastGarminError(void) {
42 return wxString(GetDeviceLastError(), wxConvUTF8);
43}
44
45/*
46 Verify and force port closure after every called routine.
47 This is necessary for aborts in Windows environment, since ports cannot be
48 multiply opened.
49*/
50
51/* Wrapped interface from higher level objects */
52int Garmin_GPS_Init(const wxString &port_name) {
53 int ret;
54 GPS_Enable_Error();
55 GPS_Enable_Warning();
56 GPS_Enable_User();
57 GPS_Enable_Diagnose();
58 char m[1];
59 m[0] = '\0';
60
61 GPS_Error(m);
62
63 ret = GPS_Init(port_name.mb_str());
64 VerifyPortClosed();
65
66 return ret;
67}
68
69int Garmin_GPS_Open(wxString &port_name) {
70 return GPS_Init(port_name.mb_str());
71}
72
73int Garmin_GPS_PVT_On(wxString &port_name) {
74 return Garmin_Serial_GPS_PVT_On(port_name.mb_str());
75}
76
77int Garmin_GPS_PVT_Off(wxString &port_name) {
78 return Garmin_Serial_GPS_PVT_Off(port_name.mb_str());
79}
80
81int Garmin_GPS_GetPVT(void *pvt) {
82 return GPS_Serial_Command_Pvt_Get((GPS_PPvt_Data *)pvt);
83}
84
85void Garmin_GPS_ClosePortVerify(void) { VerifyPortClosed(); }
86
87wxString Garmin_GPS_GetSaveString() {
88 return wxString(gps_save_string, wxConvUTF8);
89}
90
91void Garmin_GPS_PrepareWptData(GPS_PWay pway, RoutePoint *prp) {
92 pway->lat = prp->m_lat;
93 pway->lon = prp->m_lon;
94 pway->alt_is_unknown = 1;
95 pway->alt = 0.0;
96 strncpy(pway->ident, (prp->GetName().Truncate(6)).mb_str(), 6);
97}
98
99int Garmin_GPS_SendWaypoints(const wxString &port_name,
100 RoutePointList *wplist) {
101 int ret_val = 0;
102
103 int nPoints = wplist->GetCount();
104
105 // Create the array of GPS_PWays
106
107 GPS_SWay **ppway = (GPS_SWay **)malloc(nPoints * sizeof(GPS_PWay));
108
109 // and the GPS_Oways themselves
110 for (int i = 0; i < nPoints; i++) ppway[i] = GPS_Way_New();
111
112 // Now fill in the useful elements
113 for (int i = 0; i < nPoints; i++) {
114 GPS_PWay pway = ppway[i];
115 wxRoutePointListNode *node = wplist->Item(i);
116 RoutePoint *prp = node->GetData();
117
118 Garmin_GPS_PrepareWptData(pway, prp);
119 }
120
121 // Transmit the list to the GPS receiver
122 int xfer_result = GPS_Command_Send_Waypoint(
123 port_name.mb_str(), ppway, nPoints, 0 /*int (*cb)(GPS_PWay *)*/);
124 ret_val = xfer_result;
125
126 // Free all the memory
127 for (int i = 0; i < nPoints; i++) GPS_Way_Del(&ppway[i]);
128
129 free(ppway);
130
131 VerifyPortClosed();
132 return ret_val;
133}
134
135// This routine creates an array of waypoint structures for an A200 route
136// transfer according to the "Garmin GPS Interface Specification" page 20.
137// The returned array contains the following packets:
138//
139// route header packet
140// waypoint packet
141// ...
142// waypoint packet
143//
144// The total number of elements in the array (route header packet and
145// all waypoint packets) is returned in the "size" argument.
146
147GPS_SWay **Garmin_GPS_Create_A200_Route(Route *pr, int route_number,
148 int *size) {
149 RoutePointList *wplist = pr->pRoutePointList;
150 int nPoints = wplist->GetCount();
151
152 // Create the array of GPS_PWays
153 // There will be one extra for the route header
154
155 *size = nPoints + 1;
156
157 GPS_SWay **ppway = (GPS_SWay **)malloc((*size) * sizeof(GPS_PWay));
158
159 // and the GPS_Oways themselves
160 for (int i = 0; i < nPoints + 1; i++) ppway[i] = GPS_Way_New();
161
162 // Now fill in the useful elements
163
164 // Element 0 is a route record
165
166 GPS_PWay pway = ppway[0];
167 pway->isrte = true;
168 pway->rte_num = route_number;
169 strncpy(pway->rte_ident, (pr->m_RouteNameString.Truncate(255)).mb_str(), 255);
170 strncpy(pway->rte_cmnt, (pr->m_RouteNameString.Truncate(19)).mb_str(), 19);
171
172 // Elements 1..n are waypoints
173 for (int i = 1; i < *size; i++) {
174 GPS_PWay pway = ppway[i];
175 wxRoutePointListNode *node = wplist->Item(i - 1);
176 RoutePoint *prp = node->GetData();
177
178 Garmin_GPS_PrepareWptData(pway, prp);
179 }
180
181 return ppway;
182}
183
184// This routine creates an array of waypoint structures for an A201 route
185// transfer according to the "Garmin GPS Interface Specification" page 21.
186// The returned array contains the following packets:
187//
188// route header packet
189// waypoint packet
190// link packet
191// waypoint packet
192// link packet
193// ...
194// waypoint packet
195//
196// The total number of elements in the array (route header packet, link
197// packets and waypoint packets) is returned in the "size" argument.
198
199GPS_SWay **Garmin_GPS_Create_A201_Route(Route *pr, int route_number,
200 int *size) {
201 RoutePointList *wplist = pr->pRoutePointList;
202 int nPoints = wplist->GetCount();
203
204 // Create the array of GPS_PWays
205 // There will be one for the route header, n for each way point
206 // and n-1 for each link
207
208 *size = 1 + nPoints + (nPoints - 1);
209
210 GPS_SWay **ppway = (GPS_SWay **)malloc((*size) * sizeof(GPS_PWay));
211
212 // and the GPS_Oways themselves
213 for (int i = 0; i < *size; i++) ppway[i] = GPS_Way_New();
214
215 // Now fill in the useful elements
216
217 // Element 0 is a route record
218
219 GPS_PWay pway = ppway[0];
220 pway->isrte = true;
221 pway->rte_num = route_number;
222 strncpy(pway->rte_ident, (pr->m_RouteNameString.Truncate(255)).mb_str(), 255);
223 strncpy(pway->rte_cmnt, (pr->m_RouteNameString.Truncate(19)).mb_str(), 19);
224
225 // Odd elements 1,3,5... are waypoints
226 // Even elements 2,4,6... are links
227 for (int i = 1; i < *size; i++) {
228 if (i % 2 == 1) /* Odd */
229 {
230 GPS_PWay pway = ppway[i];
231 wxRoutePointListNode *node = wplist->Item((i - 1) / 2);
232 RoutePoint *prp = node->GetData();
233
234 Garmin_GPS_PrepareWptData(pway, prp);
235 } else /* Even */
236 {
237 /* Apparently, 0 filled links are OK */
238 GPS_PWay pway = ppway[i];
239 pway->islink = true;
240 pway->rte_link_class = 0;
241 memset(pway->rte_link_subclass, 0, sizeof(pway->rte_link_subclass));
242 memset(pway->rte_link_ident, 0, sizeof(pway->rte_link_ident));
243 }
244 }
245
246 return ppway;
247}
248
249int Garmin_GPS_SendRoute(const wxString &port_name, Route *pr,
250 wxGauge *pProgress) {
251 int ret_val = 0;
252
253 int route_number = 1;
254
255 // If the device supports unique numbered waypoints,
256 // Then we must query the device to find an empty number
257 if ((gps_rte_hdr_type == pD200) || (gps_rte_hdr_type == pD201)) {
258 // Retrieve <ALL> routes from the device
259 GPS_Diag("Garmin: trying to get free route number");
260 GPS_PWay *pprouteway;
261 int32 npacks = GPS_A200_Get(port_name.mb_str(), &pprouteway);
262 if (npacks < 0) return npacks;
263
264 if (pProgress) {
265 pProgress->SetValue(60);
266 pProgress->Refresh();
267 pProgress->Update();
268 }
269
270 // Iterate on the packets, finding the first route number from [0..9] that
271 // is not present
272
273 // An array of route numbers, set element to true as encountered
274 bool brn[10];
275 for (int i = 0; i < 10; i++) brn[i] = false;
276
277 for (int ip = 0; ip < npacks; ip++) {
278 GPS_PWay pway = pprouteway[ip];
279 if (pway->isrte) {
280 if ((pway->rte_num < 10)) brn[pway->rte_num] = true;
281 }
282 }
283
284 // Find the first candidate within [1..9] that is unused
285 bool bfound_empty = false;
286 for (int i = 1; i < 10; i++) {
287 if (brn[i] == false) {
288 route_number = i;
289 bfound_empty = true;
290 break;
291 }
292 }
293 GPS_Diag("Using route number: %d", route_number);
294
295#ifndef CLIAPP // FIXME (leamas) Use a callback
296 // Ask the user if it is all right to overwrite
297 if (!bfound_empty) {
298 int rv = OCPNMessageBox(
299 NULL, _("Overwrite Garmin device route number 1?"),
300 _("OpenCPN Message"), wxOK | wxCANCEL | wxICON_QUESTION);
301 if (rv != wxID_OK) return 0;
302 }
303#endif
304 }
305
306 // Based on the route transfer protocol create the array of transfer packets
307 GPS_SWay **ppway;
308 int elements = 0;
309 if (gps_route_transfer == pA201)
310 ppway = Garmin_GPS_Create_A201_Route(pr, route_number, &elements);
311 else
312 ppway = Garmin_GPS_Create_A200_Route(pr, route_number, &elements);
313
314 // Transmit the Route to the GPS receiver
315 int xfer_result = GPS_Command_Send_Route(port_name.mb_str(), ppway, elements);
316 ret_val = xfer_result;
317
318 // Free all the memory
319 for (int i = 0; i < elements; i++) GPS_Way_Del(&ppway[i]);
320
321 free(ppway);
322
323 if (pProgress) {
324 pProgress->SetValue(80);
325 pProgress->Refresh();
326 pProgress->Update();
327 }
328
329 VerifyPortClosed();
330 return ret_val;
331}
332
333/*
334int Garmin_USB_On(void)
335{
336 int ret_val = GPS_Device_On("usb:", &my_gps_devh);
337
338 return ret_val;
339}
340
341int Garmin_USB_Off(void)
342{
343 int ret_val = GPS_Device_Off(my_gps_devh);
344
345 return ret_val;
346}
347*/
Definition: route.h:70