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"));
14 const uint8_t rudderId = baseMessage->getCanFrame()[0];
16 const Byte reserved =
Byte::fromRaw((baseMessage->getCanFrame()[1] >> 3) & 0x1FU);
18 (
static_cast<uint16_t
>(baseMessage->getCanFrame()[3]) << 8));
20 (
static_cast<uint16_t
>(baseMessage->getCanFrame()[5]) << 8));
24 return std::unique_ptr<PGN127245>(
new PGN127245(std::move(*baseMessage),
34PGN127245::PGN127245(Message2000 baseMessage,
41 Byte reserved3) noexcept :
42 Message2000(std::move(baseMessage)),
44 direction_(direction),
46 angleOrder_(angleOrder),
49 reserved3(reserved3) {}
51PGN127245::PGN127245(uint8_t rudderId,
57 Byte reserved3) noexcept :
66 direction_(direction),
68 angleOrder_(angleOrder),
71 reserved3(reserved3) {}
74 return std::unique_ptr<PGN127245>(
new PGN127245(*
this));
78 std::ostringstream oss;
81 oss << this->toString(
true);
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";
89 oss << this->toString(
false);
90 oss <<
"RudderID=" <<
static_cast<int>(rudderId_)
91 <<
" Dir=" << getDirectionString()
92 <<
" AngleOrder=" << getAngleOrderDegrees() <<
"°"
93 <<
" Position=" << getPositionDegrees() <<
"°";
99std::string PGN127245::rawPayload(uint8_t rudderId,
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();
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);
143 return angleOrder_.
getValue() * 180.0f /
static_cast<float>(M_PI);
147 return position_.
getValue() * 180.0f /
static_cast<float>(M_PI);
152 case 0:
return "none";
153 case 1:
return "starboard";
154 case 2:
return "port";
155 default:
return "unavailable/reserved";
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;
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 127245 - Rudder.
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
std::string getStringContent(bool verbose) const noexcept override
Returns a human-readable string representation of the message.
float getAngleOrderDegrees() const noexcept
float getPositionDegrees() const noexcept
std::unique_ptr< nmealib::Message > clone() const override
Creates a polymorphic deep copy of this Message2000.
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.
DataType< ByteTraits > Byte
Custom type representing 8 bits of data (0-255).
DataType< HalfByteTraits > HalfByte
Custom type representing 4 bits of data (0-15).