Dev: improve robustness of CTags.cmake
[marnav.git] / src / nmeadump.cpp
blob91517b994e593a1e61281c0bc84199474e9074a3
1 // This is a diagnostics tool and also serves as demonstration
2 // on how to use the library.
3 //
4 // This tool is able to read data fromm stdin, file or a serial
5 // port.
6 //
7 // Usage, read from file:
8 //
9 // nmeadump -f logged-data.txt
11 // Usage, read from NMEA-0183 port:
13 // nmeadump -p /dev/ttyUSB0 -s 4800
15 // Usage, read from NMEA-0183-HS port:
17 // nmeadump -p /dev/ttyUSB0 -s 38400
19 // Usage, read from stdin:
21 // cat logged-data.txt | nmeadump
24 #include <marnav/nmea/nmea.hpp>
25 #include <marnav/nmea/ais_helper.hpp>
26 #include <marnav/nmea/checksum.hpp>
27 #include <marnav/nmea/sentence.hpp>
28 #include <marnav/nmea/waypoint.hpp>
29 #include <marnav/nmea/name.hpp>
30 #include <marnav/nmea/string.hpp>
32 #include <marnav/nmea/aam.hpp>
33 #include <marnav/nmea/alm.hpp>
34 #include <marnav/nmea/apa.hpp>
35 #include <marnav/nmea/apb.hpp>
36 #include <marnav/nmea/bec.hpp>
37 #include <marnav/nmea/bod.hpp>
38 #include <marnav/nmea/bwc.hpp>
39 #include <marnav/nmea/bwr.hpp>
40 #include <marnav/nmea/bww.hpp>
41 #include <marnav/nmea/dbt.hpp>
42 #include <marnav/nmea/dpt.hpp>
43 //#include <marnav/nmea/dsc.hpp>
44 //#include <marnav/nmea/dse.hpp>
45 #include <marnav/nmea/dtm.hpp>
46 #include <marnav/nmea/fsi.hpp>
47 #include <marnav/nmea/gbs.hpp>
48 #include <marnav/nmea/gga.hpp>
49 #include <marnav/nmea/glc.hpp>
50 #include <marnav/nmea/gll.hpp>
51 #include <marnav/nmea/gns.hpp>
52 #include <marnav/nmea/grs.hpp>
53 #include <marnav/nmea/gsa.hpp>
54 #include <marnav/nmea/gst.hpp>
55 #include <marnav/nmea/gsv.hpp>
56 #include <marnav/nmea/gtd.hpp>
57 #include <marnav/nmea/hdg.hpp>
58 #include <marnav/nmea/hfb.hpp>
59 #include <marnav/nmea/hdm.hpp>
60 #include <marnav/nmea/hdt.hpp>
61 #include <marnav/nmea/hsc.hpp>
62 #include <marnav/nmea/its.hpp>
63 #include <marnav/nmea/lcd.hpp>
64 #include <marnav/nmea/mob.hpp>
65 #include <marnav/nmea/msk.hpp>
66 #include <marnav/nmea/mss.hpp>
67 #include <marnav/nmea/mtw.hpp>
68 #include <marnav/nmea/mwd.hpp>
69 #include <marnav/nmea/mwv.hpp>
70 #include <marnav/nmea/osd.hpp>
71 #include <marnav/nmea/r00.hpp>
72 #include <marnav/nmea/rma.hpp>
73 #include <marnav/nmea/rmb.hpp>
74 #include <marnav/nmea/rmc.hpp>
75 #include <marnav/nmea/rot.hpp>
76 #include <marnav/nmea/rpm.hpp>
77 #include <marnav/nmea/rsa.hpp>
78 #include <marnav/nmea/rsd.hpp>
79 #include <marnav/nmea/rte.hpp>
80 #include <marnav/nmea/sfi.hpp>
81 #include <marnav/nmea/stn.hpp>
82 #include <marnav/nmea/tds.hpp>
83 #include <marnav/nmea/tfi.hpp>
84 #include <marnav/nmea/tll.hpp>
85 #include <marnav/nmea/tpc.hpp>
86 #include <marnav/nmea/tpr.hpp>
87 #include <marnav/nmea/tpt.hpp>
88 #include <marnav/nmea/ttm.hpp>
89 #include <marnav/nmea/vbw.hpp>
90 #include <marnav/nmea/vdm.hpp>
91 #include <marnav/nmea/vdo.hpp>
92 #include <marnav/nmea/vdr.hpp>
93 #include <marnav/nmea/vhw.hpp>
94 #include <marnav/nmea/vlw.hpp>
95 #include <marnav/nmea/vpw.hpp>
96 #include <marnav/nmea/vtg.hpp>
97 #include <marnav/nmea/vwr.hpp>
98 #include <marnav/nmea/wcv.hpp>
99 #include <marnav/nmea/wnc.hpp>
100 #include <marnav/nmea/wpl.hpp>
101 #include <marnav/nmea/xdr.hpp>
102 #include <marnav/nmea/xte.hpp>
103 #include <marnav/nmea/xtr.hpp>
104 #include <marnav/nmea/zda.hpp>
105 #include <marnav/nmea/zdl.hpp>
106 #include <marnav/nmea/zfo.hpp>
107 #include <marnav/nmea/ztg.hpp>
108 #include <marnav/nmea/pgrme.hpp>
109 #include <marnav/nmea/pgrmm.hpp>
110 #include <marnav/nmea/pgrmz.hpp>
111 #include <marnav/nmea/stalk.hpp>
113 #include <marnav/ais/ais.hpp>
114 #include <marnav/ais/name.hpp>
116 #include <marnav/ais/message_01.hpp>
117 #include <marnav/ais/message_02.hpp>
118 #include <marnav/ais/message_03.hpp>
119 #include <marnav/ais/message_04.hpp>
120 #include <marnav/ais/message_05.hpp>
121 #include <marnav/ais/message_06.hpp>
122 #include <marnav/ais/message_07.hpp>
123 #include <marnav/ais/message_08.hpp>
124 #include <marnav/ais/message_09.hpp>
125 #include <marnav/ais/message_10.hpp>
126 #include <marnav/ais/message_11.hpp>
127 #include <marnav/ais/message_12.hpp>
128 #include <marnav/ais/message_13.hpp>
129 #include <marnav/ais/message_14.hpp>
130 #include <marnav/ais/message_17.hpp>
131 #include <marnav/ais/message_18.hpp>
132 #include <marnav/ais/message_19.hpp>
133 #include <marnav/ais/message_20.hpp>
134 #include <marnav/ais/message_21.hpp>
135 #include <marnav/ais/message_22.hpp>
136 #include <marnav/ais/message_23.hpp>
137 #include <marnav/ais/message_24.hpp>
138 #include <marnav/ais/binary_001_11.hpp>
139 #include <marnav/ais/binary_200_10.hpp>
141 #include <marnav/io/default_nmea_reader.hpp>
142 #include <marnav/io/serial.hpp>
144 #include <marnav/units/units.hpp>
146 #include <marnav/utils/unique.hpp>
147 #include <marnav/utils/mmsi_country.hpp>
149 #include <cxxopts.hpp>
151 #include <fmt/format.h>
152 #include <fmt/printf.h>
154 #include <fstream>
155 #include <sstream>
156 #include <iostream>
157 #include <vector>
159 namespace nmeadump
161 namespace terminal
163 static constexpr const char * normal = "\033[0m";
164 static constexpr const char * black = "\033[30m";
165 static constexpr const char * red = "\033[31m";
166 static constexpr const char * green = "\033[32m";
167 static constexpr const char * yellow = "\033[33m";
168 static constexpr const char * blue = "\033[34m";
169 static constexpr const char * magenta = "\033[35m";
170 static constexpr const char * cyan = "\033[36m";
171 static constexpr const char * white = "\033[37m";
174 namespace
176 template <class Container>
177 static bool contains(
178 const Container & container, const typename Container::value_type & element)
180 return std::find(std::begin(container), std::end(container), element)
181 != std::end(container);
185 static struct {
186 struct {
187 std::string port;
188 marnav::io::serial::baud speed;
189 std::string file;
190 std::string input_string;
191 } config;
192 } global;
194 static bool parse_options(int argc, char ** argv)
196 uint32_t port_speed = 0;
198 // clang-format off
199 cxxopts::Options options{argv[0], "NMEA Dump"};
200 options.add_options()
201 ("h,help",
202 "Shows help information.")
203 ("p,port",
204 "Specifies the port to use.",
205 cxxopts::value<std::string>(global.config.port))
206 ("s,speed",
207 "Specifies the port speed. Valid values: 4800, 38400",
208 cxxopts::value<uint32_t>(port_speed))
209 ("f,file",
210 "Specifies the file to use.",
211 cxxopts::value<std::string>(global.config.file))
212 ("i,input",
213 "String to parse",
214 cxxopts::value<std::string>(global.config.input_string))
216 // clang-format on
218 const auto args = options.parse(argc, argv);
220 if (args.count("help")) {
221 fmt::printf("%s\n", options.help());
222 fmt::printf("If no file or port is specified, stdin is used to read data from.\n\n");
223 return true;
226 // validation
228 static const std::vector<uint32_t> valid_port_speeds = {4800, 38400};
230 if (args.count("port") && args.count("file"))
231 throw std::runtime_error{"specifying port and file is illegal"};
232 if (args.count("port") && !contains(valid_port_speeds, port_speed))
233 throw std::runtime_error{"invalid port speed"};
235 switch (port_speed) {
236 case 4800:
237 global.config.speed = marnav::io::serial::baud::baud_4800;
238 break;
239 case 38400:
240 global.config.speed = marnav::io::serial::baud::baud_38400;
241 break;
242 default:
243 break;
246 return false;
249 static std::string trim(const std::string & s)
251 static const char * whitespace = "\n\r\t ";
252 const auto begin = s.find_first_not_of(whitespace);
253 const auto end = s.find_last_not_of(whitespace);
254 return begin != std::string::npos ? s.substr(begin, end - begin + 1) : "";
257 /// @cond DEV
258 namespace detail
260 template <typename T> static std::string render(const T & t)
262 return marnav::nmea::to_string(t);
265 static std::string render(const std::string & t)
267 return t;
270 static std::string render(bool t)
272 return t ? "true" : "false";
275 static std::string render(char t)
277 return fmt::sprintf("%c", t);
280 static std::string render(const uint32_t t)
282 return fmt::sprintf("%u", t);
285 static std::string render(const int32_t t)
287 return fmt::sprintf("%d", t);
290 static std::string render(const uint8_t t)
292 return fmt::sprintf("%u", t);
295 static std::string render(const double t)
297 return fmt::sprintf("%-8.3f", t);
300 static std::string render(const marnav::utils::mmsi & t)
302 const auto country = mmsi_country(t).name;
303 if (!country.empty())
304 return fmt::sprintf(
305 "%09u (%s)", static_cast<marnav::utils::mmsi::value_type>(t), country);
306 return fmt::sprintf("%09u", static_cast<marnav::utils::mmsi::value_type>(t));
309 static std::string render(const marnav::nmea::time & t)
311 return fmt::sprintf("%02u:%02u:%02u", t.hour(), t.minutes(), t.seconds());
314 static std::string render(const marnav::geo::latitude & t)
316 using namespace marnav::nmea;
317 return fmt::sprintf(
318 " %02u\u00b0%02u'%04.1f%s", t.degrees(), t.minutes(), t.seconds(), to_string(t.hem()));
321 static std::string render(const marnav::geo::longitude & t)
323 using namespace marnav::nmea;
324 return fmt::sprintf(
325 "%03u\u00b0%02u'%04.1f%s", t.degrees(), t.minutes(), t.seconds(), to_string(t.hem()));
328 static std::string render(const marnav::geo::position & p)
330 using namespace marnav::nmea;
331 return fmt::sprintf("%s %s", render(p.lat()), render(p.lon()));
334 static std::string render(const marnav::ais::message_23::report_interval t)
336 switch (t) {
337 case marnav::ais::message_23::report_interval::autonomous_mode:
338 return "Autonomous Mode";
339 case marnav::ais::message_23::report_interval::minutes_10:
340 return "Minutes 10";
341 case marnav::ais::message_23::report_interval::minutes_06:
342 return "Minutes 6";
343 case marnav::ais::message_23::report_interval::minutes_03:
344 return "Minutes 3";
345 case marnav::ais::message_23::report_interval::minutes_01:
346 return "Minutes 1";
347 case marnav::ais::message_23::report_interval::seconds_30:
348 return "Seconds 30";
349 case marnav::ais::message_23::report_interval::seconds_15:
350 return "Seconds 15";
351 case marnav::ais::message_23::report_interval::seconds_10:
352 return "Seconds 10";
353 case marnav::ais::message_23::report_interval::seconds_05:
354 return "Seconds 5";
355 case marnav::ais::message_23::report_interval::next_shorter:
356 return "Next Shorter";
357 case marnav::ais::message_23::report_interval::next_longer:
358 return "Next Longer";
360 return "-";
363 static std::string render(const marnav::ais::message_24::part t)
365 switch (t) {
366 case marnav::ais::message_24::part::A:
367 return "A";
368 case marnav::ais::message_24::part::B:
369 return "B";
371 return "-";
374 static std::string render(const marnav::ais::binary_001_11::trend t)
376 switch (t) {
377 case marnav::ais::binary_001_11::trend::steady:
378 return "steady";
379 case marnav::ais::binary_001_11::trend::decreasing:
380 return "decreasing ";
381 case marnav::ais::binary_001_11::trend::increasing:
382 return "increasing";
383 case marnav::ais::binary_001_11::trend::not_available:
384 return "not available";
386 return "-";
389 static std::string render(const marnav::ais::binary_001_11::ice t)
391 switch (t) {
392 case marnav::ais::binary_001_11::ice::no:
393 return "no";
394 case marnav::ais::binary_001_11::ice::yes:
395 return "yes";
396 case marnav::ais::binary_001_11::ice::not_available:
397 return "not available";
399 return "-";
402 static std::string render(const marnav::ais::binary_001_11::precipitation t)
404 switch (t) {
405 case marnav::ais::binary_001_11::precipitation::rain:
406 return "rain";
407 case marnav::ais::binary_001_11::precipitation::thunderstorm:
408 return "thunderstorm";
409 case marnav::ais::binary_001_11::precipitation::freezing_rain:
410 return "freezing_rain";
411 case marnav::ais::binary_001_11::precipitation::mixed_ice:
412 return "mixed_ice";
413 case marnav::ais::binary_001_11::precipitation::snow:
414 return "snow";
415 case marnav::ais::binary_001_11::precipitation::not_available:
416 return "not available";
418 return "-";
421 static std::string render(const marnav::ais::binary_200_10::loaded_state t)
423 switch (t) {
424 case marnav::ais::binary_200_10::loaded_state::not_available:
425 return "not available";
426 case marnav::ais::binary_200_10::loaded_state::unloaded:
427 return "unloaded";
428 case marnav::ais::binary_200_10::loaded_state::loaded:
429 return "loaded";
431 return "-";
434 static std::string render(const marnav::ais::rate_of_turn t)
436 if (!t.available())
437 return "not available";
438 if (t.is_not_turning())
439 return "not turning";
440 if (t.is_more_5deg30s_right())
441 return "more 5deg/30s right";
442 if (t.is_more_5deg30s_left())
443 return "more 5deg/30s left";
444 return fmt::sprintf("%f", t.value());
447 static std::string render(const marnav::ais::ship_type t)
449 return marnav::ais::to_name(t);
452 static std::string render(const marnav::ais::epfd_fix_type t)
454 return marnav::ais::to_name(t);
457 static std::string render(const marnav::ais::off_position_indicator t)
459 return marnav::ais::to_name(t);
462 static std::string render(const marnav::ais::virtual_aid t)
464 return marnav::ais::to_name(t);
467 static std::string render(const marnav::ais::aid_type_id t)
469 return marnav::ais::to_name(t);
472 static std::string render(const marnav::ais::message_id t)
474 return marnav::ais::to_name(t);
477 static std::string render(const marnav::ais::maneuver_indicator_id t)
479 return marnav::ais::to_name(t);
482 static std::string render(const marnav::ais::data_terminal t)
484 return marnav::ais::to_name(t);
487 static std::string render(const marnav::ais::navigation_status t)
489 return marnav::ais::to_name(t);
492 static std::string render(const marnav::nmea::mob::mob_status t)
494 switch (t) {
495 case marnav::nmea::mob::mob_status::mob_activated:
496 return "mob activated";
497 case marnav::nmea::mob::mob_status::test_mode:
498 return "test mode";
499 case marnav::nmea::mob::mob_status::manual_button:
500 return "manual button";
501 case marnav::nmea::mob::mob_status::mob_not_in_use:
502 return "mob not in use";
503 case marnav::nmea::mob::mob_status::error:
504 return "error";
506 return "-";
509 static std::string render(const marnav::nmea::mob::mob_position_source t)
511 switch (t) {
512 case marnav::nmea::mob::mob_position_source::position_estimated:
513 return "position estimated";
514 case marnav::nmea::mob::mob_position_source::position_reported:
515 return "position reported";
516 case marnav::nmea::mob::mob_position_source::reserved:
517 return "reserved";
518 case marnav::nmea::mob::mob_position_source::error:
519 return "error";
521 return "-";
524 static std::string render(const marnav::nmea::mob::battery_status t)
526 switch (t) {
527 case marnav::nmea::mob::battery_status::good:
528 return "good";
529 case marnav::nmea::mob::battery_status::low:
530 return "low";
531 case marnav::nmea::mob::battery_status::reserved:
532 return "reserved";
533 case marnav::nmea::mob::battery_status::error:
534 return "error";
536 return "-";
539 static std::string render(const marnav::nmea::tfi::state t)
541 switch (t) {
542 case marnav::nmea::tfi::state::off:
543 return "OFF";
544 case marnav::nmea::tfi::state::on:
545 return "ON";
546 case marnav::nmea::tfi::state::no_answer:
547 return "no answer";
549 return "-";
552 static std::string render(const marnav::nmea::sentence_id t)
554 return marnav::nmea::to_name(t);
557 static std::string render(const marnav::nmea::talker t)
559 return marnav::nmea::to_name(t);
562 static std::string render(const marnav::nmea::unit::distance t)
564 return marnav::nmea::to_name(t);
567 static std::string render(const marnav::nmea::unit::temperature t)
569 return marnav::nmea::to_name(t);
572 static std::string render(const marnav::nmea::unit::velocity t)
574 return marnav::nmea::to_name(t);
577 static std::string render(const marnav::nmea::side t)
579 return marnav::nmea::to_name(t);
582 static std::string render(const marnav::nmea::reference t)
584 return marnav::nmea::to_name(t);
587 static std::string render(const marnav::nmea::quality t)
589 return marnav::nmea::to_name(t);
592 static std::string render(const marnav::nmea::direction t)
594 return marnav::nmea::to_string(t);
597 static std::string render(const marnav::nmea::selection_mode t)
599 return marnav::nmea::to_name(t);
602 static std::string render(const marnav::nmea::status t)
604 return marnav::nmea::to_name(t);
607 static std::string render(const marnav::nmea::route t)
609 return marnav::nmea::to_name(t);
612 static std::string render(const marnav::nmea::waypoint & t)
614 return t.c_str();
617 static std::string render(const marnav::nmea::mode_indicator t)
619 return marnav::nmea::to_name(t);
622 static std::string render(const std::vector<uint8_t> & t)
624 std::string s;
625 s.reserve(t.size() * 3 - 1);
626 for (auto i = begin(t); i != end(t); ++i)
627 s.append(fmt::sprintf(((i == begin(t)) ? "%02x" : " %02x"), *i));
628 return s;
631 static std::string render(const marnav::units::nautical_miles & t)
633 return fmt::sprintf("%s %s", render(t.value()), render(marnav::nmea::unit::distance::nm));
636 static std::string render(const marnav::units::knots & t)
638 return fmt::sprintf("%s %s", render(t.value()), render(marnav::nmea::unit::velocity::knot));
641 static std::string render(const marnav::units::meters & t)
643 return fmt::sprintf(
644 "%s %s", render(t.value()), render(marnav::nmea::unit::distance::meter));
647 static std::string render(const marnav::units::feet & t)
649 return fmt::sprintf("%s %s", render(t.value()), render(marnav::nmea::unit::distance::feet));
652 static std::string render(const marnav::units::meters_per_second & t)
654 return fmt::sprintf("%s %s", render(t.value()), render(marnav::nmea::unit::velocity::mps));
657 static std::string render(const marnav::units::celsius & t)
659 return fmt::sprintf(
660 "%s %s", render(t.value()), render(marnav::nmea::unit::temperature::celsius));
663 static std::string render(const marnav::units::length & t)
665 // all lengths are rendered in meters by default
666 return render(t.get<marnav::units::meters>());
669 static std::string render(const marnav::units::velocity & t)
671 // all velocities are rendered in knots by default
672 return render(t.get<marnav::units::knots>());
675 static std::string render(const marnav::units::temperature & t)
677 // all temperatures are rendered in celsius by default
678 return render(t.get<marnav::units::celsius>());
681 template <typename T> static std::string render(const marnav::utils::optional<T> & t)
683 if (!t)
684 return "-";
685 return render(*t);
688 static void print(const std::string & name, const std::string & value)
690 fmt::printf("\t%-30s : %s\n", name, value);
693 static void print(const std::string & title)
695 fmt::printf("\t%s\n", title);
698 static void print_detail_hdg(const marnav::nmea::sentence * s)
700 const auto t = marnav::nmea::sentence_cast<marnav::nmea::hdg>(s);
701 print("Heading", render(t->get_heading()));
702 print("Magn Deviation",
703 fmt::sprintf("%s %s", render(t->get_magn_dev()), render(t->get_magn_dev_hem())));
704 print("Magn Variation",
705 fmt::sprintf("%s %s", render(t->get_magn_var()), render(t->get_magn_var_hem())));
708 static void print_detail_hfb(const marnav::nmea::sentence * s)
710 const auto t = marnav::nmea::sentence_cast<marnav::nmea::hfb>(s);
711 print("Distance Head Foot [m]", render(t->get_distance_head_foot()));
712 print("Distance Head Bottom [m]", render(t->get_distance_head_bottom()));
715 static void print_detail_hdm(const marnav::nmea::sentence * s)
717 const auto t = marnav::nmea::sentence_cast<marnav::nmea::hdm>(s);
718 print("Heading", render(t->get_heading()));
721 static void print_detail_hdt(const marnav::nmea::sentence * s)
723 const auto t = marnav::nmea::sentence_cast<marnav::nmea::hdt>(s);
724 print("Heading", render(t->get_heading()));
727 static void print_detail_hsc(const marnav::nmea::sentence * s)
729 const auto t = marnav::nmea::sentence_cast<marnav::nmea::hsc>(s);
730 print("Heading True", render(t->get_heading_true()));
731 print("Heading Magnetic", render(t->get_heading_mag()));
734 static void print_detail_its(const marnav::nmea::sentence * s)
736 const auto t = marnav::nmea::sentence_cast<marnav::nmea::its>(s);
737 print("Distance [m]", render(t->get_distance()));
740 static void print_detail_lcd(const marnav::nmea::sentence * s)
742 const auto t = marnav::nmea::sentence_cast<marnav::nmea::lcd>(s);
743 print("GRI microseconds", render(t->get_gri()));
744 print("Master", fmt::sprintf("SNR:%d ECD:%d", t->get_master().snr, t->get_master().ecd));
745 for (int i = 0; i < marnav::nmea::lcd::max_differences; ++i) {
746 const auto diff = t->get_time_diff(i);
747 if (diff) {
748 print(fmt::sprintf("Time Diff %d", i),
749 fmt::sprintf("SNR:%d ECD:%d", diff->snr, diff->ecd));
754 static void print_detail_mob(const marnav::nmea::sentence * s)
756 const auto t = marnav::nmea::sentence_cast<marnav::nmea::mob>(s);
757 print("MOB Emitter ID", render(t->get_emitter_id()));
758 print("MOB Status", render(t->get_mob_status()));
759 print("MOB Time UTC", render(t->get_mob_activation_utc()));
760 print("MOB Position Source", render(t->get_mob_position_source()));
761 print("Date of Position", render(t->get_position_date()));
762 print("Time of Position", render(t->get_position_time()));
763 print("Latitude", render(t->get_lat()));
764 print("Longitude", render(t->get_lon()));
765 print("COG", render(t->get_cog()));
766 print("SOG", render(t->get_sog()));
767 print("MMSI", render(t->get_mmsi()));
768 print("Battery Status", render(t->get_battery_status()));
771 static void print_detail_msk(const marnav::nmea::sentence * s)
773 const auto t = marnav::nmea::sentence_cast<marnav::nmea::msk>(s);
774 print("Frequency to use", render(t->get_frequency()));
775 print("Frequency Mode", render(t->get_frequency_mode()));
776 print("Beacon Bit Rate", render(t->get_bitrate()));
777 print("Beacon Mode", render(t->get_bitrate_mode()));
778 print("Frequency for MSS message status", render(t->get_frequency_mss_status()));
781 static void print_detail_rmb(const marnav::nmea::sentence * s)
783 const auto t = marnav::nmea::sentence_cast<marnav::nmea::rmb>(s);
784 print("Active", render(t->get_active()));
785 print("Cross Track Error", render(t->get_cross_track_error()));
786 print("Waypoint From", render(t->get_waypoint_from()));
787 print("Waypoint To", render(t->get_waypoint_to()));
788 print("Latitude", render(t->get_lat()));
789 print("Longitude", render(t->get_lon()));
790 print("Range", render(t->get_range()));
791 print("Bearing", render(t->get_bearing()));
792 print("Dest. Velocity", render(t->get_dst_velocity()));
793 print("Arrival Status", render(t->get_arrival_status()));
794 print("Mode Indicator", render(t->get_mode_ind()));
797 static void print_detail_rmc(const marnav::nmea::sentence * s)
799 const auto t = marnav::nmea::sentence_cast<marnav::nmea::rmc>(s);
800 print("Time UTC", render(t->get_time_utc()));
801 print("Status", render(t->get_status()));
802 print("Latitude", render(t->get_lat()));
803 print("Longitude", render(t->get_lon()));
804 print("SOG", render(t->get_sog()));
805 print("Heading", render(t->get_heading()));
806 print("Date", render(t->get_date()));
807 print("Magn Dev", fmt::sprintf("%s %s", render(t->get_mag()), render(t->get_mag_hem())));
808 print("Mode Ind ", render(t->get_mode_ind()));
811 static void print_detail_rot(const marnav::nmea::sentence * s)
813 const auto t = marnav::nmea::sentence_cast<marnav::nmea::rot>(s);
814 print("Rate of Turn", render(t->get_deg_per_minute()));
815 print("Status", render(t->get_data_valid()));
818 static void print_detail_rpm(const marnav::nmea::sentence * s)
820 const auto t = marnav::nmea::sentence_cast<marnav::nmea::rpm>(s);
821 print("Source", render(t->get_source()));
822 print("Source Number", render(t->get_source_number()));
823 print("RPM", render(t->get_revolutions()));
824 print("Propeller Pitch", render(t->get_propeller_pitch()));
825 print("Status", render(t->get_data_valid()));
828 static void print_detail_rsa(const marnav::nmea::sentence * s)
830 const auto t = marnav::nmea::sentence_cast<marnav::nmea::rsa>(s);
831 print("Starbord Angle", render(t->get_rudder1()));
832 print("Starbord Status", render(t->get_rudder1_valid()));
833 print("Port Angle", render(t->get_rudder2()));
834 print("Port Status", render(t->get_rudder2_valid()));
837 static void print_detail_rsd(const marnav::nmea::sentence * s)
839 const auto t = marnav::nmea::sentence_cast<marnav::nmea::rsd>(s);
840 print("Cursor Range from own ship", render(t->get_cursor_range()));
841 print("Cursor Bearing from own ship", render(t->get_cursor_bearing()));
842 print("Range Scale", render(t->get_range_scale()));
843 print("Range Units", render(t->get_range_unit()));
846 static void print_detail_vtg(const marnav::nmea::sentence * s)
848 const auto t = marnav::nmea::sentence_cast<marnav::nmea::vtg>(s);
849 print("Track True", render(t->get_track_true()));
850 print("Track Magn", render(t->get_track_magn()));
851 print("Speed Knots", render(t->get_speed_kn()));
852 print("Speed kmh", render(t->get_speed_kmh()));
853 print("Mode Indicator", render(t->get_mode_ind()));
856 static void print_detail_gll(const marnav::nmea::sentence * s)
858 const auto t = marnav::nmea::sentence_cast<marnav::nmea::gll>(s);
859 print("Latitude", render(t->get_lat()));
860 print("Longitude", render(t->get_lon()));
861 print("Time UTC", render(t->get_time_utc()));
862 print("Status", render(t->get_data_valid()));
863 print("Mode Indicator", render(t->get_mode_ind()));
866 static void print_detail_gns(const marnav::nmea::sentence * s)
868 const auto t = marnav::nmea::sentence_cast<marnav::nmea::gns>(s);
869 print("Time UTC", render(t->get_time_utc()));
870 print("Latitude", render(t->get_lat()));
871 print("Longitude", render(t->get_lon()));
872 print("Mode Indicator", render(t->get_mode_ind()));
873 print("Number of Satellites", render(t->get_number_of_satellites()));
874 print("HDROP", render(t->get_hdrop()));
875 print("Antenna Altitude [m]", render(t->get_antenna_altitude()));
876 print("Geoidal Separation [m]", render(t->get_geodial_separation()));
877 print("Age of differential Data", render(t->get_age_of_differential_data()));
878 print("Differential Ref Station ID", render(t->get_differential_ref_station_id()));
881 static void print_detail_grs(const marnav::nmea::sentence * s)
883 const auto t = marnav::nmea::sentence_cast<marnav::nmea::grs>(s);
884 print("UTC time associated with GGA", render(t->get_time_utc()));
885 print("Status", render(t->get_usage()));
886 for (int i = 0; i < marnav::nmea::grs::num_satellite_residuals; ++i) {
887 const auto residual = t->get_sat_residual(i);
888 if (residual)
889 print(fmt::sprintf("Sat %02d Residual [m]", i), render(*residual));
893 static void print_detail_bec(const marnav::nmea::sentence * s)
895 const auto t = marnav::nmea::sentence_cast<marnav::nmea::bec>(s);
896 print("Time UTC", render(t->get_time_utc()));
897 print("Bearing True", render(t->get_bearing_true()));
898 print("Bearing Magn", render(t->get_bearing_magn()));
899 print("Distance [nm]", render(t->get_distance().get<marnav::units::nautical_miles>()));
900 print("Waypoint", render(t->get_waypoint()));
903 static void print_detail_bod(const marnav::nmea::sentence * s)
905 const auto t = marnav::nmea::sentence_cast<marnav::nmea::bod>(s);
906 print("Bearing True", render(t->get_bearing_true()));
907 print("Bearing Magn", render(t->get_bearing_magn()));
908 print("Waypoint To", render(t->get_waypoint_to()));
909 print("Waypoint From", render(t->get_waypoint_from()));
912 static void print_detail_bwc(const marnav::nmea::sentence * s)
914 const auto t = marnav::nmea::sentence_cast<marnav::nmea::bwc>(s);
915 print("Time UTC", render(t->get_time_utc()));
916 print("Bearing True", render(t->get_bearing_true()));
917 print("Bearing Magnetic", render(t->get_bearing_mag()));
918 print("Distance", fmt::sprintf("%s %s", render(t->get_distance()),
919 render(marnav::nmea::unit::distance::nm)));
920 print("Waypoint", render(t->get_waypoint_id()));
921 print("Mode Indicator", render(t->get_mode_ind()));
924 static void print_detail_bwr(const marnav::nmea::sentence * s)
926 const auto t = marnav::nmea::sentence_cast<marnav::nmea::bwr>(s);
927 print("Time UTC", render(t->get_time_utc()));
928 print("Latitude", render(t->get_lat()));
929 print("Longitude", render(t->get_lon()));
930 print("Bearing True", render(t->get_bearing_true()));
931 print("Bearing Magnetic", render(t->get_bearing_mag()));
932 print("Distance NM", render(t->get_distance()));
933 print("Waypoint", render(t->get_waypoint_id()));
934 print("Mode Indicator", render(t->get_mode_ind()));
937 static void print_detail_bww(const marnav::nmea::sentence * s)
939 const auto t = marnav::nmea::sentence_cast<marnav::nmea::bww>(s);
940 print("Bearing True", render(t->get_bearing_true()));
941 print("Bearing Magnetic", render(t->get_bearing_magn()));
942 print("Waypoint To", render(t->get_waypoint_to()));
943 print("Waypoint From", render(t->get_waypoint_from()));
946 static void print_detail_gsa(const marnav::nmea::sentence * s)
948 const auto t = marnav::nmea::sentence_cast<marnav::nmea::gsa>(s);
949 print("Selection Mode", render(t->get_sel_mode()));
950 print("Mode", render(t->get_mode()));
951 for (auto i = 0; i < marnav::nmea::gsa::max_satellite_ids; ++i) {
952 print(fmt::sprintf("Satellite %02u", i), render(t->get_satellite_id(i)));
954 print("PDOP", render(t->get_pdop()));
955 print("HDOP", render(t->get_hdop()));
956 print("VDOP", render(t->get_vdop()));
959 static void print_detail_gst(const marnav::nmea::sentence * s)
961 const auto t = marnav::nmea::sentence_cast<marnav::nmea::gst>(s);
962 print("Time UTC", render(t->get_time_utc()));
963 print("Total RMS", render(t->get_total_rms()));
964 print("Std Dev Semi-Major Axis", render(t->get_dev_semi_major()));
965 print("Std Dev Semi-Minor Axis", render(t->get_dev_semi_minor()));
966 print("Orientation Semi-Major Axis", render(t->get_orientation()));
967 print("Std Dev. Latitude Error", render(t->get_dev_lat()));
968 print("Std Dev. Longitude Error", render(t->get_dev_lon()));
969 print("Std Dev. Altitude Error", render(t->get_dev_alt()));
972 static void print_detail_glc(const marnav::nmea::sentence * s)
974 const auto t = marnav::nmea::sentence_cast<marnav::nmea::glc>(s);
975 print("GRI", render(t->get_gri()));
976 print("Master TOA", fmt::sprintf("DIFF:%s STATUS:%s", render(t->get_master().diff),
977 render(t->get_master().status)));
978 for (int i = 0; i < marnav::nmea::glc::max_differences; ++i) {
979 const auto & td = t->get_time_diff(i);
980 if (td) {
981 print(fmt::sprintf("Time Diff %d", i),
982 fmt::sprintf("DIFF:%s STATUS:%s", render(td->diff), render(td->status)));
987 static void print_detail_gga(const marnav::nmea::sentence * s)
989 const auto t = marnav::nmea::sentence_cast<marnav::nmea::gga>(s);
990 print("Time", render(t->get_time()));
991 print("Latitude", render(t->get_lat()));
992 print("Longitude", render(t->get_lon()));
993 print("Quality Ind", render(t->get_quality_indicator()));
994 print("Num Satellites", render(t->get_n_satellites()));
995 print("Horiz Dilution", render(t->get_hor_dilution()));
996 print("Altitude", render(t->get_altitude()));
997 print("Geodial Sep", render(t->get_geodial_separation()));
998 print("DGPS Age", render(t->get_dgps_age()));
999 print("DGPS Ref", render(t->get_dgps_ref()));
1002 static void print_detail_osd(const marnav::nmea::sentence * s)
1004 const auto t = marnav::nmea::sentence_cast<marnav::nmea::osd>(s);
1005 print("Heading", render(t->get_heading()));
1006 print("Status", render(t->get_data_valid()));
1007 print("Vessel Course True", render(t->get_course()));
1008 print("Vessel Speed",
1009 fmt::sprintf("%s %s", render(t->get_speed()), render(t->get_speed_unit())));
1010 print("Vessel Set", render(t->get_vessel_set()));
1011 print("Vessel Drift",
1012 fmt::sprintf("%s %s", render(t->get_vessel_drift()), render(t->get_speed_unit())));
1015 static void print_detail_r00(const marnav::nmea::sentence * s)
1017 const auto t = marnav::nmea::sentence_cast<marnav::nmea::r00>(s);
1018 for (int i = 0; i < marnav::nmea::r00::max_waypoint_ids; ++i) {
1019 const auto & wp = t->get_waypoint_id(i);
1020 if (wp) {
1021 print("Waypoint", render(*wp));
1026 static void print_detail_rma(const marnav::nmea::sentence * s)
1028 const auto t = marnav::nmea::sentence_cast<marnav::nmea::rma>(s);
1029 print("Blink Warning", render(t->get_blink_warning()));
1030 print("Latitude", render(t->get_lat()));
1031 print("Longitude", render(t->get_lon()));
1032 print("Time Diff A", render(t->get_time_diff_a()));
1033 print("Time Diff B", render(t->get_time_diff_b()));
1034 print("SOG [kn]", render(t->get_sog()));
1035 print("Track made good", render(t->get_track()));
1036 print("Magnetic Variation", fmt::sprintf("%s %s", render(t->get_magnetic_var()),
1037 render(t->get_magnetic_var_hem())));
1040 static void print_detail_mwv(const marnav::nmea::sentence * s)
1042 const auto t = marnav::nmea::sentence_cast<marnav::nmea::mwv>(s);
1043 print("Angle", fmt::sprintf("%s %s", render(t->get_angle()), render(t->get_angle_ref())));
1044 print("Speed", fmt::sprintf("%s %s", render(t->get_speed()), render(t->get_speed_unit())));
1045 print("Data Valid", render(t->get_data_valid()));
1048 static void print_detail_gsv(const marnav::nmea::sentence * s)
1050 const auto t = marnav::nmea::sentence_cast<marnav::nmea::gsv>(s);
1051 print("Num Messages", render(t->get_n_messages()));
1052 print("Messages Number", render(t->get_message_number()));
1053 print("Num Sat in View", render(t->get_n_satellites_in_view()));
1054 for (int i = 0; i < 4; ++i) {
1055 const auto sat = t->get_sat(i);
1056 if (sat) {
1057 print("Sat", fmt::sprintf("PRN:%02u ELEV:%02u AZIMUTH:%03u SNR:%s", sat->prn,
1058 sat->elevation, sat->azimuth, render(sat->snr)));
1063 static void print_detail_gtd(const marnav::nmea::sentence * s)
1065 const auto t = marnav::nmea::sentence_cast<marnav::nmea::gtd>(s);
1066 for (int i = 0; i < marnav::nmea::gtd::max_time_diffs; ++i)
1067 print(fmt::sprintf("Time Diff %d", i), render(t->get_time_diff(i)));
1070 static void print_detail_zda(const marnav::nmea::sentence * s)
1072 const auto t = marnav::nmea::sentence_cast<marnav::nmea::zda>(s);
1073 print("Time UTC", render(t->get_time_utc()));
1074 print("Date", render(t->get_date()));
1075 print("Local Zone Hours", render(t->get_local_zone_hours()));
1076 print("Local Zone Min", render(t->get_local_zone_minutes()));
1079 static void print_detail_zdl(const marnav::nmea::sentence * s)
1081 const auto t = marnav::nmea::sentence_cast<marnav::nmea::zdl>(s);
1082 print("Time to Point", render(t->get_time_to_point()));
1083 print("Distance to Point NM", render(t->get_distance()));
1084 print("Type of Point", render(t->get_type_point()));
1087 static void print_detail_zfo(const marnav::nmea::sentence * s)
1089 const auto t = marnav::nmea::sentence_cast<marnav::nmea::zfo>(s);
1090 print("Time UTC", render(t->get_time_utc()));
1091 print("Elapsed Time", render(t->get_time_elapsed()));
1092 print("Origin Waypoint", render(t->get_waypoint_id()));
1095 static void print_detail_ztg(const marnav::nmea::sentence * s)
1097 const auto t = marnav::nmea::sentence_cast<marnav::nmea::ztg>(s);
1098 print("Time UTC", render(t->get_time_utc()));
1099 print("Time Remaining", render(t->get_time_remaining()));
1100 print("Destination Waypoint", render(t->get_waypoint_id()));
1103 static void print_detail_dtm(const marnav::nmea::sentence * s)
1105 const auto t = marnav::nmea::sentence_cast<marnav::nmea::dtm>(s);
1106 print("Ref", render(t->get_ref()));
1107 print("Subcode", render(t->get_subcode()));
1108 print("Latitude Offset", render(t->get_lat_offset()));
1109 print("Latitude Hem", render(t->get_lat_hem()));
1110 print("Longitude Offset", render(t->get_lon_offset()));
1111 print("Longitude Hem", render(t->get_lon_hem()));
1112 print("Altitude", render(t->get_altitude().get<marnav::units::meters>()));
1113 print("Name", render(t->get_name()));
1116 static void print_detail_fsi(const marnav::nmea::sentence * s)
1118 const auto t = marnav::nmea::sentence_cast<marnav::nmea::fsi>(s);
1119 print("Tx Freuency 100 Hz", render(t->get_tx_frequency()));
1120 print("Rx Freuency 100 Hz", render(t->get_rx_frequency()));
1121 print("Mode of Operation", render(t->get_communications_mode()));
1122 print("Power Level", render(t->get_power_level()));
1123 print("Sentence Status Flag", render(t->get_sentence_status()));
1126 static void print_detail_gbs(const marnav::nmea::sentence * s)
1128 const auto t = marnav::nmea::sentence_cast<marnav::nmea::gbs>(s);
1129 print("Time UTC", render(t->get_time_utc()));
1130 print("Error Latitude", render(t->get_err_lat().get<marnav::units::meters>()));
1131 print("Error Longitude", render(t->get_err_lon().get<marnav::units::meters>()));
1132 print("Error Altitude", render(t->get_err_alt().get<marnav::units::meters>()));
1133 print("Satellite PRN", render(t->get_satellite()));
1134 print("Probability", render(t->get_probability()));
1135 print("Bias", render(t->get_bias().get<marnav::units::meters>()));
1136 print("Standard Deviation of bias", render(t->get_bias_dev()));
1139 static void print_detail_aam(const marnav::nmea::sentence * s)
1141 const auto t = marnav::nmea::sentence_cast<marnav::nmea::aam>(s);
1142 print("Arrival Circle Entred", render(t->get_arrival_circle_entered()));
1143 print("Perpendicular Passed", render(t->get_perpendicualar_passed()));
1144 print("Arrival Circle Radius",
1145 render(t->get_arrival_circle_radius().get<marnav::units::nautical_miles>()));
1146 print("Waypoint", render(t->get_waypoint_id()));
1149 static void print_detail_alm(const marnav::nmea::sentence * s)
1151 const auto t = marnav::nmea::sentence_cast<marnav::nmea::alm>(s);
1152 print("Number of Messages", render(t->get_number_of_messages()));
1153 print("Message Number", render(t->get_message_number()));
1154 print("Satellite PRN", render(t->get_satellite_prn()));
1155 print("GPS Week Number", render(t->get_gps_week_number()));
1156 print("SV Health", render(t->get_sv_health()));
1157 print("Eccentricity", render(t->get_eccentricity()));
1158 print("Almanac Reference Time", render(t->get_almanac_reference_time()));
1159 print("Inclination Angle", render(t->get_inclination_angle()));
1160 print("Rate of right ascension", render(t->get_rate_of_right_ascension()));
1161 print("Root of Semimajor Axis", render(t->get_root_of_semimajor_axis()));
1162 print("Argument of perigee", render(t->get_argument_of_perigee()));
1163 print("Longitude of ascension node", render(t->get_longitude_of_ascension_node()));
1164 print("Mean Anomaly", render(t->get_mean_anomaly()));
1165 print("F0 clock parameter", render(t->get_f0_clock_parameter()));
1166 print("F1 clock parameter", render(t->get_f1_clock_parameter()));
1169 static void print_detail_apa(const marnav::nmea::sentence * s)
1171 const auto t = marnav::nmea::sentence_cast<marnav::nmea::apa>(s);
1172 print("Lorac C Blink Warning", render(t->get_loran_c_blink_warning()));
1173 print("Lorac C Cycle Lock Warning", render(t->get_loran_c_cycle_lock_warning()));
1174 print("Magnitude of Cross Track Error", render(t->get_cross_track_error_magnitude()));
1175 print("Direction to Steer", render(t->get_direction_to_steer()));
1176 print("Cross Track Units", render(t->get_cross_track_unit()));
1177 print("Status Arrival", render(t->get_status_arrival()));
1178 print("Status Perpendicular Passed", render(t->get_status_perpendicular_passing()));
1179 print("Bearing Origin to Dest", render(t->get_bearing_origin_to_destination()));
1180 print("Bearing Origin to Dest Ref", render(t->get_bearing_origin_to_destination_ref()));
1181 print("Destination Waypoint", render(t->get_waypoint_id()));
1184 static void print_detail_rte(const marnav::nmea::sentence * s)
1186 const auto t = marnav::nmea::sentence_cast<marnav::nmea::rte>(s);
1187 print("Number of Messages", render(t->get_n_messages()));
1188 print("Message Number", render(t->get_message_number()));
1189 print("Message Mode", render(t->get_message_mode()));
1190 for (int i = 0; i < marnav::nmea::rte::max_waypoints; ++i) {
1191 const auto wp = t->get_waypoint_id(i);
1192 if (wp)
1193 print(fmt::sprintf("Waypoint %i", i), render(wp));
1197 static void print_detail_sfi(const marnav::nmea::sentence * s)
1199 const auto t = marnav::nmea::sentence_cast<marnav::nmea::sfi>(s);
1200 print("Number of Messages", render(t->get_n_messages()));
1201 print("Message Number", render(t->get_message_number()));
1202 for (const auto & f : t->get_frequencies())
1203 print("Frequency [kHz]", fmt::sprintf("%s %s", render(f.frequency), render(f.mode)));
1206 static void print_detail_stn(const marnav::nmea::sentence * s)
1208 const auto t = marnav::nmea::sentence_cast<marnav::nmea::stn>(s);
1209 print("Number ID", render(t->get_number()));
1212 static void print_detail_tds(const marnav::nmea::sentence * s)
1214 const auto t = marnav::nmea::sentence_cast<marnav::nmea::tds>(s);
1215 print("Distance [m]", render(t->get_distance()));
1218 static void print_detail_tfi(const marnav::nmea::sentence * s)
1220 const auto t = marnav::nmea::sentence_cast<marnav::nmea::tfi>(s);
1221 print("Sensor #1", render(t->get_sensor(0)));
1222 print("Sensor #2", render(t->get_sensor(1)));
1223 print("Sensor #3", render(t->get_sensor(2)));
1226 static void print_detail_tll(const marnav::nmea::sentence * s)
1228 const auto t = marnav::nmea::sentence_cast<marnav::nmea::tll>(s);
1229 print("Target Number", render(t->get_number()));
1230 print("Latitude", render(t->get_lat()));
1231 print("Longitude", render(t->get_lon()));
1232 print("Target Name", render(t->get_name()));
1233 print("Time UTC", render(t->get_time_utc()));
1234 print("Target Status", render(t->get_status()));
1235 print("Reference Target", render(t->get_reference_target()));
1238 static void print_detail_tpc(const marnav::nmea::sentence * s)
1240 const auto t = marnav::nmea::sentence_cast<marnav::nmea::tpc>(s);
1241 print("Horiz. Range from Center Line [m]", render(t->get_distance_centerline()));
1242 print("Horiz. dist from Transd. along [m]", render(t->get_distance_transducer()));
1243 print("Depth [m]", render(t->get_depth()));
1246 static void print_detail_tpr(const marnav::nmea::sentence * s)
1248 const auto t = marnav::nmea::sentence_cast<marnav::nmea::tpr>(s);
1249 print("Horizontal Range [m]", render(t->get_range()));
1250 print("Bearing to Target to Vessel", render(t->get_bearing()));
1251 print("Depth [m]", render(t->get_depth()));
1254 static void print_detail_tpt(const marnav::nmea::sentence * s)
1256 const auto t = marnav::nmea::sentence_cast<marnav::nmea::tpt>(s);
1257 print("Horizontal Range [m]", render(t->get_range()));
1258 print("Bearing to Target True", render(t->get_bearing()));
1259 print("Depth [m]", render(t->get_depth()));
1262 static void print_detail_ttm(const marnav::nmea::sentence * s)
1264 const auto t = marnav::nmea::sentence_cast<marnav::nmea::ttm>(s);
1265 print("Target Number", render(t->get_target_number()));
1266 print("Target Distance", render(t->get_target_distance()));
1267 print("Bearing from own ship", render(t->get_bearing_from_ownship()));
1268 print("Bearing from own ship Ref", render(t->get_bearing_from_ownship_ref()));
1269 print("Target Speed", render(t->get_target_speed()));
1270 print("Target Course", render(t->get_target_course()));
1271 print("Target Course Ref", render(t->get_target_course_ref()));
1272 print("CPA", render(t->get_distance_cpa()));
1273 print("TCPA", render(t->get_tcpa()));
1274 print("Unknown", render(t->get_unknown()));
1275 print("Target Name", render(t->get_target_name()));
1276 print("Target Status", render(t->get_target_status()));
1277 print("Reference Target", render(t->get_reference_target()));
1280 static void print_detail_vbw(const marnav::nmea::sentence * s)
1282 const auto t = marnav::nmea::sentence_cast<marnav::nmea::vbw>(s);
1283 print("Longitudinal Water Speed", render(t->get_water_speed_longitudinal()));
1284 print("Transverse Water Speed", render(t->get_water_speed_transveral()));
1285 print("Status", render(t->get_water_speed_status()));
1286 print("Longitudinal Ground Speed", render(t->get_ground_speed_longitudinal()));
1287 print("Transverse Ground Speed", render(t->get_ground_speed_transveral()));
1288 print("Status", render(t->get_ground_speed_status()));
1291 static void print_detail_vdr(const marnav::nmea::sentence * s)
1293 const auto t = marnav::nmea::sentence_cast<marnav::nmea::vdr>(s);
1294 print("Degrees True", render(t->get_degrees_true()));
1295 print("Degrees Magnetic", render(t->get_degrees_magn()));
1296 print("Speed of Current", render(t->get_speed()));
1299 static void print_detail_mss(const marnav::nmea::sentence * s)
1301 const auto t = marnav::nmea::sentence_cast<marnav::nmea::mss>(s);
1302 print("Signal Strength [dB 1uV]", render(t->get_signal_strength()));
1303 print("Signal to Noise Ratio (dB)", render(t->get_signal_to_noise_ratio()));
1304 print("Beacon Frequency [kHz]", render(t->get_beacon_frequency()));
1305 print("Beacon Data Rate BPS", render(t->get_beacon_datarate()));
1306 print("unknown", render(t->get_unknown()));
1309 static void print_detail_mtw(const marnav::nmea::sentence * s)
1311 const auto t = marnav::nmea::sentence_cast<marnav::nmea::mtw>(s);
1312 print("Water Temperature", render(t->get_temperature()));
1315 static void print_detail_mwd(const marnav::nmea::sentence * s)
1317 const auto t = marnav::nmea::sentence_cast<marnav::nmea::mwd>(s);
1318 print("Direction True", render(t->get_direction_true()));
1319 print("Direction Magnetic", render(t->get_direction_mag()));
1320 print("Speed kn", render(t->get_speed_kn()));
1321 print("Speed m/s", render(t->get_speed_ms()));
1324 static void print_detail_dbt(const marnav::nmea::sentence * s)
1326 const auto t = marnav::nmea::sentence_cast<marnav::nmea::dbt>(s);
1327 print("Depth Feet", render(t->get_depth_feet()));
1328 print("Depth Meter", render(t->get_depth_meter()));
1329 print("Depth Fathom", render(t->get_depth_fathom()));
1332 static void print_detail_dpt(const marnav::nmea::sentence * s)
1334 const auto t = marnav::nmea::sentence_cast<marnav::nmea::dpt>(s);
1335 print("Depth", render(t->get_depth_meter().get<marnav::units::meters>()));
1336 print("Offset from Transducer",
1337 render(t->get_transducer_offset().get<marnav::units::meters>()));
1338 print("Max Depth", render(t->get_max_depth()));
1341 static void print_detail_apb(const marnav::nmea::sentence * s)
1343 const auto t = marnav::nmea::sentence_cast<marnav::nmea::apb>(s);
1344 print("Loran C blink warn", render(t->get_loran_c_blink_warning()));
1345 print("Loran C cycle lock warn", render(t->get_loran_c_cycle_lock_warning()));
1346 print("Cross Track Error Magnitude", render(t->get_cross_track_error_magnitude()));
1347 print("Direction to Steer", render(t->get_direction_to_steer()));
1348 print("Cross Track Unit", render(t->get_cross_track_unit()));
1349 print("Status Arrival", render(t->get_status_arrival()));
1350 print("Status Perpendicular Pass", render(t->get_status_perpendicular_passing()));
1351 print("Bearing Org to Dest", render(t->get_bearing_origin_to_destination()));
1352 print("Bearing Org to Dest Ref", render(t->get_bearing_origin_to_destination_ref()));
1353 print("Waypoint", render(t->get_waypoint_id()));
1354 print("Bearing Pos to Dest", render(t->get_bearing_pos_to_destination()));
1355 print("Bearing Pos to Dest Ref", render(t->get_bearing_pos_to_destination_ref()));
1356 print("Heading to Steer to Dest", render(t->get_heading_to_steer_to_destination()));
1357 print("Heading to Steer to Dest Ref", render(t->get_heading_to_steer_to_destination_ref()));
1358 print("Mode Indicator", render(t->get_mode_ind()));
1361 static void print_detail_pgrme(const marnav::nmea::sentence * s)
1363 const auto t = marnav::nmea::sentence_cast<marnav::nmea::pgrme>(s);
1364 print("HPE", render(t->get_horizontal_position_error()));
1365 print("VPE", render(t->get_vertical_position_error()));
1366 print("O.sph.eq.pos err", render(t->get_overall_spherical_equiv_position_error()));
1369 static void print_detail_pgrmm(const marnav::nmea::sentence * s)
1371 const auto t = marnav::nmea::sentence_cast<marnav::nmea::pgrmm>(s);
1372 print("Map Datum", render(t->get_map_datum()));
1375 static void print_detail_pgrmz(const marnav::nmea::sentence * s)
1377 const auto t = marnav::nmea::sentence_cast<marnav::nmea::pgrmz>(s);
1378 print("Altitude", render(t->get_altitude()));
1379 print("Fix Type", render(t->get_fix()));
1382 static void print_detail_stalk(const marnav::nmea::sentence * s)
1384 const auto t = marnav::nmea::sentence_cast<marnav::nmea::stalk>(s);
1385 print("Data", render(t->get_data()));
1388 static void print_detail_vwr(const marnav::nmea::sentence * s)
1390 const auto t = marnav::nmea::sentence_cast<marnav::nmea::vwr>(s);
1391 print("Angle", fmt::sprintf("%s %s", render(t->get_angle()), render(t->get_angle_side())));
1392 print("Speed kn", render(t->get_speed_knots()));
1393 print("Speed m/s", render(t->get_speed_mps()));
1394 print("Speed km/h", render(t->get_speed_kmh()));
1397 static void print_detail_wcv(const marnav::nmea::sentence * s)
1399 const auto t = marnav::nmea::sentence_cast<marnav::nmea::wcv>(s);
1400 print("Speed kn", render(t->get_speed()));
1401 print("Waypoint", render(t->get_waypoint_id()));
1404 static void print_detail_wnc(const marnav::nmea::sentence * s)
1406 const auto t = marnav::nmea::sentence_cast<marnav::nmea::wnc>(s);
1407 print("Distnace NM", render(t->get_distance_nm()));
1408 print("Distnace km", render(t->get_distance_km()));
1409 print("Waypoint To", render(t->get_waypoint_to()));
1410 print("Waypoint From", render(t->get_waypoint_from()));
1413 static void print_detail_wpl(const marnav::nmea::sentence * s)
1415 const auto t = marnav::nmea::sentence_cast<marnav::nmea::wpl>(s);
1416 print("Latitude", render(t->get_lat()));
1417 print("Longitude", render(t->get_lon()));
1418 print("Waypoint", render(t->get_waypoint_id()));
1421 static void print_detail_xdr(const marnav::nmea::sentence * s)
1423 const auto t = marnav::nmea::sentence_cast<marnav::nmea::xdr>(s);
1424 for (auto i = 0; i < marnav::nmea::xdr::max_transducer_info; ++i) {
1425 const auto info = t->get_info(i);
1426 if (info) {
1427 print("Transducer Info",
1428 fmt::sprintf("Type:%c Data:%f Unit:%c Name:%s", info->transducer_type,
1429 info->measurement_data, info->units_of_measurement, info->name));
1434 static void print_detail_xte(const marnav::nmea::sentence * s)
1436 const auto t = marnav::nmea::sentence_cast<marnav::nmea::xte>(s);
1437 print("Status 1", render(t->get_status1()));
1438 print("Status 2", render(t->get_status2()));
1439 print("Cross Track Error Magnitude", render(t->get_cross_track_error_magnitude()));
1440 print("Direction to Steer", render(t->get_direction_to_steer()));
1441 print("Mode Indicator", render(t->get_mode_ind()));
1444 static void print_detail_xtr(const marnav::nmea::sentence * s)
1446 const auto t = marnav::nmea::sentence_cast<marnav::nmea::xtr>(s);
1447 print("Cross Track Error Magnitude", render(t->get_cross_track_error_magnitude()));
1448 print("Direction to Steer", render(t->get_direction_to_steer()));
1451 static void print_detail_vlw(const marnav::nmea::sentence * s)
1453 const auto t = marnav::nmea::sentence_cast<marnav::nmea::vlw>(s);
1454 print("Distance Cumulative NM", render(t->get_distance_cum()));
1455 print("Distance since Rest NM", render(t->get_distance_reset()));
1458 static void print_detail_vpw(const marnav::nmea::sentence * s)
1460 const auto t = marnav::nmea::sentence_cast<marnav::nmea::vpw>(s);
1461 print("Speed kn", render(t->get_speed_knots()));
1462 print("Speed m/s", render(t->get_speed_meters_per_second()));
1465 static void print_detail_vhw(const marnav::nmea::sentence * s)
1467 const auto t = marnav::nmea::sentence_cast<marnav::nmea::vhw>(s);
1468 print("Heading True", render(t->get_heading_true()));
1469 print("Heading Magn", render(t->get_heading_magn()));
1470 print("Speed kn", render(t->get_speed_knots()));
1471 print("Speed km/h", render(t->get_speed_kmh()));
1474 static void print_detail_message_01_common(const marnav::ais::message_01 * t)
1476 print("Repeat Indicator", render(t->get_repeat_indicator()));
1477 print("MMSI", render(t->get_mmsi()));
1478 print("Nav Status", render(t->get_nav_status()));
1479 print("ROT", render(t->get_rot()));
1480 print("SOG", render(t->get_sog()));
1481 print("Pos Accuracy", render(t->get_position_accuracy()));
1482 print("Latitude", render(t->get_lat()));
1483 print("Longitude", render(t->get_lon()));
1484 print("COG", render(t->get_cog()));
1485 print("HDG", render(t->get_hdg()));
1486 print("Time Stamp", render(t->get_timestamp()));
1487 print("Maneuver Indicator", render(t->get_maneuver_indicator()));
1488 print("RAIM", render(t->get_raim()));
1489 print("Radio Status", render(t->get_radio_status()));
1492 static void print_detail_message_01(const marnav::ais::message * m)
1494 print_detail_message_01_common(marnav::ais::message_cast<marnav::ais::message_01>(m));
1497 static void print_detail_message_02(const marnav::ais::message * m)
1499 print_detail_message_01_common(marnav::ais::message_cast<marnav::ais::message_02>(m));
1502 static void print_detail_message_03(const marnav::ais::message * m)
1504 print_detail_message_01_common(marnav::ais::message_cast<marnav::ais::message_03>(m));
1507 static void print_detail_message_04_common(const marnav::ais::message_04 * t)
1509 print("Repeat Indicator", render(t->get_repeat_indicator()));
1510 print("MMSI", render(t->get_mmsi()));
1511 print("Year", render(t->get_year()));
1512 print("Month", render(t->get_month()));
1513 print("Day", render(t->get_day()));
1514 print("Hour", render(t->get_hour()));
1515 print("Minute", render(t->get_minute()));
1516 print("Second", render(t->get_second()));
1517 print("Pos Accuracy", render(t->get_position_accuracy()));
1518 print("Latitude", render(t->get_lat()));
1519 print("Longitude", render(t->get_lon()));
1520 print("EPFD Fix", render(t->get_epfd_fix()));
1521 print("RAIM", render(t->get_raim()));
1522 print("Radio Status", render(t->get_radio_status()));
1525 static void print_detail_message_04(const marnav::ais::message * m)
1527 print_detail_message_04_common(marnav::ais::message_cast<marnav::ais::message_04>(m));
1530 static void print_detail_message_11(const marnav::ais::message * m)
1532 print_detail_message_04_common(marnav::ais::message_cast<marnav::ais::message_11>(m));
1535 static void print_detail_message_12(const marnav::ais::message * m)
1537 const auto t = marnav::ais::message_cast<marnav::ais::message_12>(m);
1538 print("Repeat Indicator", render(t->get_repeat_indicator()));
1539 print("MMSI", render(t->get_mmsi()));
1540 print("Seqence Number", render(t->get_seqno()));
1541 print("Destination MMSI", render(t->get_dest_mmsi()));
1542 print("Retransmit", render(t->get_retransmit()));
1543 print("Text", render(t->get_text()));
1546 static void print_detail_message_13(const marnav::ais::message * m)
1548 const auto t = marnav::ais::message_cast<marnav::ais::message_13>(m);
1549 print("Repeat Indicator", render(t->get_repeat_indicator()));
1550 print("MMSI", render(t->get_mmsi()));
1551 print("MMSI_1", render(t->get_mmsi_1()));
1552 print("MMSI_2", render(t->get_mmsi_2()));
1553 print("MMSI_3", render(t->get_mmsi_3()));
1554 print("MMSI_4", render(t->get_mmsi_4()));
1557 static void print_detail_message_14(const marnav::ais::message * m)
1559 const auto t = marnav::ais::message_cast<marnav::ais::message_14>(m);
1560 print("Repeat Indicator", render(t->get_repeat_indicator()));
1561 print("MMSI", render(t->get_mmsi()));
1562 print("Text", render(t->get_text()));
1565 static void print_detail_message_05(const marnav::ais::message * m)
1567 const auto t = marnav::ais::message_cast<marnav::ais::message_05>(m);
1568 print("Repeat Indicator", render(t->get_repeat_indicator()));
1569 print("MMSI", render(t->get_mmsi()));
1570 print("AIS Version", render(t->get_ais_version()));
1571 print("IMO", render(t->get_imo_number()));
1572 print("Callsign", render(t->get_callsign()));
1573 print("Shipname", render(t->get_shipname()));
1574 print("Shiptype", render(t->get_shiptype()));
1575 print("Length", render(t->get_vessel_dimension().length()));
1576 print("Width", render(t->get_vessel_dimension().width()));
1577 print("Draught", render(t->get_draught()));
1578 print("EPFD Fix", render(t->get_epfd_fix()));
1579 print("ETA Month", render(t->get_eta_month()));
1580 print("ETA Day", render(t->get_eta_day()));
1581 print("ETA Hour", render(t->get_eta_hour()));
1582 print("ETA Minute", render(t->get_eta_minute()));
1583 print("Destination", render(t->get_destination()));
1584 print("DTE", render(t->get_dte()));
1587 static void print_detail_message_06(const marnav::ais::message * m)
1589 const auto t = marnav::ais::message_cast<marnav::ais::message_06>(m);
1590 print("Repeat Indicator", render(t->get_repeat_indicator()));
1591 print("MMSI", render(t->get_mmsi()));
1592 print("Sequence No", render(t->get_sequnce_no()));
1593 print("Destination MMSI", render(t->get_dest_mmsi()));
1594 print("Retransmit Flag", render(t->get_retransmit_flag()));
1595 print("DAC", render(t->get_dac()));
1596 print("FID", render(t->get_fid()));
1597 // TODO
1598 fmt::printf("\n\twarning: message 06: decoding of payload not implemented: %03d/%02d\n",
1599 t->get_dac(), t->get_fid());
1602 static void print_detail_message_07(const marnav::ais::message * m)
1604 const auto t = marnav::ais::message_cast<marnav::ais::message_07>(m);
1605 print("Repeat Indicator", render(t->get_repeat_indicator()));
1606 print("MMSI", render(t->get_mmsi()));
1607 print("MMSI_1", render(t->get_mmsi_1()));
1608 print("MMSI_2", render(t->get_mmsi_2()));
1609 print("MMSI_3", render(t->get_mmsi_3()));
1610 print("MMSI_4", render(t->get_mmsi_4()));
1613 static void print_detail_message_08(const marnav::ais::message * m)
1615 const auto t = marnav::ais::message_cast<marnav::ais::message_08>(m);
1616 print("Repeat Indicator", render(t->get_repeat_indicator()));
1617 print("MMSI", render(t->get_mmsi()));
1618 print("DAC", render(t->get_dac()));
1619 print("FID", render(t->get_fid()));
1621 if (t->get_dac() == 1 && t->get_fid() == 11) {
1622 marnav::ais::binary_001_11 b;
1623 t->read_binary(b);
1624 fmt::printf("\n");
1625 print("Meteological and Hydrological Data (001/11) IMO236");
1626 print("Position", render(b.get_position()));
1627 print("Day", render(b.get_day()));
1628 print("Hour", render(b.get_hour()));
1629 print("Minute", render(b.get_minute()));
1630 print("Wind Speed 10min avg [kn]", render(b.get_wind_speed_avg()));
1631 print("Wind Gust [kn]", render(b.get_wind_gust()));
1632 print("Wind Direction", render(b.get_wind_direction()));
1633 print("Wind Gust Direction", render(b.get_wind_gust_direction()));
1634 print("Temperature [C]", render(b.get_temperature()));
1635 print("Humidity [%]", render(b.get_humidity()));
1636 print("Dew Point [%]", render(b.get_dew_point()));
1637 print("Air Pressure [hPa]", render(b.get_pressure()));
1638 print("Air Pressure Trend", render(b.get_pressure_trend()));
1639 print("Visibility [NM]", render(b.get_visibility()));
1640 print("Water Level [m]", render(b.get_water_level()));
1641 print("Water Level Trend", render(b.get_water_level_trend()));
1642 print("Sufrace Current Speed [kn]", render(b.get_surface_current_speed()));
1643 print("Sufrace Current Direction", render(b.get_surface_current_direction()));
1644 print("Current 2 Speed [kn]", render(b.get_current_2_speed()));
1645 print("Current 2 Direction", render(b.get_current_2_direction()));
1646 print("Current 2 Depth [m]", render(b.get_current_2_depth()));
1647 print("Current 3 Speed [kn]", render(b.get_current_3_speed()));
1648 print("Current 3 Direction", render(b.get_current_3_direction()));
1649 print("Current 3 Depth [m]", render(b.get_current_3_depth()));
1650 print("Wave Height [m]", render(b.get_wave_height()));
1651 print("Wave Period [s]", render(b.get_wave_period()));
1652 print("Wave Direction", render(b.get_wave_direction()));
1653 print("Swell Height [m]", render(b.get_swell_height()));
1654 print("Swell Period [s]", render(b.get_swell_period()));
1655 print("Swell Direction", render(b.get_swell_direction()));
1656 print("Sea State", render(b.get_sea_state()));
1657 print("Water Temperature [C]", render(b.get_water_temperature()));
1658 print("Precipitation", render(b.get_precipitation()));
1659 print("Salinity [%]", render(b.get_salinity()));
1660 print("Ice", render(b.get_ice()));
1661 } else if (t->get_dac() == 200 && t->get_fid() == 10) {
1662 marnav::ais::binary_200_10 b;
1663 t->read_binary(b);
1664 fmt::printf("\n");
1665 print("Inland ship static and voyage related data (200/10)");
1666 print("Vessel ID", render(b.get_vessel_id()));
1667 print("Length [m]", render(b.get_length()));
1668 print("Beam [m]", render(b.get_beam()));
1669 print("Shiptype", render(b.get_shiptype()));
1670 print("Hazard", render(b.get_hazard()));
1671 print("Draught [m]", render(b.get_draught()));
1672 print("Loaded", render(b.get_loaded()));
1673 print("Speed quality", render(b.get_speed_q()));
1674 print("Course quality", render(b.get_course_q()));
1675 print("Heading quality", render(b.get_heading_q()));
1676 } else {
1677 fmt::printf("\n\twarning: message 08: decoding of payload not implemented: %03d/%02d\n",
1678 t->get_dac(), t->get_fid());
1682 static void print_detail_message_09(const marnav::ais::message * m)
1684 const auto t = marnav::ais::message_cast<marnav::ais::message_09>(m);
1685 print("Repeat Indicator", render(t->get_repeat_indicator()));
1686 print("MMSI", render(t->get_mmsi()));
1687 print("Altitude", render(t->get_altitude()));
1688 print("Speed", render(t->get_speed()));
1689 print("Pos Accuracy", render(t->get_position_accuracy()));
1690 print("COG", render(t->get_course()));
1691 print("UTC Second", render(t->get_utc_second()));
1692 print("DTE", render(t->get_dte()));
1693 print("RAIM", render(t->get_raim()));
1694 print("Radio Status", render(t->get_radio_status()));
1697 static void print_detail_message_10(const marnav::ais::message * m)
1699 const auto t = marnav::ais::message_cast<marnav::ais::message_10>(m);
1700 print("Repeat Indicator", render(t->get_repeat_indicator()));
1701 print("MMSI", render(t->get_mmsi()));
1702 print("Destination MMSI", render(t->get_dest_mmsi()));
1705 static void print_detail_message_17(const marnav::ais::message * m)
1707 const auto t = marnav::ais::message_cast<marnav::ais::message_17>(m);
1708 print("Repeat Indicator", render(t->get_repeat_indicator()));
1709 print("MMSI", render(t->get_mmsi()));
1710 print("Latitude", render(t->get_lat()));
1711 print("Longitude", render(t->get_lon()));
1713 // TODO: print payload as hex string
1716 static void print_detail_message_18(const marnav::ais::message * m)
1718 const auto t = marnav::ais::message_cast<marnav::ais::message_18>(m);
1719 print("Repeat Indicator", render(t->get_repeat_indicator()));
1720 print("MMSI", render(t->get_mmsi()));
1721 print("SOG", render(t->get_sog()));
1722 print("Pos Accuracy", render(t->get_position_accuracy()));
1723 print("Latitude", render(t->get_lat()));
1724 print("Longitude", render(t->get_lon()));
1725 print("COG", render(t->get_cog()));
1726 print("HDG", render(t->get_hdg()));
1727 print("Time Stamp", render(t->get_timestamp()));
1728 print("CS Unit", render(t->get_cs_unit()));
1729 print("Display Flag", render(t->get_display_flag()));
1730 print("DSC Flag", render(t->get_dsc_flag()));
1731 print("Band Flag", render(t->get_band_flag()));
1732 print("Message 22 Flag", render(t->get_message_22_flag()));
1733 print("Assigned", render(t->get_assigned()));
1734 print("RAIM", render(t->get_raim()));
1735 print("Radio Status", render(t->get_radio_status()));
1738 static void print_detail_message_19(const marnav::ais::message * m)
1740 const auto t = marnav::ais::message_cast<marnav::ais::message_19>(m);
1741 print("Repeat Indicator", render(t->get_repeat_indicator()));
1742 print("MMSI", render(t->get_mmsi()));
1743 print("SOG", render(t->get_sog()));
1744 print("Pos Accuracy", render(t->get_position_accuracy()));
1745 print("Latitude", render(t->get_lat()));
1746 print("Longitude", render(t->get_lon()));
1747 print("COG", render(t->get_cog()));
1748 print("HDG", render(t->get_hdg()));
1749 print("Time Stamp", render(t->get_timestamp()));
1750 print("Ship Name", render(t->get_shipname()));
1751 print("Ship Type", render(t->get_shiptype()));
1752 print("Length", render(t->get_vessel_dimension().length()));
1753 print("Width", render(t->get_vessel_dimension().width()));
1754 print("EPFD Fix", render(t->get_epfd_fix()));
1755 print("RAIM", render(t->get_raim()));
1756 print("DTE", render(t->get_dte()));
1757 print("Assigned", render(t->get_assigned()));
1760 static void print_detail_message_20(const marnav::ais::message * m)
1762 const auto t = marnav::ais::message_cast<marnav::ais::message_20>(m);
1763 print("Repeat Indicator", render(t->get_repeat_indicator()));
1764 print("MMSI", render(t->get_mmsi()));
1765 for (int i = 0; i < 3; ++i) {
1766 const auto entry = t->get_entry(i);
1767 print(fmt::sprintf("Entry %d", i + 1),
1768 fmt::sprintf("Offset:%4u Slots:%1u Timeout:%1u Increment:%4u", entry.offset,
1769 entry.slots, entry.timeout, entry.increment));
1773 static void print_detail_message_21(const marnav::ais::message * m)
1775 const auto t = marnav::ais::message_cast<marnav::ais::message_21>(m);
1776 print("Repeat Indicator", render(t->get_repeat_indicator()));
1777 print("MMSI", render(t->get_mmsi()));
1778 print("Aid Type", render(t->get_aid_type()));
1779 print("Name", render(t->get_name()));
1780 print("Pos Accuracy", render(t->get_position_accuracy()));
1781 print("Latitude", render(t->get_lat()));
1782 print("Longitude", render(t->get_lon()));
1783 print("Length", render(t->get_vessel_dimension().length()));
1784 print("Width", render(t->get_vessel_dimension().width()));
1785 print("EPFD Fix", render(t->get_epfd_fix()));
1786 print("UTC Second", render(t->get_utc_second()));
1787 print("Off Pos Indicator", render(t->get_off_position()));
1788 print("Regional", render(t->get_regional()));
1789 print("RAIM", render(t->get_raim()));
1790 print("Virtual Aid Flag", render(t->get_virtual_aid_flag()));
1791 print("Assigned", render(t->get_assigned()));
1792 print("Name Extension", render(t->get_name_extension()));
1795 static void print_detail_message_22(const marnav::ais::message * m)
1797 const auto t = marnav::ais::message_cast<marnav::ais::message_22>(m);
1798 print("Repeat Indicator", render(t->get_repeat_indicator()));
1799 print("MMSI", render(t->get_mmsi()));
1800 print("Channel A", render(t->get_channel_a()));
1801 print("Channel B", render(t->get_channel_b()));
1802 print("TxRx Mode", render(t->get_txrx_mode()));
1803 print("Power", render(t->get_power()));
1804 print("Adressed", render(t->get_addressed()));
1805 if (t->get_addressed()) {
1806 print("MMSI 1", render(t->get_mmsi_1()));
1807 print("MMSI 2", render(t->get_mmsi_2()));
1808 } else {
1809 print("Position NE", render(t->get_position_ne()));
1810 print("Position SW", render(t->get_position_sw()));
1814 static void print_detail_message_23(const marnav::ais::message * m)
1816 const auto t = marnav::ais::message_cast<marnav::ais::message_23>(m);
1817 print("Repeat Indicator", render(t->get_repeat_indicator()));
1818 print("MMSI", render(t->get_mmsi()));
1819 print("Position NE", render(t->get_position_ne()));
1820 print("Position SW", render(t->get_position_sw()));
1821 print("Station Type", render(t->get_station_type()));
1822 print("Ship Type", render(t->get_shiptype()));
1823 print("TxRx Mode", render(t->get_txrx_mode()));
1824 print("Report Interval", render(t->get_interval()));
1825 print("Quiet Time", render(t->get_quiet_time()));
1828 static void print_detail_message_24(const marnav::ais::message * m)
1830 const auto t = marnav::ais::message_cast<marnav::ais::message_24>(m);
1831 print("Repeat Indicator", render(t->get_repeat_indicator()));
1832 print("MMSI", render(t->get_mmsi()));
1833 print("Part", render(t->get_part_number()));
1834 if (t->get_part_number() == marnav::ais::message_24::part::A) {
1835 print("Ship Name", render(t->get_shipname()));
1836 } else {
1837 print("Ship Type", render(t->get_shiptype()));
1838 print("Vendor ID", render(t->get_vendor_id()));
1839 print("Model", render(t->get_model()));
1840 print("Serial", render(t->get_serial()));
1841 print("Callsign", render(t->get_callsign()));
1842 if (t->is_auxiliary_vessel()) {
1843 print("Mothership MMSI", render(t->get_mothership_mmsi()));
1844 } else {
1845 print("Length", render(t->get_vessel_dimension().length()));
1846 print("Width", render(t->get_vessel_dimension().width()));
1851 /// @endcond
1853 static void dump_nmea(const std::string & line)
1855 #define ADD_SENTENCE(s) \
1857 marnav::nmea::s::ID, detail::print_detail_##s \
1859 struct entry {
1860 marnav::nmea::sentence_id id;
1861 std::function<void(const marnav::nmea::sentence *)> func;
1863 using container = std::vector<entry>;
1864 // clang-format off
1865 static const container sentences = {
1866 // standard
1867 ADD_SENTENCE(aam),
1868 ADD_SENTENCE(alm),
1869 ADD_SENTENCE(apa),
1870 ADD_SENTENCE(apb),
1871 ADD_SENTENCE(bec),
1872 ADD_SENTENCE(bod),
1873 ADD_SENTENCE(bwc),
1874 ADD_SENTENCE(bwr),
1875 ADD_SENTENCE(bww),
1876 ADD_SENTENCE(dbt),
1877 ADD_SENTENCE(dpt),
1878 ADD_SENTENCE(dtm),
1879 ADD_SENTENCE(fsi),
1880 ADD_SENTENCE(gbs),
1881 ADD_SENTENCE(glc),
1882 ADD_SENTENCE(gga),
1883 ADD_SENTENCE(gll),
1884 ADD_SENTENCE(gns),
1885 ADD_SENTENCE(grs),
1886 ADD_SENTENCE(gsa),
1887 ADD_SENTENCE(gst),
1888 ADD_SENTENCE(gsv),
1889 ADD_SENTENCE(gtd),
1890 ADD_SENTENCE(hdg),
1891 ADD_SENTENCE(hfb),
1892 ADD_SENTENCE(hdm),
1893 ADD_SENTENCE(hdt),
1894 ADD_SENTENCE(hsc),
1895 ADD_SENTENCE(its),
1896 ADD_SENTENCE(lcd),
1897 ADD_SENTENCE(mob),
1898 ADD_SENTENCE(msk),
1899 ADD_SENTENCE(mss),
1900 ADD_SENTENCE(mtw),
1901 ADD_SENTENCE(mwd),
1902 ADD_SENTENCE(mwv),
1903 ADD_SENTENCE(osd),
1904 ADD_SENTENCE(r00),
1905 ADD_SENTENCE(rma),
1906 ADD_SENTENCE(rmb),
1907 ADD_SENTENCE(rmc),
1908 ADD_SENTENCE(rot),
1909 ADD_SENTENCE(rpm),
1910 ADD_SENTENCE(rsa),
1911 ADD_SENTENCE(rsd),
1912 ADD_SENTENCE(rte),
1913 ADD_SENTENCE(sfi),
1914 ADD_SENTENCE(stn),
1915 ADD_SENTENCE(tds),
1916 ADD_SENTENCE(tfi),
1917 ADD_SENTENCE(tll),
1918 ADD_SENTENCE(tpc),
1919 ADD_SENTENCE(tpr),
1920 ADD_SENTENCE(tpt),
1921 ADD_SENTENCE(ttm),
1922 ADD_SENTENCE(vbw),
1923 ADD_SENTENCE(vdr),
1924 ADD_SENTENCE(vhw),
1925 ADD_SENTENCE(vlw),
1926 ADD_SENTENCE(vpw),
1927 ADD_SENTENCE(vtg),
1928 ADD_SENTENCE(vwr),
1929 ADD_SENTENCE(wcv),
1930 ADD_SENTENCE(wnc),
1931 ADD_SENTENCE(wpl),
1932 ADD_SENTENCE(xdr),
1933 ADD_SENTENCE(xte),
1934 ADD_SENTENCE(xtr),
1935 ADD_SENTENCE(zda),
1936 ADD_SENTENCE(zdl),
1937 ADD_SENTENCE(zfo),
1938 ADD_SENTENCE(ztg),
1940 // proprietary
1941 ADD_SENTENCE(pgrme),
1942 ADD_SENTENCE(pgrmm),
1943 ADD_SENTENCE(pgrmz),
1944 ADD_SENTENCE(stalk)
1946 // clang-format on
1947 #undef ADD_SENTENCE
1949 using namespace marnav;
1951 try {
1952 auto s = nmea::make_sentence(line);
1953 auto i = std::find_if(std::begin(sentences), std::end(sentences),
1954 [&s](const container::value_type & item) { return item.id == s->id(); });
1955 if (i == std::end(sentences)) {
1956 fmt::printf("\t%s\n", detail::render(s->id()));
1957 fmt::printf(
1958 "%s%s%s\n\tnot implemented\n\n", terminal::magenta, line, terminal::normal);
1959 } else {
1960 fmt::printf("%s%s%s\n", terminal::green, line, terminal::normal);
1961 fmt::printf("\tName : %s\n", detail::render(s->id()));
1962 fmt::printf("\tTalker: %s\n", detail::render(s->get_talker()));
1963 i->func(s.get());
1964 fmt::printf("\n");
1966 } catch (nmea::unknown_sentence & error) {
1967 fmt::printf("%s%s%s\n\terror: unknown sentence: %s\n\n", terminal::red, line,
1968 terminal::normal, error.what());
1969 } catch (nmea::checksum_error & error) {
1970 fmt::printf("%s%s%s\n\terror: checksum error: %s\n\n", terminal::red, line,
1971 terminal::normal, error.what());
1972 } catch (std::invalid_argument & error) {
1973 fmt::printf(
1974 "%s%s%s\n\terror: %s\n\n", terminal::red, line, terminal::normal, error.what());
1978 static void dump_ais(const std::vector<std::unique_ptr<marnav::nmea::sentence>> & sentences)
1980 #define ADD_MESSAGE(m) \
1982 marnav::ais::m::ID, detail::print_detail_##m \
1984 struct entry {
1985 marnav::ais::message_id id;
1986 std::function<void(const marnav::ais::message *)> func;
1988 using container = std::vector<entry>;
1989 // clang-format off
1990 static const container messages = {
1991 ADD_MESSAGE(message_01),
1992 ADD_MESSAGE(message_02),
1993 ADD_MESSAGE(message_03),
1994 ADD_MESSAGE(message_04),
1995 ADD_MESSAGE(message_05),
1996 ADD_MESSAGE(message_06),
1997 ADD_MESSAGE(message_07),
1998 ADD_MESSAGE(message_08),
1999 ADD_MESSAGE(message_09),
2000 ADD_MESSAGE(message_10),
2001 ADD_MESSAGE(message_11),
2002 ADD_MESSAGE(message_12),
2003 ADD_MESSAGE(message_13),
2004 ADD_MESSAGE(message_14),
2005 ADD_MESSAGE(message_17),
2006 ADD_MESSAGE(message_18),
2007 ADD_MESSAGE(message_19),
2008 ADD_MESSAGE(message_20),
2009 ADD_MESSAGE(message_21),
2010 ADD_MESSAGE(message_22),
2011 ADD_MESSAGE(message_23),
2012 ADD_MESSAGE(message_24)
2014 // clang-format on
2015 #undef ADD_MESSAGE
2017 using namespace marnav;
2019 try {
2020 auto m = ais::make_message(nmea::collect_payload(sentences.begin(), sentences.end()));
2021 auto i = std::find_if(std::begin(messages), std::end(messages),
2022 [&m](const container::value_type & item) { return item.id == m->type(); });
2023 if (i == std::end(messages)) {
2024 fmt::printf("\t%s\n", detail::render(m->type()));
2025 fmt::printf("%smessage_%02u%s\n\tnot implemented\n\n", terminal::magenta,
2026 static_cast<uint8_t>(m->type()), terminal::normal);
2027 } else {
2028 fmt::printf("\t%s\n", detail::render(m->type()));
2029 i->func(m.get());
2030 fmt::printf("\n");
2032 } catch (std::exception & error) {
2033 fmt::printf("\t%serror:%s %s\n\n", terminal::red, terminal::normal, error.what());
2037 static void process(std::function<bool(std::string &)> source)
2039 using namespace marnav;
2041 std::string line;
2042 std::vector<std::unique_ptr<nmea::sentence>> sentences;
2044 while (source(line)) {
2045 line = trim(line);
2046 if (line.empty())
2047 continue;
2048 if (line[0] == '#')
2049 continue;
2051 if (line[0] == nmea::sentence::start_token) {
2052 dump_nmea(line);
2053 } else if (line[0] == nmea::sentence::start_token_ais) {
2054 fmt::printf("%s%s%s\n", terminal::blue, line, terminal::normal);
2055 auto s = nmea::make_sentence(line);
2057 nmea::vdm * v = nullptr; // VDM is the common denominator for AIS relevant messages
2059 if (s->id() == nmea::sentence_id::VDO) {
2060 v = nmea::sentence_cast<nmea::vdo>(s.get());
2061 } else if (s->id() == nmea::sentence_id::VDM) {
2062 v = nmea::sentence_cast<nmea::vdm>(s.get());
2063 } else {
2064 // something strange happened, no VDM nor VDO
2065 fmt::printf("%s%s%s\n\terror: ignoring AIS sentence, dropping collection.\n\n",
2066 terminal::red, line, terminal::normal);
2067 sentences.clear();
2068 continue;
2071 // check sentences if a discontuniation has occurred
2072 if (sentences.size() && (sentences.back()->id() != v->id())) {
2073 sentences.clear(); // there was a discontinuation, start over collecting
2074 fmt::printf(
2075 "\t%swarning:%s dropping collection.\n", terminal::cyan, terminal::normal);
2078 // check if a previous message was not complete
2079 const auto n_fragments = v->get_n_fragments();
2080 const auto fragment = v->get_fragment();
2081 if (sentences.size() >= fragment) {
2082 sentences.clear();
2083 fmt::printf(
2084 "\t%swarning:%s dropping collection.\n", terminal::cyan, terminal::normal);
2087 sentences.push_back(std::move(s));
2088 if (fragment == n_fragments) {
2089 dump_ais(sentences);
2090 sentences.clear();
2092 } else {
2093 fmt::printf("%s%s%s\n\terror: ignoring AIS sentence.\n\n", terminal::red, line,
2094 terminal::normal);
2100 int main(int argc, char ** argv)
2102 using namespace nmeadump;
2104 if (parse_options(argc, argv))
2105 return EXIT_SUCCESS;
2107 if (!global.config.file.empty()) {
2108 std::ifstream ifs{global.config.file.c_str()};
2109 process([&](std::string & line) { return !!std::getline(ifs, line); });
2110 } else if (!global.config.port.empty()) {
2111 using namespace marnav;
2112 using namespace marnav::io;
2113 default_nmea_reader source{
2114 utils::make_unique<serial>(global.config.port, global.config.speed,
2115 serial::databits::bit_8, serial::stopbits::bit_1, serial::parity::none)};
2116 process([&](std::string & line) { return source.read_sentence(line); });
2117 } else if (!global.config.input_string.empty()) {
2118 std::istringstream is(global.config.input_string);
2119 process([&](std::string & line){ return !!std::getline(is, line); });
2120 } else {
2121 std::cin.sync_with_stdio(false);
2122 process([&](std::string & line) { return !!std::getline(std::cin, line); });
2125 return EXIT_SUCCESS;