OpenCPN Partial API docs
Loading...
Searching...
No Matches
comm_appmsg.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * Copyright (C) 2022 by David Register *
3 * Copyright (C) 2022 Alec Leamas *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, see <https://www.gnu.org/licenses/>. *
17 **************************************************************************/
18
25// For compilers that support precompilation, includes "wx.h".
26#include <wx/wxprec.h>
27
28#ifndef WX_PRECOMP
29#include <wx/wx.h>
30#endif // precompiled headers
31
32#include <sstream>
33#include <iomanip>
34
35#include "model/comm_appmsg.h"
36#include "model/ocpn_utils.h"
37
38static const auto kUtfDegrees = wxString::FromUTF8(u8"\u00B0");
39
40/* Free functions. */
41
42std::string TimeToString(const time_t t) {
43 char buff[30];
44#ifdef _MSC_VER
45 errno_t e = ctime_s(buff, sizeof(buff), &t);
46 assert(e == 0 && "Huh? ctime_s returned an error");
47 return std::string(buff);
48#else
49 const char* r = ctime_r(&t, buff);
50 assert(r != NULL && "ctime_r failed...");
51 return std::string(buff);
52#endif
53}
54
55std::string DegreesToString(double degrees) {
56 using namespace std;
57 std::stringstream buf;
58 buf << setw(2) << static_cast<int>(trunc(degrees)) << kUtfDegrees
59 << static_cast<int>(trunc(degrees * 100)) % 100 << "," << setw(2)
60 << (static_cast<int>(trunc(degrees * 10000)) % 10000) % 100;
61 return buf.str();
62}
63
64double PosPartsToDegrees(float degrees, float minutes,
65 float percent_of_minute) {
66 return degrees + minutes / 60 + percent_of_minute / 6000;
67}
68
69/* Position implementation */
70
71Position::Position(double _lat, double _lon, Type t)
72 : lat(TypeToLat(t, _lat)), lon(TypeToLong(t, _lon)), type(t) {}
73
74Position::Position(double _lat, double _lon)
75 : lat(_lat), lon(_lon), type(LatLongToType(_lat, _lon)) {};
76
77Position::Position() : lat(0), lon(0), type(Type::Undef) {};
78
79std::string Position::to_string() const {
80 std::stringstream buf;
81 const std::string NE(TypeToStr(type));
82 auto lat_s = DegreesToString(abs(lat));
83 auto lon_s = DegreesToString(abs(lon));
84 buf << lat_s << NE[0] << " " << lon_s << NE[1];
85 return buf.str();
86}
87
88std::string Position::TypeToStr(const Type t) const {
89 switch (t) {
90 case Type::NE:
91 return "NE";
92 break;
93 case Type::NW:
94 return "NW";
95 break;
96 case Type::SE:
97 return "SE";
98 break;
99 case Type::SW:
100 return "SW";
101 break;
102 case Type::Undef:
103 return "Undefined";
104 break;
105 }
106 return "??"; // Not reached, but compiler complains.
107}
108
109Position::Type Position::LatLongToType(double lat, double lon) {
110 if (lat >= 0)
111 return lon >= 0 ? Type::NE : Type::NW;
112 else
113 return lon >= 0 ? Type::SE : Type::SW;
114}
115
116double Position::TypeToLat(Type t, double lat) {
117 return t == Type::SW || t == Type::SE ? -lat : lat;
118}
119
120double Position::TypeToLong(Type t, double lon) {
121 return t == Type::NE || t == Type::SE ? lon : -lon;
122}
123
125static double GgaPartToDouble(const std::string& s) {
126 size_t dotpos = s.find('.');
127 if (dotpos < 2) return nan("");
128 auto degrees = s.substr(0, dotpos - 2);
129 auto minutes = s.substr(dotpos - 2);
130 return std::stod(degrees) + std::stod(minutes) / 60;
131}
132
133Position Position::ParseGGA(const std::string gga) {
134 auto parts = ocpn::split(gga.c_str(), ",");
135 if (parts.size() != 4) {
136 return Position();
137 }
138 double lat = GgaPartToDouble(parts[0]);
139 if (parts[1] == "S")
140 lat = -lat;
141 else if (parts[1] != "N")
142 lat = nan("");
143 double lon = GgaPartToDouble(parts[2]);
144 if (parts[3] == "W")
145 lon = -lon;
146 else if (parts[3] != "E")
147 lon = nan("");
148
149 return lat != nan("") && lon != nan("") ? Position(lat, lon) : Position();
150}
151
152/* Appmsg implementation */
153
154std::string AppMsg::TypeToString(const AppMsg::Type t) const {
155 switch (t) {
156 case AppMsg::Type::AisData:
157 return "ais-data";
158 break;
159 case AppMsg::Type::BasicNavData:
160 return "basic-nav-data";
161 break;
162 case AppMsg::Type::CustomMsg:
163 return "custom-msg";
164 break;
165 case AppMsg::Type::DataPrioNeeded:
166 return "data-prio-needed";
167 break;
168 case AppMsg::Type::GnssFix:
169 return "gnss-fix";
170 break;
171 case AppMsg::Type::GPSWatchdog:
172 return "gps-watchdog";
173 break;
174 case AppMsg::Type::Undef:
175 return "??";
176 break;
177 }
178 return "????"; // Not reached, for the compiler.
179}
180
181std::string BasicNavDataMsg::to_string() const {
182 std::stringstream ss;
183 ss << AppMsg::to_string() << " pos: " << pos.to_string() << " sog: " << sog
184 << " cog: " << cog << " var: " << var << " hdt: " << hdt
185 << " vflag: " << vflag << " set_time: " << TimeToString(set_time.tv_sec);
186 return ss.str();
187}
188std::string AisData::to_string() const {
189 std::stringstream ss;
190 ss << TimeToString(time) << " " << pos.to_string() << " sog: " << sog
191 << " cog: " << cog << " heading: " << heading
192 << " rate of turn: " << rate_of_turn << "type: 0x" << std::hex << type
193 << " name " << name << " callsign " << callsign << " dest: " << dest
194 << " length " << std::dec << length << " beam: " << beam
195 << " draft: " << draft << " status: 0x" << std::hex << status;
196 return ss.str();
197}
Position()
Construct a (0,0) position, type == Undef.
static Position ParseGGA(const std::string gga)
Parse a GGA string like "5800.588,N,01145.776,E" as present in GGA and other n0183 messages.
std::string to_string() const
Return utf string like 65°25,11N 21°12,01E.
Decoded messages definitions.
std::vector< std::string > split(const char *token_string, const std::string &delimiter)
Return vector of items in s separated by delimiter.
Miscellaneous utilities, many of which string related.