97 std::atomic<std::chrono::steady_clock::time_point>
lastReceiveTime{std::chrono::steady_clock::now()};
263 std::optional<Bytes>
GetInputData(
int slot,
int subslot,
bool allowBad =
false)
const;
282 void OnInputStatus(std::function<
void(std::uint16_t slot, std::uint16_t subslot, std::uint8_t iops)> callback);
286 void OnInput(std::function<
void(
int slot,
int subslot,
const Bytes& data)> callback);
290 void OnTimeout(std::function<
void()> callback);
294 void OnError(std::function<
void(
const std::string&)> callback);
304 void Start()
override;
310 void Stop()
override;
347 [[nodiscard]] std::optional<std::uint8_t>
GetInputStatus(std::uint16_t slot, std::uint16_t subslot)
const;
359 [[nodiscard]]
bool IsInputGood(std::uint16_t slot, std::uint16_t subslot)
const;
390 void SendOutputFrame(std::optional<std::uint8_t> dataStatusOverride = std::nullopt);
414 [[nodiscard]]
bool LocalIsInputGood(std::uint16_t slot, std::uint16_t subslot)
const;
418 std::map<std::pair<std::uint16_t, std::uint16_t>, std::uint8_t>
inputStatus;
494 std::function<void(
const std::string&)>
onError;
RT_CLASS_1 cyclic data exchange controller.
void OnInputStatus(std::function< void(std::uint16_t slot, std::uint16_t subslot, std::uint8_t iops)> callback)
Register a callback for PROFINET provider status (IOPS) changes.
const CyclicStats & Stats() const
Communication statistics for this controller.
bool iocsGood
Tracks the watchdog-driven IOCS state so the RX/timeout paths only rewrite the buffer on transitions ...
void TrackCycleCounter(std::uint16_t rxCounter)
Update cycle-counter tracking stats (gaps/duplicates/reordering) for a received frame.
bool IsRunning() const
Whether the controller is actively exchanging cyclic data.
std::uint32_t rxCounterStep
Expected cycle-counter increment per received input frame.
rt::CyclicDataBuilder outputBuilder
Double-buffered builder for output cyclic data.
void SetOutputData(int slot, int subslot, const Bytes &data)
Set output data for the next cycle.
std::uint32_t txCounterStep
Cycle-counter increment applied per sent output frame.
std::string interface
Network interface name.
void SendOutputFrame(std::optional< std::uint8_t > dataStatusOverride=std::nullopt)
Build and send one output frame.
friend class ReceivedIopsTest
void TxLoop()
TX thread body: sends output frames at the configured cycle rate.
CyclicController(const CyclicController &)=delete
Not copyable (owns sockets and background threads).
std::mutex inputLock
Guards inputData against concurrent access.
void TxCycle()
Swap the output buffer and transmit one cyclic output frame.
std::thread txThread
Thread sending output frames.
void SendStopFrames()
Send STOP_FRAME_COUNT output frames with ProviderRun cleared.
rt::IOCRConfig outputIocr
Configuration for the output (controller -> device) IOCR.
void OnError(std::function< void(const std::string &)> callback)
Register a callback invoked on TX/RX socket errors.
std::function< void(int, int, const std::uint8_t)> onInputStatus
Registered OnInputStatus callback, if any.
void OnStateChange(std::function< void(CyclicState oldState, CyclicState newState)> callback)
Register a callback invoked on every state transition.
void Stop() override
Stop gracefully.
~CyclicController() override
Stop (if running) and release resources.
std::atomic< bool > running
Whether the TX/RX threads should keep running.
void Transition(CyclicState newState)
Change state and invoke the OnStateChange callback if registered.
void CheckCycleTime()
Validate the configured cycle time, throwing if it's below 1ms.
void RxLoop()
RX thread body: receives and processes input frames, checking the watchdog.
std::optional< Bytes > GetInputData(int slot, int subslot, bool allowBad=false) const
Get the latest input data received from the device, if any or IOPS is BAD.
void HandleWatchdogTimeout()
Handle a watchdog timeout: update stats and possibly transition to Fault.
std::map< std::pair< std::uint16_t, std::uint16_t >, std::uint8_t > inputStatus
Last provider status (IOPS) the device sent per submodule. Payload bytes are only meaningful while th...
CyclicState State() const
The controller's current lifecycle state.
std::function< void()> onTimeout
Registered OnTimeout callback, if any.
CyclicController & operator=(const CyclicController &)=delete
Not copyable (owns sockets and background threads).
int maxConsecutiveTimeouts
Consecutive watchdog timeouts before transitioning to Fault.
rt::IOCRConfig inputIocr
Configuration for the input (device -> controller) IOCR.
std::optional< EthernetSocket > rxSock
Raw socket used for receiving input frames.
MacAddress srcMac
This host's MAC address.
void OnTimeout(std::function< void()> callback)
Register a callback invoked on each watchdog timeout.
bool LocalIsInputGood(std::uint16_t slot, std::uint16_t subslot) const
Check whether a submodule has GOOD provider status without locking.
CyclicStatsSnapshot StatsSnapshot() const
std::atomic< CyclicState > state
Current lifecycle state.
bool IsInputGood(std::uint16_t slot, std::uint16_t subslot) const
Check whether the device currently reports GOOD provider status.
std::function< void(CyclicState, CyclicState)> onStateChange
Registered OnStateChange callback, if any.
std::optional< std::uint8_t > GetInputStatus(std::uint16_t slot, std::uint16_t subslot) const
Get the last provider status (IOPS) received for a submodule.
std::function< void(const std::string &)> onError
Registered OnError callback, if any.
std::uint16_t etherType
Current lifecycle state.
std::optional< EthernetSocket > txSock
Raw socket used for sending output frames.
std::map< std::pair< int, int >, Bytes > inputData
Latest received data per (slot, subslot).
friend class CyclicControllerConformanceTest
std::thread rxThread
Thread receiving input frames.
MacAddress dstMac
The device's MAC address.
std::function< void(int, int, const Bytes &)> onInputData
Registered OnInput callback, if any.
void ProcessInputFrame(const Bytes &data)
Parse and process one received input frame.
void Start() override
Create TX/RX sockets and spawn the TX/RX threads.
std::uint16_t cycleCounter
Current TX cycle counter value.
CyclicStats stats
Communication statistics.
void OnInput(std::function< void(int slot, int subslot, const Bytes &data)> callback)
Register a callback invoked whenever new input data is received.
std::optional< std::uint16_t > lastRxCycleCounter
Last received cycle counter, for gap/duplicate/reorder detection.
Abstract interface for controlling cyclic PROFINET communication.
virtual void Start()=0
Starts cyclic PROFINET communication.
virtual ~ICyclicController()=default
Virtual destructor.
virtual void Stop()=0
Stops cyclic PROFINET communication.
Builds C_SDU payload from IO data objects with double-buffering.
constexpr int DEFAULT_MAX_CONSECUTIVE_TIMEOUTS
Default number of consecutive watchdog timeouts before transitioning to Fault.
std::string ToString(CyclicState state)
Human-readable name for a CyclicState value.
constexpr int MIN_CYCLE_MS
Minimum cycle time (ms) considered reliable.
CyclicState
Lifecycle state of a CyclicController.
@ Fault
Communication failure (e.g. consecutive watchdog timeouts).
@ Running
Active cyclic data exchange.
@ Stopping
Graceful shutdown in progress (sending STOP frames).
@ Stopped
Fully stopped, threads joined.
@ Starting
Sockets created, threads launching.
@ Idle
Initial state, not yet started.
constexpr int RECOMMENDED_CYCLE_MS
Recommended cycle time (ms).
constexpr int STOP_FRAME_COUNT
Number of STOP frames sent during a graceful Stop().
constexpr std::uint16_t ETHERTYPE_PROFINET
EtherType used by PROFINET RT frames (0x8892).
std::array< std::uint8_t, macAddressLength > MacAddress
A 6-byte Ethernet MAC address.
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.
Copyable snapshot of cyclic communication statistics.
std::uint64_t cycleTimeSumUs
std::uint32_t minCycleTimeUs
std::uint32_t maxJitterUs
std::uint64_t framesDuplicate
std::uint64_t framesOutOfOrder
std::uint64_t framesMissed
std::uint64_t framesReceived
std::chrono::steady_clock::time_point lastReceiveTime
std::uint64_t framesInvalid
std::uint32_t lastCycleTimeUs
std::uint64_t AvgCycleTimeUs() const
Compute average TX cycle duration.
std::uint32_t maxCycleTimeUs
Statistics for cyclic communication.
void Reset()
Reset all counters to their initial values.
std::atomic< std::uint32_t > maxJitterUs
Largest observed deviation from the target cycle time, in microseconds.
std::uint64_t AvgCycleTimeUs() const
Compute the average TX cycle duration.
std::atomic< std::uint64_t > framesReceived
Total number of input frames received.
std::atomic< std::uint64_t > framesInvalid
Total number of frames rejected for having an invalid DataStatus.
std::atomic< std::uint64_t > framesOutOfOrder
Total number of frames received out of cycle-counter order.
std::atomic< std::uint32_t > minCycleTimeUs
Smallest observed TX cycle duration, in microseconds.
std::atomic< std::uint64_t > cycleTimeSumUs
Running sum of observed TX cycle durations, in microseconds.
std::atomic< std::uint64_t > framesDuplicate
Total number of duplicate (repeated cycle counter) frames received.
std::atomic< std::uint64_t > framesMissed
Total number of watchdog timeouts (missed input frames).
std::atomic< std::uint32_t > lastCycleTimeUs
Duration of the most recently completed TX cycle, in microseconds.
std::atomic< std::uint64_t > framesSent
Total number of output frames sent.
std::atomic< std::uint64_t > cycleCount
Number of TX cycles included in CycleTimeSumUs.
std::atomic< int > consecutiveTimeouts
Current run of consecutive watchdog timeouts (resets on a good frame).
std::atomic< std::chrono::steady_clock::time_point > lastReceiveTime
Timestamp of the last received input frame (or watchdog check).
std::atomic< std::uint32_t > maxCycleTimeUs
Largest observed TX cycle duration, in microseconds.
IOCR configuration derived from AR setup: timing parameters and IO object mappings needed for cyclic ...
Declares Linux Ethernet, addressing, timing, and utility helpers used by the PROFINET stack.