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"));
14 const uint8_t sequenceId = baseMessage->getCanFrame()[0];
16 const Byte reserved =
Byte::fromRaw((baseMessage->getCanFrame()[1] >> 2) & 0x3FU);
18 (
static_cast<uint16_t
>(baseMessage->getCanFrame()[3]) << 8));
20 (
static_cast<uint16_t
>(baseMessage->getCanFrame()[5]) << 8));
24 return std::unique_ptr<PGN129026>(
new PGN129026(std::move(*baseMessage),
34PGN129026::PGN129026(Message2000 baseMessage,
41 Byte reserved3) noexcept :
42 Message2000(std::move(baseMessage)),
43 sequenceId_(sequenceId),
44 cogReference_(cogReference),
48 reserved2_(reserved2),
49 reserved3_(reserved3) {}
51PGN129026::PGN129026(uint8_t sequenceId,
57 Byte reserved3) noexcept :
65 sequenceId_(sequenceId),
66 cogReference_(cogReference),
70 reserved2_(reserved2),
71 reserved3_(reserved3) {}
74 return std::unique_ptr<PGN129026>(
new PGN129026(*
this));
78 std::ostringstream oss;
81 oss << this->toString(
true);
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;
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());
107std::string PGN129026::rawPayload(uint8_t sequenceId,
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();
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);
139 return cogReference_;
163 return cog_.
getValue() * 180.0f /
static_cast<float>(M_PI);
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_;
RawType getRaw() const noexcept
Converts physical value to raw integer representation.
static constexpr DataType fromRaw(RawType raw) noexcept
Constructs from a raw value.
constexpr TargetType getValue() const noexcept
Returns the normalized physical value.
Represents a generic NMEA 2000 message encapsulating a CAN frame.
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.
virtual bool operator==(const Message2000 &other) const noexcept
Strongly-typed class representing PGN 129026 - COG, SOG, Rapid Update.
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.
HalfByte getCogReference() const noexcept
float getCogDegrees() const noexcept
std::unique_ptr< nmealib::Message > clone() const override
Creates a polymorphic deep copy of this Message2000.
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
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.
DataType< ByteTraits > Byte
Custom type representing 8 bits of data (0-255).
DataType< HalfByteTraits > HalfByte
Custom type representing 4 bits of data (0-15).
DataType< AngleTraits > Angle
Custom type representing angles in radians.