Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add nrx (Navtex) sentence #54

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
b23316e
NRX sentence added
apidemy Apr 6, 2023
60acc39
Initial test added
apidemy Apr 6, 2023
76a5e9a
NRX sentence refactored; Tests for NRX completed
apidemy Apr 7, 2023
16835a1
NRX added to Benchmark_nmea_sentence; NRX headers refactored
apidemy Apr 7, 2023
679f631
Fixing message code value in NRX sentence
apidemy Apr 28, 2023
6b06528
NRX (Navtex) sentence added to nmeatool
apidemy Apr 28, 2023
d9014cf
Converting special characters in NRX message removed; It's not librar…
apidemy Apr 28, 2023
2bfc748
Navtex (NRX) message is usually sequential and subsequence message ar…
apidemy Apr 28, 2023
358339d
Refactoring nrx members to maintain consistency
apidemy May 25, 2023
ec238c5
Update include/marnav/nmea/constants.hpp
apidemy May 25, 2023
e8695a6
Update src/marnav/nmea/string.cpp
apidemy May 25, 2023
5aafd79
Update test/CMakeLists.txt
apidemy May 25, 2023
753b9be
Update src/marnav/nmea/nrx.cpp
apidemy May 25, 2023
0739ece
Update include/marnav/nmea/nrx.hpp
apidemy May 25, 2023
c15621f
Update include/marnav/nmea/nrx.hpp
apidemy May 25, 2023
68471a1
Update include/marnav/nmea/nrx.hpp
apidemy May 25, 2023
39a2ac1
Update src/marnav/nmea/nrx.cpp
apidemy May 25, 2023
ea967e1
NMEA: fix nrx members type; lowercase frequency_index
apidemy May 25, 2023
d3d6a0d
NRX: combine multiple test into one complete sample sentence test
apidemy May 25, 2023
9bdd25b
Fix set_message in nrx to prevent setting arbitrary message
apidemy Jun 5, 2023
c454b89
Add examples/parse_nrx sample sentenc
apidemy Jun 5, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ Supported sentences for NMEA-0183 (read and write):
- MTW: Mean Temperature of Water
- MWD: Wind Direction and Speed
- MWV: Wind Speed and Angle
- NRX: Navtex message - global maritime safety information
- OSD: Own Ship Data
- RMA: Recommended Minimum Navigation Information
- RMB: Recommended Minimum Navigation Information
Expand Down Expand Up @@ -541,6 +542,7 @@ A (non-complete) collection of resources from where information was gathered.
- [DSC Position Request](http://www.thehulltruth.com/marine-electronics-forum/43945-dsc-position-request.html)
- [NMEA-0183 Sentences DSC,DSE](http://www.cruisersforum.com/forums/f13/nmea-0183-sentences-dsc-dse-124887.html)
- [NMEA-0183 Sentence ALR](https://www.cruisersforum.com/forums/f134/opencpn-and-external-nmea0183-alarms-81396.html)
- [NMEA-0183 Sentence NRX (Navtex)](https://www.pentestpartners.com/security-blog/hacking-navtex-maritime-warning-messages/)
- [SerialMon - NMEA 0183 Protocol](http://www.serialmon.com/protocols/nmea0183.html)
- [SeaTalk Reference](http://thomasknauf.de/seatalk.htm) (by Thomas Knauf)
- [Navigation Center - AIS Standard Class B Equipment Position Report](http://www.navcen.uscg.gov/?pageName=AISMessagesB)
Expand Down
1 change: 1 addition & 0 deletions doc/nmea.dox
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Supported sentences for NMEA-0183 (read and write):
- \link marnav::nmea::mtw \c MTW \endlink : Mean Temperature of Water
- \link marnav::nmea::mwd \c MWD \endlink : Wind Direction and Speed
- \link marnav::nmea::mwv \c MWV \endlink : Wind Speed and Angle
- \link marnav::nmea::nrx \c NRX \endlink : Navtex message - global maritime safety information
- \link marnav::nmea::osd \c OSD \endlink : Own Ship Data
- \link marnav::nmea::rma \c RMA \endlink : Recommended Minimum Navigation Information
- \link marnav::nmea::rmb \c RMB \endlink : Recommended Minimum Navigation Information
Expand Down
3 changes: 3 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ target_link_libraries(create_nmea_from_ais_2 marnav::marnav)
add_executable(parse_ais parse_ais.cpp)
target_link_libraries(parse_ais marnav::marnav)

add_executable(parse_nrx parse_nrx.cpp)
target_link_libraries(parse_nrx marnav::marnav)

if(NOT MSVC)
add_executable(select select.cpp)
target_link_libraries(select marnav::marnav)
Expand Down
62 changes: 62 additions & 0 deletions examples/parse_nrx.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include <marnav/nmea/nmea.hpp>
#include <marnav/nmea/nrx.hpp>
#include <iostream>
#include <vector>

int main(int, char **)
{
using namespace marnav;

// received NMEA sentences
// const std::vector<std::string> received_strings = {
// "$CRNRX,007,001,00,IE69,1,135600,27,06,2001,241,3,A,==========================*09",
// "$CRNRX,007,002,00,,,,,,,,,,========^0D^0AISSUED ON SATURDAY 06 JANUARY 2001.*29",
// "$CRNRX,007,003,00,,,,,,,,,,^0D^0AINSHORE WATERS FORECAST TO 12 MILES^0D^0AOFF*0D",
// "$CRNRX,007,004,00,,,,,,,,,,SHORE FROM 1700 UTC TO 0500 UTC.^0D^0A^0D^0ANORT*1E",
// "$CRNRX,007,005,00,,,,,,,,,,H FORELAND TO SELSEY BILL.^0D^0A12 HOURS FOREC*09",
// "$CRNRX,007,006,00,,,,,,,,,,AST:^0D^0A^0ASHOWERY WINDS^2C "
// "STRONGEST IN NORTH.^0D*16",
// "$CRNRX,007,007,00,,,,,,,,,,^0A^0A*79",
// };

const std::vector<std::string> received_strings
= {"$CRNRX,011,001,15,IB45,2,,,,,426,0,A,IB45 ^0D^0A260909 UTC MAR 07^0D^0AWWJP83 *21",
"$CRNRX,011,002,15,,,,,,,,,,RJTD 260600^0D^0AVITAL WARNING FOR YOKOHAMA NAVTEX*00",
"$CRNRX,011,003,15,,,,,,,,,, AREA ^0D^0A260600UTC ISSUED AT 260900UTC^0D^0ACOLD*4A",
"$CRNRX,011,004,15,,,,,,,,,, FRONT FROM 48N 157E T O 42N 156E 36N^0D^0A 151E 30*23",
"$CRNRX,011,005,15,,,,,,,,,,N 147E 25N 140E^0D^0AGALE WARNING WESTERN SEA OFF *6C",
"$CRNRX,011,006,15,,,,,,,,,,SANRIKU ^0D^0AWITH MAX WINDS 35 KNOTS^0D^0AWARNING*12",
"$CRNRX,011,007,15,,,,,,,,,,(NEAR GALE) EASTERN SEA OFF^0D^0ASANRIKU^2C NORTH*32",
"$CRNRX,011,008,15,,,,,,,,,,ERN SEA OFF KANTO^2C^0D^0ASOUTHERN SEA OFF KANTO*0A",
"$CRNRX,011,009,15,,,,,,,,,,^2C EASTERN SEA OFF ^0D^0ATOKAI^0D^0ANEXT WARNING *0C",
"$CRNRX,011,010,15,,,,,,,,,,WILL BE ISSUED BEFORE ^0D^0A261500UTC^0D^0A=^0D^0A*1B",
"$CRNRX,011,011,15,,,,,,,,,,^0D^0ANNNN^0D^0A *5D"};

// parse NMEA sentences
std::vector<std::unique_ptr<nmea::sentence>> sentences;
for (auto const & txt : received_strings) {
auto sentence = nmea::make_sentence(txt);
if (sentence->id() == nmea::sentence_id::NRX) {
sentences.push_back(std::move(sentence));
}
}

// parse and process NRX messags
uint32_t last_sequence = 0;
std::for_each(std::begin(sentences), std::end(sentences),
[&](std::unique_ptr<nmea::sentence> & sentence) {
auto nrx = nmea::sentence_cast<nmea::nrx>(sentence);

if (last_sequence + 1 != nrx->get_sentence_number()) {
std::cout << "invalid sequence" << std::endl;
return;
}

last_sequence = nrx->get_sentence_number();
if (nrx->get_message().has_value()) {
std::cout << nrx->get_parsed_message().value_or("");
}
});

return 0;
}
7 changes: 7 additions & 0 deletions include/marnav/nmea/constants.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@ enum class type_of_point : char {
reference, ///< NMEA representation: 'R'
wheelover, ///< NMEA representation: 'W'
};

enum class frequency_index : uint8_t {
not_received_over_air = 0, ///< NMEA representation: 0
f_490_khz = 1, ///< NMEA representation: 1 = 490 kHz
f_518_khz = 2, ///< NMEA representation: 2 = 518 kHz
f_4209_5_khz = 3, ///< NMEA representation: 3 = 4209.5 kHz
};
}

#endif
2 changes: 2 additions & 0 deletions include/marnav/nmea/io.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ void read(const std::string & s, duration & value, data_format fmt = data_format
void read(const std::string & s, char & value, data_format fmt = data_format::none);
void read(const std::string & s, uint64_t & value, data_format fmt = data_format::dec);
void read(const std::string & s, uint32_t & value, data_format fmt = data_format::dec);
void read(const std::string & s, uint16_t & value, data_format fmt = data_format::dec);
void read(const std::string & s, uint8_t & value, data_format fmt = data_format::dec);
void read(const std::string & s, int32_t & value, data_format fmt = data_format::dec);
void read(const std::string & s, double & value, data_format fmt = data_format::none);
Expand All @@ -125,6 +126,7 @@ void read(const std::string & s, route_mode & value, data_format fmt = data_form
void read(const std::string & s, selection_mode & value, data_format fmt = data_format::none);
void read(const std::string & s, ais_channel & value, data_format fmt = data_format::none);
void read(const std::string & s, type_of_point & value, data_format fmt = data_format::none);
void read(const std::string & s, frequency_index & value, data_format fmt = data_format::none);
void read(const std::string & s, direction & value, data_format fmt = data_format::none);
void read(const std::string & s, reference & value, data_format fmt = data_format::none);
void read(const std::string & s, mode_indicator & value, data_format fmt = data_format::none);
Expand Down
131 changes: 131 additions & 0 deletions include/marnav/nmea/nrx.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
#ifndef MARNAV_NMEA_NRX_HPP
#define MARNAV_NMEA_NRX_HPP

#include "marnav/nmea/date.hpp"
#include "marnav/nmea/sentence.hpp"
#include "marnav/nmea/time.hpp"

#include <optional>

namespace marnav::nmea
{
/// @brief NRX - Navtex message: global maritime safety information
///
/// @code
/// 1 2 3 4 56789 10 11 12 13
/// | | | | ||||| | | | |
/// $--NRX,XXX,XXX,XX,aaXX,X,,,,,X.X,X.X,A,c-----c*hh<CR> <LF>
/// @endcode
///
/// Field Number:
/// 1. Number of sentences 001 – 999
/// 2. Sentence number 001 – 999
/// 3. Sequential message number 00 – 99 ( used to uniquely identify messages of same ID )
/// 4. NAVTEX message ID characters (B1, B2 , B3 , B4)
/// - B1 = Transmitter identity (alphabet)
/// - B2 = Subject indicator (alphabet)
/// - B3&B4 = Serial number of the subject indicator (integeral)
/// 5. Frequency index
/// - 0 = Not received over air
/// - 1 = 490 kHz
/// - 2 = 518 kHz
/// - 3 = 4209.5 kHz
/// 6. UTC
/// 7. Day
/// 8. Month
/// 9. Year
/// 10. Total number of characters in this series of NRX sentences
/// 11. Total number of bad characters
/// 12. Status
/// - A = Data Valid
/// - V = Invalid
/// 13. Message body (first line o f message text characters)
///
/// Example:
/// @code
/// $CRNRX,007,001,00,TD02,1,135600,27,06,2001,241,3,A,==========================*18
/// $CRNRX,007,002,00,,,,,,,,,,========^0D^0AISSUED ON SATURDAY 06 JANUARY 2001.*29
/// $CRNRX,007,003,00,,,,,,,,,,^0D^0AINSHORE WATERS FORECAST TO 12 MILES^0D^0AOFF*0D
/// $CRNRX,007,004,00,,,,,,,,,,SHORE FROM 1700 UTC TO 0500 UTC.^0D^0A^0D^0ANORT*1E
/// $CRNRX,007,005,00,,,,,,,,,,H FORELAND TO SELSEY BILL.^0D^0A12 HOURS FOREC*09
/// $CRNRX,007,006,00,,,,,,,,,,AST:^0D^0A^0ASHOWERY WINDS^2C STRONGEST IN NORTH.^0D*16
/// $CRNRX,007,007,00,,,,,,,,,,^0A^0A*79
/// @endcode
///
/// @note The data characters in fields 4 to 12 are output in the first message
/// line only; they are null fields in the subsequent message lines

class nrx : public sentence
{
friend class detail::factory;

public:
constexpr static sentence_id ID = sentence_id::NRX;
constexpr static const char * TAG = "NRX";

struct message_code {
char b1_transmitter_identity = '\0';
char b2_subject_indicator = '\0';
uint32_t b3_b4_serial = 0u;
};

nrx();
nrx(const nrx &) = default;
nrx & operator=(const nrx &) = default;
nrx(nrx &&) = default;
nrx & operator=(nrx &&) = default;

protected:
nrx(talker talk, fields::const_iterator first, fields::const_iterator last);
void append_data_to(std::string &, const version &) const override;

private:
uint32_t number_sentences_;
uint32_t sentence_number_;
int sequential_id_;
std::optional<message_code> message_code_;
std::optional<frequency_index> frequency_index_;
std::optional<time> time_utc_;
std::optional<date> date_;
std::optional<uint32_t> total_characters_;
std::optional<uint32_t> total_bad_characters_;
std::optional<status> status_;
std::optional<std::string> message_;

public:
uint32_t get_number_sentences() const { return number_sentences_; };
uint32_t get_sentence_number() const { return sentence_number_; };
uint32_t get_sequential_id() const { return sequential_id_; };
std::optional<message_code> get_message_code() const { return message_code_; };
std::optional<frequency_index> get_frequency_index() const { return frequency_index_; };
std::optional<time> get_time_utc() const { return time_utc_; };
std::optional<date> get_utc_date() const { return date_; };
std::optional<uint32_t> get_total_characters() const { return total_characters_; };
std::optional<uint32_t> get_total_bad_characters() const { return total_bad_characters_; };
std::optional<status> get_status() const { return status_; };
std::optional<std::string> get_message() const { return message_; };

/**
* @brief Return parsed reserved charachters which is showable (on screen)
* @return
*/
std::optional<std::string> get_parsed_message() const;

void set_number_sentences(uint32_t value) { number_sentences_ = value; }
void set_sentence_number(uint32_t value) { sentence_number_ = value; }
void set_sequential_id(uint32_t value) { sequential_id_ = value; }
void set_message_code(const message_code & t) noexcept { message_code_ = t; }
void set_frequency_index(frequency_index t) noexcept { frequency_index_ = t; }
void set_time_utc(const time & t) noexcept { time_utc_ = t; }
void set_date(const date & t) noexcept { date_ = t; }
void set_total_characters(uint32_t t) noexcept { total_characters_ = t; }
void set_total_bad_characters(uint32_t t) noexcept { total_bad_characters_ = t; }
void set_status(status s) noexcept { status_ = s; }
void set_message(const std::string & m);

private:
std::optional<message_code> fill_message_code(const std::string & m) const;
void check() const;
};
}
#endif // MARNAV_NMEA_NRX_HPP
1 change: 1 addition & 0 deletions include/marnav/nmea/sentence_id.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ enum class sentence_id : uint32_t {
MTW, ///< Mean Temperature of Water (II)
MWD, ///< Wind Directinon and Speed
MWV, ///< Wind Speed and Angle (II)
NRX, ///< Navtext message - global maritime safety information>
OSD, ///< Own Ship Data
RMA, ///< Recommended Minimum Navigation Information
RMB, ///< Recommended Minimum Navigation Information
Expand Down
1 change: 1 addition & 0 deletions include/marnav/nmea/string.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ std::string to_string(route_mode t);
std::string to_string(selection_mode t);
std::string to_string(ais_channel t);
std::string to_string(type_of_point t);
std::string to_string(frequency_index t);
std::string to_string(direction t);
std::string to_string(reference t);
std::string to_string(mode_indicator t);
Expand Down
1 change: 1 addition & 0 deletions include/marnav/nmea/talker_id.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ enum class talker {
computer_memory,
communications_satellite,
communications_mfhf,
communications_telex,
communications_vhf,
communications_scanning_receiver,
decca_navigation,
Expand Down
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ target_sources(marnav
marnav/nmea/mwv.cpp
marnav/nmea/name.cpp
marnav/nmea/nmea.cpp
marnav/nmea/nrx.cpp
marnav/nmea/osd.cpp
marnav/nmea/pgrme.cpp
marnav/nmea/pgrmm.cpp
Expand Down
29 changes: 29 additions & 0 deletions src/marnav/nmea/io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,13 @@ void read(const std::string & s, uint32_t & value, data_format fmt)
detail::read_integer(s, value, fmt);
}

void read(const std::string & s, uint16_t & value, data_format fmt)
{
uint32_t tmp{};
detail::read_integer(s, tmp, fmt);
value = tmp;
}

void read(const std::string & s, uint8_t & value, data_format fmt)
{
uint32_t tmp = {};
Expand Down Expand Up @@ -324,6 +331,28 @@ void read(const std::string & s, type_of_point & value, data_format fmt)
}
}

void read(const std::string & s, frequency_index & value, data_format fmt)
{
std::underlying_type_t<frequency_index> t;
read(s, t, fmt);
switch (t) {
case 0:
value = frequency_index::not_received_over_air;
break;
case 1:
value = frequency_index::f_490_khz;
break;
case 2:
value = frequency_index::f_518_khz;
break;
case 3:
value = frequency_index::f_4209_5_khz;
break;
default:
throw std::runtime_error{"invalid data for nmea/frequency_index"};
}
}

void read(const std::string & s, direction & value, data_format fmt)
{
typename std::underlying_type<direction>::type t;
Expand Down
4 changes: 4 additions & 0 deletions src/marnav/nmea/name.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ std::string to_name(sentence_id t)
return "Mean Temperature of Water (II)";
case sentence_id::MWV:
return "Wind Speed and Angle (II)";
case sentence_id::NRX:
return "Navtex";
case sentence_id::OSD:
return "Own Ship Data";
case sentence_id::RMA:
Expand Down Expand Up @@ -304,6 +306,8 @@ std::string to_name(talker t)
return "Satellite Telephone";
case talker::communications_mfhf:
return "Radio-Telephone (MF/HF)";
case talker::communications_telex:
return "Radio-Telex (MF/HF)";
case talker::communications_vhf:
return "Radio-Telephone (VHF)";
case talker::communications_scanning_receiver:
Expand Down
33 changes: 17 additions & 16 deletions src/marnav/nmea/nmea.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include <marnav/nmea/mtw.hpp>
#include <marnav/nmea/mwd.hpp>
#include <marnav/nmea/mwv.hpp>
#include <marnav/nmea/nrx.hpp>
#include <marnav/nmea/osd.hpp>
#include <marnav/nmea/r00.hpp>
#include <marnav/nmea/rma.hpp>
Expand Down Expand Up @@ -136,22 +137,22 @@ static const std::vector<entry> known_sentences = {
REGISTER_SENTENCE(its), REGISTER_SENTENCE(lcd), REGISTER_SENTENCE(mob),
REGISTER_SENTENCE(msk), REGISTER_SENTENCE(mss), REGISTER_SENTENCE(mta),
REGISTER_SENTENCE(mtw), REGISTER_SENTENCE(mwd), REGISTER_SENTENCE(mwv),
REGISTER_SENTENCE(osd), REGISTER_SENTENCE(r00), REGISTER_SENTENCE(rma),
REGISTER_SENTENCE(rmb), REGISTER_SENTENCE(rmc), REGISTER_SENTENCE(rot),
REGISTER_SENTENCE(rpm), REGISTER_SENTENCE(rsa), REGISTER_SENTENCE(rsd),
REGISTER_SENTENCE(rte), REGISTER_SENTENCE(sfi), REGISTER_SENTENCE(stn),
REGISTER_SENTENCE(tds), REGISTER_SENTENCE(tep), REGISTER_SENTENCE(tfi),
REGISTER_SENTENCE(tll), REGISTER_SENTENCE(tpc), REGISTER_SENTENCE(tpr),
REGISTER_SENTENCE(tpt), REGISTER_SENTENCE(ttm), REGISTER_SENTENCE(vbw),
REGISTER_SENTENCE(vdm), REGISTER_SENTENCE(vdo), REGISTER_SENTENCE(vdr),
REGISTER_SENTENCE(vhw), REGISTER_SENTENCE(vlw), REGISTER_SENTENCE(vpw),
REGISTER_SENTENCE(vtg), REGISTER_SENTENCE(vwe), REGISTER_SENTENCE(vwr),
REGISTER_SENTENCE(wcv), REGISTER_SENTENCE(wdc), REGISTER_SENTENCE(wdr),
REGISTER_SENTENCE(wnc), REGISTER_SENTENCE(wpl), REGISTER_SENTENCE(xdr),
REGISTER_SENTENCE(xte), REGISTER_SENTENCE(xtr), REGISTER_SENTENCE(zda),
REGISTER_SENTENCE(zdl), REGISTER_SENTENCE(zfi), REGISTER_SENTENCE(zfo),
REGISTER_SENTENCE(zlz), REGISTER_SENTENCE(zpi), REGISTER_SENTENCE(zta),
REGISTER_SENTENCE(zte), REGISTER_SENTENCE(ztg),
REGISTER_SENTENCE(nrx), REGISTER_SENTENCE(osd), REGISTER_SENTENCE(r00),
REGISTER_SENTENCE(rma), REGISTER_SENTENCE(rmb), REGISTER_SENTENCE(rmc),
REGISTER_SENTENCE(rot), REGISTER_SENTENCE(rpm), REGISTER_SENTENCE(rsa),
REGISTER_SENTENCE(rsd), REGISTER_SENTENCE(rte), REGISTER_SENTENCE(sfi),
REGISTER_SENTENCE(stn), REGISTER_SENTENCE(tds), REGISTER_SENTENCE(tep),
REGISTER_SENTENCE(tfi), REGISTER_SENTENCE(tll), REGISTER_SENTENCE(tpc),
REGISTER_SENTENCE(tpr), REGISTER_SENTENCE(tpt), REGISTER_SENTENCE(ttm),
REGISTER_SENTENCE(vbw), REGISTER_SENTENCE(vdm), REGISTER_SENTENCE(vdo),
REGISTER_SENTENCE(vdr), REGISTER_SENTENCE(vhw), REGISTER_SENTENCE(vlw),
REGISTER_SENTENCE(vpw), REGISTER_SENTENCE(vtg), REGISTER_SENTENCE(vwe),
REGISTER_SENTENCE(vwr), REGISTER_SENTENCE(wcv), REGISTER_SENTENCE(wdc),
REGISTER_SENTENCE(wdr), REGISTER_SENTENCE(wnc), REGISTER_SENTENCE(wpl),
REGISTER_SENTENCE(xdr), REGISTER_SENTENCE(xte), REGISTER_SENTENCE(xtr),
REGISTER_SENTENCE(zda), REGISTER_SENTENCE(zdl), REGISTER_SENTENCE(zfi),
REGISTER_SENTENCE(zfo), REGISTER_SENTENCE(zlz), REGISTER_SENTENCE(zpi),
REGISTER_SENTENCE(zta), REGISTER_SENTENCE(zte), REGISTER_SENTENCE(ztg),

// vendor extensions
REGISTER_SENTENCE(pgrme), REGISTER_SENTENCE(pgrmm), REGISTER_SENTENCE(pgrmz),
Expand Down
Loading