NMEA: detectio of the optional tag block in front of a sentence, ignoring it for...
[marnav.git] / src / marnav / ais / message.hpp
blob4761889e53f1f24c8698b5d0ca4a54830cbf761b
1 #ifndef __MARNAV__AIS__MESSAGE__HPP__
2 #define __MARNAV__AIS__MESSAGE__HPP__
4 #include <memory>
5 #include <string>
6 #include <marnav/ais/binary_data.hpp>
8 namespace marnav
10 namespace ais
13 /// All known AIS message IDs.
14 enum class message_id : uint8_t {
15 NONE = 0,
16 position_report_class_a = 1,
17 position_report_class_a_assigned_schedule = 2,
18 position_report_class_a_response_to_interrogation = 3,
19 base_station_report = 4,
20 static_and_voyage_related_data = 5,
21 binary_addressed_message = 6,
22 binary_acknowledge = 7,
23 binary_broadcast_message = 8,
24 standard_sar_aircraft_position_report = 9,
25 utc_and_date_inquiry = 10,
26 utc_and_date_response = 11,
27 addressed_safety_related_message = 12,
28 safety_related_acknowledgement_ = 13,
29 safety_related_broadcast_message = 14,
30 interrogation = 15,
31 assignment_mode_command = 16,
32 dgnss_binary_broadcast_message = 17,
33 standard_class_b_cs_position_report = 18,
34 extended_class_b_equipment_position_report = 19,
35 data_link_management = 20,
36 aid_to_navigation_report = 21,
37 channel_management = 22,
38 group_assignment_command = 23,
39 static_data_report = 24,
40 single_slot_binary_message = 25,
41 multiple_slot_binary_message_with_communications_state = 26,
42 position_report_for_long_range_applications = 27,
45 enum class navigation_status : uint8_t {
46 under_way_using_engine = 0,
47 at_anchor = 1,
48 not_under_command = 2,
49 restricted_maneuverability = 3,
50 constrained_by_her_draught = 4,
51 moored = 5,
52 aground = 6,
53 engaged_in_Fishing = 7,
54 under_way_sailing = 8,
55 reserved_09 = 9,
56 reserved_10 = 10,
57 reserved_11 = 11,
58 reserved_12 = 12,
59 reserved_13 = 13,
60 ais_sart_is_active = 14,
61 not_defined = 15, // default
64 enum class ship_type : uint8_t {
65 not_available = 0,
66 // 1..19 reserved for future use
67 wing_in_ground = 20,
68 wing_in_ground_hazardous_cat_a = 21,
69 wing_in_ground_hazardous_cat_b = 22,
70 wing_in_ground_hazardous_cat_c = 23,
71 wing_in_ground_hazardous_cat_d = 24,
72 // 25..29 WIG reserved for future use
73 fishing = 30,
74 towing = 31,
75 towing_large = 32, // exceeds 200m length or 25m breadth
76 dredging_or_underwater_ops = 33,
77 diving_ops = 34,
78 military_ops = 35,
79 sailing = 36,
80 pleasure_craft = 37,
81 // 38..39 reserved
82 high_speed_craft = 40,
83 high_speed_craft_hazardous_cat_a = 41,
84 high_speed_craft_hazardous_cat_b = 42,
85 high_speed_craft_hazardous_cat_c = 43,
86 high_speed_craft_hazardous_cat_d = 44,
87 // 45..48 HSC reserved for future use
88 high_speed_craft_no_info = 49,
89 pilot_vessel = 50,
90 search_and_rescue_vessel = 51,
91 tug = 52,
92 port_tender = 53,
93 anti_pollution_equipment = 54,
94 law_enforcement = 55,
95 // 56..57 spare, local vessel
96 medical_transport = 58,
97 noncombatant = 59,
98 passenger = 60,
99 passenger_hazardous_cat_a = 61,
100 passenger_hazardous_cat_b = 62,
101 passenger_hazardous_cat_c = 63,
102 passenger_hazardous_cat_d = 64,
103 // 65..68 Passenger reserved for future use
104 passenger_no_info = 69,
105 cargo = 70,
106 cargo_hazardous_cat_a = 71,
107 cargo_hazardous_cat_b = 72,
108 cargo_hazardous_cat_c = 73,
109 cargo_hazardous_cat_d = 74,
110 // 75..78 Cargo reserved for future use
111 cargo_no_info = 79,
112 tanker = 80,
113 tanker_hazardous_cat_a = 81,
114 tanker_hazardous_cat_b = 82,
115 tanker_hazardous_cat_c = 83,
116 tanker_hazardous_cat_d = 84,
117 // 85..88 Tanker reserved for future use
118 tanker_no_info = 89,
119 other = 90,
120 other_hazardous_cat_a = 91,
121 other_hazardous_cat_b = 92,
122 other_hazardous_cat_c = 93,
123 other_hazardous_cat_d = 94,
124 // 95..98 Other type reserved for future use
125 other_no_info = 99,
128 /// Electronic Position Fixing Device
129 enum class epfd_fix_type : uint8_t {
130 undefined = 0,
131 gps = 1,
132 glonass = 2,
133 combined_gps_glonass = 3,
134 loran_c = 4,
135 chayka = 5,
136 integrated_navigation_system = 6,
137 surveyed = 7,
138 galileo = 8,
141 /// Enumeration of data terminal status.
142 enum class data_terminal : uint8_t { ready = 0, not_ready = 1 };
144 enum class virtual_aid : uint32_t { real_aid = 0, virtual_aid = 1 };
146 enum class off_position_indicator : uint32_t { on_position = 0, off_position = 1 };
148 /// Enumeration of all aid types
149 enum class aid_type_id : uint32_t {
150 /// 0 : Default, Type of Aid to Navigation not specified
151 unspecified = 0,
153 /// 1 : Reference point
154 reference_point = 1,
156 /// 2 : RACON (radar transponder marking a navigation hazard)
157 racon = 2,
159 /// 3 : Fixed structure off shore, such as oil platforms, wind farms, rigs. (Note: This
160 /// code should identify an obstruction that is fitted with an Aid-to-Navigation AIS
161 /// station.)
162 fixed_structure = 3,
164 /// 4 : Spare, Reserved for future use.
165 reserved = 4,
167 /// 5 : Light, without sectors
168 light_no_sectors = 5,
170 /// 6 : Light, with sectors
171 light_sectors = 6,
173 /// 7 : Leading Light Front
174 leading_light_fromt = 7,
176 /// 8 : Leading Light Rear
177 leading_light_rear = 8,
179 /// 9 : Beacon, Cardinal N
180 beacon_cardinal_n = 9,
182 /// 10: Beacon, Cardinal E
183 beacon_cardinal_e = 10,
185 /// 11: Beacon, Cardinal S
186 beacon_cardinal_s = 11,
188 /// 12: Beacon, Cardinal W
189 beacon_cardinal_w = 12,
191 /// 13: Beacon, Port hand
192 beacon_port_hand = 13,
194 /// 14: Beacon, Starboard hand
195 beacon_starboard_hand = 14,
197 /// 15: Beacon, Preferred Channel port hand
198 beacon_preferred_channel_port_hand = 15,
200 ///< 16: Beacon, Preferred Channel starboard hand
201 beacon_preferred_channel_starboard_hand = 16,
203 /// 17: Beacon, Isolated danger
204 beacon_isolated_danger = 17,
206 /// 18: Beacon, Safe water
207 beacon_safe_water = 18,
209 /// 19: Beacon, Special mark
210 beacon_sepcial_mark = 19,
212 /// 20: Cardinal Mark N
213 cardinal_n = 20,
215 /// 21: Cardinal Mark E
216 cardinal_e = 21,
218 /// 22: Cardinal Mark S
219 cardinal_s = 22,
221 /// 23: Cardinal Mark W
222 cardinal_w = 23,
224 /// 24: Port hand Mark
225 mark_port_hand = 24,
227 /// 25: Starboard hand Mark
228 mark_starboard_hand = 25,
230 /// 26: Preferred Channel Port hand
231 preferred_channel_port_hand = 26,
233 /// 27: Preferred Channel Starboard hand
234 preferred_channel_starboard_hand = 27,
236 /// 28: Isolated danger
237 isolated_danger = 28,
239 /// 29: Safe Water
240 safe_water = 29,
242 /// 30: Special Mark
243 special_mark = 30,
245 /// 31: Light Vessel / LANBY / Rigs
246 light_vessel = 31,
250 enum class maneuver_indicator_id : uint32_t { not_available = 0, normal = 1, special = 2 };
252 // AIS data is coded in a binary form. This implies a need for special
253 // value that mark the invalidity of a certain value.
254 /// @{
256 /// Value for a longitude that is not specified.
257 constexpr static const uint32_t longitude_not_available = 0x6791AC0;
259 /// Value for a latitude that is not specified.
260 constexpr static const uint32_t latitude_not_available = 0x3412140;
262 /// Value for a longitude that is not specified, short version.
263 constexpr static const uint32_t longitude_not_available_short = 0x1a838;
265 /// Value for a latitude that is not specified, short version.
266 constexpr static const uint32_t latitude_not_available_short = 0xd548;
268 /// Value for a speed over ground that is not specified.
269 constexpr static const uint32_t sog_not_available = 1023;
271 /// Value for a course over ground that is not specified.
272 constexpr static const uint32_t cog_not_available = 3600;
274 /// Value for a heading that is not specified.
275 constexpr static const uint32_t hdg_not_available = 511;
277 /// Value for a rate of turn that is not specified.
278 constexpr static const int32_t rot_not_available = 128;
280 /// Value to indicate the absense of a timestamp.
281 constexpr static const uint8_t timestamp_not_available = 60;
283 /// Value for a year that is not specified.
284 constexpr static const uint32_t year_not_available = 0;
286 /// Value for a month that is not specified.
287 constexpr static const uint32_t month_not_available = 0;
289 /// Value for a day that is not specified.
290 constexpr static const uint32_t day_not_available = 0;
292 /// Value for a hour that is not specified.
293 constexpr static const uint32_t hour_not_available = 24;
295 /// Value for a minute that is not specified.
296 constexpr static const uint32_t minute_not_available = 60;
298 /// Value for a second that is not specified.
299 constexpr static const uint32_t second_not_available = 60;
301 /// @}
303 /// @brief Base class for all AIS messages.
304 class message : public binary_data
306 friend std::vector<std::pair<std::string, uint32_t>> encode_message(const message & msg);
308 public:
309 virtual ~message() = default;
310 message() = delete;
311 message(const message &) = default;
312 message & operator=(const message &) = default;
313 message(message &&) = default;
314 message & operator=(message &&) = default;
316 message_id type() const { return message_type; }
318 protected:
319 explicit message(message_id type)
320 : message_type(type)
324 virtual raw get_data() const = 0;
326 private:
327 message_id message_type;
330 /// Helper function to parse a specific sentence.
331 template <class T> std::unique_ptr<message> message_parse(const raw & bits)
333 return std::unique_ptr<T>(new T{bits});
336 /// @cond DEV
337 namespace detail
339 /// Checks if the specified cast is valid, throws `bad_cast` if not.
340 /// If the pointer is `nullptr`, false returns.
341 template <class T> bool check_cast(const message * s)
343 if (!s)
344 return false;
345 if (s->type() != T::ID)
346 throw std::bad_cast{};
347 return true;
350 /// @endcond
352 /// @{
354 /// Casts the specified message to the message given by the template parameter.
355 /// The object converted only if it is valid and of the correct type. It is not
356 /// possible to cast a message into a completley different one.
358 /// @param[in] s The message object to convert.
359 /// @retval nullptr The specified message is invalid.
360 /// @return The converted message.
361 /// @exception std::bad_cast The specified message has the wrong ID.
362 template <class T> T * message_cast(message * s)
364 return detail::check_cast<T>(s) ? static_cast<T *>(s) : nullptr;
367 /// Raw pointer const variant.
369 /// @see message_cast(message * s)
370 template <class T> const T * message_cast(const message * s)
372 return detail::check_cast<T>(s) ? static_cast<const T *>(s) : nullptr;
375 /// `std::unique_ptr` variant. If the cast is possible, the original `unique_ptr<message>`
376 /// will be invalidated and a new `unique_ptr<T>` will be returned. This has implications
377 /// within the calling code.
379 /// @param[in,out] s The message to cast.
380 /// @return The casted message. If the specified sentence was `nullptr`, the function
381 /// also returns `nullptr`.
382 /// @exception bad_cast This exception is thrown if the specified message is
383 /// not castable into the destination type `T`.
385 template <class T> std::unique_ptr<T> message_cast(std::unique_ptr<message> & s)
387 return detail::check_cast<T>(s.get()) ? std::unique_ptr<T>(static_cast<T *>(s.release()))
388 : nullptr;
391 /// `unique_ptr` ref ref variant.
393 /// @see message_cast(std::unique_ptr<message> & s)
394 template <class T> std::unique_ptr<T> message_cast(std::unique_ptr<message> && s)
396 return detail::check_cast<T>(s.get()) ? std::unique_ptr<T>(static_cast<T *>(s.release()))
397 : nullptr;
400 /// @}
402 /// @cond DEV
404 #define MARNAV_AIS_MESSAGE_FRIENDS(s) \
405 friend std::unique_ptr<message> detail::parse_##s(const raw & bits); \
406 template <class T> friend std::unique_ptr<message> message_parse(const raw & bits);
408 #define MARNAV_AIS_DECLARE_MESSAGE_PARSE_FUNC(s) \
409 namespace detail \
411 std::unique_ptr<message> parse_##s(const raw & bits); \
414 #define MARNAV_AIS_DEFINE_MESSAGE_PARSE_FUNC(s) \
415 namespace detail \
417 std::unique_ptr<message> parse_##s(const raw & bits) \
419 return std::unique_ptr<s>(new s{bits}); \
423 /// @endcond
427 #endif