8std::unique_ptr<PGN130306> PGN130306::create(std::unique_ptr<Message2000> baseMessage) {
9 if (baseMessage->getCanFrameLength() != 8) {
10 std::string context =
"PGN130306::create()";
11 NMEALIB_RETURN_ERROR(InvalidCanFrameException(context,
"CAN frame must be 8 bytes for PGN130306"));
14 uint8_t sequenceId = baseMessage->getCanFrame()[0];
15 Speed windSpeed =
Speed::fromRaw(baseMessage->getCanFrame()[1] | (baseMessage->getCanFrame()[2] << 8));
16 Angle windDirection =
Angle::fromRaw(baseMessage->getCanFrame()[3] | (baseMessage->getCanFrame()[4] << 8));
22 return std::unique_ptr<PGN130306>(
new PGN130306(std::move(*baseMessage),
32PGN130306::PGN130306(Message2000 baseMessage,
39 Byte reserved3) noexcept :
40 Message2000(std::move(baseMessage)),
41 sequenceId_(sequenceId),
42 windSpeed_(windSpeed),
43 windDirection_(windDirection),
44 windReference_(windReference),
45 reserved1_(reserved1),
46 reserved2_(reserved2),
47 reserved3_(reserved3) {}
49PGN130306::PGN130306(uint8_t sequenceId,
55 Byte reserved3) noexcept :
63 sequenceId_(sequenceId),
64 windSpeed_(windSpeed),
65 windDirection_(windDirection),
66 windReference_(windReference),
67 reserved1_(reserved1),
68 reserved2_(reserved2),
69 reserved3_(reserved3) {}
72 return std::unique_ptr<PGN130306>(
new PGN130306(*
this));
76 std::ostringstream oss;
79 oss << this->toString(
true);
82 oss <<
"\tSequence ID: " <<
static_cast<int>(sequenceId_) <<
"\n";
83 oss <<
"\tWind Speed: " << windSpeed_.toString() <<
" knots" <<
"\n";
84 oss <<
"\tWind Direction: " << windDirection_.toString() <<
"rad, " << getWindDirectionDegrees() <<
"°" <<
"\n";
85 oss <<
"\tWind Reference: ";
86 switch (windReference_.getValue()) {
87 case 0: oss <<
"True(North)";
break;
88 case 1: oss <<
"Magnetic(North)";
break;
89 case 2: oss <<
"Apparent";
break;
90 case 3: oss <<
"True(Boat)";
break;
91 case 4: oss <<
"True(Water)";
break;
92 default: oss <<
"Unavailable/Reserved";
break;
96 oss << this->toString(
false);
97 oss <<
"SeqID=" <<
static_cast<int>(sequenceId_)
98 <<
" WindSpeed=" << windSpeed_.getValue() <<
" knots"
99 <<
" WindDirection=" << getWindDirectionDegrees() <<
"°"
100 <<
" WindReference=" <<
static_cast<int>(windReference_.getValue());
105std::string PGN130306::rawPayload(uint8_t sequenceId,
112 std::vector<uint8_t> canFrame(8, 0);
113 canFrame[0] = sequenceId;
114 canFrame[1] = windSpeed.
getRaw() & 0xFF;
115 canFrame[2] = (windSpeed.
getRaw() >> 8) & 0xFF;
116 canFrame[3] = windDirection.
getRaw() & 0xFF;
117 canFrame[4] = (windDirection.
getRaw() >> 8) & 0xFF;
119 canFrame[5] = (reserved1.
getRaw() << 3) | (windReference.
getRaw() & 0x07);
120 canFrame[6] = reserved2.
getRaw();
121 canFrame[7] = reserved3.
getRaw();
125 const uint32_t canId = (130306U << 8U);
126 std::ostringstream oss;
127 oss << std::hex << std::uppercase << std::setfill(
'0');
128 oss << std::setw(8) << canId <<
":";
129 for (uint8_t b : canFrame) {
130 oss << std::setw(2) << static_cast<int>(b);
143 return windDirection_;
146 return windReference_;
158 return windDirection_.
getValue() * 180.0f /
static_cast<float>(M_PI);
161 return windSpeed_.
getValue() * 1.94384f;
166 sequenceId_ == other.sequenceId_ &&
167 windSpeed_ == other.windSpeed_ &&
168 windDirection_ == other.windDirection_ &&
169 windReference_ == other.windReference_ &&
170 reserved1_ == other.reserved1_ &&
171 reserved2_ == other.reserved2_ &&
172 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 127250 - Wind Data.
Speed getWindSpeed() const noexcept
HalfByte getReserved1() const noexcept
float getWindDirectionDegrees() const noexcept
Byte getReserved2() const noexcept
bool operator==(const PGN130306 &other) const noexcept
PGN130306(uint8_t sequenceId, Speed windSpeed, Angle windDirection, HalfByte windReference, HalfByte reserved1=HalfByte::fromValue(0U), Byte reserved2=Byte::fromValue(0U), Byte reserved3=Byte::fromValue(0U)) noexcept
Angle getWindDirection() const noexcept
HalfByte getWindReference() const noexcept
Byte getReserved3() const noexcept
std::unique_ptr< nmealib::Message > clone() const override
Creates a polymorphic deep copy of this Message2000.
float getWindSpeedKnots() const noexcept
uint8_t getSequenceId() const noexcept
std::string getStringContent(bool verbose) const noexcept override
Returns a human-readable string representation of the message.
#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.