diff --git a/libuavcan/include/uavcan/internal/data_type.hpp b/libuavcan/include/uavcan/internal/data_type.hpp index c9a2afaca2..8dc6f9098f 100644 --- a/libuavcan/include/uavcan/internal/data_type.hpp +++ b/libuavcan/include/uavcan/internal/data_type.hpp @@ -4,6 +4,7 @@ #pragma once +#include #include namespace uavcan diff --git a/libuavcan/include/uavcan/internal/transport/transfer.hpp b/libuavcan/include/uavcan/internal/transport/transfer.hpp index e1fb148258..9a2c96848a 100644 --- a/libuavcan/include/uavcan/internal/transport/transfer.hpp +++ b/libuavcan/include/uavcan/internal/transport/transfer.hpp @@ -6,6 +6,7 @@ #include #include +#include #include namespace uavcan @@ -71,7 +72,6 @@ public: struct Frame { enum { DATA_TYPE_ID_MAX = 1023 }; - enum { NODE_ID_MAX = 127 }; enum { FRAME_INDEX_MAX = 31 }; enum { PAYLOAD_LEN_MAX = 8 }; @@ -130,6 +130,8 @@ struct Frame (payload_len == rhs.payload_len) && std::equal(payload, payload + payload_len, rhs.payload); } + + std::string toString() const; }; @@ -151,6 +153,8 @@ struct RxFrame : public Frame iface_index = can_frame.iface_index; return true; } + + std::string toString() const; }; } diff --git a/libuavcan/src/transport/transfer.cpp b/libuavcan/src/transport/transfer.cpp index 4195317f37..7ac75a11c4 100644 --- a/libuavcan/src/transport/transfer.cpp +++ b/libuavcan/src/transport/transfer.cpp @@ -3,6 +3,8 @@ */ #include +#include +#include #include namespace uavcan @@ -74,4 +76,38 @@ CanFrame Frame::compile() const return frame; } +std::string Frame::toString() const +{ + /* + * Frame ID fields, according to UAVCAN specs: + * - Data Type ID + * - Transfer Type + * - Source Node ID + * - Frame Index + * - Last Frame + * - Transfer ID + */ + static const int BUFLEN = 100; + char buf[BUFLEN]; + int ofs = std::snprintf(buf, BUFLEN, "dtid=%i tt=%i snid=%i idx=%i last=%i tid=%i payload=[", + int(data_type_id), int(transfer_type), int(source_node_id), int(frame_index), + int(last_frame), int(transfer_id.get())); + + for (int i = 0; i < payload_len; i++) + { + ofs += std::snprintf(buf + ofs, BUFLEN - ofs, "%02x", payload[i]); + if ((i + 1) < payload_len) + ofs += std::snprintf(buf + ofs, BUFLEN - ofs, " "); + } + ofs += std::snprintf(buf + ofs, BUFLEN - ofs, "]"); + return std::string(buf); +} + +std::string RxFrame::toString() const +{ + std::ostringstream os; // C++03 doesn't support long long, so we need ostream to print the timestamp + os << Frame::toString() << " ts=" << timestamp << " iface=" << int(iface_index); + return os.str(); +} + } diff --git a/libuavcan/test/transport/transfer.cpp b/libuavcan/test/transport/transfer.cpp index b5fcb5a5c0..85625018eb 100644 --- a/libuavcan/test/transport/transfer.cpp +++ b/libuavcan/test/transport/transfer.cpp @@ -165,3 +165,39 @@ TEST(Transfer, RxFrameParse) ASSERT_EQ(456, rx_frame.data_type_id); ASSERT_EQ(uavcan::TRANSFER_TYPE_MESSAGE_BROADCAST, rx_frame.transfer_type); } + + +TEST(Transfer, FrameToString) +{ + using uavcan::Frame; + using uavcan::RxFrame; + + // RX frame default + RxFrame rx_frame; + EXPECT_EQ("dtid=0 tt=0 snid=0 idx=0 last=0 tid=0 payload=[] ts=0 iface=0", rx_frame.toString()); + + // RX frame max len + rx_frame.data_type_id = Frame::DATA_TYPE_ID_MAX; + rx_frame.transfer_type = uavcan::TransferType(uavcan::NUM_TRANSFER_TYPES - 1); + rx_frame.source_node_id = uavcan::NODE_ID_MAX; + rx_frame.frame_index = Frame::FRAME_INDEX_MAX; + rx_frame.last_frame = true; + rx_frame.transfer_id = uavcan::TransferID::MAX; + rx_frame.payload_len = Frame::PAYLOAD_LEN_MAX; + for (int i = 0; i < rx_frame.payload_len; i++) + rx_frame.payload[i] = i; + rx_frame.timestamp = 0xFFFFFFFFFFFFFFFF; + rx_frame.iface_index = 3; + + EXPECT_EQ( + "dtid=1023 tt=3 snid=127 idx=31 last=1 tid=15 payload=[00 01 02 03 04 05 06 07] ts=18446744073709551615 iface=3", + rx_frame.toString()); + + // Plain frame default + Frame frame; + EXPECT_EQ("dtid=0 tt=0 snid=0 idx=0 last=0 tid=0 payload=[]", frame.toString()); + + // Plain frame max len + frame = rx_frame; + EXPECT_EQ("dtid=1023 tt=3 snid=127 idx=31 last=1 tid=15 payload=[00 01 02 03 04 05 06 07]", frame.toString()); +}