nmealib 0.0.4
NMEA 0183/NMEA 2000 parsing library
Loading...
Searching...
No Matches
PGN130306.cpp
Go to the documentation of this file.
2
4
5namespace nmealib {
6namespace nmea2000 {
7
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"));
12 }
13
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));
17 HalfByte windReference = HalfByte::fromRaw(baseMessage->getCanFrame()[5] & 0x07);
18 HalfByte reserved1 = HalfByte::fromRaw((baseMessage->getCanFrame()[5] >> 3) & 0x1F);
19 Byte reserved2 = Byte::fromRaw(baseMessage->getCanFrame()[6]);
20 Byte reserved3 = Byte::fromRaw(baseMessage->getCanFrame()[7]);
21
22 return std::unique_ptr<PGN130306>(new PGN130306(std::move(*baseMessage),
23 sequenceId,
24 windSpeed,
25 windDirection,
26 windReference,
27 reserved1,
28 reserved2,
29 reserved3));
30}
31
32PGN130306::PGN130306(Message2000 baseMessage,
33 uint8_t sequenceId,
34 Speed windSpeed,
35 Angle windDirection,
36 HalfByte windReference,
37 HalfByte reserved1,
38 Byte reserved2,
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) {}
48
49PGN130306::PGN130306(uint8_t sequenceId,
50 Speed windSpeed,
51 Angle windDirection,
52 HalfByte windReference,
53 HalfByte reserved1,
54 Byte reserved2,
55 Byte reserved3) noexcept :
56 Message2000(*Message2000::create(rawPayload(sequenceId,
57 windSpeed,
58 windDirection,
59 windReference,
60 reserved1,
61 reserved2,
62 reserved3))),
63 sequenceId_(sequenceId),
64 windSpeed_(windSpeed),
65 windDirection_(windDirection),
66 windReference_(windReference),
67 reserved1_(reserved1),
68 reserved2_(reserved2),
69 reserved3_(reserved3) {}
70
71std::unique_ptr<Message> PGN130306::clone() const {
72 return std::unique_ptr<PGN130306>(new PGN130306(*this));
73}
74
75std::string PGN130306::getStringContent(bool verbose) const noexcept {
76 std::ostringstream oss;
77
78 if (verbose) {
79 oss << this->toString(true);
80 oss << "\n";
81 oss << "Fields:\n";
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;
93 }
94 oss << "\n";
95 } else {
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());
101 }
102 return oss.str();
103}
104
105std::string PGN130306::rawPayload(uint8_t sequenceId,
106 Speed windSpeed,
107 Angle windDirection,
108 HalfByte windReference,
109 HalfByte reserved1,
110 Byte reserved2,
111 Byte reserved3) {
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;
118 // Byte 5: lower 3 bits = windReference, upper 5 bits = reserved1
119 canFrame[5] = (reserved1.getRaw() << 3) | (windReference.getRaw() & 0x07);
120 canFrame[6] = reserved2.getRaw();
121 canFrame[7] = reserved3.getRaw();
122
123 // Produce the "CANID:data" hex string expected by Message2000::create()
124 // CAN ID encodes PGN 130306 (0x1F50A) in bits [24:8], source address 0
125 const uint32_t canId = (130306U << 8U); // 0x01F50A00
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);
131 }
132 return oss.str();
133}
134
135// Getters
136uint8_t PGN130306::getSequenceId() const noexcept {
137 return sequenceId_;
138}
140 return windSpeed_;
141}
143 return windDirection_;
144}
146 return windReference_;
147}
149 return reserved1_;
150}
152 return reserved2_;
153}
155 return reserved3_;
156}
158 return windDirection_.getValue() * 180.0f / static_cast<float>(M_PI);
159}
160float PGN130306::getWindSpeedKnots() const noexcept {
161 return windSpeed_.getValue() * 1.94384f;
162}
163
164bool PGN130306::operator==(const PGN130306& other) const noexcept {
165 return Message2000::operator==(other) &&
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_;
173}
174
175} // namespace nmea2000
176} // 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 127250 - Wind Data.
Definition PGN130306.h:26
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
Definition PGN130306.cpp:49
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.
Definition PGN130306.cpp:71
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.
Definition PGN130306.cpp:75
#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