1 // This is a diagnostics tool and also serves as demonstration
2 // on how to use the library.
8 #include <cxxopts/cxxopts.hpp>
10 #define FMT_HEADER_ONLY
11 #include <fmt/format.h>
13 #include <marnav/nmea/nmea.hpp>
14 #include <marnav/nmea/ais_helper.hpp>
15 #include <marnav/nmea/checksum.hpp>
16 #include <marnav/nmea/sentence.hpp>
17 #include <marnav/nmea/waypoint.hpp>
19 #include <marnav/nmea/aam.hpp>
20 #include <marnav/nmea/apb.hpp>
21 #include <marnav/nmea/bod.hpp>
22 #include <marnav/nmea/bwc.hpp>
23 #include <marnav/nmea/dbt.hpp>
24 #include <marnav/nmea/dtm.hpp>
25 #include <marnav/nmea/gga.hpp>
26 #include <marnav/nmea/gll.hpp>
27 #include <marnav/nmea/gsa.hpp>
28 #include <marnav/nmea/gsv.hpp>
29 #include <marnav/nmea/hdg.hpp>
30 #include <marnav/nmea/hdm.hpp>
31 #include <marnav/nmea/mtw.hpp>
32 #include <marnav/nmea/mwv.hpp>
33 #include <marnav/nmea/rmb.hpp>
34 #include <marnav/nmea/rmc.hpp>
35 #include <marnav/nmea/rte.hpp>
36 #include <marnav/nmea/vhw.hpp>
37 #include <marnav/nmea/vlw.hpp>
38 #include <marnav/nmea/vtg.hpp>
39 #include <marnav/nmea/vwr.hpp>
40 #include <marnav/nmea/zda.hpp>
41 #include <marnav/nmea/vdm.hpp>
42 #include <marnav/nmea/vdo.hpp>
44 #include <marnav/nmea/pgrme.hpp>
45 #include <marnav/nmea/pgrmm.hpp>
46 #include <marnav/nmea/pgrmz.hpp>
48 #include <marnav/ais/ais.hpp>
50 #include <marnav/ais/message_01.hpp>
51 #include <marnav/ais/message_02.hpp>
52 #include <marnav/ais/message_03.hpp>
53 #include <marnav/ais/message_04.hpp>
54 #include <marnav/ais/message_05.hpp>
55 #include <marnav/ais/message_11.hpp>
56 #include <marnav/ais/message_18.hpp>
57 #include <marnav/ais/message_21.hpp>
58 #include <marnav/ais/message_24.hpp>
60 #include <marnav/io/default_nmea_reader.hpp>
61 #include <marnav/io/serial.hpp>
63 #include <marnav/utils/unique.hpp>
69 static constexpr const char * normal
= "\033[0m";
70 static constexpr const char * black
= "\033[30m";
71 static constexpr const char * red
= "\033[31m";
72 static constexpr const char * green
= "\033[32m";
73 static constexpr const char * yellow
= "\033[33m";
74 static constexpr const char * blue
= "\033[34m";
75 static constexpr const char * magenta
= "\033[35m";
76 static constexpr const char * cyan
= "\033[36m";
77 static constexpr const char * white
= "\033[37m";
82 template <class Container
>
84 const Container
& container
, const typename
Container::value_type
& element
)
86 return std::find(std::begin(container
), std::end(container
), element
)
87 != std::end(container
);
94 uint32_t port_speed
= 0;
99 static bool parse_options(int argc
, char ** argv
)
102 cxxopts::Options options
{argv
[0], "NMEA Dump"};
103 options
.add_options()
105 "Shows help information.")
107 "Specifies the port to use.",
108 cxxopts::value
<std::string
>(global
.config
.port
))
110 "Specifies the port speed. Valid values: 4800, 38400",
111 cxxopts::value
<uint32_t>(global
.config
.port_speed
))
113 "Specifies the file to use.",
114 cxxopts::value
<std::string
>(global
.config
.file
))
118 options
.parse(argc
, argv
);
120 if (options
.count("help")) {
121 fmt::printf("%s\n", options
.help());
122 fmt::printf("If no file or port is specified, stdin is used to read data from.\n\n");
128 static const std::vector
<uint32_t> valid_port_speeds
= {4800, 38400};
130 if (options
.count("port") && options
.count("file"))
131 throw std::runtime_error
{"specifying port and file is illegal"};
132 if (options
.count("port") && !contains(valid_port_speeds
, global
.config
.port_speed
))
133 throw std::runtime_error
{"invalid port speed"};
138 static std::string
trim(const std::string
& s
)
140 static const char * whitespace
= "\n\r\t ";
141 const auto begin
= s
.find_first_not_of(whitespace
);
142 const auto end
= s
.find_last_not_of(whitespace
);
143 return begin
!= std::string::npos
? s
.substr(begin
, end
- begin
+ 1) : "";
148 template <typename T
> static std::string
render(const T
& t
)
150 return marnav::nmea::to_string(t
);
153 static std::string
render(const std::string
& t
) { return t
; }
155 static std::string
render(bool t
) { return t
? "true" : "false"; }
157 static std::string
render(char t
) { return fmt::sprintf("%c", t
); }
159 static std::string
render(const uint32_t t
) { return fmt::sprintf("%u", t
); }
161 static std::string
render(const int32_t t
) { return fmt::sprintf("%d", t
); }
163 static std::string
render(const int8_t t
) { return fmt::sprintf("%d", t
); }
165 static std::string
render(const uint8_t t
) { return fmt::sprintf("%u", t
); }
167 static std::string
render(const double t
) { return fmt::sprintf("%-8.3f", t
); }
169 static std::string
render(const marnav::utils::mmsi
& t
)
171 return fmt::sprintf("%09u", static_cast<marnav::utils::mmsi::value_type
>(t
));
174 static std::string
render(const marnav::nmea::time
& t
)
176 return fmt::sprintf("%02u:%02u:%02u", t
.hour(), t
.minutes(), t
.seconds());
179 static std::string
render(const marnav::geo::latitude
& t
)
181 using namespace marnav::nmea
;
183 " %02u\u00b0%02u'%04.1f%s", t
.degrees(), t
.minutes(), t
.seconds(), to_string(t
.hem()));
186 static std::string
render(const marnav::geo::longitude
& t
)
188 using namespace marnav::nmea
;
190 "%03u\u00b0%02u'%04.1f%s", t
.degrees(), t
.minutes(), t
.seconds(), to_string(t
.hem()));
193 static std::string
render(const marnav::ais::message_24::part t
)
196 case marnav::ais::message_24::part::A
:
198 case marnav::ais::message_24::part::B
:
204 static std::string
render(const marnav::ais::ship_type t
)
207 case marnav::ais::ship_type::not_available
:
208 return "Not Available";
209 case marnav::ais::ship_type::wing_in_ground
:
210 return "Wing in ground";
211 case marnav::ais::ship_type::wing_in_ground_hazardous_cat_a
:
212 return "Wing in ground hazardous Cat A";
213 case marnav::ais::ship_type::wing_in_ground_hazardous_cat_b
:
214 return "Wing in ground hazardous Cat B";
215 case marnav::ais::ship_type::wing_in_ground_hazardous_cat_c
:
216 return "Wing in ground hazardous Cat C";
217 case marnav::ais::ship_type::wing_in_ground_hazardous_cat_d
:
218 return "Wing in ground hazardous Cat D";
219 case marnav::ais::ship_type::fishing
:
221 case marnav::ais::ship_type::towing
:
223 case marnav::ais::ship_type::towing_large
:
224 return "Towing large";
225 case marnav::ais::ship_type::dredging_or_underwater_ops
:
226 return "Dredging or underwater ops";
227 case marnav::ais::ship_type::diving_ops
:
229 case marnav::ais::ship_type::military_ops
:
230 return "Military ops";
231 case marnav::ais::ship_type::sailing
:
233 case marnav::ais::ship_type::pleasure_craft
:
234 return "Pleasure Craft";
235 case marnav::ais::ship_type::high_speed_craft
:
236 return "High speed craft";
237 case marnav::ais::ship_type::high_speed_craft_hazardous_cat_a
:
238 return "High speed craft hazardous Cat A";
239 case marnav::ais::ship_type::high_speed_craft_hazardous_cat_b
:
240 return "High speed craft hazardous Cat B";
241 case marnav::ais::ship_type::high_speed_craft_hazardous_cat_c
:
242 return "High speed craft hazardous Cat C";
243 case marnav::ais::ship_type::high_speed_craft_hazardous_cat_d
:
244 return "High speed craft hazardous Cat D";
245 case marnav::ais::ship_type::high_speed_craft_no_info
:
246 return "High speed craft no_info";
247 case marnav::ais::ship_type::pilot_vessel
:
248 return "Pilot Vessel";
249 case marnav::ais::ship_type::search_and_rescue_vessel
:
250 return "Search and Rescue Vessel";
251 case marnav::ais::ship_type::tug
:
253 case marnav::ais::ship_type::port_tender
:
254 return "Port Tender";
255 case marnav::ais::ship_type::anti_pollution_equipment
:
256 return "Anti Pollution Equipment";
257 case marnav::ais::ship_type::law_enforcement
:
258 return "Law Enforcement";
259 case marnav::ais::ship_type::medical_transport
:
260 return "Medical Transport";
261 case marnav::ais::ship_type::noncombatant
:
262 return "Noncombatant";
263 case marnav::ais::ship_type::passenger
:
265 case marnav::ais::ship_type::passenger_hazardous_cat_a
:
266 return "Passenger hazardous Cat A";
267 case marnav::ais::ship_type::passenger_hazardous_cat_b
:
268 return "Passenger hazardous Cat B";
269 case marnav::ais::ship_type::passenger_hazardous_cat_c
:
270 return "Passenger hazardous Cat C";
271 case marnav::ais::ship_type::passenger_hazardous_cat_d
:
272 return "Passenger hazardous Cat D";
273 case marnav::ais::ship_type::passenger_no_info
:
274 return "Passenger no info";
275 case marnav::ais::ship_type::cargo
:
277 case marnav::ais::ship_type::cargo_hazardous_cat_a
:
278 return "Cargo hazardous Cat A";
279 case marnav::ais::ship_type::cargo_hazardous_cat_b
:
280 return "Cargo hazardous Cat B";
281 case marnav::ais::ship_type::cargo_hazardous_cat_c
:
282 return "Cargo hazardous Cat C";
283 case marnav::ais::ship_type::cargo_hazardous_cat_d
:
284 return "Cargo hazardous Cat D";
285 case marnav::ais::ship_type::cargo_no_info
:
286 return "Cargo no info";
287 case marnav::ais::ship_type::tanker
:
289 case marnav::ais::ship_type::tanker_hazardous_cat_a
:
290 return "Tanker hazardous Cat A";
291 case marnav::ais::ship_type::tanker_hazardous_cat_b
:
292 return "Tanker hazardous Cat B";
293 case marnav::ais::ship_type::tanker_hazardous_cat_c
:
294 return "Tanker hazardous Cat C";
295 case marnav::ais::ship_type::tanker_hazardous_cat_d
:
296 return "Tanker hazardous Cat D";
297 case marnav::ais::ship_type::tanker_no_info
:
298 return "Tanker no info";
299 case marnav::ais::ship_type::other
:
301 case marnav::ais::ship_type::other_hazardous_cat_a
:
302 return "Other hazardous Cat A";
303 case marnav::ais::ship_type::other_hazardous_cat_b
:
304 return "Other hazardous Cat B";
305 case marnav::ais::ship_type::other_hazardous_cat_c
:
306 return "Other hazardous Cat C";
307 case marnav::ais::ship_type::other_hazardous_cat_d
:
308 return "Other hazardous Cat D";
309 case marnav::ais::ship_type::other_no_info
:
310 return "Other no info";
315 static std::string
render(const marnav::ais::epfd_fix_type t
)
318 case marnav::ais::epfd_fix_type::undefined
:
320 case marnav::ais::epfd_fix_type::gps
:
322 case marnav::ais::epfd_fix_type::glonass
:
324 case marnav::ais::epfd_fix_type::combined_gps_glonass
:
325 return "Combined GPS GLONASS";
326 case marnav::ais::epfd_fix_type::loran_c
:
328 case marnav::ais::epfd_fix_type::chayka
:
330 case marnav::ais::epfd_fix_type::integrated_navigation_system
:
331 return "Integrated Navigation System";
332 case marnav::ais::epfd_fix_type::surveyed
:
334 case marnav::ais::epfd_fix_type::galileo
:
340 static std::string
render(const marnav::ais::message_21::off_position_indicator t
)
343 case marnav::ais::message_21::off_position_indicator::on_position
:
344 return "On Position";
345 case marnav::ais::message_21::off_position_indicator::off_position
:
346 return "Off Position";
351 static std::string
render(const marnav::ais::message_21::virtual_aid t
)
354 case marnav::ais::message_21::virtual_aid::real_aid
:
356 case marnav::ais::message_21::virtual_aid::virtual_aid
:
357 return "Virtual Aid";
362 static std::string
render(const marnav::ais::message_21::aid_type_id t
)
365 case marnav::ais::message_21::aid_type_id::unspecified
:
366 return "unspecified";
367 case marnav::ais::message_21::aid_type_id::reference_point
:
368 return "Reference point";
369 case marnav::ais::message_21::aid_type_id::racon
:
370 return "RACON (radar transponder marking a navigation hazard)";
371 case marnav::ais::message_21::aid_type_id::fixed_structure
:
372 return "Fixed structure";
373 case marnav::ais::message_21::aid_type_id::reserved
:
374 return "Spare, Reserved for future use";
375 case marnav::ais::message_21::aid_type_id::light_no_sectors
:
376 return "Light, without sectors";
377 case marnav::ais::message_21::aid_type_id::light_sectors
:
378 return "Light, with sectors";
379 case marnav::ais::message_21::aid_type_id::leading_light_fromt
:
380 return "Leading Light Front";
381 case marnav::ais::message_21::aid_type_id::leading_light_rear
:
382 return "Leading Light Rear";
383 case marnav::ais::message_21::aid_type_id::beacon_cardinal_n
:
384 return "Beacon, Cardinal N";
385 case marnav::ais::message_21::aid_type_id::beacon_cardinal_e
:
386 return "Beacon, Cardinal E";
387 case marnav::ais::message_21::aid_type_id::beacon_cardinal_s
:
388 return "Beacon, Cardinal S";
389 case marnav::ais::message_21::aid_type_id::beacon_cardinal_w
:
390 return "Beacon, Cardinal W";
391 case marnav::ais::message_21::aid_type_id::beacon_port_hand
:
392 return "Beacon, Port hand";
393 case marnav::ais::message_21::aid_type_id::beacon_starboard_hand
:
394 return "Beacon, Starboard hand";
395 case marnav::ais::message_21::aid_type_id::beacon_preferred_channel_port_hand
:
396 return "Beacon, Preferred Channel port hand";
397 case marnav::ais::message_21::aid_type_id::beacon_preferred_channel_starboard_hand
:
398 return "Beacon, Preferred Channel starboard hand";
399 case marnav::ais::message_21::aid_type_id::beacon_isolated_danger
:
400 return "Beacon, Isolated danger";
401 case marnav::ais::message_21::aid_type_id::beacon_safe_water
:
402 return "Beacon, Safe water";
403 case marnav::ais::message_21::aid_type_id::beacon_sepcial_mark
:
404 return "Beacon, Special mark";
405 case marnav::ais::message_21::aid_type_id::cardinal_n
:
406 return "Cardinal Mark N";
407 case marnav::ais::message_21::aid_type_id::cardinal_e
:
408 return "Cardinal Mark E";
409 case marnav::ais::message_21::aid_type_id::cardinal_s
:
410 return "Cardinal Mark S";
411 case marnav::ais::message_21::aid_type_id::cardinal_w
:
412 return "Cardinal Mark W";
413 case marnav::ais::message_21::aid_type_id::mark_port_hand
:
414 return "Port hand Mark";
415 case marnav::ais::message_21::aid_type_id::mark_starboard_hand
:
416 return "Starboard hand Mark";
417 case marnav::ais::message_21::aid_type_id::preferred_channel_port_hand
:
418 return "Preferred Channel Port hand";
419 case marnav::ais::message_21::aid_type_id::preferred_channel_starboard_hand
:
420 return "Preferred Channel Starboard hand";
421 case marnav::ais::message_21::aid_type_id::isolated_danger
:
422 return "Isolated danger";
423 case marnav::ais::message_21::aid_type_id::safe_water
:
425 case marnav::ais::message_21::aid_type_id::special_mark
:
426 return "Special Mark";
427 case marnav::ais::message_21::aid_type_id::light_vessel
:
428 return "Light Vessel / LANBY / Rigs";
433 static std::string
render(const marnav::ais::message_id t
)
436 case marnav::ais::message_id::NONE
:
438 case marnav::ais::message_id::position_report_class_a
:
439 return "Position Report Class A";
440 case marnav::ais::message_id::position_report_class_a_assigned_schedule
:
441 return "Position Report Class A - Assigned Schedule";
442 case marnav::ais::message_id::position_report_class_a_response_to_interrogation
:
443 return "Position Report Class A - Response to Interrogation";
444 case marnav::ais::message_id::base_station_report
:
445 return "Base Station Report";
446 case marnav::ais::message_id::static_and_voyage_related_data
:
447 return "Static and Voyage related Data";
448 case marnav::ais::message_id::binary_addressed_message
:
449 return "Binary Addressed Message";
450 case marnav::ais::message_id::binary_acknowledge
:
451 return "Binary Acknowledge";
452 case marnav::ais::message_id::binary_broadcast_message
:
453 return "Binary Broadcast Message";
454 case marnav::ais::message_id::standard_sar_aircraft_position_report
:
455 return "Standard SAR Aircraft Position Report";
456 case marnav::ais::message_id::utc_and_date_inquiry
:
457 return "UTC and Date Inquiry";
458 case marnav::ais::message_id::utc_and_date_response
:
459 return "UTC and Date Response";
460 case marnav::ais::message_id::addressed_safety_related_message
:
461 return "Addresed Safety related Message";
462 case marnav::ais::message_id::safety_related_acknowledgement_
:
463 return "Safety related Acknowledgement";
464 case marnav::ais::message_id::safety_related_broadcast_message
:
465 return "Safety related Broadcast Message";
466 case marnav::ais::message_id::interrogation
:
467 return "Interrogation";
468 case marnav::ais::message_id::assignment_mode_command
:
469 return "Assignment Mode Command";
470 case marnav::ais::message_id::dgnss_binary_broadcast_message
:
471 return "DGNSS Binary Broadcast Message";
472 case marnav::ais::message_id::standard_class_b_cs_position_report
:
473 return "Standard Class B CS Position Report";
474 case marnav::ais::message_id::extended_class_b_equipment_position_report
:
475 return "Extended Class B Equipment Position Report";
476 case marnav::ais::message_id::data_link_management
:
477 return "Data Link Management";
478 case marnav::ais::message_id::aid_to_navigation_report
:
479 return "Aid to Navigation Report";
480 case marnav::ais::message_id::channel_management
:
481 return "Channel Management";
482 case marnav::ais::message_id::group_assignment_command
:
483 return "Group Assignment Command";
484 case marnav::ais::message_id::static_data_report
:
485 return "Static Data Report";
486 case marnav::ais::message_id::single_slot_binary_message
:
487 return "Single Slot Binary Message";
488 case marnav::ais::message_id::multiple_slot_binary_message_with_communications_state
:
489 return "Multiple slot Binary Message with Communication State";
490 case marnav::ais::message_id::position_report_for_long_range_applications
:
491 return "Position Report for long range Applications";
496 static std::string
render(const marnav::nmea::sentence_id t
)
499 case marnav::nmea::sentence_id::NONE
:
501 case marnav::nmea::sentence_id::AAM
:
502 return "Waypoint Arrival Alarm";
503 case marnav::nmea::sentence_id::ALM
:
504 return "GPS Almanac Data";
505 case marnav::nmea::sentence_id::APB
:
506 return "Autopilot Sentence 'B'";
507 case marnav::nmea::sentence_id::BOD
:
508 return "Bearing - Waypoint to Waypoint";
509 case marnav::nmea::sentence_id::BWC
:
510 return "Bearing & Distance to Waypoint - Geat Circle";
511 case marnav::nmea::sentence_id::BWR
:
512 return "Bearing and Distance to Waypoint - Rhumb Line";
513 case marnav::nmea::sentence_id::BWW
:
514 return "Bearing - Waypoint to Waypoint";
515 case marnav::nmea::sentence_id::DBT
:
516 return "Depth below transducer (II)";
517 case marnav::nmea::sentence_id::DPT
:
518 return "Depth of Water";
519 case marnav::nmea::sentence_id::DSC
:
520 return "Digital Selective Calling Information";
521 case marnav::nmea::sentence_id::DSE
:
522 return "Extended DSC";
523 case marnav::nmea::sentence_id::DSI
:
524 return "DSC Transponder Initiate";
525 case marnav::nmea::sentence_id::DSR
:
526 return "DSC Transponder Response";
527 case marnav::nmea::sentence_id::DTM
:
528 return "Datum Reference";
529 case marnav::nmea::sentence_id::FSI
:
530 return "Frequency Set Information";
531 case marnav::nmea::sentence_id::GBS
:
532 return "GPS Satellite Fault Detection";
533 case marnav::nmea::sentence_id::GGA
:
534 return "Global Positioning System Fix Data";
535 case marnav::nmea::sentence_id::GLC
:
536 return "Geographic Position, Loran-C";
537 case marnav::nmea::sentence_id::GLL
:
538 return "Geographic Position - Latitude/Longitude";
539 case marnav::nmea::sentence_id::GNS
:
541 case marnav::nmea::sentence_id::GRS
:
542 return "GPS Range Residuals";
543 case marnav::nmea::sentence_id::GST
:
544 return "GPS Pseudorange Noise Statistics";
545 case marnav::nmea::sentence_id::GSA
:
546 return "GPS DOP and active satellites";
547 case marnav::nmea::sentence_id::GSV
:
548 return "Satellites in view";
549 case marnav::nmea::sentence_id::HDG
:
550 return "Heading - Deviation & Variation (vendor extension)";
551 case marnav::nmea::sentence_id::HFB
:
552 return "Trawl Headrope to Footrope and Bottom";
553 case marnav::nmea::sentence_id::HSC
:
554 return "Heading Steering Command";
555 case marnav::nmea::sentence_id::ITS
:
556 return "Trawl Door Spread 2 Distance";
557 case marnav::nmea::sentence_id::LCD
:
558 return "Loran-C Signal Data";
559 case marnav::nmea::sentence_id::MSK
:
560 return "Control for a Beacon Receiver";
561 case marnav::nmea::sentence_id::MSS
:
562 return "Beacon Receiver Status";
563 case marnav::nmea::sentence_id::MWD
:
564 return "Wind Directinon and Speed";
565 case marnav::nmea::sentence_id::MTW
:
566 return "Mean Temperature of Water (II)";
567 case marnav::nmea::sentence_id::MWV
:
568 return "Wind Speed and Angle (II)";
569 case marnav::nmea::sentence_id::OSD
:
570 return "Own Ship Data";
571 case marnav::nmea::sentence_id::RMA
:
572 return "Recommended Minimum Navigation Information A";
573 case marnav::nmea::sentence_id::RMB
:
574 return "Recommended Minimum Navigation Information B";
575 case marnav::nmea::sentence_id::RMC
:
576 return "Recommended Minimum Navigation Information C";
577 case marnav::nmea::sentence_id::ROT
:
578 return "Rate Of Turn";
579 case marnav::nmea::sentence_id::RPM
:
580 return "Revolutions";
581 case marnav::nmea::sentence_id::RSA
:
582 return "Rudder Sensor Angle";
583 case marnav::nmea::sentence_id::RSD
:
584 return "RADAR System Data";
585 case marnav::nmea::sentence_id::RTE
:
587 case marnav::nmea::sentence_id::SFI
:
588 return "Scanning Frequency Information";
589 case marnav::nmea::sentence_id::STN
:
590 return "Multiple Data ID";
591 case marnav::nmea::sentence_id::TDS
:
592 return "Trawl Door Spread Distance";
593 case marnav::nmea::sentence_id::TFI
:
594 return "Trawl Filling Indicator";
595 case marnav::nmea::sentence_id::TPC
:
596 return "Trawl Position Cartesian Coordinates";
597 case marnav::nmea::sentence_id::TPR
:
598 return "Trawl Position Relative Vessel";
599 case marnav::nmea::sentence_id::TPT
:
600 return "Trawl Position True";
601 case marnav::nmea::sentence_id::TRF
:
602 return "TRANSIT Fix Data";
603 case marnav::nmea::sentence_id::TLL
:
604 return "Target latitude and longitude";
605 case marnav::nmea::sentence_id::TTM
:
606 return "Tracked Target Message";
607 case marnav::nmea::sentence_id::VBW
:
608 return "Dual Ground/Water Speed";
609 case marnav::nmea::sentence_id::VDM
:
611 case marnav::nmea::sentence_id::VDO
:
612 return "AIS, own ship data";
613 case marnav::nmea::sentence_id::VDR
:
614 return "Set and Drift";
615 case marnav::nmea::sentence_id::VHW
:
616 return "Water speed and heading (II)";
617 case marnav::nmea::sentence_id::VLW
:
618 return "Distance Traveled through Water (II)";
619 case marnav::nmea::sentence_id::VPW
:
620 return "Speed - Measured Parallel to Wind";
621 case marnav::nmea::sentence_id::VTG
:
622 return "Track made good and Ground speed";
623 case marnav::nmea::sentence_id::VWR
:
624 return "Relative Wind Speed and Angle (II)";
625 case marnav::nmea::sentence_id::WCV
:
626 return "Waypoint Closure Velocity";
627 case marnav::nmea::sentence_id::WNC
:
628 return "Distance - Waypoint to Waypoint";
629 case marnav::nmea::sentence_id::WPL
:
630 return "Waypoint Location";
631 case marnav::nmea::sentence_id::XDR
:
632 return "Transducer Measurement";
633 case marnav::nmea::sentence_id::XTE
:
634 return "Cross-Track Error, Measured";
635 case marnav::nmea::sentence_id::XTR
:
636 return "Cross Track Error - Dead Reckoning";
637 case marnav::nmea::sentence_id::ZDA
:
638 return "Time & Date - UTC, day, month, year and local time zone";
639 case marnav::nmea::sentence_id::ZDL
:
640 return "Time and Distance to Variable Point";
641 case marnav::nmea::sentence_id::ZFO
:
642 return "UTC & Time from origin Waypoint";
643 case marnav::nmea::sentence_id::ZTG
:
644 return "UTC & Time to Destination Waypoint";
645 case marnav::nmea::sentence_id::APA
:
646 return "Autopilot Sentence 'A'";
647 case marnav::nmea::sentence_id::BER
:
648 return "Bearing & Distance to Waypoint, Dead Reckoning, Rhumb Line";
649 case marnav::nmea::sentence_id::BPI
:
650 return "Bearing & Distance to Point of Interest";
651 case marnav::nmea::sentence_id::DBK
:
652 return "Depth Below Keel";
653 case marnav::nmea::sentence_id::DBS
:
654 return "Depth Below Surface";
655 case marnav::nmea::sentence_id::DCN
:
656 return "Decca Position";
657 case marnav::nmea::sentence_id::DRU
:
658 return "Dual Doppler Auxiliary Data";
659 case marnav::nmea::sentence_id::GDA
:
660 return "Dead Reckoning Positions";
661 case marnav::nmea::sentence_id::GLA
:
662 return "Loran-C Positions";
663 case marnav::nmea::sentence_id::GOA
:
664 return "OMEGA Positions";
665 case marnav::nmea::sentence_id::GTD
:
666 return "Geographical Position, Loran-C TDs";
667 case marnav::nmea::sentence_id::GXA
:
668 return "TRANSIT Position";
669 case marnav::nmea::sentence_id::HCC
:
670 return "Compass Heading";
671 case marnav::nmea::sentence_id::HCD
:
672 return "Heading and Deviation";
673 case marnav::nmea::sentence_id::HDM
:
674 return "Heading, Magnetic";
675 case marnav::nmea::sentence_id::HDT
:
676 return "Heading, True";
677 case marnav::nmea::sentence_id::HVD
:
678 return "Magnetic Variation, Automatic";
679 case marnav::nmea::sentence_id::HVM
:
680 return "Magnetic Variation, Manually Set";
681 case marnav::nmea::sentence_id::IMA
:
682 return "Vessel Identification";
683 case marnav::nmea::sentence_id::MDA
:
684 return "Meteorological Composite";
685 case marnav::nmea::sentence_id::MHU
:
687 case marnav::nmea::sentence_id::MMB
:
689 case marnav::nmea::sentence_id::MTA
:
690 return "Air Temperature";
691 case marnav::nmea::sentence_id::MWH
:
692 return "Wave Height";
693 case marnav::nmea::sentence_id::MWS
:
694 return "Wind & Sea State";
695 case marnav::nmea::sentence_id::OLN
:
696 return "Omega Lane Numbers";
697 case marnav::nmea::sentence_id::R00
:
698 return "(Rnn) Waypoints in active route";
699 case marnav::nmea::sentence_id::SBK
:
700 return "Loran-C Blink Status";
701 case marnav::nmea::sentence_id::SCY
:
702 return "Loran-C Cycle Lock Status";
703 case marnav::nmea::sentence_id::SCD
:
704 return "Loran-C ECDs";
705 case marnav::nmea::sentence_id::SDB
:
706 return "Loran-C Signal Strength";
707 case marnav::nmea::sentence_id::SGD
:
708 return "Position Accuracy Estimate";
709 case marnav::nmea::sentence_id::SGR
:
710 return "Loran-C Chain Identifier";
711 case marnav::nmea::sentence_id::SIU
:
712 return "Loran-C Stations in Use";
713 case marnav::nmea::sentence_id::SLC
:
714 return "Loran-C Status";
715 case marnav::nmea::sentence_id::SNC
:
716 return "Navigation Calculation Basis";
717 case marnav::nmea::sentence_id::SNU
:
718 return "Loran-C SNR Status";
719 case marnav::nmea::sentence_id::SPS
:
720 return "Loran-C Predicted Signal Strength";
721 case marnav::nmea::sentence_id::SSF
:
722 return "Position Correction Offset";
723 case marnav::nmea::sentence_id::STC
:
724 return "Time Constant";
725 case marnav::nmea::sentence_id::STR
:
726 return "Tracking Reference";
727 case marnav::nmea::sentence_id::SYS
:
728 return "Hybrid System Configuration";
729 case marnav::nmea::sentence_id::VWT
:
730 return "True Wind Speed and Angle";
731 case marnav::nmea::sentence_id::PGRME
:
732 return "Estimated Error Information (Garmin Extension)";
733 case marnav::nmea::sentence_id::PGRMM
:
734 return "Map Datum (Garmin Extension)";
735 case marnav::nmea::sentence_id::PGRMZ
:
736 return "Altitude (Garmin Extension)";
737 case marnav::nmea::sentence_id::PMGNST
:
738 return "Magellan Status";
739 case marnav::nmea::sentence_id::PRWIZCH
:
740 return "Rockwell Channel Status";
741 case marnav::nmea::sentence_id::PUBX
:
742 return "u-blox (misc formats, depending on first field)";
743 case marnav::nmea::sentence_id::TMVTD
:
744 return "Transas VTS / SML tracking system report";
749 static std::string
render(const marnav::nmea::unit::distance t
)
752 case marnav::nmea::unit::distance::meter
:
754 case marnav::nmea::unit::distance::feet
:
756 case marnav::nmea::unit::distance::nm
:
758 case marnav::nmea::unit::distance::km
:
760 case marnav::nmea::unit::distance::fathom
:
766 static std::string
render(const marnav::nmea::unit::temperature t
)
769 case marnav::nmea::unit::temperature::celsius
:
775 static std::string
render(const marnav::nmea::unit::velocity t
)
778 case marnav::nmea::unit::velocity::knot
:
780 case marnav::nmea::unit::velocity::kmh
:
782 case marnav::nmea::unit::velocity::mps
:
788 static std::string
render(const marnav::nmea::side t
)
791 case marnav::nmea::side::left
:
793 case marnav::nmea::side::right
:
799 static std::string
render(const marnav::nmea::reference t
)
802 case marnav::nmea::reference::RELATIVE
:
804 case marnav::nmea::reference::TRUE
:
806 case marnav::nmea::reference::MAGNETIC
:
812 static std::string
render(const marnav::nmea::quality t
)
815 case marnav::nmea::quality::invalid
:
817 case marnav::nmea::quality::gps_fix
:
819 case marnav::nmea::quality::dgps_fix
:
821 case marnav::nmea::quality::guess
:
823 case marnav::nmea::quality::simulation
:
829 static std::string
render(const marnav::nmea::direction t
)
832 case marnav::nmea::direction::north
:
834 case marnav::nmea::direction::south
:
836 case marnav::nmea::direction::west
:
838 case marnav::nmea::direction::east
:
840 case marnav::nmea::direction::none
:
846 static std::string
render(const marnav::nmea::selection_mode t
)
849 case marnav::nmea::selection_mode::manual
:
851 case marnav::nmea::selection_mode::automatic
:
857 static std::string
render(const marnav::nmea::status t
)
860 case marnav::nmea::status::ok
:
862 case marnav::nmea::status::warning
:
868 static std::string
render(const marnav::nmea::route t
)
871 case marnav::nmea::route::complete
:
873 case marnav::nmea::route::working
:
879 static std::string
render(const marnav::nmea::waypoint
& t
) { return t
.c_str(); }
881 static std::string
render(const marnav::nmea::mode_indicator t
)
884 case marnav::nmea::mode_indicator::invalid
:
886 case marnav::nmea::mode_indicator::autonomous
:
888 case marnav::nmea::mode_indicator::differential
:
889 return "differential";
890 case marnav::nmea::mode_indicator::estimated
:
892 case marnav::nmea::mode_indicator::manual_input
:
893 return "manual input";
894 case marnav::nmea::mode_indicator::simulated
:
896 case marnav::nmea::mode_indicator::data_not_valid
:
898 case marnav::nmea::mode_indicator::precise
:
904 template <typename T
> static std::string
render(const marnav::utils::optional
<T
> & t
)
911 static void print(const std::string
& name
, const std::string
& value
)
913 fmt::printf("\t%-30s : %s\n", name
, value
);
916 static void print_detail_hdg(const marnav::nmea::sentence
* s
)
918 const auto t
= marnav::nmea::sentence_cast
<marnav::nmea::hdg
>(s
);
919 print("Heading", render(t
->get_heading()));
920 print("Magn Deviation",
921 fmt::sprintf("%s %s", render(t
->get_magn_dev()), render(t
->get_magn_dev_hem())));
922 print("Magn Variation",
923 fmt::sprintf("%s %s", render(t
->get_magn_var()), render(t
->get_magn_var_hem())));
926 static void print_detail_hdm(const marnav::nmea::sentence
* s
)
928 const auto t
= marnav::nmea::sentence_cast
<marnav::nmea::hdm
>(s
);
929 print("Heading", render(t
->get_heading()));
932 static void print_detail_rmb(const marnav::nmea::sentence
* s
)
934 const auto t
= marnav::nmea::sentence_cast
<marnav::nmea::rmb
>(s
);
935 print("Active", render(t
->get_active()));
936 print("Cross Track Error", render(t
->get_cross_track_error()));
937 print("Waypoint To", render(t
->get_waypoint_to()));
938 print("Waypoint From", render(t
->get_waypoint_from()));
939 print("Latitude", render(t
->get_latitude()));
940 print("Longitude", render(t
->get_longitude()));
941 print("Range", render(t
->get_range()));
942 print("Bearing", render(t
->get_bearing()));
943 print("Dest. Velocity", render(t
->get_dst_velocity()));
944 print("Arrival Status", render(t
->get_arrival_status()));
945 print("Mode Indicator", render(t
->get_mode_ind()));
948 static void print_detail_rmc(const marnav::nmea::sentence
* s
)
950 const auto t
= marnav::nmea::sentence_cast
<marnav::nmea::rmc
>(s
);
951 print("Time UTC", render(t
->get_time_utc()));
952 print("Status", render(t
->get_status()));
953 print("Latitude", render(t
->get_latitude()));
954 print("Longitude", render(t
->get_longitude()));
955 print("SOG", render(t
->get_sog()));
956 print("Heading", render(t
->get_heading()));
957 print("Date", render(t
->get_date()));
958 print("Magn Dev", fmt::sprintf("%s %s", render(t
->get_mag()), render(t
->get_mag_hem())));
959 print("Mode Ind ", render(t
->get_mode_ind()));
962 static void print_detail_vtg(const marnav::nmea::sentence
* s
)
964 const auto t
= marnav::nmea::sentence_cast
<marnav::nmea::vtg
>(s
);
965 print("Track True", render(t
->get_track_true()));
966 print("Track Magn", render(t
->get_track_magn()));
967 print("Speed Knots", render(t
->get_speed_kn()));
968 print("Speed kmh", render(t
->get_speed_kmh()));
969 print("Mode Indicator", render(t
->get_mode_ind()));
972 static void print_detail_gll(const marnav::nmea::sentence
* s
)
974 const auto t
= marnav::nmea::sentence_cast
<marnav::nmea::gll
>(s
);
975 print("Latitude", render(t
->get_latitude()));
976 print("Longitude", render(t
->get_longitude()));
977 print("Time UTC", render(t
->get_time_utc()));
978 print("Status", render(t
->get_data_valid()));
979 print("Mode Indicator", render(t
->get_mode_ind()));
982 static void print_detail_bod(const marnav::nmea::sentence
* s
)
984 const auto t
= marnav::nmea::sentence_cast
<marnav::nmea::bod
>(s
);
985 print("Bearing True", render(t
->get_bearing_true()));
986 print("Bearing Magn", render(t
->get_bearing_magn()));
987 print("Waypoint To", render(t
->get_waypoint_to()));
988 print("Waypoint From", render(t
->get_waypoint_from()));
991 static void print_detail_bwc(const marnav::nmea::sentence
* s
)
993 const auto t
= marnav::nmea::sentence_cast
<marnav::nmea::bwc
>(s
);
994 print("Time UTC", render(t
->get_time_utc()));
995 print("Bearing True", render(t
->get_bearing_true()));
996 print("Bearing Magnetic", render(t
->get_bearing_mag()));
998 fmt::sprintf("%s %s", render(t
->get_distance()), render(t
->get_distance_unit())));
999 print("Waypoint", render(t
->get_waypoint_id()));
1000 print("Mode Indicator", render(t
->get_mode_ind()));
1003 static void print_detail_gsa(const marnav::nmea::sentence
* s
)
1005 const auto t
= marnav::nmea::sentence_cast
<marnav::nmea::gsa
>(s
);
1006 print("Selection Mode", render(t
->get_sel_mode()));
1007 print("Mode", render(t
->get_mode()));
1008 for (auto i
= 0; i
< marnav::nmea::gsa::max_satellite_ids
; ++i
) {
1009 print(fmt::sprintf("Satellite %02u", i
), render(t
->get_satellite_id(i
)));
1011 print("PDOP", render(t
->get_pdop()));
1012 print("HDOP", render(t
->get_hdop()));
1013 print("VDOP", render(t
->get_vdop()));
1016 static void print_detail_gga(const marnav::nmea::sentence
* s
)
1018 const auto t
= marnav::nmea::sentence_cast
<marnav::nmea::gga
>(s
);
1019 print("Time", render(t
->get_time()));
1020 print("Latitude", render(t
->get_latitude()));
1021 print("Longitude", render(t
->get_longitude()));
1022 print("Quality Ind", render(t
->get_quality_indicator()));
1023 print("Num Satellites", render(t
->get_n_satellites()));
1024 print("Horiz Dilution", render(t
->get_hor_dilution()));
1026 fmt::sprintf("%s %s", render(t
->get_altitude()), render(t
->get_altitude_unit())));
1027 print("Geodial Sep", fmt::sprintf("%s %s", render(t
->get_geodial_separation()),
1028 render(t
->get_geodial_separation_unit())));
1029 print("DGPS Age", render(t
->get_dgps_age()));
1030 print("DGPS Ref", render(t
->get_dgps_ref()));
1033 static void print_detail_mwv(const marnav::nmea::sentence
* s
)
1035 const auto t
= marnav::nmea::sentence_cast
<marnav::nmea::mwv
>(s
);
1036 print("Angle", fmt::sprintf("%s %s", render(t
->get_angle()), render(t
->get_angle_ref())));
1037 print("Speed", fmt::sprintf("%s %s", render(t
->get_speed()), render(t
->get_speed_unit())));
1038 print("Data Valid", render(t
->get_data_valid()));
1041 static void print_detail_gsv(const marnav::nmea::sentence
* s
)
1043 const auto t
= marnav::nmea::sentence_cast
<marnav::nmea::gsv
>(s
);
1044 print("Num Messages", render(t
->get_n_messages()));
1045 print("Messages Number", render(t
->get_message_number()));
1046 print("Num Sat in View", render(t
->get_n_satellites_in_view()));
1047 for (int i
= 0; i
< 4; ++i
) {
1048 const auto sat
= t
->get_sat(i
);
1050 print("Sat", fmt::sprintf("ID:%02u ELEV:%02u AZIMUTH:%03u SNR:%02u", sat
->id
,
1051 sat
->elevation
, sat
->azimuth
, sat
->snr
));
1056 static void print_detail_zda(const marnav::nmea::sentence
* s
)
1058 const auto t
= marnav::nmea::sentence_cast
<marnav::nmea::zda
>(s
);
1059 print("Time UTC", render(t
->get_time_utc()));
1060 print("Day", render(t
->get_day()));
1061 print("Month", render(t
->get_month()));
1062 print("Year", render(t
->get_year()));
1063 print("Local Zone Hours", render(t
->get_local_zone_hours()));
1064 print("Local Zone Min", render(t
->get_local_zone_minutes()));
1067 static void print_detail_dtm(const marnav::nmea::sentence
* s
)
1069 const auto t
= marnav::nmea::sentence_cast
<marnav::nmea::dtm
>(s
);
1070 print("Ref", render(t
->get_ref()));
1071 print("Subcode", render(t
->get_subcode()));
1072 print("Latitude Offset", render(t
->get_lat_offset()));
1073 print("Latitude Hem", render(t
->get_lat_hem()));
1074 print("Longitude Offset", render(t
->get_lon_offset()));
1075 print("Longitude Hem", render(t
->get_lon_hem()));
1076 print("Altitude", render(t
->get_altitude()));
1077 print("Name", render(t
->get_name()));
1080 static void print_detail_aam(const marnav::nmea::sentence
* s
)
1082 const auto t
= marnav::nmea::sentence_cast
<marnav::nmea::aam
>(s
);
1083 print("Arrival Circle Entred", render(t
->get_arrival_circle_entered()));
1084 print("Perpendicular Passed", render(t
->get_perpendicualar_passed()));
1085 print("Arrival Circle Radius", fmt::sprintf("%s %s", render(t
->get_arrival_circle_radius()),
1086 render(t
->get_arrival_circle_radius_unit())));
1087 print("Waypoint", render(t
->get_waypoint_id()));
1090 static void print_detail_rte(const marnav::nmea::sentence
* s
)
1092 const auto t
= marnav::nmea::sentence_cast
<marnav::nmea::rte
>(s
);
1093 print("Number of Messages", render(t
->get_n_messages()));
1094 print("Message Number", render(t
->get_message_number()));
1095 print("Message Mode", render(t
->get_message_mode()));
1096 for (int i
= 0; i
< marnav::nmea::rte::max_waypoints
; ++i
) {
1097 const auto wp
= t
->get_waypoint_id(i
);
1099 print(fmt::sprintf("Waypoint %i", i
), render(wp
));
1103 static void print_detail_mtw(const marnav::nmea::sentence
* s
)
1105 const auto t
= marnav::nmea::sentence_cast
<marnav::nmea::mtw
>(s
);
1106 print("Water Temperature",
1107 fmt::sprintf("%s %s", render(t
->get_temperature()), render(t
->get_temperature_unit())));
1110 static void print_detail_dbt(const marnav::nmea::sentence
* s
)
1112 const auto t
= marnav::nmea::sentence_cast
<marnav::nmea::dbt
>(s
);
1113 print("Depth Feet", render(t
->get_depth_feet()));
1114 print("Depth Meter", render(t
->get_depth_meter()));
1115 print("Depth Fathom", render(t
->get_depth_fathom()));
1118 static void print_detail_apb(const marnav::nmea::sentence
* s
)
1120 const auto t
= marnav::nmea::sentence_cast
<marnav::nmea::apb
>(s
);
1121 print("Loran C blink warn", render(t
->get_loran_c_blink_warning()));
1122 print("Loran C cycle lock warn", render(t
->get_loran_c_cycle_lock_warning()));
1123 print("Cross Track Error Magnitude", render(t
->get_cross_track_error_magnitude()));
1124 print("Direction to Steer", render(t
->get_direction_to_steer()));
1125 print("Cross Track Unit", render(t
->get_cross_track_unit()));
1126 print("Status Arrival", render(t
->get_status_arrival()));
1127 print("Status Perpendicular Pass", render(t
->get_status_perpendicular_passing()));
1128 print("Bearing Org to Dest", render(t
->get_bearing_origin_to_destination()));
1129 print("Bearing Org to Dest Ref", render(t
->get_bearing_origin_to_destination_ref()));
1130 print("Waypoint", render(t
->get_waypoint_id()));
1131 print("Bearing Pos to Dest", render(t
->get_bearing_pos_to_destination()));
1132 print("Bearing Pos to Dest Ref", render(t
->get_bearing_pos_to_destination_ref()));
1133 print("Heading to Steer to Dest", render(t
->get_heading_to_steer_to_destination()));
1134 print("Heading to Steer to Dest Ref", render(t
->get_heading_to_steer_to_destination_ref()));
1135 print("Mode Indicator", render(t
->get_mode_ind()));
1138 static void print_detail_pgrme(const marnav::nmea::sentence
* s
)
1140 const auto t
= marnav::nmea::sentence_cast
<marnav::nmea::pgrme
>(s
);
1141 print("HPE", render(t
->get_horizontal_position_error()));
1142 print("VPE", render(t
->get_vertical_position_error()));
1143 print("O.sph.eq.pos err", render(t
->get_overall_spherical_equiv_position_error()));
1146 static void print_detail_pgrmm(const marnav::nmea::sentence
* s
)
1148 const auto t
= marnav::nmea::sentence_cast
<marnav::nmea::pgrmm
>(s
);
1149 print("Map Datum", render(t
->get_map_datum()));
1152 static void print_detail_pgrmz(const marnav::nmea::sentence
* s
)
1154 const auto t
= marnav::nmea::sentence_cast
<marnav::nmea::pgrmz
>(s
);
1156 fmt::sprintf("%s %s", render(t
->get_altitude()), render(t
->get_altitude_unit())));
1157 print("Fix Type", render(t
->get_fix()));
1160 static void print_detail_vwr(const marnav::nmea::sentence
* s
)
1162 const auto t
= marnav::nmea::sentence_cast
<marnav::nmea::vwr
>(s
);
1163 print("Angle", fmt::sprintf("%s %s", render(t
->get_angle()), render(t
->get_angle_side())));
1164 print("Speed Knots", render(t
->get_speed_knots()));
1165 print("Speed m/s", render(t
->get_speed_mps()));
1166 print("Speed km/h", render(t
->get_speed_kmh()));
1169 static void print_detail_vlw(const marnav::nmea::sentence
* s
)
1171 const auto t
= marnav::nmea::sentence_cast
<marnav::nmea::vlw
>(s
);
1172 print("Distance Cumulative nm", render(t
->get_distance_cum()));
1173 print("Distance since Rest nm", render(t
->get_distance_reset()));
1176 static void print_detail_vhw(const marnav::nmea::sentence
* s
)
1178 const auto t
= marnav::nmea::sentence_cast
<marnav::nmea::vhw
>(s
);
1179 print("Heading True", render(t
->get_heading_empty()));
1180 print("Heading Magn", render(t
->get_heading()));
1181 print("Speed kn", render(t
->get_speed_knots()));
1182 print("Speed km/h", render(t
->get_speed_kmh()));
1185 static void print_detail_message_01_common(const marnav::ais::message_01
* t
)
1187 print("Repeat Indicator", render(t
->get_repeat_indicator()));
1188 print("MMSI", render(t
->get_mmsi()));
1189 print("ROT", render(t
->get_rot()));
1190 print("SOG", render(t
->get_sog()));
1191 print("Pos Accuracy", render(t
->get_position_accuracy()));
1192 print("Latitude", render(t
->get_latitude()));
1193 print("Longitude", render(t
->get_longitude()));
1194 print("COG", render(t
->get_cog()));
1195 print("HDG", render(t
->get_hdg()));
1196 print("Time Stamp", render(t
->get_timestamp()));
1197 print("RAIM", render(t
->get_raim()));
1198 print("Radio Status", render(t
->get_radio_status()));
1201 static void print_detail_message_01(const marnav::ais::message
* m
)
1203 print_detail_message_01_common(marnav::ais::message_cast
<marnav::ais::message_01
>(m
));
1206 static void print_detail_message_02(const marnav::ais::message
* m
)
1208 print_detail_message_01_common(marnav::ais::message_cast
<marnav::ais::message_02
>(m
));
1211 static void print_detail_message_03(const marnav::ais::message
* m
)
1213 print_detail_message_01_common(marnav::ais::message_cast
<marnav::ais::message_03
>(m
));
1216 static void print_detail_message_04_common(const marnav::ais::message_04
* t
)
1218 print("Repeat Indicator", render(t
->get_repeat_indicator()));
1219 print("MMSI", render(t
->get_mmsi()));
1220 print("Year", render(t
->get_year()));
1221 print("Month", render(t
->get_month()));
1222 print("Day", render(t
->get_day()));
1223 print("Hour", render(t
->get_hour()));
1224 print("Minute", render(t
->get_minute()));
1225 print("Second", render(t
->get_second()));
1226 print("Pos Accuracy", render(t
->get_position_accuracy()));
1227 print("Latitude", render(t
->get_latitude()));
1228 print("Longitude", render(t
->get_longitude()));
1229 print("EPFD Fix", render(t
->get_epfd_fix()));
1230 print("RAIM", render(t
->get_raim()));
1231 print("Radio Status", render(t
->get_radio_status()));
1234 static void print_detail_message_04(const marnav::ais::message
* m
)
1236 print_detail_message_04_common(marnav::ais::message_cast
<marnav::ais::message_04
>(m
));
1239 static void print_detail_message_11(const marnav::ais::message
* m
)
1241 print_detail_message_04_common(marnav::ais::message_cast
<marnav::ais::message_11
>(m
));
1244 static void print_detail_message_05(const marnav::ais::message
* m
)
1246 const auto t
= marnav::ais::message_cast
<marnav::ais::message_05
>(m
);
1247 print("Repeat Indicator", render(t
->get_repeat_indicator()));
1248 print("MMSI", render(t
->get_mmsi()));
1249 print("AIS Version", render(t
->get_ais_version()));
1250 print("IMO", render(t
->get_imo_number()));
1251 print("Callsign", render(t
->get_callsign()));
1252 print("Shipname", render(t
->get_shipname()));
1253 print("Shiptype", render(t
->get_shiptype()));
1254 print("Length", render(t
->get_to_bow() + t
->get_to_stern()));
1255 print("Width", render(t
->get_to_port() + t
->get_to_starboard()));
1256 print("Draught", render(t
->get_draught()));
1257 print("EPFD Fix", render(t
->get_epfd_fix()));
1258 print("ETA Month", render(t
->get_eta_month()));
1259 print("ETA Day", render(t
->get_eta_day()));
1260 print("ETA Hour", render(t
->get_eta_hour()));
1261 print("ETA Minute", render(t
->get_eta_minute()));
1262 print("Destination", render(t
->get_destination()));
1263 print("DTE", render(t
->get_dte()));
1266 static void print_detail_message_18(const marnav::ais::message
* m
)
1268 const auto t
= marnav::ais::message_cast
<marnav::ais::message_18
>(m
);
1269 print("Repeat Indicator", render(t
->get_repeat_indicator()));
1270 print("MMSI", render(t
->get_mmsi()));
1271 print("SOG", render(t
->get_sog()));
1272 print("Pos Accuracy", render(t
->get_position_accuracy()));
1273 print("Latitude", render(t
->get_latitude()));
1274 print("Longitude", render(t
->get_longitude()));
1275 print("COG", render(t
->get_cog()));
1276 print("HDG", render(t
->get_hdg()));
1277 print("Time Stamp", render(t
->get_timestamp()));
1278 print("CS Unit", render(t
->get_cs_unit()));
1279 print("Display Flag", render(t
->get_display_flag()));
1280 print("DSC Flag", render(t
->get_dsc_flag()));
1281 print("Band Flag", render(t
->get_band_flag()));
1282 print("Message 22 Flag", render(t
->get_message_22_flag()));
1283 print("Assigned", render(t
->get_assigned()));
1284 print("RAIM", render(t
->get_raim()));
1285 print("Radio Status", render(t
->get_radio_status()));
1288 static void print_detail_message_21(const marnav::ais::message
* m
)
1290 const auto t
= marnav::ais::message_cast
<marnav::ais::message_21
>(m
);
1291 print("Repeat Indicator", render(t
->get_repeat_indicator()));
1292 print("MMSI", render(t
->get_mmsi()));
1293 print("Aid Type", render(t
->get_aid_type()));
1294 print("Name", render(t
->get_name()));
1295 print("Pos Accuracy", render(t
->get_position_accuracy()));
1296 print("Latitude", render(t
->get_latitude()));
1297 print("Longitude", render(t
->get_longitude()));
1298 print("Length", render(t
->get_to_bow() + t
->get_to_stern()));
1299 print("Width", render(t
->get_to_port() + t
->get_to_starboard()));
1300 print("EPFD Fix", render(t
->get_epfd_fix()));
1301 print("UTC Second", render(t
->get_utc_second()));
1302 print("Off Pos Indicator", render(t
->get_off_position()));
1303 print("Regional", render(t
->get_regional()));
1304 print("RAIM", render(t
->get_raim()));
1305 print("Virtual Aid Flag", render(t
->get_virtual_aid_flag()));
1306 print("Assigned", render(t
->get_assigned()));
1307 print("Name Extension", render(t
->get_name_extension()));
1310 static void print_detail_message_24(const marnav::ais::message
* m
)
1312 const auto t
= marnav::ais::message_cast
<marnav::ais::message_24
>(m
);
1313 print("Repeat Indicator", render(t
->get_repeat_indicator()));
1314 print("MMSI", render(t
->get_mmsi()));
1315 print("Part", render(t
->get_part_number()));
1316 if (t
->get_part_number() == marnav::ais::message_24::part::A
) {
1317 print("Ship Name", render(t
->get_shipname()));
1319 print("Ship Type", render(t
->get_shiptype()));
1320 print("Vendor ID", render(t
->get_vendor_id()));
1321 print("Model", render(t
->get_model()));
1322 print("Serial", render(t
->get_serial()));
1323 print("Callsign", render(t
->get_callsign()));
1324 if (t
->is_auxiliary_vessel()) {
1325 print("Mothership MMSI", render(t
->get_mothership_mmsi()));
1327 print("Length", render(t
->get_to_bow() + t
->get_to_stern()));
1328 print("Width", render(t
->get_to_port() + t
->get_to_starboard()));
1334 static void dump_nmea(const std::string
& line
)
1336 #define ADD_SENTENCE(s) \
1338 marnav::nmea::s::ID, detail::print_detail_##s \
1341 marnav::nmea::sentence_id id
;
1342 std::function
<void(const marnav::nmea::sentence
*)> func
;
1344 using container
= std::vector
<entry
>;
1346 static const container sentences
= {
1372 ADD_SENTENCE(pgrme
),
1373 ADD_SENTENCE(pgrmm
),
1379 using namespace marnav
;
1382 auto s
= nmea::make_sentence(line
);
1383 auto i
= std::find_if(std::begin(sentences
), std::end(sentences
),
1384 [&s
](const container::value_type
& item
) { return item
.id
== s
->id(); });
1385 if (i
== std::end(sentences
)) {
1386 fmt::printf("\t%s\n", detail::render(s
->id()));
1388 "%s%s%s\n\tnot implemented\n\n", terminal::magenta
, line
, terminal::normal
);
1390 fmt::printf("%s%s%s\n", terminal::green
, line
, terminal::normal
);
1391 fmt::printf("\t%s\n", detail::render(s
->id()));
1395 } catch (nmea::unknown_sentence
& error
) {
1396 fmt::printf("%s%s%s\n\terror: unknown sentence: %s\n\n", terminal::red
, line
,
1397 terminal::normal
, error
.what());
1398 } catch (nmea::checksum_error
& error
) {
1399 fmt::printf("%s%s%s\n\terror: checksum error: %s\n\n", terminal::red
, line
,
1400 terminal::normal
, error
.what());
1401 } catch (std::invalid_argument
& error
) {
1403 "%s%s%s\n\terror: %s\n\n", terminal::red
, line
, terminal::normal
, error
.what());
1407 static void dump_ais(const std::vector
<std::unique_ptr
<marnav::nmea::sentence
>> & sentences
)
1409 #define ADD_MESSAGE(m) \
1411 marnav::ais::m::ID, detail::print_detail_##m \
1414 marnav::ais::message_id id
;
1415 std::function
<void(const marnav::ais::message
*)> func
;
1417 using container
= std::vector
<entry
>;
1419 static const container messages
= {
1420 ADD_MESSAGE(message_01
),
1421 ADD_MESSAGE(message_02
),
1422 ADD_MESSAGE(message_03
),
1423 ADD_MESSAGE(message_04
),
1424 ADD_MESSAGE(message_05
),
1425 ADD_MESSAGE(message_11
),
1426 ADD_MESSAGE(message_18
),
1427 ADD_MESSAGE(message_21
),
1428 ADD_MESSAGE(message_24
)
1433 using namespace marnav
;
1436 auto m
= ais::make_message(nmea::collect_payload(sentences
.begin(), sentences
.end()));
1437 auto i
= std::find_if(std::begin(messages
), std::end(messages
),
1438 [&m
](const container::value_type
& item
) { return item
.id
== m
->type(); });
1439 if (i
== std::end(messages
)) {
1440 fmt::printf("\t%s\n", detail::render(m
->type()));
1441 fmt::printf("%smessage_%02u%s\n\tnot implemented\n\n", terminal::magenta
,
1442 static_cast<uint8_t>(m
->type()), terminal::normal
);
1444 fmt::printf("\t%s\n", detail::render(m
->type()));
1448 } catch (std::exception
& error
) {
1449 fmt::printf("\t%serror:%s %s\n\n", terminal::red
, terminal::normal
, error
.what());
1453 static void process(std::function
<bool(std::string
&)> source
)
1455 using namespace marnav
;
1458 std::vector
<std::unique_ptr
<nmea::sentence
>> sentences
;
1460 while (source(line
)) {
1467 if (line
[0] == nmea::sentence::start_token
) {
1469 } else if (line
[0] == nmea::sentence::start_token_ais
) {
1470 fmt::printf("%s%s%s\n", terminal::blue
, line
, terminal::normal
);
1471 auto s
= nmea::make_sentence(line
);
1473 nmea::vdm
* v
= nullptr; // VDM is the common denominator for AIS relevant messages
1475 if (s
->id() == nmea::sentence_id::VDO
) {
1476 v
= nmea::sentence_cast
<nmea::vdo
>(s
);
1477 } else if (s
->id() == nmea::sentence_id::VDM
) {
1478 v
= nmea::sentence_cast
<nmea::vdm
>(s
);
1480 // something strange happened, no VDM nor VDO
1481 fmt::printf("%s%s%s\n\terror: ignoring AIS sentence, dropping collection.\n\n",
1482 terminal::red
, line
, terminal::normal
);
1487 // check sentences if a discontuniation has occurred
1488 if (sentences
.size() && (sentences
.back()->id() != v
->id())) {
1489 sentences
.clear(); // there was a discontinuation, start over collecting
1491 "\t%swarning:%s dropping collection.\n", terminal::cyan
, terminal::normal
);
1494 // check if a previous message was not complete
1495 const auto n_fragments
= v
->get_n_fragments();
1496 const auto fragment
= v
->get_fragment();
1497 if (sentences
.size() >= fragment
) {
1500 "\t%swarning:%s dropping collection.\n", terminal::cyan
, terminal::normal
);
1503 sentences
.push_back(std::move(s
));
1504 if (fragment
== n_fragments
) {
1505 dump_ais(sentences
);
1509 fmt::printf("%s%s%s\n\terror: ignoring AIS sentence.\n\n", terminal::red
, line
,
1515 static marnav::io::serial::baud
get_baud_rate(uint32_t speed
)
1519 return marnav::io::serial::baud::baud_4800
;
1521 return marnav::io::serial::baud::baud_38400
;
1525 throw std::runtime_error
{"invalid baud rate"};
1529 int main(int argc
, char ** argv
)
1531 using namespace nmeadump
;
1533 if (parse_options(argc
, argv
))
1534 return EXIT_SUCCESS
;
1536 if (!global
.config
.file
.empty()) {
1537 std::ifstream ifs
{global
.config
.file
.c_str()};
1538 process([&](std::string
& line
) { return !!std::getline(ifs
, line
); });
1539 } else if (!global
.config
.port
.empty()) {
1540 using namespace marnav
;
1541 using namespace marnav::io
;
1542 default_nmea_reader source
{utils::make_unique
<serial
>(global
.config
.port
,
1543 get_baud_rate(global
.config
.port_speed
), serial::databits::bit_8
,
1544 serial::stopbits::bit_1
, serial::parity::none
)};
1545 process([&](std::string
& line
) { return source
.read_sentence(line
); });
1547 process([&](std::string
& line
) { return !!std::getline(std::cin
, line
); });
1550 return EXIT_SUCCESS
;