NMEA: sentence ALR added
[marnav.git] / src / nmeadump.cpp
blobdf79f86909b6286e3e7d3623f4275a9ac1521739
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/ais_helper.hpp>
25 #include <marnav/nmea/checksum.hpp>
26 #include <marnav/nmea/name.hpp>
27 #include <marnav/nmea/nmea.hpp>
28 #include <marnav/nmea/route.hpp>
29 #include <marnav/nmea/sentence.hpp>
30 #include <marnav/nmea/string.hpp>
31 #include <marnav/nmea/waypoint.hpp>
33 #include <marnav/nmea/aam.hpp>
34 #include <marnav/nmea/alm.hpp>
35 #include <marnav/nmea/alr.hpp>
36 #include <marnav/nmea/apa.hpp>
37 #include <marnav/nmea/apb.hpp>
38 #include <marnav/nmea/bec.hpp>
39 #include <marnav/nmea/bod.hpp>
40 #include <marnav/nmea/bwc.hpp>
41 #include <marnav/nmea/bwr.hpp>
42 #include <marnav/nmea/bww.hpp>
43 #include <marnav/nmea/dbk.hpp>
44 #include <marnav/nmea/dbt.hpp>
45 #include <marnav/nmea/dpt.hpp>
46 #include <marnav/nmea/dsc.hpp>
47 #include <marnav/nmea/dse.hpp>
48 #include <marnav/nmea/dtm.hpp>
49 #include <marnav/nmea/fsi.hpp>
50 #include <marnav/nmea/gbs.hpp>
51 #include <marnav/nmea/gga.hpp>
52 #include <marnav/nmea/glc.hpp>
53 #include <marnav/nmea/gll.hpp>
54 #include <marnav/nmea/gns.hpp>
55 #include <marnav/nmea/grs.hpp>
56 #include <marnav/nmea/gsa.hpp>
57 #include <marnav/nmea/gst.hpp>
58 #include <marnav/nmea/gsv.hpp>
59 #include <marnav/nmea/gtd.hpp>
60 #include <marnav/nmea/hdg.hpp>
61 #include <marnav/nmea/hfb.hpp>
62 #include <marnav/nmea/hdm.hpp>
63 #include <marnav/nmea/hdt.hpp>
64 #include <marnav/nmea/hsc.hpp>
65 #include <marnav/nmea/its.hpp>
66 #include <marnav/nmea/lcd.hpp>
67 #include <marnav/nmea/mob.hpp>
68 #include <marnav/nmea/msk.hpp>
69 #include <marnav/nmea/mss.hpp>
70 #include <marnav/nmea/mta.hpp>
71 #include <marnav/nmea/mtw.hpp>
72 #include <marnav/nmea/mwd.hpp>
73 #include <marnav/nmea/mwv.hpp>
74 #include <marnav/nmea/osd.hpp>
75 #include <marnav/nmea/r00.hpp>
76 #include <marnav/nmea/rma.hpp>
77 #include <marnav/nmea/rmb.hpp>
78 #include <marnav/nmea/rmc.hpp>
79 #include <marnav/nmea/rot.hpp>
80 #include <marnav/nmea/rpm.hpp>
81 #include <marnav/nmea/rsa.hpp>
82 #include <marnav/nmea/rsd.hpp>
83 #include <marnav/nmea/rte.hpp>
84 #include <marnav/nmea/sfi.hpp>
85 #include <marnav/nmea/stn.hpp>
86 #include <marnav/nmea/tds.hpp>
87 #include <marnav/nmea/tfi.hpp>
88 #include <marnav/nmea/tll.hpp>
89 #include <marnav/nmea/tpc.hpp>
90 #include <marnav/nmea/tpr.hpp>
91 #include <marnav/nmea/tpt.hpp>
92 #include <marnav/nmea/ttm.hpp>
93 #include <marnav/nmea/vbw.hpp>
94 #include <marnav/nmea/vdm.hpp>
95 #include <marnav/nmea/vdo.hpp>
96 #include <marnav/nmea/vdr.hpp>
97 #include <marnav/nmea/vhw.hpp>
98 #include <marnav/nmea/vlw.hpp>
99 #include <marnav/nmea/vpw.hpp>
100 #include <marnav/nmea/vtg.hpp>
101 #include <marnav/nmea/vwe.hpp>
102 #include <marnav/nmea/vwr.hpp>
103 #include <marnav/nmea/wcv.hpp>
104 #include <marnav/nmea/wdc.hpp>
105 #include <marnav/nmea/wdr.hpp>
106 #include <marnav/nmea/wnc.hpp>
107 #include <marnav/nmea/wpl.hpp>
108 #include <marnav/nmea/xdr.hpp>
109 #include <marnav/nmea/xte.hpp>
110 #include <marnav/nmea/xtr.hpp>
111 #include <marnav/nmea/zda.hpp>
112 #include <marnav/nmea/zdl.hpp>
113 #include <marnav/nmea/zfi.hpp>
114 #include <marnav/nmea/zfo.hpp>
115 #include <marnav/nmea/zlz.hpp>
116 #include <marnav/nmea/zpi.hpp>
117 #include <marnav/nmea/zta.hpp>
118 #include <marnav/nmea/zte.hpp>
119 #include <marnav/nmea/ztg.hpp>
120 #include <marnav/nmea/pgrme.hpp>
121 #include <marnav/nmea/pgrmm.hpp>
122 #include <marnav/nmea/pgrmz.hpp>
123 #include <marnav/nmea/stalk.hpp>
125 #include <marnav/ais/ais.hpp>
126 #include <marnav/ais/name.hpp>
128 #include <marnav/ais/message_01.hpp>
129 #include <marnav/ais/message_02.hpp>
130 #include <marnav/ais/message_03.hpp>
131 #include <marnav/ais/message_04.hpp>
132 #include <marnav/ais/message_05.hpp>
133 #include <marnav/ais/message_06.hpp>
134 #include <marnav/ais/message_07.hpp>
135 #include <marnav/ais/message_08.hpp>
136 #include <marnav/ais/message_09.hpp>
137 #include <marnav/ais/message_10.hpp>
138 #include <marnav/ais/message_11.hpp>
139 #include <marnav/ais/message_12.hpp>
140 #include <marnav/ais/message_13.hpp>
141 #include <marnav/ais/message_14.hpp>
142 #include <marnav/ais/message_17.hpp>
143 #include <marnav/ais/message_18.hpp>
144 #include <marnav/ais/message_19.hpp>
145 #include <marnav/ais/message_20.hpp>
146 #include <marnav/ais/message_21.hpp>
147 #include <marnav/ais/message_22.hpp>
148 #include <marnav/ais/message_23.hpp>
149 #include <marnav/ais/message_24.hpp>
150 #include <marnav/ais/binary_001_11.hpp>
151 #include <marnav/ais/binary_200_10.hpp>
153 #include <marnav/io/default_nmea_reader.hpp>
154 #include <marnav/io/serial.hpp>
156 #include <marnav/units/units.hpp>
158 #include <marnav/utils/unique.hpp>
159 #include <marnav/utils/mmsi_country.hpp>
161 #include <cxxopts.hpp>
163 #include <fmt/format.h>
164 #include <fmt/printf.h>
166 #include <fstream>
167 #include <sstream>
168 #include <iostream>
169 #include <vector>
171 namespace nmeadump
173 namespace terminal
175 static constexpr const char * normal = "\033[0m";
176 static constexpr const char * black = "\033[30m";
177 static constexpr const char * red = "\033[31m";
178 static constexpr const char * green = "\033[32m";
179 static constexpr const char * yellow = "\033[33m";
180 static constexpr const char * blue = "\033[34m";
181 static constexpr const char * magenta = "\033[35m";
182 static constexpr const char * cyan = "\033[36m";
183 static constexpr const char * white = "\033[37m";
186 namespace
188 template <class Container>
189 static bool contains(
190 const Container & container, const typename Container::value_type & element)
192 return std::find(std::begin(container), std::end(container), element)
193 != std::end(container);
197 static struct {
198 struct {
199 std::string port;
200 marnav::io::serial::baud speed;
201 std::string file;
202 std::string input_string;
203 } config;
204 } global;
206 static std::string trim(const std::string & s)
208 static const char * whitespace = "\n\r\t ";
209 const auto begin = s.find_first_not_of(whitespace);
210 const auto end = s.find_last_not_of(whitespace);
211 return begin != std::string::npos ? s.substr(begin, end - begin + 1) : "";
214 /// @cond DEV
215 namespace detail
217 template <typename T>
218 static std::string render(const T & t)
220 return marnav::nmea::to_string(t);
223 static std::string render(const std::string & t)
225 return t;
228 static std::string render(bool t)
230 return t ? "true" : "false";
233 static std::string render(char t)
235 return fmt::sprintf("%c", t);
238 static std::string render(const uint32_t t)
240 return fmt::sprintf("%u", t);
243 static std::string render(const int32_t t)
245 return fmt::sprintf("%d", t);
248 static std::string render(const uint8_t t)
250 return fmt::sprintf("%u", t);
253 static std::string render(const double t)
255 return fmt::sprintf("%-8.3f", t);
258 static std::string render(const marnav::utils::mmsi & t)
260 const auto country = mmsi_country(t).name;
261 if (!country.empty())
262 return fmt::sprintf(
263 "%09u (%s)", static_cast<marnav::utils::mmsi::value_type>(t), country);
264 return fmt::sprintf("%09u", static_cast<marnav::utils::mmsi::value_type>(t));
267 static std::string render(const marnav::nmea::time & t)
269 return fmt::sprintf("%02u:%02u:%02u", t.hour(), t.minutes(), t.seconds());
272 static std::string render(const marnav::geo::latitude & t)
274 using namespace marnav::nmea;
275 return fmt::sprintf(
276 " %02u\u00b0%02u'%04.1f%s", t.degrees(), t.minutes(), t.seconds(), to_string(t.hem()));
279 static std::string render(const marnav::geo::longitude & t)
281 using namespace marnav::nmea;
282 return fmt::sprintf(
283 "%03u\u00b0%02u'%04.1f%s", t.degrees(), t.minutes(), t.seconds(), to_string(t.hem()));
286 static std::string render(const marnav::geo::position & p)
288 using namespace marnav::nmea;
289 return fmt::sprintf("%s %s", render(p.lat()), render(p.lon()));
292 static std::string render(const marnav::ais::message_23::report_interval t)
294 switch (t) {
295 case marnav::ais::message_23::report_interval::autonomous_mode:
296 return "Autonomous Mode";
297 case marnav::ais::message_23::report_interval::minutes_10:
298 return "Minutes 10";
299 case marnav::ais::message_23::report_interval::minutes_06:
300 return "Minutes 6";
301 case marnav::ais::message_23::report_interval::minutes_03:
302 return "Minutes 3";
303 case marnav::ais::message_23::report_interval::minutes_01:
304 return "Minutes 1";
305 case marnav::ais::message_23::report_interval::seconds_30:
306 return "Seconds 30";
307 case marnav::ais::message_23::report_interval::seconds_15:
308 return "Seconds 15";
309 case marnav::ais::message_23::report_interval::seconds_10:
310 return "Seconds 10";
311 case marnav::ais::message_23::report_interval::seconds_05:
312 return "Seconds 5";
313 case marnav::ais::message_23::report_interval::next_shorter:
314 return "Next Shorter";
315 case marnav::ais::message_23::report_interval::next_longer:
316 return "Next Longer";
318 return "-";
321 static std::string render(const marnav::ais::message_24::part t)
323 switch (t) {
324 case marnav::ais::message_24::part::A:
325 return "A";
326 case marnav::ais::message_24::part::B:
327 return "B";
329 return "-";
332 static std::string render(const marnav::ais::binary_001_11::trend t)
334 switch (t) {
335 case marnav::ais::binary_001_11::trend::steady:
336 return "steady";
337 case marnav::ais::binary_001_11::trend::decreasing:
338 return "decreasing ";
339 case marnav::ais::binary_001_11::trend::increasing:
340 return "increasing";
341 case marnav::ais::binary_001_11::trend::not_available:
342 return "not available";
344 return "-";
347 static std::string render(const marnav::ais::binary_001_11::ice t)
349 switch (t) {
350 case marnav::ais::binary_001_11::ice::no:
351 return "no";
352 case marnav::ais::binary_001_11::ice::yes:
353 return "yes";
354 case marnav::ais::binary_001_11::ice::not_available:
355 return "not available";
357 return "-";
360 static std::string render(const marnav::ais::binary_001_11::precipitation t)
362 switch (t) {
363 case marnav::ais::binary_001_11::precipitation::rain:
364 return "rain";
365 case marnav::ais::binary_001_11::precipitation::thunderstorm:
366 return "thunderstorm";
367 case marnav::ais::binary_001_11::precipitation::freezing_rain:
368 return "freezing_rain";
369 case marnav::ais::binary_001_11::precipitation::mixed_ice:
370 return "mixed_ice";
371 case marnav::ais::binary_001_11::precipitation::snow:
372 return "snow";
373 case marnav::ais::binary_001_11::precipitation::not_available:
374 return "not available";
376 return "-";
379 static std::string render(const marnav::ais::binary_200_10::loaded_state t)
381 switch (t) {
382 case marnav::ais::binary_200_10::loaded_state::not_available:
383 return "not available";
384 case marnav::ais::binary_200_10::loaded_state::unloaded:
385 return "unloaded";
386 case marnav::ais::binary_200_10::loaded_state::loaded:
387 return "loaded";
389 return "-";
392 static std::string render(const marnav::ais::rate_of_turn t)
394 if (!t.available())
395 return "not available";
396 if (t.is_not_turning())
397 return "not turning";
398 if (t.is_more_5deg30s_right())
399 return "more 5deg/30s right";
400 if (t.is_more_5deg30s_left())
401 return "more 5deg/30s left";
402 return fmt::sprintf("%f", t.value());
405 static std::string render(const marnav::ais::ship_type t)
407 return marnav::ais::to_name(t);
410 static std::string render(const marnav::ais::epfd_fix_type t)
412 return marnav::ais::to_name(t);
415 static std::string render(const marnav::ais::off_position_indicator t)
417 return marnav::ais::to_name(t);
420 static std::string render(const marnav::ais::virtual_aid t)
422 return marnav::ais::to_name(t);
425 static std::string render(const marnav::ais::aid_type_id t)
427 return marnav::ais::to_name(t);
430 static std::string render(const marnav::ais::message_id t)
432 return marnav::ais::to_name(t);
435 static std::string render(const marnav::ais::maneuver_indicator_id t)
437 return marnav::ais::to_name(t);
440 static std::string render(const marnav::ais::data_terminal t)
442 return marnav::ais::to_name(t);
445 static std::string render(const marnav::ais::navigation_status t)
447 return marnav::ais::to_name(t);
450 static std::string render(const marnav::nmea::mob::mob_status t)
452 switch (t) {
453 case marnav::nmea::mob::mob_status::mob_activated:
454 return "mob activated";
455 case marnav::nmea::mob::mob_status::test_mode:
456 return "test mode";
457 case marnav::nmea::mob::mob_status::manual_button:
458 return "manual button";
459 case marnav::nmea::mob::mob_status::mob_not_in_use:
460 return "mob not in use";
461 case marnav::nmea::mob::mob_status::error:
462 return "error";
464 return "-";
467 static std::string render(const marnav::nmea::mob::mob_position_source t)
469 switch (t) {
470 case marnav::nmea::mob::mob_position_source::position_estimated:
471 return "position estimated";
472 case marnav::nmea::mob::mob_position_source::position_reported:
473 return "position reported";
474 case marnav::nmea::mob::mob_position_source::reserved:
475 return "reserved";
476 case marnav::nmea::mob::mob_position_source::error:
477 return "error";
479 return "-";
482 static std::string render(const marnav::nmea::mob::battery_status t)
484 switch (t) {
485 case marnav::nmea::mob::battery_status::good:
486 return "good";
487 case marnav::nmea::mob::battery_status::low:
488 return "low";
489 case marnav::nmea::mob::battery_status::reserved:
490 return "reserved";
491 case marnav::nmea::mob::battery_status::error:
492 return "error";
494 return "-";
497 static std::string render(const marnav::nmea::tfi::state t)
499 switch (t) {
500 case marnav::nmea::tfi::state::off:
501 return "OFF";
502 case marnav::nmea::tfi::state::on:
503 return "ON";
504 case marnav::nmea::tfi::state::no_answer:
505 return "no answer";
507 return "-";
510 static std::string render(const marnav::nmea::sentence_id t)
512 return marnav::nmea::to_name(t);
515 static std::string render(const marnav::nmea::talker t)
517 return marnav::nmea::to_name(t);
520 static std::string render(const marnav::nmea::unit::distance t)
522 return marnav::nmea::to_name(t);
525 static std::string render(const marnav::nmea::unit::temperature t)
527 return marnav::nmea::to_name(t);
530 static std::string render(const marnav::nmea::unit::velocity t)
532 return marnav::nmea::to_name(t);
535 static std::string render(const marnav::nmea::side t)
537 return marnav::nmea::to_name(t);
540 static std::string render(const marnav::nmea::reference t)
542 return marnav::nmea::to_name(t);
545 static std::string render(const marnav::nmea::quality t)
547 return marnav::nmea::to_name(t);
550 static std::string render(const marnav::nmea::direction t)
552 return marnav::nmea::to_string(t);
555 static std::string render(const marnav::nmea::selection_mode t)
557 return marnav::nmea::to_name(t);
560 static std::string render(const marnav::nmea::status t)
562 return marnav::nmea::to_name(t);
565 static std::string render(const marnav::nmea::route_mode t)
567 return marnav::nmea::to_name(t);
570 static std::string render(const marnav::nmea::route & t)
572 return t.c_str();
575 static std::string render(const marnav::nmea::waypoint & t)
577 return t.c_str();
580 static std::string render(const marnav::nmea::mode_indicator t)
582 return marnav::nmea::to_name(t);
585 static std::string render(const marnav::nmea::dsc::format_specifier t)
587 return marnav::nmea::to_name(t);
590 static std::string render(const marnav::nmea::dsc::category t)
592 return marnav::nmea::to_name(t);
595 static std::string render(const marnav::nmea::dsc::acknowledgement t)
597 return marnav::nmea::to_name(t);
600 static std::string render(const marnav::nmea::dsc::extension_indicator t)
602 return marnav::nmea::to_name(t);
605 static std::string render(const marnav::nmea::dse::query_flag t)
607 return marnav::nmea::to_name(t);
610 static std::string render(const marnav::nmea::dse::code_id t)
612 return marnav::nmea::to_name(t);
615 static std::string render(const marnav::nmea::alr::condition t)
617 return marnav::nmea::to_name(t);
620 static std::string render(const marnav::nmea::alr::acknowledge t)
622 return marnav::nmea::to_name(t);
625 static std::string render(const std::vector<uint8_t> & t)
627 std::string s;
628 s.reserve(t.size() * 3 - 1);
629 for (auto i = begin(t); i != end(t); ++i)
630 s.append(fmt::sprintf(((i == begin(t)) ? "%02x" : " %02x"), *i));
631 return s;
634 static std::string render(const marnav::units::nautical_miles & t)
636 return fmt::sprintf("%s %s", render(t.value()), render(marnav::nmea::unit::distance::nm));
639 static std::string render(const marnav::units::knots & t)
641 return fmt::sprintf("%s %s", render(t.value()), render(marnav::nmea::unit::velocity::knot));
644 static std::string render(const marnav::units::meters & t)
646 return fmt::sprintf(
647 "%s %s", render(t.value()), render(marnav::nmea::unit::distance::meter));
650 static std::string render(const marnav::units::feet & t)
652 return fmt::sprintf("%s %s", render(t.value()), render(marnav::nmea::unit::distance::feet));
655 static std::string render(const marnav::units::meters_per_second & t)
657 return fmt::sprintf("%s %s", render(t.value()), render(marnav::nmea::unit::velocity::mps));
660 static std::string render(const marnav::units::celsius & t)
662 return fmt::sprintf(
663 "%s %s", render(t.value()), render(marnav::nmea::unit::temperature::celsius));
666 static std::string render(const marnav::units::length & t)
668 // all lengths are rendered in meters by default
669 return render(t.get<marnav::units::meters>());
672 static std::string render(const marnav::units::velocity & t)
674 // all velocities are rendered in knots by default
675 return render(t.get<marnav::units::knots>());
678 static std::string render(const marnav::units::temperature & t)
680 // all temperatures are rendered in celsius by default
681 return render(t.get<marnav::units::celsius>());
684 static std::string render(const marnav::geo::region & t)
686 return fmt::sprintf("%s/%s - %s/%s", render(t.top()), render(t.left()), render(t.bottom()),
687 render(t.right()));
690 template <typename T>
691 static std::string render(const marnav::utils::optional<T> & t)
693 if (!t)
694 return "-";
695 return render(*t);
698 static void print(const std::string & name, const std::string & value)
700 fmt::printf("\t%-30s : %s\n", name, value);
703 static void print(const std::string & title)
705 fmt::printf("\t%s\n", title);
708 static void print_detail_hdg(const marnav::nmea::sentence * s)
710 const auto t = marnav::nmea::sentence_cast<marnav::nmea::hdg>(s);
711 print("Heading", render(t->get_heading()));
712 print("Magn Deviation",
713 fmt::sprintf("%s %s", render(t->get_magn_dev()), render(t->get_magn_dev_hem())));
714 print("Magn Variation",
715 fmt::sprintf("%s %s", render(t->get_magn_var()), render(t->get_magn_var_hem())));
718 static void print_detail_hfb(const marnav::nmea::sentence * s)
720 const auto t = marnav::nmea::sentence_cast<marnav::nmea::hfb>(s);
721 print("Distance Head Foot [m]", render(t->get_distance_head_foot()));
722 print("Distance Head Bottom [m]", render(t->get_distance_head_bottom()));
725 static void print_detail_hdm(const marnav::nmea::sentence * s)
727 const auto t = marnav::nmea::sentence_cast<marnav::nmea::hdm>(s);
728 print("Heading", render(t->get_heading()));
731 static void print_detail_hdt(const marnav::nmea::sentence * s)
733 const auto t = marnav::nmea::sentence_cast<marnav::nmea::hdt>(s);
734 print("Heading", render(t->get_heading()));
737 static void print_detail_hsc(const marnav::nmea::sentence * s)
739 const auto t = marnav::nmea::sentence_cast<marnav::nmea::hsc>(s);
740 print("Heading True", render(t->get_heading_true()));
741 print("Heading Magnetic", render(t->get_heading_mag()));
744 static void print_detail_its(const marnav::nmea::sentence * s)
746 const auto t = marnav::nmea::sentence_cast<marnav::nmea::its>(s);
747 print("Distance [m]", render(t->get_distance()));
750 static void print_detail_lcd(const marnav::nmea::sentence * s)
752 const auto t = marnav::nmea::sentence_cast<marnav::nmea::lcd>(s);
753 print("GRI microseconds", render(t->get_gri()));
754 print("Master", fmt::sprintf("SNR:%d ECD:%d", t->get_master().snr, t->get_master().ecd));
755 for (int i = 0; i < marnav::nmea::lcd::max_differences; ++i) {
756 const auto diff = t->get_time_diff(i);
757 if (diff) {
758 print(fmt::sprintf("Time Diff %d", i),
759 fmt::sprintf("SNR:%d ECD:%d", diff->snr, diff->ecd));
764 static void print_detail_mob(const marnav::nmea::sentence * s)
766 const auto t = marnav::nmea::sentence_cast<marnav::nmea::mob>(s);
767 print("MOB Emitter ID", render(t->get_emitter_id()));
768 print("MOB Status", render(t->get_mob_status()));
769 print("MOB Time UTC", render(t->get_mob_activation_utc()));
770 print("MOB Position Source", render(t->get_mob_position_source()));
771 print("Date of Position", render(t->get_position_date()));
772 print("Time of Position", render(t->get_position_time()));
773 print("Latitude", render(t->get_lat()));
774 print("Longitude", render(t->get_lon()));
775 print("COG", render(t->get_cog()));
776 print("SOG", render(t->get_sog()));
777 print("MMSI", render(t->get_mmsi()));
778 print("Battery Status", render(t->get_battery_status()));
781 static void print_detail_msk(const marnav::nmea::sentence * s)
783 const auto t = marnav::nmea::sentence_cast<marnav::nmea::msk>(s);
784 print("Frequency to use", render(t->get_frequency()));
785 print("Frequency Mode", render(t->get_frequency_mode()));
786 print("Beacon Bit Rate", render(t->get_bitrate()));
787 print("Beacon Mode", render(t->get_bitrate_mode()));
788 print("Frequency for MSS message status", render(t->get_frequency_mss_status()));
791 static void print_detail_rmb(const marnav::nmea::sentence * s)
793 const auto t = marnav::nmea::sentence_cast<marnav::nmea::rmb>(s);
794 print("Active", render(t->get_active()));
795 print("Cross Track Error", render(t->get_cross_track_error()));
796 print("Waypoint From", render(t->get_waypoint_from()));
797 print("Waypoint To", render(t->get_waypoint_to()));
798 print("Latitude", render(t->get_lat()));
799 print("Longitude", render(t->get_lon()));
800 print("Range", render(t->get_range()));
801 print("Bearing", render(t->get_bearing()));
802 print("Dest. Velocity", render(t->get_dst_velocity()));
803 print("Arrival Status", render(t->get_arrival_status()));
804 print("Mode Indicator", render(t->get_mode_ind()));
807 static void print_detail_rmc(const marnav::nmea::sentence * s)
809 const auto t = marnav::nmea::sentence_cast<marnav::nmea::rmc>(s);
810 print("Time UTC", render(t->get_time_utc()));
811 print("Status", render(t->get_status()));
812 print("Latitude", render(t->get_lat()));
813 print("Longitude", render(t->get_lon()));
814 print("SOG", render(t->get_sog()));
815 print("Heading", render(t->get_heading()));
816 print("Date", render(t->get_date()));
817 print("Magn Dev", fmt::sprintf("%s %s", render(t->get_mag()), render(t->get_mag_hem())));
818 print("Mode Ind ", render(t->get_mode_ind()));
821 static void print_detail_rot(const marnav::nmea::sentence * s)
823 const auto t = marnav::nmea::sentence_cast<marnav::nmea::rot>(s);
824 print("Rate of Turn", render(t->get_deg_per_minute()));
825 print("Status", render(t->get_data_valid()));
828 static void print_detail_rpm(const marnav::nmea::sentence * s)
830 const auto t = marnav::nmea::sentence_cast<marnav::nmea::rpm>(s);
831 print("Source", render(t->get_source()));
832 print("Source Number", render(t->get_source_number()));
833 print("RPM", render(t->get_revolutions()));
834 print("Propeller Pitch", render(t->get_propeller_pitch()));
835 print("Status", render(t->get_data_valid()));
838 static void print_detail_rsa(const marnav::nmea::sentence * s)
840 const auto t = marnav::nmea::sentence_cast<marnav::nmea::rsa>(s);
841 print("Starbord Angle", render(t->get_rudder1()));
842 print("Starbord Status", render(t->get_rudder1_valid()));
843 print("Port Angle", render(t->get_rudder2()));
844 print("Port Status", render(t->get_rudder2_valid()));
847 static void print_detail_rsd(const marnav::nmea::sentence * s)
849 const auto t = marnav::nmea::sentence_cast<marnav::nmea::rsd>(s);
850 print("Cursor Range from own ship", render(t->get_cursor_range()));
851 print("Cursor Bearing from own ship", render(t->get_cursor_bearing()));
852 print("Range Scale", render(t->get_range_scale()));
853 print("Range Units", render(t->get_range_unit()));
856 static void print_detail_vtg(const marnav::nmea::sentence * s)
858 const auto t = marnav::nmea::sentence_cast<marnav::nmea::vtg>(s);
859 print("Track True", render(t->get_track_true()));
860 print("Track Magn", render(t->get_track_magn()));
861 print("Speed Knots", render(t->get_speed_kn()));
862 print("Speed kmh", render(t->get_speed_kmh()));
863 print("Mode Indicator", render(t->get_mode_ind()));
866 static void print_detail_gll(const marnav::nmea::sentence * s)
868 const auto t = marnav::nmea::sentence_cast<marnav::nmea::gll>(s);
869 print("Latitude", render(t->get_lat()));
870 print("Longitude", render(t->get_lon()));
871 print("Time UTC", render(t->get_time_utc()));
872 print("Status", render(t->get_data_valid()));
873 print("Mode Indicator", render(t->get_mode_ind()));
876 static void print_detail_gns(const marnav::nmea::sentence * s)
878 const auto t = marnav::nmea::sentence_cast<marnav::nmea::gns>(s);
879 print("Time UTC", render(t->get_time_utc()));
880 print("Latitude", render(t->get_lat()));
881 print("Longitude", render(t->get_lon()));
882 print("Mode Indicator", render(t->get_mode_ind()));
883 print("Number of Satellites", render(t->get_number_of_satellites()));
884 print("HDROP", render(t->get_hdrop()));
885 print("Antenna Altitude [m]", render(t->get_antenna_altitude()));
886 print("Geoidal Separation [m]", render(t->get_geodial_separation()));
887 print("Age of differential Data", render(t->get_age_of_differential_data()));
888 print("Differential Ref Station ID", render(t->get_differential_ref_station_id()));
891 static void print_detail_grs(const marnav::nmea::sentence * s)
893 const auto t = marnav::nmea::sentence_cast<marnav::nmea::grs>(s);
894 print("UTC time associated with GGA", render(t->get_time_utc()));
895 print("Status", render(t->get_usage()));
896 for (int i = 0; i < marnav::nmea::grs::num_satellite_residuals; ++i) {
897 const auto residual = t->get_sat_residual(i);
898 if (residual)
899 print(fmt::sprintf("Sat %02d Residual [m]", i), render(*residual));
903 static void print_detail_bec(const marnav::nmea::sentence * s)
905 const auto t = marnav::nmea::sentence_cast<marnav::nmea::bec>(s);
906 print("Time UTC", render(t->get_time_utc()));
907 print("Bearing True", render(t->get_bearing_true()));
908 print("Bearing Magn", render(t->get_bearing_magn()));
909 print("Distance [nm]", render(t->get_distance().get<marnav::units::nautical_miles>()));
910 print("Waypoint", render(t->get_waypoint()));
913 static void print_detail_bod(const marnav::nmea::sentence * s)
915 const auto t = marnav::nmea::sentence_cast<marnav::nmea::bod>(s);
916 print("Bearing True", render(t->get_bearing_true()));
917 print("Bearing Magn", render(t->get_bearing_magn()));
918 print("Waypoint To", render(t->get_waypoint_to()));
919 print("Waypoint From", render(t->get_waypoint_from()));
922 static void print_detail_bwc(const marnav::nmea::sentence * s)
924 const auto t = marnav::nmea::sentence_cast<marnav::nmea::bwc>(s);
925 print("Time UTC", render(t->get_time_utc()));
926 print("Bearing True", render(t->get_bearing_true()));
927 print("Bearing Magnetic", render(t->get_bearing_mag()));
928 print("Distance",
929 fmt::sprintf(
930 "%s %s", render(t->get_distance()), render(marnav::nmea::unit::distance::nm)));
931 print("Waypoint", render(t->get_waypoint_id()));
932 print("Mode Indicator", render(t->get_mode_ind()));
935 static void print_detail_bwr(const marnav::nmea::sentence * s)
937 const auto t = marnav::nmea::sentence_cast<marnav::nmea::bwr>(s);
938 print("Time UTC", render(t->get_time_utc()));
939 print("Latitude", render(t->get_lat()));
940 print("Longitude", render(t->get_lon()));
941 print("Bearing True", render(t->get_bearing_true()));
942 print("Bearing Magnetic", render(t->get_bearing_mag()));
943 print("Distance NM", render(t->get_distance()));
944 print("Waypoint", render(t->get_waypoint_id()));
945 print("Mode Indicator", render(t->get_mode_ind()));
948 static void print_detail_bww(const marnav::nmea::sentence * s)
950 const auto t = marnav::nmea::sentence_cast<marnav::nmea::bww>(s);
951 print("Bearing True", render(t->get_bearing_true()));
952 print("Bearing Magnetic", render(t->get_bearing_magn()));
953 print("Waypoint To", render(t->get_waypoint_to()));
954 print("Waypoint From", render(t->get_waypoint_from()));
957 static void print_detail_gsa(const marnav::nmea::sentence * s)
959 const auto t = marnav::nmea::sentence_cast<marnav::nmea::gsa>(s);
960 print("Selection Mode", render(t->get_sel_mode()));
961 print("Mode", render(t->get_mode()));
962 for (auto i = 0; i < marnav::nmea::gsa::max_satellite_ids; ++i) {
963 print(fmt::sprintf("Satellite %02u", i), render(t->get_satellite_id(i)));
965 print("PDOP", render(t->get_pdop()));
966 print("HDOP", render(t->get_hdop()));
967 print("VDOP", render(t->get_vdop()));
970 static void print_detail_gst(const marnav::nmea::sentence * s)
972 const auto t = marnav::nmea::sentence_cast<marnav::nmea::gst>(s);
973 print("Time UTC", render(t->get_time_utc()));
974 print("Total RMS", render(t->get_total_rms()));
975 print("Std Dev Semi-Major Axis", render(t->get_dev_semi_major()));
976 print("Std Dev Semi-Minor Axis", render(t->get_dev_semi_minor()));
977 print("Orientation Semi-Major Axis", render(t->get_orientation()));
978 print("Std Dev. Latitude Error", render(t->get_dev_lat()));
979 print("Std Dev. Longitude Error", render(t->get_dev_lon()));
980 print("Std Dev. Altitude Error", render(t->get_dev_alt()));
983 static void print_detail_glc(const marnav::nmea::sentence * s)
985 const auto t = marnav::nmea::sentence_cast<marnav::nmea::glc>(s);
986 print("GRI", render(t->get_gri()));
987 print("Master TOA",
988 fmt::sprintf(
989 "DIFF:%s STATUS:%s", render(t->get_master().diff), render(t->get_master().status)));
990 for (int i = 0; i < marnav::nmea::glc::max_differences; ++i) {
991 const auto & td = t->get_time_diff(i);
992 if (td) {
993 print(fmt::sprintf("Time Diff %d", i),
994 fmt::sprintf("DIFF:%s STATUS:%s", render(td->diff), render(td->status)));
999 static void print_detail_gga(const marnav::nmea::sentence * s)
1001 const auto t = marnav::nmea::sentence_cast<marnav::nmea::gga>(s);
1002 print("Time", render(t->get_time()));
1003 print("Latitude", render(t->get_lat()));
1004 print("Longitude", render(t->get_lon()));
1005 print("Quality Ind", render(t->get_quality_indicator()));
1006 print("Num Satellites", render(t->get_n_satellites()));
1007 print("Horiz Dilution", render(t->get_hor_dilution()));
1008 print("Altitude", render(t->get_altitude()));
1009 print("Geodial Sep", render(t->get_geodial_separation()));
1010 print("DGPS Age", render(t->get_dgps_age()));
1011 print("DGPS Ref", render(t->get_dgps_ref()));
1014 static void print_detail_osd(const marnav::nmea::sentence * s)
1016 const auto t = marnav::nmea::sentence_cast<marnav::nmea::osd>(s);
1017 print("Heading", render(t->get_heading()));
1018 print("Status", render(t->get_data_valid()));
1019 print("Vessel Course True", render(t->get_course()));
1020 print("Vessel Speed",
1021 fmt::sprintf("%s %s", render(t->get_speed()), render(t->get_speed_unit())));
1022 print("Vessel Set", render(t->get_vessel_set()));
1023 print("Vessel Drift",
1024 fmt::sprintf("%s %s", render(t->get_vessel_drift()), render(t->get_speed_unit())));
1027 static void print_detail_r00(const marnav::nmea::sentence * s)
1029 const auto t = marnav::nmea::sentence_cast<marnav::nmea::r00>(s);
1030 for (int i = 0; i < marnav::nmea::r00::max_waypoint_ids; ++i) {
1031 const auto & wp = t->get_waypoint_id(i);
1032 if (wp) {
1033 print("Waypoint", render(*wp));
1038 static void print_detail_rma(const marnav::nmea::sentence * s)
1040 const auto t = marnav::nmea::sentence_cast<marnav::nmea::rma>(s);
1041 print("Blink Warning", render(t->get_blink_warning()));
1042 print("Latitude", render(t->get_lat()));
1043 print("Longitude", render(t->get_lon()));
1044 print("Time Diff A", render(t->get_time_diff_a()));
1045 print("Time Diff B", render(t->get_time_diff_b()));
1046 print("SOG [kn]", render(t->get_sog()));
1047 print("Track made good", render(t->get_track()));
1048 print("Magnetic Variation",
1049 fmt::sprintf(
1050 "%s %s", render(t->get_magnetic_var()), render(t->get_magnetic_var_hem())));
1053 static void print_detail_mwv(const marnav::nmea::sentence * s)
1055 const auto t = marnav::nmea::sentence_cast<marnav::nmea::mwv>(s);
1056 print("Angle", fmt::sprintf("%s %s", render(t->get_angle()), render(t->get_angle_ref())));
1057 print("Speed", fmt::sprintf("%s %s", render(t->get_speed()), render(t->get_speed_unit())));
1058 print("Data Valid", render(t->get_data_valid()));
1061 static void print_detail_gsv(const marnav::nmea::sentence * s)
1063 const auto t = marnav::nmea::sentence_cast<marnav::nmea::gsv>(s);
1064 print("Num Messages", render(t->get_n_messages()));
1065 print("Messages Number", render(t->get_message_number()));
1066 print("Num Sat in View", render(t->get_n_satellites_in_view()));
1067 for (int i = 0; i < 4; ++i) {
1068 const auto sat = t->get_sat(i);
1069 if (sat) {
1070 print("Sat",
1071 fmt::sprintf("PRN:%02u ELEV:%02u AZIMUTH:%03u SNR:%s", sat->prn, sat->elevation,
1072 sat->azimuth, render(sat->snr)));
1077 static void print_detail_gtd(const marnav::nmea::sentence * s)
1079 const auto t = marnav::nmea::sentence_cast<marnav::nmea::gtd>(s);
1080 for (int i = 0; i < marnav::nmea::gtd::max_time_diffs; ++i)
1081 print(fmt::sprintf("Time Diff %d", i), render(t->get_time_diff(i)));
1084 static void print_detail_zda(const marnav::nmea::sentence * s)
1086 const auto t = marnav::nmea::sentence_cast<marnav::nmea::zda>(s);
1087 print("Time UTC", render(t->get_time_utc()));
1088 print("Date", render(t->get_date()));
1089 print("Local Zone Hours", render(t->get_local_zone_hours()));
1090 print("Local Zone Min", render(t->get_local_zone_minutes()));
1093 static void print_detail_zdl(const marnav::nmea::sentence * s)
1095 const auto t = marnav::nmea::sentence_cast<marnav::nmea::zdl>(s);
1096 print("Time to Point", render(t->get_time_to_point()));
1097 print("Distance to Point NM", render(t->get_distance()));
1098 print("Type of Point", render(t->get_type_point()));
1101 static void print_detail_zfi(const marnav::nmea::sentence * s)
1103 const auto t = marnav::nmea::sentence_cast<marnav::nmea::zfi>(s);
1104 print("Time UTC", render(t->get_time_utc()));
1105 print("Elapsed Time", render(t->get_time_elapsed()));
1106 print("Origin Waypoint", render(t->get_waypoint_id()));
1109 static void print_detail_zfo(const marnav::nmea::sentence * s)
1111 const auto t = marnav::nmea::sentence_cast<marnav::nmea::zfo>(s);
1112 print("Time UTC", render(t->get_time_utc()));
1113 print("Elapsed Time", render(t->get_time_elapsed()));
1114 print("Origin Waypoint", render(t->get_waypoint_id()));
1117 static void print_detail_zta(const marnav::nmea::sentence * s)
1119 const auto t = marnav::nmea::sentence_cast<marnav::nmea::zta>(s);
1120 print("Time UTC", render(t->get_time_utc()));
1121 print("Time Arrival", render(t->get_time_arrival()));
1122 print("Destination Waypoint", render(t->get_waypoint_id()));
1125 static void print_detail_zte(const marnav::nmea::sentence * s)
1127 const auto t = marnav::nmea::sentence_cast<marnav::nmea::zte>(s);
1128 print("Time UTC", render(t->get_time_utc()));
1129 print("Time Remaining", render(t->get_time_remaining()));
1130 print("Destination Waypoint", render(t->get_waypoint_id()));
1133 static void print_detail_zlz(const marnav::nmea::sentence * s)
1135 const auto t = marnav::nmea::sentence_cast<marnav::nmea::zlz>(s);
1136 print("Time UTC", render(t->get_time_utc()));
1137 print("Time Local", render(t->get_time_local()));
1138 print("Local Zone Description", render(t->get_local_zone_description()));
1141 static void print_detail_zpi(const marnav::nmea::sentence * s)
1143 const auto t = marnav::nmea::sentence_cast<marnav::nmea::zpi>(s);
1144 print("Time UTC", render(t->get_time_utc()));
1145 print("Time at Arrival", render(t->get_time_arrival()));
1146 print("Destination Waypoint", render(t->get_waypoint_id()));
1149 static void print_detail_ztg(const marnav::nmea::sentence * s)
1151 const auto t = marnav::nmea::sentence_cast<marnav::nmea::ztg>(s);
1152 print("Time UTC", render(t->get_time_utc()));
1153 print("Time Remaining", render(t->get_time_remaining()));
1154 print("Destination Waypoint", render(t->get_waypoint_id()));
1157 static void print_detail_dtm(const marnav::nmea::sentence * s)
1159 const auto t = marnav::nmea::sentence_cast<marnav::nmea::dtm>(s);
1160 print("Ref", render(t->get_ref()));
1161 print("Subcode", render(t->get_subcode()));
1162 print("Latitude Offset", render(t->get_lat_offset()));
1163 print("Latitude Hem", render(t->get_lat_hem()));
1164 print("Longitude Offset", render(t->get_lon_offset()));
1165 print("Longitude Hem", render(t->get_lon_hem()));
1166 print("Altitude", render(t->get_altitude().get<marnav::units::meters>()));
1167 print("Name", render(t->get_name()));
1170 static void print_detail_fsi(const marnav::nmea::sentence * s)
1172 const auto t = marnav::nmea::sentence_cast<marnav::nmea::fsi>(s);
1173 print("Tx Freuency 100 Hz", render(t->get_tx_frequency()));
1174 print("Rx Freuency 100 Hz", render(t->get_rx_frequency()));
1175 print("Mode of Operation", render(t->get_communications_mode()));
1176 print("Power Level", render(t->get_power_level()));
1177 print("Sentence Status Flag", render(t->get_sentence_status()));
1180 static void print_detail_gbs(const marnav::nmea::sentence * s)
1182 const auto t = marnav::nmea::sentence_cast<marnav::nmea::gbs>(s);
1183 print("Time UTC", render(t->get_time_utc()));
1184 print("Error Latitude", render(t->get_err_lat().get<marnav::units::meters>()));
1185 print("Error Longitude", render(t->get_err_lon().get<marnav::units::meters>()));
1186 print("Error Altitude", render(t->get_err_alt().get<marnav::units::meters>()));
1187 print("Satellite PRN", render(t->get_satellite()));
1188 print("Probability", render(t->get_probability()));
1189 print("Bias", render(t->get_bias().get<marnav::units::meters>()));
1190 print("Standard Deviation of bias", render(t->get_bias_dev()));
1193 static void print_detail_aam(const marnav::nmea::sentence * s)
1195 const auto t = marnav::nmea::sentence_cast<marnav::nmea::aam>(s);
1196 print("Arrival Circle Entred", render(t->get_arrival_circle_entered()));
1197 print("Perpendicular Passed", render(t->get_perpendicualar_passed()));
1198 print("Arrival Circle Radius",
1199 render(t->get_arrival_circle_radius().get<marnav::units::nautical_miles>()));
1200 print("Waypoint", render(t->get_waypoint_id()));
1203 static void print_detail_alm(const marnav::nmea::sentence * s)
1205 const auto t = marnav::nmea::sentence_cast<marnav::nmea::alm>(s);
1206 print("Number of Messages", render(t->get_number_of_messages()));
1207 print("Message Number", render(t->get_message_number()));
1208 print("Satellite PRN", render(t->get_satellite_prn()));
1209 print("GPS Week Number", render(t->get_gps_week_number()));
1210 print("SV Health", render(t->get_sv_health()));
1211 print("Eccentricity", render(t->get_eccentricity()));
1212 print("Almanac Reference Time", render(t->get_almanac_reference_time()));
1213 print("Inclination Angle", render(t->get_inclination_angle()));
1214 print("Rate of right ascension", render(t->get_rate_of_right_ascension()));
1215 print("Root of Semimajor Axis", render(t->get_root_of_semimajor_axis()));
1216 print("Argument of perigee", render(t->get_argument_of_perigee()));
1217 print("Longitude of ascension node", render(t->get_longitude_of_ascension_node()));
1218 print("Mean Anomaly", render(t->get_mean_anomaly()));
1219 print("F0 clock parameter", render(t->get_f0_clock_parameter()));
1220 print("F1 clock parameter", render(t->get_f1_clock_parameter()));
1223 static void print_detail_alr(const marnav::nmea::sentence * s)
1225 const auto t = marnav::nmea::sentence_cast<marnav::nmea::alr>(s);
1226 print("Time UTC", render(t->get_time_utc()));
1227 print("Alarm Number", render(t->get_number()));
1228 print("Alarm Condition", render(t->get_condition()));
1229 print("Alarm Acknowledge", render(t->get_acknowledge()));
1230 print("Alarm Text", render(t->get_text()));
1233 static void print_detail_apa(const marnav::nmea::sentence * s)
1235 const auto t = marnav::nmea::sentence_cast<marnav::nmea::apa>(s);
1236 print("Lorac C Blink Warning", render(t->get_loran_c_blink_warning()));
1237 print("Lorac C Cycle Lock Warning", render(t->get_loran_c_cycle_lock_warning()));
1238 print("Magnitude of Cross Track Error", render(t->get_cross_track_error_magnitude()));
1239 print("Direction to Steer", render(t->get_direction_to_steer()));
1240 print("Cross Track Units", render(t->get_cross_track_unit()));
1241 print("Status Arrival", render(t->get_status_arrival()));
1242 print("Status Perpendicular Passed", render(t->get_status_perpendicular_passing()));
1243 print("Bearing Origin to Dest", render(t->get_bearing_origin_to_destination()));
1244 print("Bearing Origin to Dest Ref", render(t->get_bearing_origin_to_destination_ref()));
1245 print("Destination Waypoint", render(t->get_waypoint_id()));
1248 static void print_detail_rte(const marnav::nmea::sentence * s)
1250 const auto t = marnav::nmea::sentence_cast<marnav::nmea::rte>(s);
1251 print("Number of Messages", render(t->get_n_messages()));
1252 print("Message Number", render(t->get_message_number()));
1253 print("Message Mode", render(t->get_message_mode()));
1254 for (int i = 0; i < marnav::nmea::rte::max_waypoints; ++i) {
1255 const auto wp = t->get_waypoint_id(i);
1256 if (wp)
1257 print(fmt::sprintf("Waypoint %i", i), render(wp));
1261 static void print_detail_sfi(const marnav::nmea::sentence * s)
1263 const auto t = marnav::nmea::sentence_cast<marnav::nmea::sfi>(s);
1264 print("Number of Messages", render(t->get_n_messages()));
1265 print("Message Number", render(t->get_message_number()));
1266 for (const auto & f : t->get_frequencies())
1267 print("Frequency [kHz]", fmt::sprintf("%s %s", render(f.frequency), render(f.mode)));
1270 static void print_detail_stn(const marnav::nmea::sentence * s)
1272 const auto t = marnav::nmea::sentence_cast<marnav::nmea::stn>(s);
1273 print("Number ID", render(t->get_number()));
1276 static void print_detail_tds(const marnav::nmea::sentence * s)
1278 const auto t = marnav::nmea::sentence_cast<marnav::nmea::tds>(s);
1279 print("Distance [m]", render(t->get_distance()));
1282 static void print_detail_tfi(const marnav::nmea::sentence * s)
1284 const auto t = marnav::nmea::sentence_cast<marnav::nmea::tfi>(s);
1285 print("Sensor #1", render(t->get_sensor(0)));
1286 print("Sensor #2", render(t->get_sensor(1)));
1287 print("Sensor #3", render(t->get_sensor(2)));
1290 static void print_detail_tll(const marnav::nmea::sentence * s)
1292 const auto t = marnav::nmea::sentence_cast<marnav::nmea::tll>(s);
1293 print("Target Number", render(t->get_number()));
1294 print("Latitude", render(t->get_lat()));
1295 print("Longitude", render(t->get_lon()));
1296 print("Target Name", render(t->get_name()));
1297 print("Time UTC", render(t->get_time_utc()));
1298 print("Target Status", render(t->get_status()));
1299 print("Reference Target", render(t->get_reference_target()));
1302 static void print_detail_tpc(const marnav::nmea::sentence * s)
1304 const auto t = marnav::nmea::sentence_cast<marnav::nmea::tpc>(s);
1305 print("Horiz. Range from Center Line [m]", render(t->get_distance_centerline()));
1306 print("Horiz. dist from Transd. along [m]", render(t->get_distance_transducer()));
1307 print("Depth [m]", render(t->get_depth()));
1310 static void print_detail_tpr(const marnav::nmea::sentence * s)
1312 const auto t = marnav::nmea::sentence_cast<marnav::nmea::tpr>(s);
1313 print("Horizontal Range [m]", render(t->get_range()));
1314 print("Bearing to Target to Vessel", render(t->get_bearing()));
1315 print("Depth [m]", render(t->get_depth()));
1318 static void print_detail_tpt(const marnav::nmea::sentence * s)
1320 const auto t = marnav::nmea::sentence_cast<marnav::nmea::tpt>(s);
1321 print("Horizontal Range [m]", render(t->get_range()));
1322 print("Bearing to Target True", render(t->get_bearing()));
1323 print("Depth [m]", render(t->get_depth()));
1326 static void print_detail_ttm(const marnav::nmea::sentence * s)
1328 const auto t = marnav::nmea::sentence_cast<marnav::nmea::ttm>(s);
1329 print("Target Number", render(t->get_target_number()));
1330 print("Target Distance", render(t->get_target_distance()));
1331 print("Bearing from own ship", render(t->get_bearing_from_ownship()));
1332 print("Bearing from own ship Ref", render(t->get_bearing_from_ownship_ref()));
1333 print("Target Speed", render(t->get_target_speed()));
1334 print("Target Course", render(t->get_target_course()));
1335 print("Target Course Ref", render(t->get_target_course_ref()));
1336 print("CPA", render(t->get_distance_cpa()));
1337 print("TCPA", render(t->get_tcpa()));
1338 print("Unknown", render(t->get_unknown()));
1339 print("Target Name", render(t->get_target_name()));
1340 print("Target Status", render(t->get_target_status()));
1341 print("Reference Target", render(t->get_reference_target()));
1344 static void print_detail_vbw(const marnav::nmea::sentence * s)
1346 const auto t = marnav::nmea::sentence_cast<marnav::nmea::vbw>(s);
1347 print("Longitudinal Water Speed", render(t->get_water_speed_longitudinal()));
1348 print("Transverse Water Speed", render(t->get_water_speed_transveral()));
1349 print("Status", render(t->get_water_speed_status()));
1350 print("Longitudinal Ground Speed", render(t->get_ground_speed_longitudinal()));
1351 print("Transverse Ground Speed", render(t->get_ground_speed_transveral()));
1352 print("Status", render(t->get_ground_speed_status()));
1355 static void print_detail_vdr(const marnav::nmea::sentence * s)
1357 const auto t = marnav::nmea::sentence_cast<marnav::nmea::vdr>(s);
1358 print("Degrees True", render(t->get_degrees_true()));
1359 print("Degrees Magnetic", render(t->get_degrees_magn()));
1360 print("Speed of Current", render(t->get_speed()));
1363 static void print_detail_mss(const marnav::nmea::sentence * s)
1365 const auto t = marnav::nmea::sentence_cast<marnav::nmea::mss>(s);
1366 print("Signal Strength [dB 1uV]", render(t->get_signal_strength()));
1367 print("Signal to Noise Ratio (dB)", render(t->get_signal_to_noise_ratio()));
1368 print("Beacon Frequency [kHz]", render(t->get_beacon_frequency()));
1369 print("Beacon Data Rate BPS", render(t->get_beacon_datarate()));
1370 print("unknown", render(t->get_unknown()));
1373 static void print_detail_mta(const marnav::nmea::sentence * s)
1375 const auto t = marnav::nmea::sentence_cast<marnav::nmea::mta>(s);
1376 print("Air Temperature", render(t->get_temperature()));
1379 static void print_detail_mtw(const marnav::nmea::sentence * s)
1381 const auto t = marnav::nmea::sentence_cast<marnav::nmea::mtw>(s);
1382 print("Water Temperature", render(t->get_temperature()));
1385 static void print_detail_mwd(const marnav::nmea::sentence * s)
1387 const auto t = marnav::nmea::sentence_cast<marnav::nmea::mwd>(s);
1388 print("Direction True", render(t->get_direction_true()));
1389 print("Direction Magnetic", render(t->get_direction_mag()));
1390 print("Speed kn", render(t->get_speed_kn()));
1391 print("Speed m/s", render(t->get_speed_ms()));
1394 static void print_detail_dbk(const marnav::nmea::sentence * s)
1396 const auto t = marnav::nmea::sentence_cast<marnav::nmea::dbk>(s);
1397 print("Depth Feet", render(t->get_depth_feet()));
1398 print("Depth Meter", render(t->get_depth_meter()));
1399 print("Depth Fathom", render(t->get_depth_fathom()));
1402 static void print_detail_dbt(const marnav::nmea::sentence * s)
1404 const auto t = marnav::nmea::sentence_cast<marnav::nmea::dbt>(s);
1405 print("Depth Feet", render(t->get_depth_feet()));
1406 print("Depth Meter", render(t->get_depth_meter()));
1407 print("Depth Fathom", render(t->get_depth_fathom()));
1410 static void print_detail_dpt(const marnav::nmea::sentence * s)
1412 const auto t = marnav::nmea::sentence_cast<marnav::nmea::dpt>(s);
1413 print("Depth", render(t->get_depth_meter().get<marnav::units::meters>()));
1414 print("Offset from Transducer",
1415 render(t->get_transducer_offset().get<marnav::units::meters>()));
1416 print("Max Depth", render(t->get_max_depth()));
1419 static void print_detail_dsc(const marnav::nmea::sentence * s)
1421 const auto t = marnav::nmea::sentence_cast<marnav::nmea::dsc>(s);
1422 print("Format Specificer", render(t->get_fmt_spec()));
1423 print("Category", render(t->get_cat()));
1424 print("MMSI", render(t->get_mmsi()));
1425 print("Geographical Area", render(t->get_geographical_area()));
1426 print("Acklowledgement", render(t->get_ack()));
1427 print("Extension Indicator", render(t->get_extension()));
1430 static void print_detail_dse(const marnav::nmea::sentence * s)
1432 const auto t = marnav::nmea::sentence_cast<marnav::nmea::dse>(s);
1433 print("Number of Messages", render(t->get_number_of_messages()));
1434 print("Sentence Number", render(t->get_sentence_number()));
1435 print("Query Flag", render(t->get_flag()));
1436 print("MMSI", render(t->get_mmsi()));
1439 static void print_detail_apb(const marnav::nmea::sentence * s)
1441 const auto t = marnav::nmea::sentence_cast<marnav::nmea::apb>(s);
1442 print("Loran C blink warn", render(t->get_loran_c_blink_warning()));
1443 print("Loran C cycle lock warn", render(t->get_loran_c_cycle_lock_warning()));
1444 print("Cross Track Error Magnitude", render(t->get_cross_track_error_magnitude()));
1445 print("Direction to Steer", render(t->get_direction_to_steer()));
1446 print("Cross Track Unit", render(t->get_cross_track_unit()));
1447 print("Status Arrival", render(t->get_status_arrival()));
1448 print("Status Perpendicular Pass", render(t->get_status_perpendicular_passing()));
1449 print("Bearing Org to Dest", render(t->get_bearing_origin_to_destination()));
1450 print("Bearing Org to Dest Ref", render(t->get_bearing_origin_to_destination_ref()));
1451 print("Waypoint", render(t->get_waypoint_id()));
1452 print("Bearing Pos to Dest", render(t->get_bearing_pos_to_destination()));
1453 print("Bearing Pos to Dest Ref", render(t->get_bearing_pos_to_destination_ref()));
1454 print("Heading to Steer to Dest", render(t->get_heading_to_steer_to_destination()));
1455 print("Heading to Steer to Dest Ref", render(t->get_heading_to_steer_to_destination_ref()));
1456 print("Mode Indicator", render(t->get_mode_ind()));
1459 static void print_detail_pgrme(const marnav::nmea::sentence * s)
1461 const auto t = marnav::nmea::sentence_cast<marnav::nmea::pgrme>(s);
1462 print("HPE", render(t->get_horizontal_position_error()));
1463 print("VPE", render(t->get_vertical_position_error()));
1464 print("O.sph.eq.pos err", render(t->get_overall_spherical_equiv_position_error()));
1467 static void print_detail_pgrmm(const marnav::nmea::sentence * s)
1469 const auto t = marnav::nmea::sentence_cast<marnav::nmea::pgrmm>(s);
1470 print("Map Datum", render(t->get_map_datum()));
1473 static void print_detail_pgrmz(const marnav::nmea::sentence * s)
1475 const auto t = marnav::nmea::sentence_cast<marnav::nmea::pgrmz>(s);
1476 print("Altitude", render(t->get_altitude()));
1477 print("Fix Type", render(t->get_fix()));
1480 static void print_detail_stalk(const marnav::nmea::sentence * s)
1482 const auto t = marnav::nmea::sentence_cast<marnav::nmea::stalk>(s);
1483 print("Data", render(t->get_data()));
1486 static void print_detail_vwe(const marnav::nmea::sentence * s)
1488 const auto t = marnav::nmea::sentence_cast<marnav::nmea::vwe>(s);
1489 print("Efficiency", render(t->get_efficiency()));
1492 static void print_detail_vwr(const marnav::nmea::sentence * s)
1494 const auto t = marnav::nmea::sentence_cast<marnav::nmea::vwr>(s);
1495 print("Angle", fmt::sprintf("%s %s", render(t->get_angle()), render(t->get_angle_side())));
1496 print("Speed kn", render(t->get_speed_knots()));
1497 print("Speed m/s", render(t->get_speed_mps()));
1498 print("Speed km/h", render(t->get_speed_kmh()));
1501 static void print_detail_wcv(const marnav::nmea::sentence * s)
1503 const auto t = marnav::nmea::sentence_cast<marnav::nmea::wcv>(s);
1504 print("Speed kn", render(t->get_speed()));
1505 print("Waypoint", render(t->get_waypoint_id()));
1508 static void print_detail_wdc(const marnav::nmea::sentence * s)
1510 const auto t = marnav::nmea::sentence_cast<marnav::nmea::wdc>(s);
1511 print("Distance NM", render(t->get_distance()));
1512 print("Waypoint", render(t->get_waypoint_id()));
1515 static void print_detail_wdr(const marnav::nmea::sentence * s)
1517 const auto t = marnav::nmea::sentence_cast<marnav::nmea::wdr>(s);
1518 print("Distance NM", render(t->get_distance()));
1519 print("Waypoint", render(t->get_waypoint_id()));
1522 static void print_detail_wnc(const marnav::nmea::sentence * s)
1524 const auto t = marnav::nmea::sentence_cast<marnav::nmea::wnc>(s);
1525 print("Distnace NM", render(t->get_distance_nm()));
1526 print("Distnace km", render(t->get_distance_km()));
1527 print("Waypoint To", render(t->get_waypoint_to()));
1528 print("Waypoint From", render(t->get_waypoint_from()));
1531 static void print_detail_wpl(const marnav::nmea::sentence * s)
1533 const auto t = marnav::nmea::sentence_cast<marnav::nmea::wpl>(s);
1534 print("Latitude", render(t->get_lat()));
1535 print("Longitude", render(t->get_lon()));
1536 print("Waypoint", render(t->get_waypoint_id()));
1539 static void print_detail_xdr(const marnav::nmea::sentence * s)
1541 const auto t = marnav::nmea::sentence_cast<marnav::nmea::xdr>(s);
1542 for (auto i = 0; i < marnav::nmea::xdr::max_transducer_info; ++i) {
1543 const auto info = t->get_info(i);
1544 if (info) {
1545 print("Transducer Info",
1546 fmt::sprintf("Type:%c Data:%f Unit:%c Name:%s", info->transducer_type,
1547 info->measurement_data, info->units_of_measurement, info->name));
1552 static void print_detail_xte(const marnav::nmea::sentence * s)
1554 const auto t = marnav::nmea::sentence_cast<marnav::nmea::xte>(s);
1555 print("Status 1", render(t->get_status1()));
1556 print("Status 2", render(t->get_status2()));
1557 print("Cross Track Error Magnitude", render(t->get_cross_track_error_magnitude()));
1558 print("Direction to Steer", render(t->get_direction_to_steer()));
1559 print("Mode Indicator", render(t->get_mode_ind()));
1562 static void print_detail_xtr(const marnav::nmea::sentence * s)
1564 const auto t = marnav::nmea::sentence_cast<marnav::nmea::xtr>(s);
1565 print("Cross Track Error Magnitude", render(t->get_cross_track_error_magnitude()));
1566 print("Direction to Steer", render(t->get_direction_to_steer()));
1569 static void print_detail_vlw(const marnav::nmea::sentence * s)
1571 const auto t = marnav::nmea::sentence_cast<marnav::nmea::vlw>(s);
1572 print("Distance Cumulative NM", render(t->get_distance_cum()));
1573 print("Distance since Rest NM", render(t->get_distance_reset()));
1576 static void print_detail_vpw(const marnav::nmea::sentence * s)
1578 const auto t = marnav::nmea::sentence_cast<marnav::nmea::vpw>(s);
1579 print("Speed kn", render(t->get_speed_knots()));
1580 print("Speed m/s", render(t->get_speed_meters_per_second()));
1583 static void print_detail_vhw(const marnav::nmea::sentence * s)
1585 const auto t = marnav::nmea::sentence_cast<marnav::nmea::vhw>(s);
1586 print("Heading True", render(t->get_heading_true()));
1587 print("Heading Magn", render(t->get_heading_magn()));
1588 print("Speed kn", render(t->get_speed_knots()));
1589 print("Speed km/h", render(t->get_speed_kmh()));
1592 static void print_detail_message_01_common(const marnav::ais::message_01 * t)
1594 print("Repeat Indicator", render(t->get_repeat_indicator()));
1595 print("MMSI", render(t->get_mmsi()));
1596 print("Nav Status", render(t->get_nav_status()));
1597 print("ROT", render(t->get_rot()));
1598 print("SOG", render(t->get_sog()));
1599 print("Pos Accuracy", render(t->get_position_accuracy()));
1600 print("Latitude", render(t->get_lat()));
1601 print("Longitude", render(t->get_lon()));
1602 print("COG", render(t->get_cog()));
1603 print("HDG", render(t->get_hdg()));
1604 print("Time Stamp", render(t->get_timestamp()));
1605 print("Maneuver Indicator", render(t->get_maneuver_indicator()));
1606 print("RAIM", render(t->get_raim()));
1607 print("Radio Status", render(t->get_radio_status()));
1610 static void print_detail_message_01(const marnav::ais::message * m)
1612 print_detail_message_01_common(marnav::ais::message_cast<marnav::ais::message_01>(m));
1615 static void print_detail_message_02(const marnav::ais::message * m)
1617 print_detail_message_01_common(marnav::ais::message_cast<marnav::ais::message_02>(m));
1620 static void print_detail_message_03(const marnav::ais::message * m)
1622 print_detail_message_01_common(marnav::ais::message_cast<marnav::ais::message_03>(m));
1625 static void print_detail_message_04_common(const marnav::ais::message_04 * t)
1627 print("Repeat Indicator", render(t->get_repeat_indicator()));
1628 print("MMSI", render(t->get_mmsi()));
1629 print("Year", render(t->get_year()));
1630 print("Month", render(t->get_month()));
1631 print("Day", render(t->get_day()));
1632 print("Hour", render(t->get_hour()));
1633 print("Minute", render(t->get_minute()));
1634 print("Second", render(t->get_second()));
1635 print("Pos Accuracy", render(t->get_position_accuracy()));
1636 print("Latitude", render(t->get_lat()));
1637 print("Longitude", render(t->get_lon()));
1638 print("EPFD Fix", render(t->get_epfd_fix()));
1639 print("RAIM", render(t->get_raim()));
1640 print("Radio Status", render(t->get_radio_status()));
1643 static void print_detail_message_04(const marnav::ais::message * m)
1645 print_detail_message_04_common(marnav::ais::message_cast<marnav::ais::message_04>(m));
1648 static void print_detail_message_11(const marnav::ais::message * m)
1650 print_detail_message_04_common(marnav::ais::message_cast<marnav::ais::message_11>(m));
1653 static void print_detail_message_12(const marnav::ais::message * m)
1655 const auto t = marnav::ais::message_cast<marnav::ais::message_12>(m);
1656 print("Repeat Indicator", render(t->get_repeat_indicator()));
1657 print("MMSI", render(t->get_mmsi()));
1658 print("Seqence Number", render(t->get_seqno()));
1659 print("Destination MMSI", render(t->get_dest_mmsi()));
1660 print("Retransmit", render(t->get_retransmit()));
1661 print("Text", render(t->get_text()));
1664 static void print_detail_message_13(const marnav::ais::message * m)
1666 const auto t = marnav::ais::message_cast<marnav::ais::message_13>(m);
1667 print("Repeat Indicator", render(t->get_repeat_indicator()));
1668 print("MMSI", render(t->get_mmsi()));
1669 print("MMSI_1", render(t->get_mmsi_1()));
1670 print("MMSI_2", render(t->get_mmsi_2()));
1671 print("MMSI_3", render(t->get_mmsi_3()));
1672 print("MMSI_4", render(t->get_mmsi_4()));
1675 static void print_detail_message_14(const marnav::ais::message * m)
1677 const auto t = marnav::ais::message_cast<marnav::ais::message_14>(m);
1678 print("Repeat Indicator", render(t->get_repeat_indicator()));
1679 print("MMSI", render(t->get_mmsi()));
1680 print("Text", render(t->get_text()));
1683 static void print_detail_message_05(const marnav::ais::message * m)
1685 const auto t = marnav::ais::message_cast<marnav::ais::message_05>(m);
1686 print("Repeat Indicator", render(t->get_repeat_indicator()));
1687 print("MMSI", render(t->get_mmsi()));
1688 print("AIS Version", render(t->get_ais_version()));
1689 print("IMO", render(t->get_imo_number()));
1690 print("Callsign", render(t->get_callsign()));
1691 print("Shipname", render(t->get_shipname()));
1692 print("Shiptype", render(t->get_shiptype()));
1693 print("Length", render(t->get_vessel_dimension().length()));
1694 print("Width", render(t->get_vessel_dimension().width()));
1695 print("Draught", render(t->get_draught()));
1696 print("EPFD Fix", render(t->get_epfd_fix()));
1697 print("ETA Month", render(t->get_eta_month()));
1698 print("ETA Day", render(t->get_eta_day()));
1699 print("ETA Hour", render(t->get_eta_hour()));
1700 print("ETA Minute", render(t->get_eta_minute()));
1701 print("Destination", render(t->get_destination()));
1702 print("DTE", render(t->get_dte()));
1705 static void print_detail_message_06(const marnav::ais::message * m)
1707 const auto t = marnav::ais::message_cast<marnav::ais::message_06>(m);
1708 print("Repeat Indicator", render(t->get_repeat_indicator()));
1709 print("MMSI", render(t->get_mmsi()));
1710 print("Sequence No", render(t->get_sequnce_no()));
1711 print("Destination MMSI", render(t->get_dest_mmsi()));
1712 print("Retransmit Flag", render(t->get_retransmit_flag()));
1713 print("DAC", render(t->get_dac()));
1714 print("FID", render(t->get_fid()));
1715 // TODO
1716 fmt::printf("\n\twarning: message 06: decoding of payload not implemented: %03d/%02d\n",
1717 t->get_dac(), t->get_fid());
1720 static void print_detail_message_07(const marnav::ais::message * m)
1722 const auto t = marnav::ais::message_cast<marnav::ais::message_07>(m);
1723 print("Repeat Indicator", render(t->get_repeat_indicator()));
1724 print("MMSI", render(t->get_mmsi()));
1725 print("MMSI_1", render(t->get_mmsi_1()));
1726 print("MMSI_2", render(t->get_mmsi_2()));
1727 print("MMSI_3", render(t->get_mmsi_3()));
1728 print("MMSI_4", render(t->get_mmsi_4()));
1731 static void print_detail_message_08(const marnav::ais::message * m)
1733 const auto t = marnav::ais::message_cast<marnav::ais::message_08>(m);
1734 print("Repeat Indicator", render(t->get_repeat_indicator()));
1735 print("MMSI", render(t->get_mmsi()));
1736 print("DAC", render(t->get_dac()));
1737 print("FID", render(t->get_fid()));
1739 if (t->get_dac() == 1 && t->get_fid() == 11) {
1740 marnav::ais::binary_001_11 b;
1741 t->read_binary(b);
1742 fmt::printf("\n");
1743 print("Meteological and Hydrological Data (001/11) IMO236");
1744 print("Position", render(b.get_position()));
1745 print("Day", render(b.get_day()));
1746 print("Hour", render(b.get_hour()));
1747 print("Minute", render(b.get_minute()));
1748 print("Wind Speed 10min avg [kn]", render(b.get_wind_speed_avg()));
1749 print("Wind Gust [kn]", render(b.get_wind_gust()));
1750 print("Wind Direction", render(b.get_wind_direction()));
1751 print("Wind Gust Direction", render(b.get_wind_gust_direction()));
1752 print("Temperature [C]", render(b.get_temperature()));
1753 print("Humidity [%]", render(b.get_humidity()));
1754 print("Dew Point [%]", render(b.get_dew_point()));
1755 print("Air Pressure [hPa]", render(b.get_pressure()));
1756 print("Air Pressure Trend", render(b.get_pressure_trend()));
1757 print("Visibility [NM]", render(b.get_visibility()));
1758 print("Water Level [m]", render(b.get_water_level()));
1759 print("Water Level Trend", render(b.get_water_level_trend()));
1760 print("Sufrace Current Speed [kn]", render(b.get_surface_current_speed()));
1761 print("Sufrace Current Direction", render(b.get_surface_current_direction()));
1762 print("Current 2 Speed [kn]", render(b.get_current_2_speed()));
1763 print("Current 2 Direction", render(b.get_current_2_direction()));
1764 print("Current 2 Depth [m]", render(b.get_current_2_depth()));
1765 print("Current 3 Speed [kn]", render(b.get_current_3_speed()));
1766 print("Current 3 Direction", render(b.get_current_3_direction()));
1767 print("Current 3 Depth [m]", render(b.get_current_3_depth()));
1768 print("Wave Height [m]", render(b.get_wave_height()));
1769 print("Wave Period [s]", render(b.get_wave_period()));
1770 print("Wave Direction", render(b.get_wave_direction()));
1771 print("Swell Height [m]", render(b.get_swell_height()));
1772 print("Swell Period [s]", render(b.get_swell_period()));
1773 print("Swell Direction", render(b.get_swell_direction()));
1774 print("Sea State", render(b.get_sea_state()));
1775 print("Water Temperature [C]", render(b.get_water_temperature()));
1776 print("Precipitation", render(b.get_precipitation()));
1777 print("Salinity [%]", render(b.get_salinity()));
1778 print("Ice", render(b.get_ice()));
1779 } else if (t->get_dac() == 200 && t->get_fid() == 10) {
1780 marnav::ais::binary_200_10 b;
1781 t->read_binary(b);
1782 fmt::printf("\n");
1783 print("Inland ship static and voyage related data (200/10)");
1784 print("Vessel ID", render(b.get_vessel_id()));
1785 print("Length [m]", render(b.get_length()));
1786 print("Beam [m]", render(b.get_beam()));
1787 print("Shiptype", render(b.get_shiptype()));
1788 print("Hazard", render(b.get_hazard()));
1789 print("Draught [m]", render(b.get_draught()));
1790 print("Loaded", render(b.get_loaded()));
1791 print("Speed quality", render(b.get_speed_q()));
1792 print("Course quality", render(b.get_course_q()));
1793 print("Heading quality", render(b.get_heading_q()));
1794 } else {
1795 fmt::printf("\n\twarning: message 08: decoding of payload not implemented: %03d/%02d\n",
1796 t->get_dac(), t->get_fid());
1800 static void print_detail_message_09(const marnav::ais::message * m)
1802 const auto t = marnav::ais::message_cast<marnav::ais::message_09>(m);
1803 print("Repeat Indicator", render(t->get_repeat_indicator()));
1804 print("MMSI", render(t->get_mmsi()));
1805 print("Altitude", render(t->get_altitude()));
1806 print("Speed", render(t->get_speed()));
1807 print("Pos Accuracy", render(t->get_position_accuracy()));
1808 print("COG", render(t->get_course()));
1809 print("UTC Second", render(t->get_utc_second()));
1810 print("DTE", render(t->get_dte()));
1811 print("RAIM", render(t->get_raim()));
1812 print("Radio Status", render(t->get_radio_status()));
1815 static void print_detail_message_10(const marnav::ais::message * m)
1817 const auto t = marnav::ais::message_cast<marnav::ais::message_10>(m);
1818 print("Repeat Indicator", render(t->get_repeat_indicator()));
1819 print("MMSI", render(t->get_mmsi()));
1820 print("Destination MMSI", render(t->get_dest_mmsi()));
1823 static void print_detail_message_17(const marnav::ais::message * m)
1825 const auto t = marnav::ais::message_cast<marnav::ais::message_17>(m);
1826 print("Repeat Indicator", render(t->get_repeat_indicator()));
1827 print("MMSI", render(t->get_mmsi()));
1828 print("Latitude", render(t->get_lat()));
1829 print("Longitude", render(t->get_lon()));
1831 // TODO: print payload as hex string
1834 static void print_detail_message_18(const marnav::ais::message * m)
1836 const auto t = marnav::ais::message_cast<marnav::ais::message_18>(m);
1837 print("Repeat Indicator", render(t->get_repeat_indicator()));
1838 print("MMSI", render(t->get_mmsi()));
1839 print("SOG", render(t->get_sog()));
1840 print("Pos Accuracy", render(t->get_position_accuracy()));
1841 print("Latitude", render(t->get_lat()));
1842 print("Longitude", render(t->get_lon()));
1843 print("COG", render(t->get_cog()));
1844 print("HDG", render(t->get_hdg()));
1845 print("Time Stamp", render(t->get_timestamp()));
1846 print("CS Unit", render(t->get_cs_unit()));
1847 print("Display Flag", render(t->get_display_flag()));
1848 print("DSC Flag", render(t->get_dsc_flag()));
1849 print("Band Flag", render(t->get_band_flag()));
1850 print("Message 22 Flag", render(t->get_message_22_flag()));
1851 print("Assigned", render(t->get_assigned()));
1852 print("RAIM", render(t->get_raim()));
1853 print("Radio Status", render(t->get_radio_status()));
1856 static void print_detail_message_19(const marnav::ais::message * m)
1858 const auto t = marnav::ais::message_cast<marnav::ais::message_19>(m);
1859 print("Repeat Indicator", render(t->get_repeat_indicator()));
1860 print("MMSI", render(t->get_mmsi()));
1861 print("SOG", render(t->get_sog()));
1862 print("Pos Accuracy", render(t->get_position_accuracy()));
1863 print("Latitude", render(t->get_lat()));
1864 print("Longitude", render(t->get_lon()));
1865 print("COG", render(t->get_cog()));
1866 print("HDG", render(t->get_hdg()));
1867 print("Time Stamp", render(t->get_timestamp()));
1868 print("Ship Name", render(t->get_shipname()));
1869 print("Ship Type", render(t->get_shiptype()));
1870 print("Length", render(t->get_vessel_dimension().length()));
1871 print("Width", render(t->get_vessel_dimension().width()));
1872 print("EPFD Fix", render(t->get_epfd_fix()));
1873 print("RAIM", render(t->get_raim()));
1874 print("DTE", render(t->get_dte()));
1875 print("Assigned", render(t->get_assigned()));
1878 static void print_detail_message_20(const marnav::ais::message * m)
1880 const auto t = marnav::ais::message_cast<marnav::ais::message_20>(m);
1881 print("Repeat Indicator", render(t->get_repeat_indicator()));
1882 print("MMSI", render(t->get_mmsi()));
1883 for (int i = 0; i < 3; ++i) {
1884 const auto entry = t->get_entry(i);
1885 print(fmt::sprintf("Entry %d", i + 1),
1886 fmt::sprintf("Offset:%4u Slots:%1u Timeout:%1u Increment:%4u", entry.offset,
1887 entry.slots, entry.timeout, entry.increment));
1891 static void print_detail_message_21(const marnav::ais::message * m)
1893 const auto t = marnav::ais::message_cast<marnav::ais::message_21>(m);
1894 print("Repeat Indicator", render(t->get_repeat_indicator()));
1895 print("MMSI", render(t->get_mmsi()));
1896 print("Aid Type", render(t->get_aid_type()));
1897 print("Name", render(t->get_name()));
1898 print("Pos Accuracy", render(t->get_position_accuracy()));
1899 print("Latitude", render(t->get_lat()));
1900 print("Longitude", render(t->get_lon()));
1901 print("Length", render(t->get_vessel_dimension().length()));
1902 print("Width", render(t->get_vessel_dimension().width()));
1903 print("EPFD Fix", render(t->get_epfd_fix()));
1904 print("UTC Second", render(t->get_utc_second()));
1905 print("Off Pos Indicator", render(t->get_off_position()));
1906 print("Regional", render(t->get_regional()));
1907 print("RAIM", render(t->get_raim()));
1908 print("Virtual Aid Flag", render(t->get_virtual_aid_flag()));
1909 print("Assigned", render(t->get_assigned()));
1910 print("Name Extension", render(t->get_name_extension()));
1913 static void print_detail_message_22(const marnav::ais::message * m)
1915 const auto t = marnav::ais::message_cast<marnav::ais::message_22>(m);
1916 print("Repeat Indicator", render(t->get_repeat_indicator()));
1917 print("MMSI", render(t->get_mmsi()));
1918 print("Channel A", render(t->get_channel_a()));
1919 print("Channel B", render(t->get_channel_b()));
1920 print("TxRx Mode", render(t->get_txrx_mode()));
1921 print("Power", render(t->get_power()));
1922 print("Adressed", render(t->get_addressed()));
1923 if (t->get_addressed()) {
1924 print("MMSI 1", render(t->get_mmsi_1()));
1925 print("MMSI 2", render(t->get_mmsi_2()));
1926 } else {
1927 print("Position NE", render(t->get_position_ne()));
1928 print("Position SW", render(t->get_position_sw()));
1932 static void print_detail_message_23(const marnav::ais::message * m)
1934 const auto t = marnav::ais::message_cast<marnav::ais::message_23>(m);
1935 print("Repeat Indicator", render(t->get_repeat_indicator()));
1936 print("MMSI", render(t->get_mmsi()));
1937 print("Position NE", render(t->get_position_ne()));
1938 print("Position SW", render(t->get_position_sw()));
1939 print("Station Type", render(t->get_station_type()));
1940 print("Ship Type", render(t->get_shiptype()));
1941 print("TxRx Mode", render(t->get_txrx_mode()));
1942 print("Report Interval", render(t->get_interval()));
1943 print("Quiet Time", render(t->get_quiet_time()));
1946 static void print_detail_message_24(const marnav::ais::message * m)
1948 const auto t = marnav::ais::message_cast<marnav::ais::message_24>(m);
1949 print("Repeat Indicator", render(t->get_repeat_indicator()));
1950 print("MMSI", render(t->get_mmsi()));
1951 print("Part", render(t->get_part_number()));
1952 if (t->get_part_number() == marnav::ais::message_24::part::A) {
1953 print("Ship Name", render(t->get_shipname()));
1954 } else {
1955 print("Ship Type", render(t->get_shiptype()));
1956 print("Vendor ID", render(t->get_vendor_id()));
1957 print("Model", render(t->get_model()));
1958 print("Serial", render(t->get_serial()));
1959 print("Callsign", render(t->get_callsign()));
1960 if (t->is_auxiliary_vessel()) {
1961 print("Mothership MMSI", render(t->get_mothership_mmsi()));
1962 } else {
1963 print("Length", render(t->get_vessel_dimension().length()));
1964 print("Width", render(t->get_vessel_dimension().width()));
1969 /// @endcond
1971 struct nmea_entry {
1972 marnav::nmea::sentence_id id;
1973 std::function<void(const marnav::nmea::sentence *)> func;
1976 static const std::vector<nmea_entry> & nmea_sentences()
1978 #define ADD_SENTENCE(s) \
1980 marnav::nmea::s::ID, detail::print_detail_##s \
1982 using container = std::vector<nmea_entry>;
1983 // clang-format off
1984 static const container sentences = {
1985 // standard
1986 ADD_SENTENCE(aam),
1987 ADD_SENTENCE(alm),
1988 ADD_SENTENCE(alr),
1989 ADD_SENTENCE(apa),
1990 ADD_SENTENCE(apb),
1991 ADD_SENTENCE(bec),
1992 ADD_SENTENCE(bod),
1993 ADD_SENTENCE(bwc),
1994 ADD_SENTENCE(bwr),
1995 ADD_SENTENCE(bww),
1996 ADD_SENTENCE(dbk),
1997 ADD_SENTENCE(dbt),
1998 ADD_SENTENCE(dpt),
1999 ADD_SENTENCE(dsc),
2000 ADD_SENTENCE(dse),
2001 ADD_SENTENCE(dtm),
2002 ADD_SENTENCE(fsi),
2003 ADD_SENTENCE(gbs),
2004 ADD_SENTENCE(glc),
2005 ADD_SENTENCE(gga),
2006 ADD_SENTENCE(gll),
2007 ADD_SENTENCE(gns),
2008 ADD_SENTENCE(grs),
2009 ADD_SENTENCE(gsa),
2010 ADD_SENTENCE(gst),
2011 ADD_SENTENCE(gsv),
2012 ADD_SENTENCE(gtd),
2013 ADD_SENTENCE(hdg),
2014 ADD_SENTENCE(hfb),
2015 ADD_SENTENCE(hdm),
2016 ADD_SENTENCE(hdt),
2017 ADD_SENTENCE(hsc),
2018 ADD_SENTENCE(its),
2019 ADD_SENTENCE(lcd),
2020 ADD_SENTENCE(mob),
2021 ADD_SENTENCE(msk),
2022 ADD_SENTENCE(mss),
2023 ADD_SENTENCE(mta),
2024 ADD_SENTENCE(mtw),
2025 ADD_SENTENCE(mwd),
2026 ADD_SENTENCE(mwv),
2027 ADD_SENTENCE(osd),
2028 ADD_SENTENCE(r00),
2029 ADD_SENTENCE(rma),
2030 ADD_SENTENCE(rmb),
2031 ADD_SENTENCE(rmc),
2032 ADD_SENTENCE(rot),
2033 ADD_SENTENCE(rpm),
2034 ADD_SENTENCE(rsa),
2035 ADD_SENTENCE(rsd),
2036 ADD_SENTENCE(rte),
2037 ADD_SENTENCE(sfi),
2038 ADD_SENTENCE(stn),
2039 ADD_SENTENCE(tds),
2040 ADD_SENTENCE(tfi),
2041 ADD_SENTENCE(tll),
2042 ADD_SENTENCE(tpc),
2043 ADD_SENTENCE(tpr),
2044 ADD_SENTENCE(tpt),
2045 ADD_SENTENCE(ttm),
2046 ADD_SENTENCE(vbw),
2047 ADD_SENTENCE(vdr),
2048 ADD_SENTENCE(vhw),
2049 ADD_SENTENCE(vlw),
2050 ADD_SENTENCE(vpw),
2051 ADD_SENTENCE(vtg),
2052 ADD_SENTENCE(vwe),
2053 ADD_SENTENCE(vwr),
2054 ADD_SENTENCE(wcv),
2055 ADD_SENTENCE(wdc),
2056 ADD_SENTENCE(wdr),
2057 ADD_SENTENCE(wnc),
2058 ADD_SENTENCE(wpl),
2059 ADD_SENTENCE(xdr),
2060 ADD_SENTENCE(xte),
2061 ADD_SENTENCE(xtr),
2062 ADD_SENTENCE(zda),
2063 ADD_SENTENCE(zdl),
2064 ADD_SENTENCE(zfi),
2065 ADD_SENTENCE(zfo),
2066 ADD_SENTENCE(zlz),
2067 ADD_SENTENCE(zpi),
2068 ADD_SENTENCE(zta),
2069 ADD_SENTENCE(zte),
2070 ADD_SENTENCE(ztg),
2072 // proprietary
2073 ADD_SENTENCE(pgrme),
2074 ADD_SENTENCE(pgrmm),
2075 ADD_SENTENCE(pgrmz),
2076 ADD_SENTENCE(stalk)
2078 // clang-format on
2079 #undef ADD_SENTENCE
2080 return sentences;
2083 static int dump_nmea(const std::string & line)
2085 using namespace marnav;
2087 try {
2088 const auto & sentences = nmea_sentences();
2089 auto s = nmea::make_sentence(line);
2090 auto i = std::find_if(std::begin(sentences), std::end(sentences),
2091 [&s](const nmea_entry & item) { return item.id == s->id(); });
2092 if (i == std::end(sentences)) {
2093 fmt::printf("\t%s\n", detail::render(s->id()));
2094 fmt::printf(
2095 "%s%s%s\n\tnot implemented\n\n", terminal::magenta, line, terminal::normal);
2096 } else {
2097 fmt::printf("%s%s%s\n", terminal::green, line, terminal::normal);
2098 fmt::printf("\tName : %s\n", detail::render(s->id()));
2099 fmt::printf("\tTalker: %s\n", detail::render(s->get_talker()));
2100 i->func(s.get());
2101 fmt::printf("\n");
2102 return 0;
2104 } catch (nmea::unknown_sentence & error) {
2105 fmt::printf("%s%s%s\n\terror: unknown sentence: %s\n\n", terminal::red, line,
2106 terminal::normal, error.what());
2107 } catch (nmea::checksum_error & error) {
2108 fmt::printf("%s%s%s\n\terror: checksum error: %s\n\n", terminal::red, line,
2109 terminal::normal, error.what());
2110 } catch (std::invalid_argument & error) {
2111 fmt::printf(
2112 "%s%s%s\n\terror: %s\n\n", terminal::red, line, terminal::normal, error.what());
2114 return -1;
2117 static int dump_ais(const std::vector<std::unique_ptr<marnav::nmea::sentence>> & sentences)
2119 #define ADD_MESSAGE(m) \
2121 marnav::ais::m::ID, detail::print_detail_##m \
2123 struct entry {
2124 marnav::ais::message_id id;
2125 std::function<void(const marnav::ais::message *)> func;
2127 using container = std::vector<entry>;
2128 // clang-format off
2129 static const container messages = {
2130 ADD_MESSAGE(message_01),
2131 ADD_MESSAGE(message_02),
2132 ADD_MESSAGE(message_03),
2133 ADD_MESSAGE(message_04),
2134 ADD_MESSAGE(message_05),
2135 ADD_MESSAGE(message_06),
2136 ADD_MESSAGE(message_07),
2137 ADD_MESSAGE(message_08),
2138 ADD_MESSAGE(message_09),
2139 ADD_MESSAGE(message_10),
2140 ADD_MESSAGE(message_11),
2141 ADD_MESSAGE(message_12),
2142 ADD_MESSAGE(message_13),
2143 ADD_MESSAGE(message_14),
2144 ADD_MESSAGE(message_17),
2145 ADD_MESSAGE(message_18),
2146 ADD_MESSAGE(message_19),
2147 ADD_MESSAGE(message_20),
2148 ADD_MESSAGE(message_21),
2149 ADD_MESSAGE(message_22),
2150 ADD_MESSAGE(message_23),
2151 ADD_MESSAGE(message_24)
2153 // clang-format on
2154 #undef ADD_MESSAGE
2156 using namespace marnav;
2158 try {
2159 auto m = ais::make_message(nmea::collect_payload(sentences.begin(), sentences.end()));
2160 auto i = std::find_if(std::begin(messages), std::end(messages),
2161 [&m](const container::value_type & item) { return item.id == m->type(); });
2162 if (i == std::end(messages)) {
2163 fmt::printf("\t%s\n", detail::render(m->type()));
2164 fmt::printf("%smessage_%02u%s\n\tnot implemented\n\n", terminal::magenta,
2165 static_cast<uint8_t>(m->type()), terminal::normal);
2166 } else {
2167 fmt::printf("\t%s\n", detail::render(m->type()));
2168 i->func(m.get());
2169 fmt::printf("\n");
2170 return 0;
2172 } catch (std::exception & error) {
2173 fmt::printf("\t%serror:%s %s\n\n", terminal::red, terminal::normal, error.what());
2175 return -1;
2178 static int process(std::function<bool(std::string &)> source)
2180 using namespace marnav;
2182 std::string line;
2183 std::vector<std::unique_ptr<nmea::sentence>> sentences;
2185 int result = 0;
2187 while (source(line)) {
2188 line = trim(line);
2189 if (line.empty())
2190 continue;
2191 if (line[0] == '#')
2192 continue;
2194 if (line[0] == nmea::sentence::start_token) {
2195 result += dump_nmea(line);
2196 } else if (line[0] == nmea::sentence::start_token_ais) {
2197 fmt::printf("%s%s%s\n", terminal::blue, line, terminal::normal);
2198 auto s = nmea::make_sentence(line);
2200 nmea::vdm * v = nullptr; // VDM is the common denominator for AIS relevant messages
2202 if (s->id() == nmea::sentence_id::VDO) {
2203 v = nmea::sentence_cast<nmea::vdo>(s.get());
2204 } else if (s->id() == nmea::sentence_id::VDM) {
2205 v = nmea::sentence_cast<nmea::vdm>(s.get());
2206 } else {
2207 // something strange happened, no VDM nor VDO
2208 fmt::printf("%s%s%s\n\terror: ignoring AIS sentence, dropping collection.\n\n",
2209 terminal::red, line, terminal::normal);
2210 sentences.clear();
2211 --result;
2212 continue;
2215 // check sentences if a discontuniation has occurred
2216 if (sentences.size() && (sentences.back()->id() != v->id())) {
2217 sentences.clear(); // there was a discontinuation, start over collecting
2218 fmt::printf(
2219 "\t%swarning:%s dropping collection.\n", terminal::cyan, terminal::normal);
2222 // check if a previous message was not complete
2223 const auto n_fragments = v->get_n_fragments();
2224 const auto fragment = v->get_fragment();
2225 if (sentences.size() >= fragment) {
2226 sentences.clear();
2227 fmt::printf(
2228 "\t%swarning:%s dropping collection.\n", terminal::cyan, terminal::normal);
2231 sentences.push_back(std::move(s));
2232 if (fragment == n_fragments) {
2233 result += dump_ais(sentences);
2234 sentences.clear();
2236 } else {
2237 fmt::printf("%s%s%s\n\terror: ignoring AIS sentence.\n\n", terminal::red, line,
2238 terminal::normal);
2242 return result;
2245 static bool parse_options(int argc, char ** argv)
2247 uint32_t port_speed = 0;
2249 // clang-format off
2250 cxxopts::Options options{argv[0], "NMEA Dump"};
2251 options.add_options()
2252 ("h,help",
2253 "Shows help information.")
2254 ("help-nmea-list",
2255 "Shows a list of supported NMEA sentences.")
2256 ("p,port",
2257 "Specifies the port to use.",
2258 cxxopts::value<std::string>(global.config.port))
2259 ("s,speed",
2260 "Specifies the port speed. Valid values: 4800, 38400",
2261 cxxopts::value<uint32_t>(port_speed))
2262 ("f,file",
2263 "Specifies the file to use.",
2264 cxxopts::value<std::string>(global.config.file))
2265 ("i,input",
2266 "String to parse",
2267 cxxopts::value<std::string>(global.config.input_string))
2269 // clang-format on
2271 const auto args = options.parse(argc, argv);
2273 if (args.count("help")) {
2274 fmt::printf("%s\n", options.help());
2275 fmt::printf("If no file or port is specified, stdin is used to read data from.\n\n");
2276 return true;
2279 using namespace marnav;
2281 if (args.count("help-nmea-list")) {
2282 const auto is_impl = [](nmea::sentence_id id) {
2283 return std::find_if(begin(nmea_sentences()), end(nmea_sentences()),
2284 [id](const nmea_entry & entry) {
2285 return id == entry.id
2286 // AIS data carrying NMEA sentences are decoded as AIS messages
2287 || id == nmea::sentence_id::VDM || id == nmea::sentence_id::VDO;
2289 != end(nmea_sentences());
2292 for (const auto id : nmea::get_supported_sentences_id()) {
2293 fmt::printf("%c %s %s\n", is_impl(id) ? '-' : '*', to_string(id), to_name(id));
2296 return true;
2299 // validation
2301 static const std::vector<uint32_t> valid_port_speeds = {4800, 38400};
2303 if (args.count("port") && args.count("file"))
2304 throw std::runtime_error{"specifying port and file is illegal"};
2305 if (args.count("port") && !contains(valid_port_speeds, port_speed))
2306 throw std::runtime_error{"invalid port speed"};
2308 switch (port_speed) {
2309 case 4800:
2310 global.config.speed = io::serial::baud::baud_4800;
2311 break;
2312 case 38400:
2313 global.config.speed = io::serial::baud::baud_38400;
2314 break;
2315 default:
2316 break;
2319 return false;
2323 int main(int argc, char ** argv)
2325 using namespace nmeadump;
2327 if (parse_options(argc, argv))
2328 return EXIT_SUCCESS;
2330 int result = 0;
2331 if (!global.config.file.empty()) {
2332 std::ifstream ifs{global.config.file.c_str()};
2333 result = process([&](std::string & line) { return !!std::getline(ifs, line); });
2334 } else if (!global.config.port.empty()) {
2335 using namespace marnav;
2336 using namespace marnav::io;
2337 default_nmea_reader source{
2338 utils::make_unique<serial>(global.config.port, global.config.speed,
2339 serial::databits::bit_8, serial::stopbits::bit_1, serial::parity::none)};
2340 result = process([&](std::string & line) { return source.read_sentence(line); });
2341 } else if (!global.config.input_string.empty()) {
2342 std::istringstream is(global.config.input_string);
2343 result = process([&](std::string & line) { return !!std::getline(is, line); });
2344 } else {
2345 std::cin.sync_with_stdio(false);
2346 result = process([&](std::string & line) { return !!std::getline(std::cin, line); });
2349 return result;