nmealib 0.0.4
NMEA 0183/NMEA 2000 parsing library
Loading...
Searching...
No Matches
PGN129026.cpp
Go to the documentation of this file.
2
4
5namespace nmealib {
6namespace nmea2000 {
7
8std::unique_ptr<PGN129026> PGN129026::create(std::unique_ptr<Message2000> baseMessage) {
9 if (baseMessage->getCanFrameLength() != 8) {
10 std::string context = "PGN129026::create()";
11 NMEALIB_RETURN_ERROR(InvalidCanFrameException(context, "CAN frame must be 8 bytes for PGN129026"));
12 }
13
14 const uint8_t sequenceId = baseMessage->getCanFrame()[0];
15 const HalfByte cogReference = HalfByte::fromRaw(baseMessage->getCanFrame()[1] & 0x03U);
16 const Byte reserved = Byte::fromRaw((baseMessage->getCanFrame()[1] >> 2) & 0x3FU);
17 const Angle cog = Angle::fromRaw(static_cast<uint16_t>(baseMessage->getCanFrame()[2]) |
18 (static_cast<uint16_t>(baseMessage->getCanFrame()[3]) << 8));
19 const Speed sog = Speed::fromRaw(static_cast<uint16_t>(baseMessage->getCanFrame()[4]) |
20 (static_cast<uint16_t>(baseMessage->getCanFrame()[5]) << 8));
21 const Byte reserved2 = Byte::fromRaw(baseMessage->getCanFrame()[6]);
22 const Byte reserved3 = Byte::fromRaw(baseMessage->getCanFrame()[7]);
23
24 return std::unique_ptr<PGN129026>(new PGN129026(std::move(*baseMessage),
25 sequenceId,
26 cogReference,
27 reserved,
28 cog,
29 sog,
30 reserved2,
31 reserved3));
32}
33
34PGN129026::PGN129026(Message2000 baseMessage,
35 uint8_t sequenceId,
36 HalfByte cogReference,
37 Byte reserved,
38 Angle cog,
39 Speed sog,
40 Byte reserved2,
41 Byte reserved3) noexcept :
42 Message2000(std::move(baseMessage)),
43 sequenceId_(sequenceId),
44 cogReference_(cogReference),
45 cog_(cog),
46 sog_(sog),
47 reserved_(reserved),
48 reserved2_(reserved2),
49 reserved3_(reserved3) {}
50
51PGN129026::PGN129026(uint8_t sequenceId,
52 HalfByte cogReference,
53 Angle cog,
54 Speed sog,
55 Byte reserved,
56 Byte reserved2,
57 Byte reserved3) noexcept :
58 Message2000(*Message2000::create(rawPayload(sequenceId,
59 cogReference,
60 reserved,
61 cog,
62 sog,
63 reserved2,
64 reserved3))),
65 sequenceId_(sequenceId),
66 cogReference_(cogReference),
67 cog_(cog),
68 sog_(sog),
69 reserved_(reserved),
70 reserved2_(reserved2),
71 reserved3_(reserved3) {}
72
73std::unique_ptr<Message> PGN129026::clone() const {
74 return std::unique_ptr<PGN129026>(new PGN129026(*this));
75}
76
77std::string PGN129026::getStringContent(bool verbose) const noexcept {
78 std::ostringstream oss;
79
80 if (verbose) {
81 oss << this->toString(true);
82 oss << "\n";
83 oss << "Fields:\n";
84 oss << "\tSequence ID: " << static_cast<int>(sequenceId_) << "\n";
85 oss << "\tCourse Over Ground: " << cog_.toString() << "rad, " << getCogDegrees() << "°\n";
86 oss << "\tSpeed Over Ground: " << getSogKnots() << " knots\n";
87 oss << "\tCOG Reference: ";
88 switch (cogReference_.getValue()) {
89 case 0: oss << "True"; break;
90 case 1: oss << "Magnetic"; break;
91 case 2: oss << "Error"; break;
92 case 3: oss << "Null"; break;
93 default: oss << "Unavailable/Reserved"; break;
94 }
95 oss << "\n";
96 } else {
97 oss << this->toString(false);
98 oss << "SeqID=" << static_cast<int>(sequenceId_)
99 << " COG=" << getCogDegrees() << "°"
100 << " SOG=" << getSogKnots() << " knots"
101 << " COGRef=" << static_cast<int>(cogReference_.getValue());
102 }
103
104 return oss.str();
105}
106
107std::string PGN129026::rawPayload(uint8_t sequenceId,
108 HalfByte cogReference,
109 Byte reserved,
110 Angle cog,
111 Speed sog,
112 Byte reserved2,
113 Byte reserved3) {
114 std::vector<uint8_t> canFrame(8, 0);
115 canFrame[0] = sequenceId;
116 canFrame[1] = static_cast<uint8_t>(((reserved.getRaw() & 0x3FU) << 2) | (cogReference.getRaw() & 0x03U));
117 canFrame[2] = static_cast<uint8_t>(cog.getRaw() & 0xFFU);
118 canFrame[3] = static_cast<uint8_t>((cog.getRaw() >> 8) & 0xFFU);
119 canFrame[4] = static_cast<uint8_t>(sog.getRaw() & 0xFFU);
120 canFrame[5] = static_cast<uint8_t>((sog.getRaw() >> 8) & 0xFFU);
121 canFrame[6] = reserved2.getRaw();
122 canFrame[7] = reserved3.getRaw();
123
124 const uint32_t canId = (129026U << 8U);
125 std::ostringstream oss;
126 oss << std::hex << std::uppercase << std::setfill('0');
127 oss << std::setw(8) << canId << ":";
128 for (uint8_t b : canFrame) {
129 oss << std::setw(2) << static_cast<int>(b);
130 }
131 return oss.str();
132}
133
134uint8_t PGN129026::getSequenceId() const noexcept {
135 return sequenceId_;
136}
137
139 return cogReference_;
140}
141
142Angle PGN129026::getCog() const noexcept {
143 return cog_;
144}
145
146Speed PGN129026::getSog() const noexcept {
147 return sog_;
148}
149
151 return reserved_;
152}
153
155 return reserved2_;
156}
157
159 return reserved3_;
160}
161
162float PGN129026::getCogDegrees() const noexcept {
163 return cog_.getValue() * 180.0f / static_cast<float>(M_PI);
164}
165
166float PGN129026::getSogKnots() const noexcept {
167 return sog_.getValue() * 1.94384f;
168}
169
170bool PGN129026::operator==(const PGN129026& other) const noexcept {
171 return Message2000::operator==(other) &&
172 sequenceId_ == other.sequenceId_ &&
173 cogReference_ == other.cogReference_ &&
174 cog_ == other.cog_ &&
175 sog_ == other.sog_ &&
176 reserved_ == other.reserved_ &&
177 reserved2_ == other.reserved2_ &&
178 reserved3_ == other.reserved3_;
179}
180
181} // namespace nmea2000
182} // namespace nmealib
RawType getRaw() const noexcept
Converts physical value to raw integer representation.
Definition dataTypes.h:128
static constexpr DataType fromRaw(RawType raw) noexcept
Constructs from a raw value.
Definition dataTypes.h:97
constexpr TargetType getValue() const noexcept
Returns the normalized physical value.
Definition dataTypes.h:113
Represents a generic NMEA 2000 message encapsulating a CAN frame.
Definition nmea2000.h:62
static std::unique_ptr< Message2000 > create(std::string raw, TimePoint ts=std::chrono::system_clock::now())
Protected factory — parses "CANID:data" (and variant formats) into a Message2000.
Definition nmea2000.cpp:109
virtual bool operator==(const Message2000 &other) const noexcept
Definition nmea2000.cpp:401
Strongly-typed class representing PGN 129026 - COG, SOG, Rapid Update.
Definition PGN129026.h:28
Byte getReserved3() const noexcept
Speed getSog() const noexcept
std::string getStringContent(bool verbose) const noexcept override
Returns a human-readable string representation of the message.
Definition PGN129026.cpp:77
HalfByte getCogReference() const noexcept
float getCogDegrees() const noexcept
std::unique_ptr< nmealib::Message > clone() const override
Creates a polymorphic deep copy of this Message2000.
Definition PGN129026.cpp:73
Byte getReserved2() const noexcept
Angle getCog() const noexcept
bool operator==(const PGN129026 &other) const noexcept
Byte getReserved1() const noexcept
PGN129026(uint8_t sequenceId, HalfByte cogReference, Angle cog, Speed sog, Byte reserved=Byte::fromValue(0U), Byte reserved2=Byte::fromValue(0U), Byte reserved3=Byte::fromValue(0U)) noexcept
Definition PGN129026.cpp:51
float getSogKnots() const noexcept
uint8_t getSequenceId() const noexcept
#define NMEALIB_RETURN_ERROR(exceptionExpr)
DataType< SpeedTraits > Speed
Custom type representing speeds in meters per second.
Definition dataTypes.h:304
DataType< ByteTraits > Byte
Custom type representing 8 bits of data (0-255).
Definition dataTypes.h:330
DataType< HalfByteTraits > HalfByte
Custom type representing 4 bits of data (0-15).
Definition dataTypes.h:317
DataType< AngleTraits > Angle
Custom type representing angles in radians.
Definition dataTypes.h:343