1 #ifndef MARNAV__AIS__MESSAGE__HPP
2 #define MARNAV__AIS__MESSAGE__HPP
6 #include <marnav/ais/binary_data.hpp>
13 /// All known AIS message IDs.
14 enum class message_id
: uint8_t {
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,
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,
48 not_under_command
= 2,
49 restricted_maneuverability
= 3,
50 constrained_by_her_draught
= 4,
53 engaged_in_Fishing
= 7,
54 under_way_sailing
= 8,
60 ais_sart_is_active
= 14,
61 not_defined
= 15, // default
64 enum class ship_type
: uint8_t {
66 // 1..19 reserved for future use
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
75 towing_large
= 32, // exceeds 200m length or 25m breadth
76 dredging_or_underwater_ops
= 33,
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,
90 search_and_rescue_vessel
= 51,
93 anti_pollution_equipment
= 54,
95 // 56..57 spare, local vessel
96 medical_transport
= 58,
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,
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
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
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
128 /// Electronic Position Fixing Device
129 enum class epfd_fix_type
: uint8_t {
133 combined_gps_glonass
= 3,
136 integrated_navigation_system
= 6,
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
153 /// 1 : Reference point
156 /// 2 : RACON (radar transponder marking a navigation hazard)
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
164 /// 4 : Spare, Reserved for future use.
167 /// 5 : Light, without sectors
168 light_no_sectors
= 5,
170 /// 6 : Light, with sectors
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
215 /// 21: Cardinal Mark E
218 /// 22: Cardinal Mark S
221 /// 23: Cardinal Mark W
224 /// 24: Port hand Mark
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,
245 /// 31: Light Vessel / LANBY / Rigs
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.
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 to indicate the absense of a timestamp.
278 constexpr static const uint8_t timestamp_not_available
= 60;
280 /// Value for a year that is not specified.
281 constexpr static const uint32_t year_not_available
= 0;
283 /// Value for a month that is not specified.
284 constexpr static const uint32_t month_not_available
= 0;
286 /// Value for a day that is not specified.
287 constexpr static const uint32_t day_not_available
= 0;
289 /// Value for a hour that is not specified.
290 constexpr static const uint32_t hour_not_available
= 24;
292 /// Value for a minute that is not specified.
293 constexpr static const uint32_t minute_not_available
= 60;
295 /// Value for a second that is not specified.
296 constexpr static const uint32_t second_not_available
= 60;
300 /// @brief Base class for all AIS messages.
301 class message
: public binary_data
303 friend std::vector
<std::pair
<std::string
, uint32_t>> encode_message(const message
& msg
);
306 virtual ~message() = default;
308 message(const message
&) = default;
309 message
& operator=(const message
&) = default;
310 message(message
&&) = default;
311 message
& operator=(message
&&) = default;
313 message_id
type() const { return message_type
; }
316 explicit message(message_id type
)
321 virtual raw
get_data() const = 0;
324 message_id message_type
;
330 /// Checks if the specified cast is valid, throws `bad_cast` if not.
331 /// If the pointer is `nullptr`, false returns.
332 template <class T
> bool check_cast(const message
* s
)
336 if (s
->type() != T::ID
)
337 throw std::bad_cast
{};
345 typename
std::enable_if
<std::is_base_of
<message
, T
>::value
, int>::type
= 0>
346 static std::unique_ptr
<message
> parse(const raw
& bits
)
348 return std::unique_ptr
<T
>(new T
{bits
});
354 /// Helper function to parse a specific message, to be used in unit tests.
356 /// @todo This breaks encapsulation.
357 template <class T
, typename
std::enable_if
<std::is_base_of
<message
, T
>::value
, int>::type
= 0>
358 std::unique_ptr
<message
> message_parse(const raw
& bits
)
360 return detail::factory::parse
<T
>(bits
);
365 /// Casts the specified message to the message given by the template parameter.
366 /// The object converted only if it is valid and of the correct type. It is not
367 /// possible to cast a message into a completley different one.
369 /// @param[in] s The message object to convert.
370 /// @retval nullptr The specified message is invalid.
371 /// @return The converted message.
372 /// @exception std::bad_cast The specified message has the wrong ID.
373 template <class T
> T
* message_cast(message
* s
)
375 return detail::check_cast
<T
>(s
) ? static_cast<T
*>(s
) : nullptr;
378 /// Raw pointer const variant.
380 /// @see message_cast(message * s)
381 template <class T
> const T
* message_cast(const message
* s
)
383 return detail::check_cast
<T
>(s
) ? static_cast<const T
*>(s
) : nullptr;
386 /// `std::unique_ptr` variant. If the cast is possible, the original `unique_ptr<message>`
387 /// will be invalidated and a new `unique_ptr<T>` will be returned. This has implications
388 /// within the calling code.
390 /// @param[in,out] s The message to cast.
391 /// @return The casted message. If the specified sentence was `nullptr`, the function
392 /// also returns `nullptr`.
393 /// @exception bad_cast This exception is thrown if the specified message is
394 /// not castable into the destination type `T`.
396 template <class T
> std::unique_ptr
<T
> message_cast(std::unique_ptr
<message
> & s
)
398 return detail::check_cast
<T
>(s
.get()) ? std::unique_ptr
<T
>(static_cast<T
*>(s
.release()))
402 /// `unique_ptr` ref ref variant.
404 /// @see message_cast(std::unique_ptr<message> & s)
405 template <class T
> std::unique_ptr
<T
> message_cast(std::unique_ptr
<message
> && s
)
407 return detail::check_cast
<T
>(s
.get()) ? std::unique_ptr
<T
>(static_cast<T
*>(s
.release()))