nmealib 0.0.4
NMEA 0183/NMEA 2000 parsing library
Loading...
Searching...
No Matches
PGN127245.cpp
Go to the documentation of this file.
2
4
5namespace nmealib {
6namespace nmea2000 {
7
8std::unique_ptr<PGN127245> PGN127245::create(std::unique_ptr<Message2000> baseMessage) {
9 if (baseMessage->getCanFrameLength() != 8) {
10 std::string context = "PGN127245::create()";
11 NMEALIB_RETURN_ERROR(InvalidCanFrameException(context, "CAN frame must be 8 bytes for PGN127245"));
12 }
13
14 const uint8_t rudderId = baseMessage->getCanFrame()[0];
15 const HalfByte direction = HalfByte::fromRaw(baseMessage->getCanFrame()[1] & 0x07U);
16 const Byte reserved = Byte::fromRaw((baseMessage->getCanFrame()[1] >> 3) & 0x1FU);
17 const SignedAngle angleOrder = SignedAngle::fromRaw(static_cast<uint16_t>(baseMessage->getCanFrame()[2]) |
18 (static_cast<uint16_t>(baseMessage->getCanFrame()[3]) << 8));
19 const SignedAngle position = SignedAngle::fromRaw(static_cast<uint16_t>(baseMessage->getCanFrame()[4]) |
20 (static_cast<uint16_t>(baseMessage->getCanFrame()[5]) << 8));
21 const Byte reserved2 = Byte::fromRaw(baseMessage->getCanFrame()[6]);
22 const Byte reserved3 = Byte::fromRaw(baseMessage->getCanFrame()[7]);
23
24 return std::unique_ptr<PGN127245>(new PGN127245(std::move(*baseMessage),
25 rudderId,
26 direction,
27 reserved,
28 angleOrder,
29 position,
30 reserved2,
31 reserved3));
32}
33
34PGN127245::PGN127245(Message2000 baseMessage,
35 uint8_t rudderId,
36 HalfByte direction,
37 Byte reserved,
38 SignedAngle angleOrder,
39 SignedAngle position,
40 Byte reserved2,
41 Byte reserved3) noexcept :
42 Message2000(std::move(baseMessage)),
43 rudderId_(rudderId),
44 direction_(direction),
45 reserved_(reserved),
46 angleOrder_(angleOrder),
47 position_(position),
48 reserved2(reserved2),
49 reserved3(reserved3) {}
50
51PGN127245::PGN127245(uint8_t rudderId,
52 HalfByte direction,
53 SignedAngle angleOrder,
54 SignedAngle position,
55 Byte reserved,
56 Byte reserved2,
57 Byte reserved3) noexcept :
58 Message2000(*Message2000::create(rawPayload(rudderId,
59 direction,
60 reserved,
61 angleOrder,
62 position,
63 reserved2,
64 reserved3))),
65 rudderId_(rudderId),
66 direction_(direction),
67 reserved_(reserved),
68 angleOrder_(angleOrder),
69 position_(position),
70 reserved2(reserved2),
71 reserved3(reserved3) {}
72
73std::unique_ptr<Message> PGN127245::clone() const {
74 return std::unique_ptr<PGN127245>(new PGN127245(*this));
75}
76
77std::string PGN127245::getStringContent(bool verbose) const noexcept {
78 std::ostringstream oss;
79
80 if (verbose) {
81 oss << this->toString(true);
82 oss << "\n";
83 oss << "Fields:\n";
84 oss << "\tRudder ID: " << static_cast<int>(rudderId_) << "\n";
85 oss << "\tDirection: " << getDirectionString() << " (" << static_cast<int>(direction_.getValue()) << ")\n";
86 oss << "\tAngle Order: " << angleOrder_.toString() << "rad, " << getAngleOrderDegrees() << "°\n";
87 oss << "\tPosition: " << position_.toString() << "rad, " << getPositionDegrees() << "°\n";
88 } else {
89 oss << this->toString(false);
90 oss << "RudderID=" << static_cast<int>(rudderId_)
91 << " Dir=" << getDirectionString()
92 << " AngleOrder=" << getAngleOrderDegrees() << "°"
93 << " Position=" << getPositionDegrees() << "°";
94 }
95
96 return oss.str();
97}
98
99std::string PGN127245::rawPayload(uint8_t rudderId,
100 HalfByte direction,
101 Byte reserved,
102 SignedAngle angleOrder,
103 SignedAngle position,
104 Byte reserved2,
105 Byte reserved3) {
106 std::vector<uint8_t> canFrame(8, 0);
107 canFrame[0] = rudderId;
108 canFrame[1] = static_cast<uint8_t>(((reserved.getRaw() & 0x1FU) << 3) | (direction.getRaw() & 0x07U));
109 canFrame[2] = static_cast<uint8_t>(angleOrder.getRaw() & 0xFFU);
110 canFrame[3] = static_cast<uint8_t>((angleOrder.getRaw() >> 8) & 0xFFU);
111 canFrame[4] = static_cast<uint8_t>(position.getRaw() & 0xFFU);
112 canFrame[5] = static_cast<uint8_t>((position.getRaw() >> 8) & 0xFFU);
113 canFrame[6] = reserved2.getRaw();
114 canFrame[7] = reserved3.getRaw();
115
116 const uint32_t canId = (127245U << 8U);
117 std::ostringstream oss;
118 oss << std::hex << std::uppercase << std::setfill('0');
119 oss << std::setw(8) << canId << ":";
120 for (uint8_t b : canFrame) {
121 oss << std::setw(2) << static_cast<int>(b);
122 }
123 return oss.str();
124}
125
126uint8_t PGN127245::getRudderId() const noexcept {
127 return rudderId_;
128}
129
131 return direction_;
132}
133
135 return angleOrder_;
136}
137
139 return position_;
140}
141
142float PGN127245::getAngleOrderDegrees() const noexcept {
143 return angleOrder_.getValue() * 180.0f / static_cast<float>(M_PI);
144}
145
146float PGN127245::getPositionDegrees() const noexcept {
147 return position_.getValue() * 180.0f / static_cast<float>(M_PI);
148}
149
150std::string PGN127245::getDirectionString() const noexcept {
151 switch (direction_.getValue()) {
152 case 0: return "none";
153 case 1: return "starboard";
154 case 2: return "port";
155 default: return "unavailable/reserved";
156 }
157}
158
159bool PGN127245::operator==(const PGN127245& other) const noexcept {
160 return Message2000::operator==(other) &&
161 rudderId_ == other.rudderId_ &&
162 direction_ == other.direction_ &&
163 reserved_ == other.reserved_ &&
164 angleOrder_ == other.angleOrder_ &&
165 position_ == other.position_ &&
166 reserved2 == other.reserved2 &&
167 reserved3 == other.reserved3;
168}
169
170} // namespace nmea2000
171} // 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 127245 - Rudder.
Definition PGN127245.h:28
SignedAngle getPosition() const noexcept
PGN127245(uint8_t rudderId, HalfByte direction, SignedAngle angleOrder, SignedAngle position, Byte reserved=Byte::fromValue(0U), Byte reserved2=Byte::fromRaw(255U), Byte reserved3=Byte::fromRaw(255U)) noexcept
Definition PGN127245.cpp:51
std::string getStringContent(bool verbose) const noexcept override
Returns a human-readable string representation of the message.
Definition PGN127245.cpp:77
float getAngleOrderDegrees() const noexcept
float getPositionDegrees() const noexcept
std::unique_ptr< nmealib::Message > clone() const override
Creates a polymorphic deep copy of this Message2000.
Definition PGN127245.cpp:73
std::string getDirectionString() const noexcept
HalfByte getDirection() const noexcept
bool operator==(const PGN127245 &other) const noexcept
uint8_t getRudderId() const noexcept
SignedAngle getAngleOrder() const noexcept
#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