38static const auto kUtfDegrees = wxString::FromUTF8(u8
"\u00B0");
42std::string TimeToString(
const time_t t) {
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);
49 const char* r = ctime_r(&t, buff);
50 assert(r != NULL &&
"ctime_r failed...");
51 return std::string(buff);
55std::string DegreesToString(
double degrees) {
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;
64double PosPartsToDegrees(
float degrees,
float minutes,
65 float percent_of_minute) {
66 return degrees + minutes / 60 + percent_of_minute / 6000;
72 : lat(TypeToLat(t, _lat)), lon(TypeToLong(t, _lon)), type(t) {}
75 : lat(_lat), lon(_lon), type(LatLongToType(_lat, _lon)) {};
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];
88std::string Position::TypeToStr(
const Type t)
const {
109Position::Type Position::LatLongToType(
double lat,
double lon) {
111 return lon >= 0 ? Type::NE : Type::NW;
113 return lon >= 0 ? Type::SE : Type::SW;
116double Position::TypeToLat(Type t,
double lat) {
117 return t == Type::SW || t == Type::SE ? -lat : lat;
120double Position::TypeToLong(Type t,
double lon) {
121 return t == Type::NE || t == Type::SE ? lon : -lon;
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;
135 if (parts.size() != 4) {
138 double lat = GgaPartToDouble(parts[0]);
141 else if (parts[1] !=
"N")
143 double lon = GgaPartToDouble(parts[2]);
146 else if (parts[3] !=
"E")
154std::string AppMsg::TypeToString(
const AppMsg::Type t)
const {
156 case AppMsg::Type::AisData:
159 case AppMsg::Type::BasicNavData:
160 return "basic-nav-data";
162 case AppMsg::Type::CustomMsg:
165 case AppMsg::Type::DataPrioNeeded:
166 return "data-prio-needed";
168 case AppMsg::Type::GnssFix:
171 case AppMsg::Type::GPSWatchdog:
172 return "gps-watchdog";
174 case AppMsg::Type::Undef:
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);
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;
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.