📄 garmin_application.cp
字号:
// -*- mode: c++; c-basic-offset: 8; -*-// $Id: garmin_application.cp,v 1.1.1.1 2000/02/21 06:17:21 decouto Exp $// garmin_application.cp// Douglas S. J. De Couto// September 9, 1998// Copyright (C) 1998 Douglas S. J. De Couto// <decouto@lcs.mit.edu>//// This program is free software; you can redistribute it and/or// modify it under the terms of the GNU General Public License// as published by the Free Software Foundation; either version 2// of the License, or (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.#include "garmin_application.h"#include "garmin_command.h"#include "garmin_util.h"#ifdef DBUG#include <iostream>#endif#include <cctype>#include <algorithm>namespace garmin {using namespace std;#define check_init() if (!m_init) throw not_possible("The garmin application layer is not initialized")//////////////////product_data_typeapplication_layer::get_product_data(void) throw (not_possible, timeout){ check_init(); uint8 sz; packet_id pid; m_ll->put_packet(pid_product_rqst, m_buf, 0); pid = m_ll->get_packet(m_buf, sz); if (pid != pid_product_data) { throw not_possible("GPS did not reply with product data packet"); } if (sz < 5) { throw not_possible("Product data packet is too small"); } product_data_type pd; sint16 *buf16 = (sint16 *) m_buf; pd.product_id = garmin2host16(buf16[0]); pd.software_version = garmin2host16(buf16[1]); pd.product_description = &((char *) m_buf)[4]; // get capability protocol info... (A001), // but not supported on all units! try { pid = m_ll->get_packet(m_buf, sz); } catch (timeout &ex) { // timeout indicates gps is not sending capability protocol info m_got_protocol_info = false; return pd; } m_got_protocol_info = true; if (pid != pid_protocol_array) { throw not_possible("Product data packet followed by some packet besides capability protocol"); } if ((sz % 3) != 0) { throw not_possible("Capability protocol packet is strange size"); } for (sint16 i = 0; i < sz; i +=3) { // char tag = (char) m_buf[i]; // uint16 *data = (uint16 *) (m_buf + i + 1); // cout << "tag: " << tag << "; data: " << garmin2host16(*data) << endl; } return pd;}/////////////////waypt_vec_t *application_layer::get_waypoints(void) throw (not_possible, timeout){ check_init(); uint8 sz; sint16 *buf16 = (sint16 *) m_buf; char ident[7]; char cmnt[41]; ident[6] = cmnt[40] = 0; buf16[0] = host2garmin16((sint16) cmnd_transfer_wpt); m_ll->put_packet(pid_command_data, m_buf, 2); packet_id pid = m_ll->get_packet(m_buf, sz); if (pid != pid_records) { throw not_possible("GPS did not reply with start of records data packet for waypoint data"); } if (sz != 2) { throw not_possible("Waypoint data start of records packet is wrong size"); } sint16 num_recs = garmin2host16(buf16[0]); waypt_vec_t *waypts = new waypt_vec_t(num_recs); for (sint16 i = 0; i < num_recs; i++) { basic_waypt_type &waypt = (*waypts)[i]; pid = m_ll->get_packet(m_buf, sz); if (pid != pid_wpt_data) { delete waypts; throw not_possible("GPS did not send waypoint data packet"); } if (sz < (6 + 8 + 4 + 40)) { delete waypts; throw not_possible("Waypoint data packet is too small"); } uint32 *buf32 = (uint32 *) (m_buf + 6); waypt.pos.lat = garmin2host32(buf32[0]); waypt.pos.lon = garmin2host32(buf32[1]); strncpy(ident, (char *) m_buf, 6); waypt.id = string(ident); strncpy(cmnt, (char *) (m_buf + 18), 40); waypt.comment = string(cmnt); } pid = m_ll->get_packet(m_buf, sz); if (pid != pid_xfer_cmplt) { delete waypts; throw not_possible("GPS did not terminate waypoint data with end of records packet"); } if (garmin2host16(buf16[0]) != cmnd_transfer_wpt) { delete waypts; throw not_possible("End of records packet does not match original waypoint transfer command"); } return waypts; }/////////////////////void application_layer::send_waypoints(waypt_vec_t *waypts) throw (not_possible, timeout){ check_init(); product_data_type pd = get_product_data(); sint16 valid_products[] = { 73, 77, 87, 95, 96, 97, 100, 105, 106, -1 }; const int d103_sz = 6 + 8 + 4 + 40 + 2; bool is_valid_product = false; int i = 0; while (valid_products[i] != -1) { if (pd.product_id == valid_products[i]) { is_valid_product = true; break; } i++; } if (!is_valid_product) { throw not_possible("Waypoint download not supported for this GPS"); } sint16 *buf16 = (sint16 *) m_buf; buf16[0] = host2garmin16(waypts->size()); m_ll->put_packet(pid_records, m_buf, 2); for (unsigned int i = 0; i < waypts->size(); i++) { basic_waypt_type &w = (*waypts)[i]; // clear all fields memset(m_buf, 0, d103_sz); // set all waypt strings to blank spaces memset(m_buf, ' ', 6); memset(m_buf + 18, ' ', 40); // copy in strings, fixing up for GPS; leave bad characters as spaces for (size_t j = 0; j < min<size_t>(6, w.id.size()); j++) { char c = w.id[j]; if (isalnum(c)) { m_buf[j] = toupper(c); } } for (size_t j = 0; j < min<size_t>(40, w.comment.length()); j++) { char c = w.comment[j]; if (isalnum(c) || c == '-') { m_buf[j + 18] = toupper(c); } } // copy in position data uint32 *buf32 = (uint32 *) (m_buf + 6); buf32[0] = host2garmin32(w.pos.lat); buf32[1] = host2garmin32(w.pos.lon); m_ll->put_packet(pid_wpt_data, m_buf, d103_sz); } buf16[0] = host2garmin16(cmnd_transfer_wpt); m_ll->put_packet(pid_xfer_cmplt, m_buf, 2);}/////////////////////route_list_t *application_layer::get_routes(void) throw (not_possible, timeout){ check_init(); uint16 *buf16 = (uint16 *) m_buf; buf16[0] = host2garmin16((sint16) cmnd_transfer_rte); m_ll->put_packet(pid_command_data, m_buf, 2); uint8 sz; packet_id pid = m_ll->get_packet(m_buf, sz); if (pid != pid_records) { throw not_possible("GPS did not reply with start of records data packet for route data"); } if (sz != 2) { throw not_possible("Route data start of records packet is wrong size"); } sint16 num_packets = garmin2host16(buf16[0]); // create route list with no routes route_list_t *retval = new route_list_t(0); bool curr_rt_exists = false; for (sint16 i = 0; i < num_packets; i++) { pid = m_ll->get_packet(m_buf, sz); if (pid == pid_rte_hdr) { // start new route retval->push_back(list<basic_waypt_type>()); curr_rt_exists = true; continue; } if (pid != pid_rte_wpt_data) { delete retval; throw not_possible("Packet is not route waypoint data or route header"); } if (!curr_rt_exists) { delete retval; throw not_possible("Route waypoint data packet was not preceded by a route header packet"); } if (sz < (6 + 8 + 2 + 40)) { delete retval; throw not_possible("Route waypoint data packet is too small"); } semicircle_type *sp = (semicircle_type *) (m_buf + 6); sp->lat = garmin2host32(sp->lat); sp->lon = garmin2host32(sp->lon); basic_waypt_type waypt; char ident[7], cmnt[41]; ident[6] = cmnt[40] = 0; strncpy(ident, (char *) m_buf, 6); waypt.id = string(ident); waypt.pos = *sp; strncpy(cmnt, (char *) m_buf + 14, 40); waypt.comment = string(cmnt); // add this waypoint to end of last route in route list. retval->back().push_back(waypt); } pid = m_ll->get_packet(m_buf, sz); if (pid != pid_xfer_cmplt) { delete retval; throw not_possible("GPS did not terminate route data with end of records packet"); } if (garmin2host16(buf16[0]) != cmnd_transfer_rte) { delete retval; throw not_possible("End of records packet does not match original route transfer command"); } return retval; }/////////////////////void application_layer::send_routes(route_list_t *routes) throw (not_possible, timeout){ check_init(); product_data_type pd = get_product_data(); sint16 valid_products[] = { 73, 77, 87, 95, 96, 97, 100, 105, 106, -1 }; const int d103_sz = 6 + 8 + 4 + 40 + 2; bool is_valid_product = false; int i = 0; while (valid_products[i] != -1) { if (pd.product_id == valid_products[i]) { is_valid_product = true; break; } i++; } if (!is_valid_product) { throw not_possible("Route download not supported for this GPS"); } // how many data packets? sint16 num_recs = 0; route_list_t::const_iterator llw; for (llw = routes->begin(); llw != routes->end(); llw++) { num_recs += llw->size(); } num_recs += routes->size(); // plus 1 header packet for each route sint16 *buf16 = (sint16 *) m_buf; buf16[0] = host2garmin16(num_recs); m_ll->put_packet(pid_records, m_buf, 2); for (llw = routes->begin(); llw != routes->end(); llw++) { // put route header m_buf[0] = 10; char *test = "TESTING COMMENT "; for (int k = 0; k < 20; k++) { m_buf[k + 1] = test[k]; } m_ll->put_packet(pid_rte_hdr, m_buf, 21); // put route waypoints route_t::const_iterator lw; for (lw = llw->begin(); lw != llw->end(); lw++) { memset(m_buf, 0, d103_sz); // set all waypt strings to blank spaces memset(m_buf, ' ', 6); memset(m_buf + 18, ' ', 40); // copy in strings, fixing up for GPS; leave bad characters as spaces for (size_t j = 0; j < min<size_t>(6, lw->id.size()); j++) { char c = lw->id[j]; if (isalnum(c)) { m_buf[j] = toupper(c); } } for (size_t j = 0; j < min<size_t>(40, lw->comment.length()); j++) { char c = lw->comment[j]; if (isalnum(c) || c == '-') { m_buf[j + 18] = toupper(c); } } // copy in position data uint32 *buf32 = (uint32 *) (m_buf + 6); buf32[0] = host2garmin32(lw->pos.lat); buf32[1] = host2garmin32(lw->pos.lon); m_ll->put_packet(pid_rte_wpt_data, m_buf, d103_sz); } } buf16[0] = host2garmin16(cmnd_transfer_rte); m_ll->put_packet(pid_xfer_cmplt, m_buf, 2);} /////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -