20#include <gmock/gmock.h>
21#include <gtest/gtest.h>
44using ::testing::StrictMock;
46constexpr std::array<std::uint8_t, 6>
kControllerMac{0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
48constexpr std::array<std::uint8_t, 6> kDeviceMac{0x02, 0x00, 0x00, 0x00, 0x00, 0x01};
50constexpr std::uint16_t kVlanTpid = 0x8100;
51constexpr std::uint16_t kVlanPcp6Vid0 = 0xC000;
52constexpr std::uint16_t kVlanPcp5Vid0 = 0xA000;
53constexpr std::uint16_t kProfinetEtherType = 0x8892;
55constexpr std::uint16_t kControllerReference = 1;
56constexpr std::uint16_t kDeviceReference = 42;
58constexpr std::uint8_t kRtaVersion = 1;
60constexpr std::uint8_t kRtaTypeData = 0x01;
61constexpr std::uint8_t kRtaTypeAck = 0x03;
62constexpr std::uint8_t kRtaTypeNack = 0x02;
63constexpr std::uint8_t kRtaTypeErr = 0x0F;
65constexpr std::uint8_t kAddFlagsWindow1 = 0x80;
66constexpr std::uint8_t kAddFlagsTack = 0x10;
71Bytes MakeChannelDiagnosisItem()
89[[nodiscard]]
Bytes BuildAlarmBlock(
bool highPriority =
false, std::uint16_t specifier = 0x0401, std::span<const std::uint8_t> items = {})
101 EXPECT_EQ(body.size(), 20U);
103 Bytes rest{0x01, 0x00};
105 rest.insert(rest.end(), body.begin(), body.end());
106 rest.insert(rest.end(), items.begin(), items.end());
108 const std::uint16_t blockType = highPriority ? 0x0001 : 0x0002;
113 wire::PutU16(block,
static_cast<std::uint16_t
>(rest.size()));
114 block.insert(block.end(), rest.begin(), rest.end());
133[[nodiscard]]
Bytes BuildRtaFrame(
138 std::span<const std::uint8_t>
varPart = {},
139 std::uint16_t
dstRef = kControllerReference,
140 std::uint16_t
srcRef = kDeviceReference,
141 std::uint8_t version = kRtaVersion,
149 rta.push_back(
static_cast<std::uint8_t
>((version << 4U) |
pduType));
160 frame.insert(
frame.end(), kDeviceMac.begin(), kDeviceMac.end());
170 frame.insert(
frame.end(), rta.begin(), rta.end());
212[[nodiscard]] SentRtaFrame ParseSentRta(std::span<const std::uint8_t>
frame)
214 EXPECT_GE(
frame.size(), 32U);
215 if (
frame.size() < 32U)
220 wire::Reader r(
frame);
226 EXPECT_EQ(r.U16(), kVlanTpid);
228 const std::uint16_t tci = r.U16();
229 EXPECT_TRUE(tci == kVlanPcp6Vid0 || tci == kVlanPcp5Vid0);
231 EXPECT_EQ(r.U16(), kProfinetEtherType);
234 result.frameId = r.U16();
235 result.dstRef = r.U16();
236 result.srcRef = r.U16();
237 result.pduType = r.U8();
238 result.addFlags = r.U8();
239 result.sendSeq = r.U16();
240 result.ackSeq = r.U16();
242 const std::uint16_t variablePartLength = r.U16();
243 EXPECT_EQ(
frame.size(), 32U + variablePartLength);
245 if (
frame.size() >= 32U + variablePartLength)
247 result.varPart.assign(
frame.begin() + 32,
frame.begin() + 32 + variablePartLength);
268 socket = std::make_unique<StrictMock<MockRawEthernetSocket>>();
278 ioContext = std::make_unique<asio::io_context>();
279 listener = std::make_unique<AlarmListener>(*
ioContext, endpoint, kControllerMac);
288 EXPECT_CALL(*
mockSocket, Recv()).WillOnce(::testing::Return(std::move(
frame)));
301 return ParseSentRta(
frame);
304 std::unique_ptr<testing::StrictMock<MockRawEthernetSocket>>
socket;
329 socket = std::make_unique<StrictMock<MockRawEthernetSocket>>();
339 ioContext = std::make_unique<asio::io_context>();
341 listener = std::make_unique<AlarmListener>(*
ioContext, endpoint, kControllerMac);
350 EXPECT_CALL(*
mockSocket, Recv()).WillOnce(::testing::Return(std::move(
frame)));
355 std::unique_ptr<testing::StrictMock<MockRawEthernetSocket>>
socket;
378 socket = std::make_unique<StrictMock<MockRawEthernetSocket>>();
387 ioContext = std::make_unique<asio::io_context>();
388 listener = std::make_unique<AlarmListener>(*
ioContext, endpoint, kControllerMac);
397 EXPECT_CALL(*
mockSocket, Recv()).WillOnce(::testing::Return(std::move(
frame)));
402 std::unique_ptr<testing::StrictMock<MockRawEthernetSocket>>
socket;
417 const Bytes alarm = BuildAlarmBlock();
419 EXPECT_CALL(*mockSocket, Send(_)).Times(1).WillOnce([&](
const Bytes&
frame)
421 const SentRtaFrame sent = ParseSentFrame(
frame);
424 EXPECT_EQ(sent.pduType, 0x11);
425 EXPECT_EQ(sent.dstRef, kDeviceReference);
426 EXPECT_EQ(sent.srcRef, kControllerReference);
427 EXPECT_EQ(sent.varPart.size(), alarm.size() - 4U);
430 Feed(BuildRtaFrame(kRtaTypeData,
431 static_cast<std::uint8_t
>(kAddFlagsWindow1 | kAddFlagsTack),
435 kControllerReference,
445 const Bytes alarm = BuildAlarmBlock();
446 EXPECT_CALL(*mockSocket, Send(_)).Times(1).WillOnce([&](
const Bytes&
frame)
448 const SentRtaFrame sent = ParseSentFrame(
frame);
450 EXPECT_EQ(sent.pduType, 0x11);
452 Feed(BuildRtaFrame(kRtaTypeData,
453 static_cast<std::uint8_t
>(kAddFlagsWindow1 | kAddFlagsTack),
457 kControllerReference,
467 const Bytes alarm = BuildAlarmBlock(
true);
469 EXPECT_CALL(*mockSocket, Send(_)).Times(1).WillOnce([&](
const Bytes&
frame)
471 const SentRtaFrame sent = ParseSentFrame(
frame);
474 EXPECT_EQ(sent.pduType, 0x11);
477 Feed(BuildRtaFrame(kRtaTypeData,
478 static_cast<std::uint8_t
>(kAddFlagsWindow1 | kAddFlagsTack),
482 kControllerReference,
502 EXPECT_CALL(*mockSocket, Send(_)).Times(0);
504 Feed(std::move(
frame));
524 EXPECT_CALL(*mockSocket, Send(_)).Times(0);
526 Feed(std::move(
frame));
532 EXPECT_CALL(*mockSocket, Send(_)).Times(0);
534 Feed(BuildRtaFrame(kRtaTypeData,
535 static_cast<std::uint8_t
>(
548 EXPECT_CALL(*mockSocket, Send(_)).Times(0);
550 Feed(
Bytes(15U, 0x00));
556 EXPECT_CALL(*mockSocket, Send(_)).Times(1).WillOnce([&](
const Bytes&
frame)
558 ASSERT_GE(
frame.size(), 20U);
563 EXPECT_EQ(r.
U16(), kVlanTpid);
565 const std::uint16_t tci = r.
U16();
567 EXPECT_TRUE(tci == kVlanPcp6Vid0 || tci == kVlanPcp5Vid0);
569 EXPECT_EQ(r.
U16(), kProfinetEtherType);
572 Feed(BuildRtaFrame(kRtaTypeData,
573 static_cast<std::uint8_t
>(
584 EXPECT_CALL(*mockSocket, Send(_)).Times(1).WillOnce([&](
const Bytes&
frame)
586 const SentRtaFrame sent = ParseSentFrame(
frame);
588 EXPECT_EQ(sent.pduType, 0x11);
591 Feed(BuildRtaFrame(kRtaTypeData,
592 static_cast<std::uint8_t
>(
603 EXPECT_CALL(*mockSocket, Send(_)).Times(1).WillOnce([&](
const Bytes&
frame)
605 const SentRtaFrame sent = ParseSentFrame(
frame);
607 EXPECT_EQ(sent.dstRef, kDeviceReference);
609 EXPECT_EQ(sent.srcRef, kControllerReference);
612 Feed(BuildRtaFrame(kRtaTypeData,
613 static_cast<std::uint8_t
>(
624 constexpr std::uint16_t kReceivedSequence = 0x1234;
626 EXPECT_CALL(*mockSocket, Send(_)).Times(1).WillOnce([&](
const Bytes&
frame)
628 const SentRtaFrame sent = ParseSentFrame(
frame);
630 EXPECT_EQ(sent.ackSeq, kReceivedSequence);
633 Feed(BuildRtaFrame(kRtaTypeData,
634 static_cast<std::uint8_t
>(
645 std::vector<AlarmNotification> received;
647 listener->AddAlarmNotificationCallback([&received](
const AlarmNotification& alarm)
649 received.push_back(alarm);
652 EXPECT_CALL(*mockSocket, Send(_)).Times(1);
654 Feed(BuildRtaFrame(kRtaTypeData,
655 static_cast<std::uint8_t
>(kAddFlagsWindow1 | kAddFlagsTack),
660 ASSERT_EQ(received.size(), 1U);
661 EXPECT_EQ(received[0].slotNumber, 1U);
667 std::uint32_t callback1Count = 0;
668 std::uint32_t callback2Count = 0;
670 listener->AddAlarmNotificationCallback([&callback1Count](
const AlarmNotification&)
671 { ++callback1Count; });
672 listener->AddAlarmNotificationCallback([&callback2Count](
const AlarmNotification&)
673 { ++callback2Count; });
675 EXPECT_CALL(*mockSocket, Send(_)).Times(1);
677 Feed(BuildRtaFrame(kRtaTypeData,
678 static_cast<std::uint8_t
>(kAddFlagsWindow1 | kAddFlagsTack),
683 EXPECT_EQ(callback1Count, 1U);
684 EXPECT_EQ(callback2Count, 1U);
690 listener->AddAlarmNotificationCallback({});
692 EXPECT_CALL(*mockSocket, Send(_)).Times(1);
694 Feed(BuildRtaFrame(kRtaTypeData,
695 static_cast<std::uint8_t
>(kAddFlagsWindow1 | kAddFlagsTack),
704 std::uint32_t callbackCount = 0;
708 throw std::runtime_error(
"test callback failure");
711 listener->AddAlarmNotificationCallback([&callbackCount](
const AlarmNotification&)
712 { ++callbackCount; });
714 EXPECT_CALL(*mockSocket, Send(_)).Times(1);
716 EXPECT_NO_THROW(Feed(BuildRtaFrame(kRtaTypeData,
717 static_cast<std::uint8_t
>(kAddFlagsWindow1 | kAddFlagsTack),
720 BuildAlarmBlock())));
722 EXPECT_EQ(callbackCount, 1U);
728 std::uint32_t alarmCount = 0;
733 EXPECT_CALL(*mockSocket, Send(_)).Times(2);
735 Feed(BuildRtaFrame(kRtaTypeData,
736 static_cast<std::uint8_t
>(kAddFlagsWindow1 | kAddFlagsTack),
741 Feed(BuildRtaFrame(kRtaTypeData,
742 static_cast<std::uint8_t
>(kAddFlagsWindow1 | kAddFlagsTack),
747 EXPECT_EQ(alarmCount, 2U);
753 EXPECT_CALL(*mockSocket, Send(_)).Times(0);
755 const Bytes invalidAlarm{0x00, 0x01, 0x00, 0x02, 0x00, 0x00};
757 Feed(BuildRtaFrame(kRtaTypeData,
758 static_cast<std::uint8_t
>(kAddFlagsWindow1 | kAddFlagsTack),
771 EXPECT_CALL(*mockSocket, Send(_)).Times(0);
772 const Bytes alarm = BuildAlarmBlock(
775 MakeChannelDiagnosisItem());
779 static_cast<std::uint8_t
>(kAddFlagsWindow1 | kAddFlagsTack),
783 kControllerReference,
789 Feed(std::move(
frame));
799 EXPECT_CALL(*mockSocket, Send(_)).Times(0);
801 Feed(BuildRtaFrame(kRtaTypeData, kAddFlagsWindow1, 0xFFFF, 0xFFFE, BuildAlarmBlock()));
814 std::uint32_t alarmCount = 0;
819 const Bytes frame = BuildRtaFrame(kRtaTypeData,
820 static_cast<std::uint8_t
>(kAddFlagsWindow1 | kAddFlagsTack),
825 EXPECT_CALL(*mockSocket, Send(_)).Times(2);
830 EXPECT_EQ(alarmCount, 1U);
842 std::uint32_t alarmCount = 0;
847 EXPECT_CALL(*mockSocket, Send(_)).Times(1);
849 Feed(BuildRtaFrame(kRtaTypeData,
850 static_cast<std::uint8_t
>(kAddFlagsWindow1 | kAddFlagsTack),
855 EXPECT_EQ(alarmCount, 0U);
868 EXPECT_CALL(*mockSocket, Send(_)).Times(1).WillOnce([&](
const Bytes&
frame)
870 const SentRtaFrame sent = ParseSentFrame(
frame);
872 EXPECT_EQ(sent.sendSeq, 0x01);
875 Feed(BuildRtaFrame(kRtaTypeData,
876 static_cast<std::uint8_t
>(kAddFlagsWindow1 | kAddFlagsTack),
907 header.
payload.assign(status.begin(), status.end());
908 header.
payload.insert(header.
payload.end(), padding.begin(), padding.end());
917 const Bytes data = BuildRtaErrorPdu({0xCFU, 0x81U, 0xFDU, 0x0FU},
918 {0x00U, 0x00U, 0x00U, 0x00U});
922 EXPECT_EQ(
error.header.alarmDstEndpoint, 0x8001U);
923 EXPECT_EQ(
error.header.alarmSrcEndpoint, 0x0000U);
924 EXPECT_EQ(
error.header.pduType, 0x14U);
925 EXPECT_EQ(
error.header.addFlags, 0x01U);
926 EXPECT_EQ(
error.header.sendSeqNum, 0xFFFFU);
927 EXPECT_EQ(
error.header.ackSeqNum, 0xFFFEU);
928 EXPECT_EQ(
error.header.variablePartLenght, 4U);
930 EXPECT_EQ(
error.statusPnio, 0xCF81FD0FU);
931 EXPECT_EQ(
error.errorCode, 0xCFU);
932 EXPECT_EQ(
error.errorDecode, 0x81U);
933 EXPECT_EQ(
error.errorCode1, 0xFDU);
934 EXPECT_EQ(
error.errorCode2, 0x0FU);
936 EXPECT_TRUE(
error.IsRtaProtocolError());
938 EXPECT_EQ(
error.ReasonName(),
"AR release.ind received");
944 const Bytes data = BuildRtaErrorPdu(
945 {0xCFU, 0x81U, 0xFDU, 0x0FU},
950 EXPECT_EQ(
error.statusPnio, 0xCF81FD0FU);
951 EXPECT_EQ(
error.errorCode2, 0x0FU);
961 header.
payload = {0xCFU, 0x81U, 0xFDU, 0x0FU};
973 header.
payload = {0xCFU, 0x81U, 0xFDU};
985 header.
payload = {0xCFU, 0x81U, 0xFDU};
993 const Bytes data = BuildRtaErrorPdu(
994 {0xCFU, 0x81U, 0xFDU, 0x01U});
998 EXPECT_TRUE(
error.IsRtaProtocolError());
1000 EXPECT_EQ(
error.ReasonName(),
"Error within the coordination of sequence numbers");
1006 const Bytes data = BuildRtaErrorPdu({0x81U, 0x81U, 0x05U, 0x00U});
1010 EXPECT_FALSE(
error.IsRtaProtocolError());
1012 EXPECT_EQ(
error.ReasonName(),
"Reserved");
1037 const auto testCase = GetParam();
1041 static_cast<std::uint8_t
>(
1045 header.
payload = {0xCFU, 0x81U, 0xFDU, testCase.code};
1049 EXPECT_EQ(
error.errorCode, 0xCFU);
1050 EXPECT_EQ(
error.errorDecode, 0x81U);
1051 EXPECT_EQ(
error.errorCode1, 0xFDU);
1052 EXPECT_EQ(
error.errorCode2, testCase.code);
1053 EXPECT_EQ(
error.ErrorClass(), testCase.errorClass);
1108 [](const ::testing::TestParamInfo<RtaErrorReasonTestCase>& info)
1110 return std::format(
"{:#04x}", info.param.code);
1116 constexpr std::uint8_t kUnknownErrorCode2 = 0x30;
Private-access adapter used by AlarmListener tests.
Declares the PROFINET RTA alarm listener and AlarmAck transmission support.
Declares PROFINET alarm, diagnosis, maintenance, and USI payload types and parsers.
Test fixture for AlarmListener callback behavior.
std::unique_ptr< AlarmListener > listener
Listener under test.
std::unique_ptr< testing::StrictMock< MockRawEthernetSocket > > socket
Mock Ethernet transport pointer owned by the listener.
StrictMock< MockRawEthernetSocket > * mockSocket
Mock Ethernet transport owned by the listener.
void Feed(Bytes frame)
Inject one Ethernet frame into the listener.
std::unique_ptr< asio::io_context > ioContext
Shared ASIO context.
void SetUp() override
Construct the listener with a mocked Layer 2 transport.
Test fixture for multi-frame RTA alarm exchanges.
std::unique_ptr< asio::io_context > ioContext
Shared ASIO context.
std::unique_ptr< testing::StrictMock< MockRawEthernetSocket > > socket
Mock Ethernet transport pointer owned by the listener.
StrictMock< MockRawEthernetSocket > * mockSocket
Mock Ethernet transport owned by the listener.
void Feed(Bytes frame)
Inject one Ethernet frame into the listener.
std::unique_ptr< AlarmListener > listener
Listener under test.
void SetUp() override
Construct the listener with a mocked Layer 2 transport.
Test fixture for Layer 2 RTA alarm handling.
StrictMock< MockRawEthernetSocket > * mockSocket
Mock Ethernet transport owned by the listener.
void SetUp() override
Construct the test listener with a mocked raw Ethernet socket.
std::unique_ptr< asio::io_context > ioContext
Shared ASIO context.
void Feed(Bytes frame)
Inject one Ethernet frame into the listener.
static SentRtaFrame ParseSentFrame(std::span< const std::uint8_t > frame)
Return all transmitted RTA frames.
std::unique_ptr< testing::StrictMock< MockRawEthernetSocket > > socket
Mock Ethernet transport pointer owned by the listener.
std::unique_ptr< AlarmListener > listener
Listener under test.
static void SetSock(AlarmListener &listener, std::unique_ptr< IRawEthernetSocket > sock)
Set the Layer 2 Ethernet socket used by the listener.
static void HandleLayer2Frame(AlarmListener &listener)
Receive and process one Layer 2 RTA frame.
Tests for PROFINET RTA ERR-PDU decoding.
static Bytes BuildRtaErrorPdu(std::array< std::uint8_t, 4 > status, const Bytes &padding={})
Build the RTA header used by the AUMA ERR-RTA example.
Lightweight cursor for parsing a big-endian byte buffer without copies.
std::array< std::uint8_t, N > Fixed()
Read and consume a fixed-size byte array.
std::uint16_t U16()
Read and consume a big-endian 16-bit value.
GoogleMock implementation of IRawEthernetSocket.
constexpr MacAddress kControllerMac
void PutU16(std::vector< std::uint8_t > &out, std::uint16_t value)
Append a 16-bit value to a buffer in big-endian order.
void PutU32(std::vector< std::uint8_t > &out, std::uint32_t value)
Append a 32-bit value to a buffer in big-endian order.
TEST_F(AlarmListenerTests, InitializesWithEndpoint)
TEST(AlarmEndpointTests, DefaultTransportIsLayer2)
std::array< std::uint8_t, macAddressLength > MacAddress
A 6-byte Ethernet MAC address.
RtaErrorReason
Exact current PROFINET RTA ErrorCode2 values.
@ PdevPlugPortWithoutCombinedObjectContainer
@ ArAddProviderConsumerFailed
@ ArRpcClientCallConfirmationNegative
@ PdevNoRequiredSpeedDuplexity
@ IocarSrRedundantInterfaceLost
@ IocarSrPdevParameterizationImpossible
@ RemoteApplicationReadyTimeout
@ ObsoletedNmeNoConfiguration
@ ArAlarmSendConfirmationNegative
@ ArConsumerDhtWdtExpired
@ CompanionAr8ippSubmodule
@ DcpResetToFactorySettings
@ IocarSrArProtocolViolation
@ ArAlarmAckSendConfirmationNegative
@ ArMulticastMacRegistrationFailed
RtaError ParseRtaError(const PNRTAHeader &header)
Parse an RTA ERR-PDU from an already parsed RTA header.
constexpr int macAddressLength
Constant lenght of a mac address.
TEST_P(RtaErrorsTests, EveryDefinedReasonIsDecoded)
RtaErrorClass
Classification of an RTA protocol error reason.
@ SequenceNumber
Error coordinating RTA sequence numbers.
@ Abort
RTA error that aborts the application relation.
@ Reserved
No error / reserved reason.
@ Obsoleted
Obsoleted reason code.
@ Extended
Additional AR/IOCARSR/PDEV RTA reason defined by PROFINET.
std::vector< std::uint8_t > Bytes
Generic byte buffer alias used throughout the library for raw wire data.
INSTANTIATE_TEST_SUITE_P(AllDefinedReasons, RtaErrorsTests, ::testing::Values(RtaErrorReasonTestCase{0x00, RtaErrorReason::Reserved, RtaErrorClass::Reserved}, RtaErrorReasonTestCase{0x01, RtaErrorReason::SequenceNumber, RtaErrorClass::SequenceNumber}, RtaErrorReasonTestCase{0x02, RtaErrorReason::InstanceClosed, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x03, RtaErrorReason::ArOutOfMemory, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x04, RtaErrorReason::ArAddProviderConsumerFailed, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x05, RtaErrorReason::ArConsumerDhtWdtExpired, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x06, RtaErrorReason::ArCmiTimeout, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x07, RtaErrorReason::ArAlarmOpenFailed, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x08, RtaErrorReason::ArAlarmSendConfirmationNegative, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x09, RtaErrorReason::ArAlarmAckSendConfirmationNegative, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x0A, RtaErrorReason::ArAlarmDataTooLong, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x0B, RtaErrorReason::ArAlarmIndError, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x0C, RtaErrorReason::ArRpcClientCallConfirmationNegative, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x0D, RtaErrorReason::ArAbortRequest, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x0E, RtaErrorReason::ArRerunAbortsExisting, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x0F, RtaErrorReason::ArReleaseIndReceived, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x10, RtaErrorReason::ArDeviceDeactivated, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x11, RtaErrorReason::ArRemoved, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x12, RtaErrorReason::ArProtocolViolation, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x13, RtaErrorReason::ArNameResolutionError, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x14, RtaErrorReason::ArRpcBindError, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x15, RtaErrorReason::ArRpcConnectError, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x16, RtaErrorReason::ArRpcReadError, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x17, RtaErrorReason::ArRpcWriteError, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x18, RtaErrorReason::ArRpcControlError, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x19, RtaErrorReason::ArForbiddenPullPlug, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x1A, RtaErrorReason::ArApRemoved, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x1B, RtaErrorReason::ArLinkDown, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x1C, RtaErrorReason::ArMulticastMacRegistrationFailed, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x1D, RtaErrorReason::NotSynchronized, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x1E, RtaErrorReason::WrongTopology, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x1F, RtaErrorReason::DcpStationNameChanged, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x20, RtaErrorReason::DcpResetToFactorySettings, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x21, RtaErrorReason::CompanionAr8ippSubmodule, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x22, RtaErrorReason::NoIrdataRecordYet, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x23, RtaErrorReason::Pdev, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x24, RtaErrorReason::PdevNoRequiredSpeedDuplexity, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x25, RtaErrorReason::IpSuiteChanged, RtaErrorClass::Abort}, RtaErrorReasonTestCase{0x26, RtaErrorReason::IocarSrRdhtExpired, RtaErrorClass::Extended}, RtaErrorReasonTestCase{0x27, RtaErrorReason::IocarSrPdevParameterizationImpossible, RtaErrorClass::Extended}, RtaErrorReasonTestCase{0x28, RtaErrorReason::RemoteApplicationReadyTimeout, RtaErrorClass::Extended}, RtaErrorReasonTestCase{0x29, RtaErrorReason::IocarSrRedundantInterfaceLost, RtaErrorClass::Extended}, RtaErrorReasonTestCase{0x2A, RtaErrorReason::IocarSrMtotExpired, RtaErrorClass::Extended}, RtaErrorReasonTestCase{0x2B, RtaErrorReason::IocarSrArProtocolViolation, RtaErrorClass::Extended}, RtaErrorReasonTestCase{0x2C, RtaErrorReason::PdevPlugPortWithoutCombinedObjectContainer, RtaErrorClass::Extended}, RtaErrorReasonTestCase{0x2D, RtaErrorReason::ObsoletedNmeNoConfiguration, RtaErrorClass::Obsoleted}, RtaErrorReasonTestCase{0xFF, RtaErrorReason::UserAbort, RtaErrorClass::Abort}), [](const ::testing::TestParamInfo< RtaErrorReasonTestCase > &info) { return std::format("{:#04x}", info.param.code);})
constexpr std::uint16_t FRAME_ID_ALARM_HIGH
Frame ID used for high-priority alarms.
constexpr std::uint16_t FRAME_ID_ALARM_LOW
Frame ID used for low-priority alarms.
PROFINET protocol wire-format structures and serialization helpers.
Alarm endpoint configuration.
int transport
Transport: 0 = Layer2 (RTA), 1 = UDP.
std::string interface
Network interface name to bind to, e.g. "eth0".
std::uint16_t controllerRef
Controller's local alarm reference (from AlarmCRBlockReq).
std::uint16_t deviceRef
Device's local alarm reference (from AlarmCRBlockRes).
MacAddress deviceMac
The device's MAC address.
Complete parsed AlarmNotification PDU: header fields + parsed items.
One complete RTA ErrorCode2 test case.
std::uint8_t code
ErrorCode2 byte.
RtaErrorClass errorClass
Expected semantic class.
RtaErrorReason errorReason
Expected error reason.
Decoded PROFINET RTA ERR-PDU.
static RtaErrorReason ClassifyRtaErrorReason(std::uint8_t errorCode2)
Return the decoded RTA reason.
static RtaErrorClass ClassifyRtaError(std::uint8_t errorCode2)
Return the decoded RTA reason.
std::uint8_t pduType
RTA PDU type including version nibble.
std::uint16_t srcRef
RTA source alarm endpoint.
std::uint8_t addFlags
RTA AdditionalFlags field.
std::uint16_t dstRef
RTA destination alarm endpoint.
std::uint16_t sendSeq
RTA SendSeqNum.
std::uint16_t frameId
Ethernet FrameID.
Bytes varPart
RTA variable part.
std::uint16_t ackSeq
RTA AckSeqNum.