NMEA: AIS helper functions moved into its separate files.
[marnav.git] / test / test-ais-sample.cpp
blobd9cdb1ce53600064077a75ac57b25f79bbd2c66b
1 #include <fstream>
2 #include <string>
3 #include <iostream>
4 #include <marnav/nmea/nmea.hpp>
5 #include <marnav/nmea/ais_helper.hpp>
6 #include <marnav/ais/ais.hpp>
8 namespace stackoverflow
10 // source:
11 // http://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf
13 // changes:
14 // - old-style C type cast changed to c++ cast
15 // - reformatting
16 // - renaming and put into the namespace
17 // - break inserted for the default option of switch
18 std::istream & getline(std::istream & is, std::string & t)
20 t.clear();
22 // The characters in the stream are read one-by-one using a std::streambuf.
23 // That is faster than reading them one-by-one using the std::istream.
24 // Code that uses streambuf this way must be guarded by a sentry object.
25 // The sentry object performs various tasks,
26 // such as thread synchronization and updating the stream state.
28 std::istream::sentry se(is, true);
29 std::streambuf * sb = is.rdbuf();
31 for (;;) {
32 int c = sb->sbumpc();
33 switch (c) {
34 case '\n':
35 return is;
36 case '\r':
37 if (sb->sgetc() == '\n')
38 sb->sbumpc();
39 return is;
40 case EOF:
41 // Also handle the case when the last line has no line ending
42 if (t.empty())
43 is.setstate(std::ios::eofbit);
44 return is;
45 default:
46 t += static_cast<char>(c);
47 break;
53 namespace marnav_test
55 void process_ais_message(const std::vector<std::unique_ptr<marnav::nmea::sentence>> & sentences)
57 using namespace marnav;
58 using namespace std;
60 // create AIS message
61 std::unique_ptr<ais::message> message;
62 try {
63 message = ais::make_message(nmea::collect_payload(sentences.begin(), sentences.end()));
64 } catch (ais::unknown_message & e) {
65 std::cout << "AIS unknown: " << e.what() << "\n";
66 return;
67 } catch (std::invalid_argument & e) {
68 std::cout << "AIS error: " << e.what() << "\n";
69 return;
72 // process the message. for this test, we only do some of them.
73 switch (message->type()) {
74 case ais::message_id::position_report_class_a:
75 std::cout << "AIS: Position report class A\n";
76 break;
77 case ais::message_id::position_report_class_a_assigned_schedule:
78 std::cout << "AIS: Position report class A (assigned schedule)\n";
79 break;
80 case ais::message_id::position_report_class_a_response_to_interrogation:
81 std::cout << "AIS: Position report class A (response to interrogation)\n";
82 break;
83 case ais::message_id::base_station_report:
84 std::cout << "AIS: Base Station Report\n";
85 break;
86 case ais::message_id::static_and_voyage_related_data:
87 std::cout << "AIS: Static and voyage related data\n";
88 break;
89 case ais::message_id::standard_sar_aircraft_position_report:
90 std::cout << "AIS: Standard SAR Aircraft Position Report\n";
91 break;
92 case ais::message_id::utc_and_date_inquiry:
93 std::cout << "AIS: UTC/Date Inquiry\n";
94 break;
95 case ais::message_id::utc_and_date_response:
96 std::cout << "AIS: UTC/Date Response\n";
97 break;
98 case ais::message_id::standard_class_b_cs_position_report:
99 std::cout << "AIS: Standard class B CS position report\n";
100 break;
101 case ais::message_id::extended_class_b_equipment_position_report:
102 std::cout << "AIS: Extended class B equipment position report\n";
103 break;
104 case ais::message_id::aid_to_navigation_report:
105 std::cout << "AIS: Aid-to-Navigation report\n";
106 break;
107 case ais::message_id::static_data_report:
108 std::cout << "AIS: Static Data Report\n";
109 break;
110 default:
111 // ignore all others
112 std::cout << "AIS: ignored, message type: " << static_cast<int>(message->type())
113 << "\n";
114 break;
119 int main(int, char **)
121 using namespace marnav;
123 std::ifstream ifs{"ais-sample.txt"};
124 std::string line;
125 std::vector<std::unique_ptr<nmea::sentence>> sentences;
127 // this function implements almost the same as examples/read_ais.cpp
129 while (stackoverflow::getline(ifs, line)) {
130 try {
131 auto sentence = nmea::make_sentence(line);
132 if (sentence->id() == nmea::sentence_id::VDM) {
133 const auto vdm = nmea::sentence_cast<nmea::vdm>(sentence);
134 const auto n_fragments = vdm->get_n_fragments();
135 const auto fragment = vdm->get_fragment();
136 sentences.push_back(std::move(sentence));
137 if (fragment == n_fragments) {
138 marnav_test::process_ais_message(sentences);
139 sentences.clear();
141 } else {
142 std::cout << "NMEA/AIS ignored: " << line << "\n";
144 } catch (nmea::unknown_sentence & e) {
145 std::cout << "NMEA unknown: " << e.what() << "\n";
146 } catch (std::runtime_error & e) {
147 std::cout << "NMEA/AIS runtime_error: " << e.what() << " for sentence: [" << line
148 << "]\n";
149 } catch (std::out_of_range & e) {
150 std::cout << "NMEA/AIS out_of_range: " << e.what() << " for sentence: [" << line
151 << "]\n";
152 } catch (std::exception & e) {
153 std::cout << "NMEA/AIS error: " << e.what() << " for sentence: [" << line << "]\n";
157 return 0;