18#include <gtest/gtest.h>
28constexpr std::array<std::uint8_t, 6>
kControllerMac{0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
29constexpr std::array<std::uint8_t, 6> kDeviceMac{0x02, 0x00, 0x00, 0x00, 0x00, 0x01};
30constexpr std::array<std::uint8_t, 4> kVlanTag{0x81, 0x00, 0xC0, 0x00};
31constexpr std::uint16_t kProfinetEtherType = 0x8892;
127 return std::make_unique<CyclicController>(
152 payload = {0xAA, 0xBB, 0xCC, 0xDD, 0x80};
167 frame.insert(
frame.end(), kControllerMac.begin(), kControllerMac.end());
169 frame.insert(
frame.end(), kDeviceMac.begin(), kDeviceMac.end());
173 frame.insert(
frame.end(), kVlanTag.begin(), kVlanTag.end());
176 frame.push_back(
static_cast<std::uint8_t
>((kProfinetEtherType >> 8U) & 0xFFU));
178 frame.push_back(
static_cast<std::uint8_t
>(kProfinetEtherType & 0xFFU));
182 frame.insert(
frame.end(), rtBytes.begin(), rtBytes.end());
192 InvokeProcessInputFrame(BuildInputFrame());
194 EXPECT_EQ(
controller->StatsSnapshot().framesReceived, 1U);
196 const auto data =
controller->GetInputData(1, 1);
198 ASSERT_TRUE(data.has_value());
207 InvokeProcessInputFrame(BuildInputFrame(
true));
209 EXPECT_EQ(
controller->StatsSnapshot().framesReceived, 1U);
211 const auto data =
controller->GetInputData(1, 1);
213 ASSERT_TRUE(data.has_value());
226 InvokeProcessInputFrame(BuildInputFrame(
false, 1));
228 EXPECT_EQ(
controller->StatsSnapshot().framesInvalid, 1U);
229 EXPECT_FALSE(
controller->GetInputData(1, 1).has_value());
246 EXPECT_EQ(
controller->StatsSnapshot().framesSent, 1U);
Declares the PROFINET RTC1 cyclic IO controller and process-data exchange API.
TEST_F(CyclicTest, CyclicStateToStringCoversAllStates)
CyclicState
Lifecycle state of a CyclicController.
@ Fault
Communication failure (e.g. consecutive watchdog timeouts).
@ Running
Active cyclic data exchange.
constexpr std::uint16_t IOCR_TYPE_INPUT
IOCR direction: Device -> Controller.
constexpr std::uint16_t IOCR_TYPE_OUTPUT
IOCR direction: Controller -> Device.
constexpr MacAddress kControllerMac
std::vector< std::uint8_t > Bytes
Generic byte buffer alias used throughout the library for raw wire data.
Declares PROFINET RT_CLASS_1 cyclic frame and IOCR data structures.
IOCR configuration derived from AR setup: timing parameters and IO object mappings needed for cyclic ...
std::vector< IODataObject > objects
IO data objects carried in this IOCR's cyclic frame.
std::uint16_t dataLength
Total cyclic data length in bytes.
std::uint16_t typeIOCR
IOCR direction: 1=Input, 2=Output.
std::uint16_t referenceIOCR
IOCR reference assigned during AR establishment.
std::uint16_t sendClockFactor
Send clock base factor (31.25us units).
std::uint16_t frameId
Frame ID assigned to this IOCR.
std::uint16_t reductionRatio
Reduction ratio relative to the send clock.
std::uint16_t watchdogFactor
Watchdog factor (missed-frame tolerance before a timeout fault).
Single IO data object within the C_SDU: one piece of process data mapped to a slot/subslot,...
std::uint16_t slot
Slot number.
A single PROFINET Real-Time cyclic frame: Frame ID + C_SDU payload + cycle counter/status trailer.
std::uint8_t dataStatus
Data status bitmask (see DATA_STATUS_* constants).
std::uint8_t transferStatus
Transfer status (0 = OK).
Bytes ToBytes() const
Serialize this frame back to raw bytes.
std::uint16_t frameId
Frame ID identifying which IOCR this frame belongs to.
std::uint16_t cycleCounter
Cycle counter, incremented each transmission.
static constexpr std::uint8_t DATA_RUN
Alias for DATA_STATUS_PROVIDER_RUN, for readability at call sites.
static constexpr std::uint8_t DATA_VALID
Alias for DATA_STATUS_VALID, for readability at call sites.
Bytes payload
C_SDU payload: process data plus IOPS/IOCS trailers.
std::unique_ptr< cyclic::CyclicController > controller
std::unique_ptr< asio::io_context > ioContext
Shared ASIO context.