2 #include <marnav/nmea/checks.hpp>
3 #include <marnav/nmea/io.hpp>
9 MARNAV_NMEA_DEFINE_SENTENCE_PARSE_FUNC(dsc
)
13 /// Converts data read from the NMEA string to the corresponding
15 /// @note This function already takes care about the two lowest digit
16 /// representation of the values in the string.
18 /// @param[in] value The numerical value to convert.
19 /// @return The corresponding enumerator.
20 /// @exception std::invalid_argument The specified value to convert is unknown.
22 static dsc::format_specifier
format_specifier_mapping(
23 typename
std::underlying_type
<dsc::format_specifier
>::type value
)
27 return dsc::format_specifier::geographical_area
;
29 return dsc::format_specifier::distress
;
31 return dsc::format_specifier::all_ships
;
33 return dsc::format_specifier::individual_station
;
35 throw std::invalid_argument
{"invaild value for conversion to dsc::format_specifier"};
38 /// Converts data read from the NMEA string to the corresponding
40 /// @note This function already takes care about the two lowest digit
41 /// representation of the values in the string.
43 /// @param[in] value The numerical value to convert.
44 /// @return The corresponding enumerator.
45 /// @exception std::invalid_argument The specified value to convert is unknown.
47 static dsc::category
category_mapping(typename
std::underlying_type
<dsc::category
>::type value
)
51 return dsc::category::routine
;
53 return dsc::category::safety
;
55 return dsc::category::urgency
;
57 return dsc::category::distress
;
59 throw std::invalid_argument
{"invaild value for conversion to dsc::category"};
62 /// Converts data read from the NMEA string to the corresponding
64 /// @note This function already takes care about the two lowest digit
65 /// representation of the values in the string.
67 /// @param[in] value The numerical value to convert.
68 /// @return The corresponding enumerator.
69 /// @exception std::invalid_argument The specified value to convert is unknown.
71 static dsc::acknowledgement
acknowledgement_mapping(
72 typename
std::underlying_type
<dsc::acknowledgement
>::type value
)
76 return dsc::acknowledgement::B
;
78 return dsc::acknowledgement::R
;
80 return dsc::acknowledgement::end_of_sequence
;
82 throw std::invalid_argument
{"invaild value for conversion to dsc::acknowledgement"};
85 /// Converts data read from the NMEA string to the corresponding
87 /// @note This function already takes care about the two lowest digit
88 /// representation of the values in the string.
90 /// @param[in] value The numerical value to convert.
91 /// @return The corresponding enumerator.
92 /// @exception std::invalid_argument The specified value to convert is unknown.
94 static dsc::extension_indicator
extension_indicator_mapping(
95 typename
std::underlying_type
<dsc::extension_indicator
>::type value
)
98 case 0: // works beause 'value' is default initialized in the calling 'read' function
99 return dsc::extension_indicator::none
;
101 return dsc::extension_indicator::extension_follows
;
103 throw std::invalid_argument
{"invaild value for conversion to dsc::extension_indicator"};
107 std::string
to_string(dsc::format_specifier value
)
110 case dsc::format_specifier::geographical_area
:
112 case dsc::format_specifier::distress
:
114 case dsc::format_specifier::all_ships
:
116 case dsc::format_specifier::individual_station
:
119 throw std::invalid_argument
{"invaild value for conversion of dsc::format_specifier"};
122 std::string
to_string(dsc::category value
)
125 case dsc::category::routine
:
127 case dsc::category::safety
:
129 case dsc::category::urgency
:
131 case dsc::category::distress
:
134 throw std::invalid_argument
{"invaild value for conversion of dsc::category"};
137 std::string
to_string(dsc::acknowledgement value
)
140 case dsc::acknowledgement::B
:
142 case dsc::acknowledgement::R
:
144 case dsc::acknowledgement::end_of_sequence
:
147 throw std::invalid_argument
{"invaild value for conversion of dsc::acknowledgement"};
150 std::string
to_string(dsc::extension_indicator value
)
153 case dsc::extension_indicator::none
:
155 case dsc::extension_indicator::extension_follows
:
158 throw std::invalid_argument
{"invaild value for conversion of dsc::extension_indicator"};
161 constexpr const char * dsc::TAG
;
164 : sentence(ID
, TAG
, talker_id::communications_dsc
)
168 /// @todo Read and interpret more fields
169 dsc::dsc(talker talk
, fields::const_iterator first
, fields::const_iterator last
)
170 : sentence(ID
, TAG
, talk
)
172 if (std::distance(first
, last
) != 11)
173 throw std::invalid_argument
{"invalid number of fields in dsc"};
175 read(*(first
+ 0), fmt_spec
, format_specifier_mapping
);
176 read(*(first
+ 1), address
);
177 read(*(first
+ 2), cat
, category_mapping
);
178 // @todo read other 6 data members
179 read(*(first
+ 9), ack
, acknowledgement_mapping
);
180 read(*(first
+ 10), extension
, extension_indicator_mapping
);
183 /// Valid only for format specifier other than geographical area.
184 /// However, there are no checks and special treatment, the MMSI is
185 /// simply wrong if taken with an invalid format specifier.
186 utils::mmsi
dsc::get_mmsi() const
188 return utils::mmsi
{static_cast<utils::mmsi::value_type
>(address
/ 10)};
191 /// Valid only for format specifier geographical_area.
192 /// However, there are no checks and special treatment, the data is
193 /// simply wrong if taken with an invalid format specifier.
205 /// 2. Latitude in degrees, 2 digits
206 /// 3. Longitude in degrees, 3 digits
207 /// 4. Vertical side of the rectangle (north to south) in degrees, 2 digits
208 /// 5. Horizontal side of the rectangle (west to east) in degrees, 2 digits
210 geo::region
dsc::get_geographical_area() const
212 const auto quadrant
= (address
/ 1000000000) % 10;
214 geo::latitude::hemisphere lat_hem
= geo::latitude::hemisphere::north
;
215 geo::longitude::hemisphere lon_hem
= geo::longitude::hemisphere::west
;
217 case 0: // NE quadrant
218 lat_hem
= geo::latitude::hemisphere::north
;
219 lon_hem
= geo::longitude::hemisphere::east
;
221 case 1: // NW quadrant
222 lat_hem
= geo::latitude::hemisphere::north
;
223 lon_hem
= geo::longitude::hemisphere::west
;
225 case 2: // SE quadrant
226 lat_hem
= geo::latitude::hemisphere::south
;
227 lon_hem
= geo::longitude::hemisphere::east
;
229 case 3: // SW quadrant
230 lat_hem
= geo::latitude::hemisphere::south
;
231 lon_hem
= geo::longitude::hemisphere::west
;
234 throw std::invalid_argument
{"invalid quadrant"};
237 const uint32_t lat
= static_cast<uint32_t>((address
/ 10000000) % 100);
238 const uint32_t lon
= static_cast<uint32_t>((address
/ 10000) % 1000);
239 const double d_lat
= static_cast<double>((address
/ 100) % 100);
240 const double d_lon
= static_cast<double>(address
% 100);
242 return geo::region
{{{lat
, 0, 0, lat_hem
}, {lon
, 0, 0, lon_hem
}}, d_lat
, d_lon
};
245 /// @todo Implementation
247 std::vector
<std::string
> dsc::get_data() const
250 to_string(fmt_spec
), format(address
, 10), to_string(cat
), "", "", "", "", "", "",
251 to_string(ack
), to_string(extension
),