From 7ad40363232db32174a670488da161836d1f3a39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danijel=20Tomi=C4=87?= Date: Thu, 9 Oct 2025 14:15:03 +0200 Subject: [PATCH] Add support for TECMP Ethernet payload --- include/asam_cmp/tecmp_converter.h | 5 +- include/asam_cmp/tecmp_decoder.h | 1 + include/asam_cmp/tecmp_ethernet_payload.h | 17 +++++++ src/CMakeLists.txt | 6 ++- src/tecmp_converter.cpp | 32 +++++++++---- src/tecmp_decoder.cpp | 17 ++++++- src/tecmp_ethernet_payload.cpp | 20 ++++++++ tests/CMakeLists.txt | 1 + tests/test_tecmp_decoder.cpp | 56 +++++++++++++++++++++++ tests/test_tecmp_ethernet_payload.cpp | 37 +++++++++++++++ 10 files changed, 179 insertions(+), 13 deletions(-) create mode 100644 include/asam_cmp/tecmp_ethernet_payload.h create mode 100644 src/tecmp_ethernet_payload.cpp create mode 100644 tests/test_tecmp_ethernet_payload.cpp diff --git a/include/asam_cmp/tecmp_converter.h b/include/asam_cmp/tecmp_converter.h index 16e329a..1b127b8 100644 --- a/include/asam_cmp/tecmp_converter.h +++ b/include/asam_cmp/tecmp_converter.h @@ -36,12 +36,13 @@ class Converter final static PacketPtr ConvertCaptureModulePayload(CmpHeader& header, const TecmpPayloadPtr& payload); static PacketPtr ConvertInterfacePayload(CmpHeader& header, const TecmpPayloadPtr& payload); static PacketPtr ConvertDataPayload(CmpHeader& header, const TecmpPayloadPtr& payload); - static PacketPtr GetPackageFromTecmpHeader(const TECMP::CmpHeader& header); + static PacketPtr GetPacketFromTecmpHeader(const TECMP::CmpHeader& header); private: static PacketPtr ConvertCanPayload(CmpHeader& header, const TecmpPayloadPtr& payload); static PacketPtr ConvertCanFdPayload(TECMP::CanPayload* canPayload, PacketPtr packet); - static PacketPtr convertLinPayload(CmpHeader& header, const TecmpPayloadPtr& payload); + static PacketPtr ConvertLinPayload(CmpHeader& header, const TecmpPayloadPtr& payload); + static PacketPtr ConvertEthernetPayload(CmpHeader& header, const TecmpPayloadPtr& payload); }; END_NAMESPACE_TECMP \ No newline at end of file diff --git a/include/asam_cmp/tecmp_decoder.h b/include/asam_cmp/tecmp_decoder.h index 8710331..360025e 100644 --- a/include/asam_cmp/tecmp_decoder.h +++ b/include/asam_cmp/tecmp_decoder.h @@ -44,6 +44,7 @@ class Decoder final static TecmpPayloadPtr GetCaptureModulePayload(const uint8_t* payloadData, const std::size_t size); static TecmpPayloadPtr GetCanPayload(const uint8_t* payloadData, const std::size_t size); static TecmpPayloadPtr GetLinPayload(const uint8_t* payloadData, const std::size_t size); + static TecmpPayloadPtr GetEthernetPayload(const uint8_t* payloadData, const std::size_t size); }; END_NAMESPACE_TECMP diff --git a/include/asam_cmp/tecmp_ethernet_payload.h b/include/asam_cmp/tecmp_ethernet_payload.h new file mode 100644 index 0000000..da54a63 --- /dev/null +++ b/include/asam_cmp/tecmp_ethernet_payload.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include + +BEGIN_NAMESPACE_TECMP + +class EthernetPayload : public Payload +{ +public: + EthernetPayload(const uint8_t* data, size_t size); + + const uint8_t* getData() const; + std::size_t getDataLength() const; +}; + +END_NAMESPACE_TECMP diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dd368b0..26c0618 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -28,6 +28,7 @@ set(SRC_Headers ../include/${LIB_NAME}/common.h ../include/${LIB_NAME}/tecmp_decoder.h ../include/${LIB_NAME}/tecmp_interface_payload.h ../include/${LIB_NAME}/tecmp_converter.h + ../include/${LIB_NAME}/tecmp_ethernet_payload.h ) set(SRC_Sources cmp_header.cpp @@ -55,13 +56,14 @@ set(SRC_Sources cmp_header.cpp tecmp_decoder.cpp tecmp_interface_payload.cpp tecmp_converter.cpp + tecmp_ethernet_payload.cpp ) add_library(${LIB_NAME} STATIC ${SRC_Headers} ${SRC_Sources}) -if(UNIX) +if (UNIX) target_compile_options(${LIB_NAME} PRIVATE -fPIC) -endif() +endif () target_include_directories(${LIB_NAME} PUBLIC $ diff --git a/src/tecmp_converter.cpp b/src/tecmp_converter.cpp index 1e48f5a..74076b4 100644 --- a/src/tecmp_converter.cpp +++ b/src/tecmp_converter.cpp @@ -1,11 +1,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include @@ -54,7 +56,7 @@ PacketPtr TECMP::Converter::ConvertPacket(CmpHeader& header, const TecmpPayloadP PacketPtr TECMP::Converter::ConvertCanPayload(CmpHeader& header, const TecmpPayloadPtr& payload) { auto tecmpCanPayload = reinterpret_cast(payload.get()); - auto packet = GetPackageFromTecmpHeader(header); + auto packet = GetPacketFromTecmpHeader(header); if (tecmpCanPayload->getDlc() > 8) { return ConvertCanFdPayload(tecmpCanPayload, packet); @@ -73,7 +75,7 @@ PacketPtr TECMP::Converter::ConvertCanPayload(CmpHeader& header, const TecmpPayl PacketPtr TECMP::Converter::ConvertCaptureModulePayload(CmpHeader& header, const TecmpPayloadPtr& payload) { auto tecmpCmPayload = reinterpret_cast(payload.get()); - auto packet = GetPackageFromTecmpHeader(header); + auto packet = GetPacketFromTecmpHeader(header); ASAM::CMP::CaptureModulePayload cmPayload; cmPayload.setData( "", std::to_string(tecmpCmPayload->getSerialNumber()), tecmpCmPayload->getHwVersion(), tecmpCmPayload->getSwVersion(), {}); @@ -86,7 +88,7 @@ PacketPtr TECMP::Converter::ConvertCaptureModulePayload(CmpHeader& header, const PacketPtr TECMP::Converter::ConvertInterfacePayload(CmpHeader& header, const TecmpPayloadPtr& payload) { auto tecmpInterfacePayload = reinterpret_cast(payload.get()); - auto packet = GetPackageFromTecmpHeader(header); + auto packet = GetPacketFromTecmpHeader(header); ASAM::CMP::InterfacePayload interfacePayload; interfacePayload.setInterfaceId(tecmpInterfacePayload->getInterfaceId()); @@ -107,12 +109,14 @@ PacketPtr TECMP::Converter::ConvertDataPayload(CmpHeader& header, const TecmpPay return ConvertCanPayload(header, payload); break; case CmpHeader::DataType::lin: - return convertLinPayload(header, payload); + return ConvertLinPayload(header, payload); + break; + case CmpHeader::DataType::ethernet: + return ConvertEthernetPayload(header, payload); break; case CmpHeader::DataType::flexRay: case CmpHeader::DataType::uartRs232: case CmpHeader::DataType::analog: - case CmpHeader::DataType::ethernet: case CmpHeader::DataType::invalid: break; } @@ -133,10 +137,10 @@ PacketPtr TECMP::Converter::ConvertCanFdPayload(TECMP::CanPayload* canPayload, P return packet; } -PacketPtr TECMP::Converter::convertLinPayload(TECMP::CmpHeader& header, const TecmpPayloadPtr& payload) +PacketPtr TECMP::Converter::ConvertLinPayload(TECMP::CmpHeader& header, const TecmpPayloadPtr& payload) { auto tecmpLinPayload = reinterpret_cast(payload.get()); - auto packet = GetPackageFromTecmpHeader(header); + auto packet = GetPacketFromTecmpHeader(header); ASAM::CMP::LinPayload linPayload; @@ -148,8 +152,20 @@ PacketPtr TECMP::Converter::convertLinPayload(TECMP::CmpHeader& header, const Te return packet; } +PacketPtr TECMP::Converter::ConvertEthernetPayload(CmpHeader& header, const TecmpPayloadPtr& payload) +{ + auto tecmpEthPayload = reinterpret_cast(payload.get()); + auto packet = GetPacketFromTecmpHeader(header); + + ASAM::CMP::EthernetPayload ethPayload; + + ethPayload.setData(tecmpEthPayload->getData(), static_cast(tecmpEthPayload->getDataLength())); + + packet->setPayload(ethPayload); + return packet; +} -PacketPtr TECMP::Converter::GetPackageFromTecmpHeader(const TECMP::CmpHeader& header) +PacketPtr TECMP::Converter::GetPacketFromTecmpHeader(const TECMP::CmpHeader& header) { PacketPtr packet = std::make_shared(); packet->setDeviceId(header.getDeviceId()); diff --git a/src/tecmp_decoder.cpp b/src/tecmp_decoder.cpp index 261a63b..dedb47c 100644 --- a/src/tecmp_decoder.cpp +++ b/src/tecmp_decoder.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -111,10 +112,16 @@ TecmpPayloadPtr TECMP::Decoder::GetDataPayload(const uint8_t* payloadData, const return payload; break; } + case CmpHeader::DataType::ethernet: + { + auto payload = GetEthernetPayload(payloadData, size); + if (payload->getMessageType() == CmpHeader::MessageType::data && payload->getType() == PayloadType::ethernet) + return payload; + break; + } case CmpHeader::DataType::flexRay: case CmpHeader::DataType::uartRs232: case CmpHeader::DataType::analog: - case CmpHeader::DataType::ethernet: case CmpHeader::DataType::invalid: break; // Not implimented } @@ -160,6 +167,14 @@ TecmpPayloadPtr TECMP::Decoder::GetLinPayload(const uint8_t* payloadData, const return {}; } +TecmpPayloadPtr TECMP::Decoder::GetEthernetPayload(const uint8_t* payloadData, const std::size_t size) +{ + EthernetPayload payload(payloadData, size); + if (payload.isValid()) + return std::make_shared(payload); + + return {}; +} std::vector TECMP::Decoder::ConvertPacketsToAsam(std::vector payloads, TECMP::CmpHeader& header) { std::vector packets; diff --git a/src/tecmp_ethernet_payload.cpp b/src/tecmp_ethernet_payload.cpp new file mode 100644 index 0000000..d45760d --- /dev/null +++ b/src/tecmp_ethernet_payload.cpp @@ -0,0 +1,20 @@ +#include + +BEGIN_NAMESPACE_TECMP + +EthernetPayload::EthernetPayload(const uint8_t* data, size_t size) + : Payload(TECMP::PayloadType::ethernet, data, size) +{ +} + +const uint8_t* EthernetPayload::getData() const +{ + return payloadData.data(); +} + +std::size_t EthernetPayload::getDataLength() const +{ + return payloadData.size(); +} + +END_NAMESPACE_TECMP diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 68bfb67..e8a4dc5 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -25,6 +25,7 @@ set(SRC_Cpp testapp.cpp test_tecmp_can_payload.cpp test_tecmp_interface_payload.cpp test_tecmp_decoder.cpp + test_tecmp_ethernet_payload.cpp ) add_executable(${TEST_APP} ${SRC_Cpp} diff --git a/tests/test_tecmp_decoder.cpp b/tests/test_tecmp_decoder.cpp index 2cec85e..f45766f 100644 --- a/tests/test_tecmp_decoder.cpp +++ b/tests/test_tecmp_decoder.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -9,6 +10,40 @@ using TECMP::Decoder; class TecmpDecoderFixture : public ::testing::Test { +public: + TecmpDecoderFixture() + { + tecmpEthernetPayloadFrame = { + 0x00, // IsTecmp + 0x7B, // deviceId + 0x00, 0x00, // sequenceCounter + 0x00, // version + 0x03, // messageType + 0x00, 0x80, // dataType (big-endian) + 0x00, 0x00, // reserved + 0x00, 0x00, // deviceFlags + 0x00, 0x00, 0x00, 0x7B, // interfaceId + 0x00, 0x00, 0x00, 0x61, 0x14, 0xB5, 0x3D, 0xE0, // timestamp + 0x00, 0x90, // payloadLength + 0x00, 0x00 // dataFlags + }; + + rawEthFrame = {0x0, 0xe0, 0x4c, 0x68, 0x6, 0x5c, 0x38, 0x2a, 0x19, 0x80, 0x40, 0x5e, 0x99, 0xfe, 0x0, 0x43, 0x0, 0x38, + 0x3, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0x0, 0xf, 0xff, 0x0, 0x0, 0x0, 0x0, 0x6, 0x4, 0xc5, + 0xd0, 0x8, 0x0, 0x78, 0x0, 0x0, 0xc, 0x1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x43, 0x1, 0x61, 0x16, 0xe1, + 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x50, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x90, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + + tecmpEthernetPayloadFrame.insert(tecmpEthernetPayloadFrame.end(), rawEthFrame.begin(), rawEthFrame.end()); + } + +protected: + std::vector tecmpEthernetPayloadFrame; + std::vector rawEthFrame; }; TEST_F(TecmpDecoderFixture, FailsWithASAMCMP) @@ -101,3 +136,24 @@ TEST_F(TecmpDecoderFixture, DecodeCanFdPayload) auto data2 = *(reinterpret_cast(payload.getData() + sizeof(double))); ASSERT_EQ(data2, 321.321); } + +TEST_F(TecmpDecoderFixture, DecodeEthernetPayload) +{ + auto packets = Decoder::Decode(tecmpEthernetPayloadFrame.data(), tecmpEthernetPayloadFrame.size()); + ASSERT_FALSE(packets.empty()); + ASSERT_EQ(packets.size(), 1u); + + ASSERT_EQ(packets[0]->getInterfaceId(), 123); + ASSERT_EQ(packets[0]->getDeviceId(), 123); + ASSERT_EQ(packets[0]->getTimestamp(), 0x0000006114b53de0u); + + auto payload = packets[0]->getPayload(); + ASSERT_EQ(payload.getMessageType(), ASAM::CMP::CmpHeader::MessageType::data); + ASSERT_EQ(payload.getType(), ASAM::CMP::PayloadType::ethernet); + + auto ethPayload = reinterpret_cast(payload); + std::vector frameBytes(ethPayload.getData(), ethPayload.getData() + ethPayload.getDataLength()); + + ASSERT_EQ(frameBytes.size(), rawEthFrame.size()); + ASSERT_EQ(frameBytes, rawEthFrame); +} diff --git a/tests/test_tecmp_ethernet_payload.cpp b/tests/test_tecmp_ethernet_payload.cpp new file mode 100644 index 0000000..d051799 --- /dev/null +++ b/tests/test_tecmp_ethernet_payload.cpp @@ -0,0 +1,37 @@ +#include + +#include +#include + +class TecmpEthernetPayloadTest : public ::testing::Test +{ +public: + TecmpEthernetPayloadTest() + { + data = {0x0, 0xe0, 0x4c, 0x68, 0x6, 0x5c, 0x38, 0x2a, 0x19, 0x80, 0x40, 0x5e, 0x99, 0xfe, 0x0, 0x43, 0x0, 0x38, 0x3, 0x2, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xf, 0x0, 0xf, 0xff, 0x0, 0x0, 0x0, 0x0, 0x6, 0x4, 0xc5, 0xd0, 0x8, 0x0, 0x78, 0x0, 0x0, + 0xc, 0x1, 0x4, 0x0, 0x0, 0x0, 0x0, 0x43, 0x1, 0x61, 0x16, 0xe1, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x30, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x50, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x90, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + payload = std::make_unique(data.data(), data.size()); + } + +protected: + std::vector data; + std::unique_ptr payload; +}; + +TEST_F(TecmpEthernetPayloadTest, IsValid) +{ + ASSERT_TRUE(payload->isValid()); +} + +TEST_F(TecmpEthernetPayloadTest, DataIntegrity) +{ + std::vector payloadData(payload->getData(), payload->getData() + payload->getDataLength()); + ASSERT_EQ(payloadData.size(), data.size()); + ASSERT_EQ(payloadData, data); +}