nmealib 0.0.4
NMEA 0183/NMEA 2000 parsing library
Loading...
Searching...
No Matches
PGN127250.cpp
Go to the documentation of this file.
2
4
5namespace nmealib {
6namespace nmea2000 {
7
8std::unique_ptr<PGN127250> PGN127250::create(std::unique_ptr<Message2000> baseMessage) {
9 if (baseMessage->getCanFrameLength() != 8) {
10 std::string context = "PGN127250::create()";
11 NMEALIB_RETURN_ERROR(InvalidCanFrameException(context, "CAN frame must be 8 bytes for PGN127250"));
12 }
13
14 uint8_t sequenceId = baseMessage->getCanFrame()[0];
15 Angle heading = Angle::fromRaw(baseMessage->getCanFrame()[1] | (baseMessage->getCanFrame()[2] << 8));
16 SignedAngle deviation = SignedAngle::fromRaw(baseMessage->getCanFrame()[3] | (baseMessage->getCanFrame()[4] << 8));
17 SignedAngle variation = SignedAngle::fromRaw(baseMessage->getCanFrame()[5] | (baseMessage->getCanFrame()[6] << 8));
18 HalfByte headingReference = HalfByte::fromRaw(baseMessage->getCanFrame()[7] & 0x03);
19 Byte reserved = Byte::fromRaw((baseMessage->getCanFrame()[7] >> 6) & 0x3F);
20
21 return std::unique_ptr<PGN127250>(new PGN127250(std::move(*baseMessage),
22 sequenceId,
23 heading,
24 deviation,
25 variation,
26 headingReference,
27 reserved));
28}
29
30PGN127250::PGN127250(Message2000 baseMessage,
31 uint8_t sequenceId,
32 Angle heading,
33 SignedAngle deviation,
34 SignedAngle variation,
35 HalfByte headingReference,
36 Byte reserved) noexcept :
37 Message2000(std::move(baseMessage)),
38 sequenceId_(sequenceId),
39 heading_(heading),
40 deviation_(deviation),
41 variation_(variation),
42 headingReference_(headingReference),
43 reserved_(reserved) {}
44
45PGN127250::PGN127250(uint8_t sequenceId,
46 Angle heading,
47 SignedAngle deviation,
48 SignedAngle variation,
49 HalfByte headingReference,
50 Byte reserved) noexcept :
51 Message2000(*Message2000::create(rawPayload(sequenceId,
52 heading,
53 deviation,
54 variation,
55 headingReference,
56 reserved))),
57 sequenceId_(sequenceId),
58 heading_(heading),
59 deviation_(deviation),
60 variation_(variation),
61 headingReference_(headingReference),
62 reserved_(reserved) {}
63
64
65std::unique_ptr<Message> PGN127250::clone() const{
66 return std::unique_ptr<PGN127250>(new PGN127250(*this));
67}
68
69std::string PGN127250::getStringContent(bool verbose) const noexcept {
70 std::ostringstream oss;
71
72 if (verbose) {
73 oss << this->toString(true);
74 oss << "\n";
75 oss << "Fields:\n";
76 oss << "\tSequence ID: " << static_cast<int>(sequenceId_) << "\n";
77 oss << "\tHeading: " << heading_.toString() << "rad, " << getHeadingDegrees() << "°" << "\n";
78 oss << "\tDeviation: " << deviation_.toString() << "rad, " << getDeviationDegrees() << "°" << "\n";
79 oss << "\tVariation: " << variation_.toString() << "rad, " << getVariationDegrees() << "°" << "\n";
80 oss << "\tHeading Reference: ";
81 switch (headingReference_.getValue()) {
82 case 0: oss << "True"; break;
83 case 1: oss << "Magnetic"; break;
84 case 2: oss << "Error"; break;
85 case 3: oss << "Null"; break;
86 default: oss << "Unavailable/Reserved"; break;
87 }
88 oss << "\n";
89 } else {
90 oss << this->toString(false);
91 oss << "SeqID=" << static_cast<int>(sequenceId_)
92 << " Heading=" << getHeadingDegrees() << "°"
93 << " Deviation=" << getDeviationDegrees() << "°"
94 << " Variation=" << getVariationDegrees() << "°"
95 << " HeadingRef=" << static_cast<int>(headingReference_.getValue());
96 }
97 return oss.str();
98}
99
100std::string PGN127250::rawPayload(uint8_t sequenceId,
101 Angle heading,
102 SignedAngle deviation,
103 SignedAngle variation,
104 HalfByte headingReference,
105 Byte reserved) {
106 std::vector<uint8_t> canFrame(8, 0);
107 canFrame[0] = sequenceId;
108 canFrame[1] = heading.getRaw() & 0xFF;
109 canFrame[2] = (heading.getRaw() >> 8) & 0xFF;
110 canFrame[3] = deviation.getRaw() & 0xFF;
111 canFrame[4] = (deviation.getRaw() >> 8) & 0xFF;
112 canFrame[5] = variation.getRaw() & 0xFF;
113 canFrame[6] = (variation.getRaw() >> 8) & 0xFF;
114 // Byte 7: lower 2 bits = headingReference, upper 6 bits = reserved
115 canFrame[7] = (reserved.getRaw() << 6) | (headingReference.getRaw() & 0x03);
116
117 // Produce the "CANID:data" hex string expected by Message2000::create()
118 // CAN ID encodes PGN 127250 (0x1F503) in bits [24:8], source address 0
119 const uint32_t canId = (127250U << 8U); // 0x01F50300
120 std::ostringstream oss;
121 oss << std::hex << std::uppercase << std::setfill('0');
122 oss << std::setw(8) << canId << ":";
123 for (uint8_t b : canFrame) {
124 oss << std::setw(2) << static_cast<int>(b);
125 }
126 return oss.str();
127}
128
129uint8_t PGN127250::getSequenceId() const noexcept {
130 return sequenceId_;
131}
132Angle PGN127250::getHeading() const noexcept {
133 return heading_;
134}
136 return deviation_;
137}
139 return variation_;
140}
142 return headingReference_;
143}
144float PGN127250::getHeadingDegrees() const noexcept {
145 return heading_.getValue() * 180.0f / static_cast<float>(M_PI);
146}
147float PGN127250::getDeviationDegrees() const noexcept {
148 return deviation_.getValue() * 180.0f / static_cast<float>(M_PI);
149}
150float PGN127250::getVariationDegrees() const noexcept {
151 return variation_.getValue() * 180.0f / static_cast<float>(M_PI);
152}
153
154bool PGN127250::operator==(const PGN127250& other) const noexcept {
155 return Message2000::operator==(other) &&
156 sequenceId_ == other.sequenceId_ &&
157 heading_ == other.heading_ &&
158 deviation_ == other.deviation_ &&
159 variation_ == other.variation_ &&
160 headingReference_ == other.headingReference_ &&
161 reserved_ == other.reserved_;
162}
163
164} // namespace nmea2000
165} // 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 - Heading.
Definition PGN127250.h:28
HalfByte getHeadingReference() const noexcept
SignedAngle getVariation() const noexcept
PGN127250(uint8_t sequenceId, Angle heading, SignedAngle deviation, SignedAngle variation, HalfByte headingReference, Byte reserved=Byte::fromValue(0U)) noexcept
Definition PGN127250.cpp:45
bool operator==(const PGN127250 &other) const noexcept
std::unique_ptr< nmealib::Message > clone() const override
Creates a polymorphic deep copy of this Message2000.
Definition PGN127250.cpp:65
float getVariationDegrees() const noexcept
float getHeadingDegrees() const noexcept
Angle getHeading() const noexcept
uint8_t getSequenceId() const noexcept
float getDeviationDegrees() const noexcept
SignedAngle getDeviation() const noexcept
std::string getStringContent(bool verbose) const noexcept override
Returns a human-readable string representation of the message.
Definition PGN127250.cpp:69
#define NMEALIB_RETURN_ERROR(exceptionExpr)
DataType< SignedAngleTraits > SignedAngle
Custom type representing signed angles in radians.
Definition dataTypes.h:356
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