nmealib 0.0.4
NMEA 0183/NMEA 2000 parsing library
Loading...
Searching...
No Matches
PGN128259.cpp
Go to the documentation of this file.
2
4
5namespace nmealib {
6namespace nmea2000 {
7
8std::unique_ptr<PGN128259> PGN128259::create(std::unique_ptr<Message2000> baseMessage) {
9 if (baseMessage->getCanFrameLength() != 8) {
10 std::string context = "PGN128259::create()";
11 NMEALIB_RETURN_ERROR(InvalidCanFrameException(context, "CAN frame must be 8 bytes for PGN128259"));
12 }
13
14 uint8_t sequenceId = baseMessage->getCanFrame()[0];
15 Speed speedWaterReferenced = Speed::fromRaw(baseMessage->getCanFrame()[1] | (baseMessage->getCanFrame()[2] << 8));
16 Speed speedGroundReferenced = Speed::fromRaw(baseMessage->getCanFrame()[3] | (baseMessage->getCanFrame()[4] << 8));
17 Byte speedWaterReferencedType = Byte::fromRaw(baseMessage->getCanFrame()[5]);
18 HalfByte speedDirection = HalfByte::fromRaw(baseMessage->getCanFrame()[6] & 0x0F);
19 HalfByte reserved2 = HalfByte::fromRaw((baseMessage->getCanFrame()[6] >> 4) & 0x0F);
20 Byte reserved1 = Byte::fromRaw(baseMessage->getCanFrame()[7]);
21
22 return std::unique_ptr<PGN128259>(new PGN128259(std::move(*baseMessage),
23 sequenceId,
24 speedWaterReferenced,
25 speedGroundReferenced,
26 speedWaterReferencedType,
27 speedDirection,
28 reserved1,
29 reserved2));
30}
31
32PGN128259::PGN128259(Message2000 baseMessage,
33 uint8_t sequenceId,
34 Speed speedWaterReferenced,
35 Speed speedGroundReferenced,
36 Byte speedWaterReferencedType,
37 HalfByte speedDirection,
38 Byte reserved1,
39 HalfByte reserved2) noexcept :
40 Message2000(std::move(baseMessage)),
41 sequenceId_(sequenceId),
42 speedWaterReferenced_(speedWaterReferenced),
43 speedGroundReferenced_(speedGroundReferenced),
44 speedWaterReferencedType_(speedWaterReferencedType),
45 speedDirection_(speedDirection),
46 reserved1_(reserved1),
47 reserved2_(reserved2) {}
48
49PGN128259::PGN128259(uint8_t sequenceId,
50 Speed speedWaterReferenced,
51 Speed speedGroundReferenced,
52 Byte speedWaterReferencedType,
53 HalfByte speedDirection,
54 Byte reserved1,
55 HalfByte reserved2) :
56 Message2000(*Message2000::create(rawPayload(sequenceId,
57 speedWaterReferenced,
58 speedGroundReferenced,
59 speedWaterReferencedType,
60 speedDirection,
61 reserved1,
62 reserved2))),
63 sequenceId_(sequenceId),
64 speedWaterReferenced_(speedWaterReferenced),
65 speedGroundReferenced_(speedGroundReferenced),
66 speedWaterReferencedType_(speedWaterReferencedType),
67 speedDirection_(speedDirection),
68 reserved1_(reserved1),
69 reserved2_(reserved2) {}
70
71
72std::unique_ptr<Message> PGN128259::clone() const{
73 return std::unique_ptr<PGN128259>(new PGN128259(*this));
74}
75
76std::string PGN128259::getStringContent(bool verbose) const noexcept {
77 std::ostringstream oss;
78
79 if (verbose) {
80 oss << this->toString(true);
81 oss << "\n";
82 oss << "Fields:\n";
83 oss << "\tSequence ID: " << static_cast<int>(sequenceId_) << "\n";
84 oss << "\tSpeed Water Referenced: " << speedWaterReferenced_.toString() << " m/s\n";
85 oss << "\tSpeed Ground Referenced: " << speedGroundReferenced_.toString() << " m/s\n";
86 oss << "\tSpeed Water Referenced Type: ";
87 switch (speedWaterReferencedType_.getValue()) {
88 case 0: oss << "Paddle"; break;
89 case 1: oss << "Pitot"; break;
90 case 2: oss << "Doppler"; break;
91 case 3: oss << "Correlation"; break;
92 case 4: oss << "EM"; break;
93 default: oss << "Unavailable/Reserved"; break;
94 }
95 oss << "\n";
96 oss << "\tSpeed Direction: ";
97 if (speedDirection_.getValue() == 0b00) oss << "Forward";
98 else if (speedDirection_.getValue() == 0b01) oss << "Reverse";
99 else oss << "Unavailable/Reserved";
100 oss << "\n";
101 } else {
102 oss << this->toString(false);
103 oss << "SeqID=" << static_cast<int>(sequenceId_)
104 << " SpeedWater=" << speedWaterReferenced_.toString() << "m/s"
105 << " SpeedGround=" << speedGroundReferenced_.toString() << "m/s"
106 << " WaterRefType=" << static_cast<int>(speedWaterReferencedType_.getValue())
107 << " SpeedDir=";
108 if (speedDirection_.getValue() == 0b00) oss << "F";
109 else if (speedDirection_.getValue() == 0b01) oss << "R";
110 else oss << "X";
111 }
112 return oss.str();
113}
114
115std::string PGN128259::rawPayload(uint8_t sequenceId,
116 Speed speedWaterReferenced,
117 Speed speedGroundReferenced,
118 Byte speedWaterReferencedType,
119 HalfByte speedDirection,
120 Byte reserved1,
121 HalfByte reserved2) {
122 std::vector<uint8_t> canFrame(8, 0);
123 canFrame[0] = sequenceId;
124 canFrame[1] = speedWaterReferenced.getRaw() & 0xFF;
125 canFrame[2] = (speedWaterReferenced.getRaw() >> 8) & 0xFF;
126 canFrame[3] = speedGroundReferenced.getRaw() & 0xFF;
127 canFrame[4] = (speedGroundReferenced.getRaw() >> 8) & 0xFF;
128 canFrame[5] = speedWaterReferencedType.getRaw();
129 // Byte 6: upper nibble = reserved2, lower nibble = speedDirection
130 canFrame[6] = (reserved2.getRaw() << 4) | (speedDirection.getRaw() & 0x0F);
131 // Byte 7: full 8-bit reserved field
132 canFrame[7] = reserved1.getRaw();
133
134 // Produce the "CANID:data" hex string expected by Message2000::create()
135 // CAN ID encodes PGN 128259 (0x1F503) in bits [24:8], source address 0
136 const uint32_t canId = (128259U << 8U); // 0x01F50300
137 std::ostringstream oss;
138 oss << std::hex << std::uppercase << std::setfill('0');
139 oss << std::setw(8) << canId << ":";
140 for (uint8_t b : canFrame) {
141 oss << std::setw(2) << static_cast<int>(b);
142 }
143 return oss.str();
144}
145
146uint8_t PGN128259::getSequenceId() const noexcept {
147 return sequenceId_;
148}
149
151 return speedWaterReferenced_;
152}
153
155 return speedGroundReferenced_;
156}
157
159 return speedWaterReferencedType_;
160}
161
163 return speedDirection_;
164}
165
167 return reserved1_;
168}
169
171 return reserved2_;
172}
173
174bool PGN128259::operator==(const PGN128259& other) const noexcept {
175 return Message2000::operator==(other) &&
176 sequenceId_ == other.sequenceId_ &&
177 speedWaterReferenced_ == other.speedWaterReferenced_ &&
178 speedGroundReferenced_ == other.speedGroundReferenced_ &&
179 speedWaterReferencedType_ == other.speedWaterReferencedType_ &&
180 speedDirection_ == other.speedDirection_ &&
181 reserved1_ == other.reserved1_ &&
182 reserved2_ == other.reserved2_;
183}
184
185} // namespace nmea2000
186} // 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
Represents a generic NMEA 2000 message encapsulating a CAN frame.
Definition nmea2000.h:62
virtual bool operator==(const Message2000 &other) const noexcept
Definition nmea2000.cpp:401
Strongly-typed class representing PGN 128259 - Speed, Water Referenced.
Definition PGN128259.h:32
std::string getStringContent(bool verbose) const noexcept override
Returns a human-readable string representation of the message.
Definition PGN128259.cpp:76
Speed getSpeedGroundReferenced() const noexcept
bool operator==(const PGN128259 &other) const noexcept
HalfByte getReserved2() const noexcept
uint8_t getSequenceId() const noexcept
Speed getSpeedWaterReferenced() const noexcept
std::unique_ptr< nmealib::Message > clone() const override
Creates a polymorphic deep copy of this Message2000.
Definition PGN128259.cpp:72
PGN128259(uint8_t sequenceId, Speed speedWaterReferenced, Speed speedGroundReferenced, Byte speedWaterReferencedType, HalfByte speedDirection, Byte reserved1=Byte::fromValue(0U), HalfByte reserved2=HalfByte::fromValue(0U))
Definition PGN128259.cpp:49
Byte getSpeedWaterReferencedType() const noexcept
Byte getReserved1() const noexcept
HalfByte getSpeedDirection() 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