|
PROFINET IO Controller Stack 1.0.0
Modern C++ implementation of a PROFINET IO Controller stack
|
Background listener for PROFINET alarm notifications. More...
#include <alarmListener.h>
Inheritance diagram for profinet::AlarmListener:
Collaboration diagram for profinet::AlarmListener:Public Member Functions | |
| AlarmListener (AlarmEndpoint endpoint, std::optional< MacAddress > controllerMac=std::nullopt, std::unique_ptr< IRawEthernetSocket > l2Socket=nullptr) | |
| Construct a listener for the given endpoint. | |
| ~AlarmListener () override | |
| Stop (if running) and release resources. | |
| AlarmListener (const AlarmListener &)=delete | |
| Not copyable (owns a socket and background thread). | |
| AlarmListener & | operator= (const AlarmListener &)=delete |
| Not copyable (owns a socket and background thread). | |
| void | AddCallback (std::function< void(const AlarmNotification &)> callback) override |
| Register a callback for received alarms. | |
| void | RemoveCallback (std::function< void(const AlarmNotification &)> callback) override |
| Remove a registered callback. | |
| void | Start () override |
| Start the background listener (socket + thread). | |
| void | Stop () override |
| Stop the listener. | |
| bool | IsRunning () const override |
| Whether the listener thread is currently running. | |
Public Member Functions inherited from profinet::IAlarmListener | |
| virtual | ~IAlarmListener ()=default |
| Virtual destructor. | |
Private Member Functions | |
| void | ListenLoop () |
| Listener thread body: dispatches to the Layer 2 or UDP handler. | |
| void | HandleLayer2Frame () |
| Receive and process one Layer 2 (RTA-PDU) frame. | |
| void | HandleUdpFrame () |
| Receive and process one UDP frame. | |
| void | ProcessAlarm (const Bytes &payload, std::optional< bool > highPriority, std::optional< MacAddress > srcMac) |
| Parse an alarm payload and dispatch it to registered callbacks. | |
| void | SendAck (const AlarmNotification &alarm, std::optional< MacAddress > srcMac) |
| Build and send an AlarmAck-PDU for a received notification. | |
| void | SendLayer2Ack (const Bytes &ackData, const MacAddress &dstMac, bool highPriority) |
| Send an AlarmAck-PDU over the Layer 2 transport. | |
| void | SendUdpAck (const Bytes &ackData, const sockaddr_in &dstAddr) const |
| Send an AlarmAck-PDU over the UDP transport. | |
Private Attributes | |
| AlarmEndpoint | endpoint |
| Alarm endpoint configuration. | |
| MacAddress | controllerMac {} |
| This host's MAC address. | |
| std::atomic< bool > | running {false} |
| Whether the listener thread should keep running. | |
| std::thread | thread |
| Background thread receiving and processing alarms. | |
| std::mutex | callbacksMutex |
| Protects concurrent access to callbacks. | |
| std::vector< std::function< void(const AlarmNotification &)> > | callbacks |
| Registered callbacks invoked for successfully parsed alarms. | |
| std::uint16_t | sendSeqNum = 0 |
| Sequence number for outgoing AlarmAck-PDUs. | |
| std::uint16_t | recvSeqNum = 0 |
| Last received sequence number, for duplicate detection. | |
| std::unique_ptr< IRawEthernetSocket > | l2Sock |
| Raw Ethernet transport used for Layer 2 alarm reception. | |
| int | udpFd = -1 |
| Socket file descriptor used for the UDP transport. | |
| std::optional< sockaddr_in > | lastUdpSrc |
| Address of the most recently received UDP alarm, for replying. | |
Friends | |
| class | AlarmListenerTests |
| Test fixture for AlarmListener unit tests. | |
| class | AlarmListenerRtaTest |
| Test fixture for RTA transport regression tests. | |
| class | AlarmListenerRtaIntegrationTest |
| Test fixture for multi-frame RTA integration tests. | |
| class | AlarmListenerCallbackTest |
| Test fixture for callback behavior tests. | |
Background listener for PROFINET alarm notifications.
Example:
Definition at line 80 of file alarmListener.h.
|
explicit |
Construct a listener for the given endpoint.
Creates a listener for the supplied AlarmCR endpoint. When a Layer 2 transport is configured, an optional Ethernet socket may be supplied. This dependency-injection mechanism allows alarm processing to be tested without accessing a physical network interface.
| endpoint | Alarm endpoint configuration. |
| controllerMac | This host's MAC address (required for the Layer 2 transport). |
| l2Socket | Optional Layer 2 Ethernet transport. When omitted, Start() creates the production EthernetSocket. |
Definition at line 17 of file alarmListener.cpp.
|
override |
Stop (if running) and release resources.
Definition at line 26 of file alarmListener.cpp.
References Stop().
Here is the call graph for this function:
|
delete |
Not copyable (owns a socket and background thread).
|
overridevirtual |
Register a callback for received alarms.
The callback is invoked from the listener thread for each successfully parsed alarm notification.
Multiple callbacks may be registered. Registration is thread-safe and may be performed while the listener is running.
| callback | Invoked from the listener thread for each successfully parsed alarm. |
Implements profinet::IAlarmListener.
Definition at line 31 of file alarmListener.cpp.
References callbacks, and callbacksMutex.
|
private |
Receive and process one Layer 2 (RTA-PDU) frame.
Definition at line 169 of file alarmListener.cpp.
References profinet::AlarmEndpoint::deviceMac, endpoint, profinet::ETHERTYPE_PROFINET, profinet::FRAME_ID_ALARM_HIGH, profinet::FRAME_ID_ALARM_LOW, l2Sock, profinet::macAddressLength, profinet::OneOctetShift, ProcessAlarm(), and profinet::SkipVlanTags().
Referenced by ListenLoop().
Here is the call graph for this function:
Here is the caller graph for this function:
|
private |
Receive and process one UDP frame.
Definition at line 227 of file alarmListener.cpp.
References lastUdpSrc, ProcessAlarm(), profinet::RECEIVE_BUFFER_LENGTH, running, and udpFd.
Referenced by ListenLoop().
Here is the call graph for this function:
Here is the caller graph for this function:
|
inlineoverridevirtual |
Whether the listener thread is currently running.
Implements profinet::IAlarmListener.
Definition at line 148 of file alarmListener.h.
References running.
|
private |
Listener thread body: dispatches to the Layer 2 or UDP handler.
Definition at line 141 of file alarmListener.cpp.
References endpoint, HandleLayer2Frame(), HandleUdpFrame(), running, and profinet::AlarmEndpoint::transport.
Referenced by Start().
Here is the call graph for this function:
Here is the caller graph for this function:
|
delete |
Not copyable (owns a socket and background thread).
|
private |
Parse an alarm payload and dispatch it to registered callbacks.
| payload | Raw alarm notification payload. |
| highPriority | Whether this arrived on the high-priority path, if known. |
| srcMac | Sender's MAC address, for the Layer 2 transport. |
Definition at line 259 of file alarmListener.cpp.
References profinet::PNRTAHeader::ADD_FLAGS_TACK, profinet::PNRTAHeader::addFlags, profinet::PNRTAHeader::alarmDstEndpoint, callbacks, callbacksMutex, profinet::AlarmEndpoint::controllerRef, endpoint, profinet::PNRTAHeader::Parse(), profinet::ParseAlarmNotification(), payload, profinet::PNRTAHeader::pduType, recvSeqNum, SendAck(), profinet::PNRTAHeader::sendSeqNum, profinet::AlarmEndpoint::transport, version, and profinet::PNRTAHeader::VERSION_1.
Referenced by HandleLayer2Frame(), and HandleUdpFrame().
Here is the call graph for this function:
Here is the caller graph for this function:
|
overridevirtual |
Remove a registered callback.
| callback | Previously registered callback to remove. |
Implements profinet::IAlarmListener.
Definition at line 41 of file alarmListener.cpp.
References callbacks, and callbacksMutex.
|
private |
Build and send an AlarmAck-PDU for a received notification.
| alarm | The notification being acknowledged. |
| srcMac | Sender's MAC address, for the Layer 2 transport. |
Definition at line 337 of file alarmListener.cpp.
References profinet::AlarmAcknowledgementHigh, profinet::AlarmAcknowledgementLow, profinet::AlarmNotification::alarmSequenceNumber, profinet::PNAlarmAckPDU::alarmSpecifier, profinet::AlarmNotification::alarmType, profinet::PNAlarmAckPDU::alarmType, profinet::AlarmNotification::api, profinet::PNAlarmAckPDU::api, profinet::AlarmNotification::arDiagnosisState, profinet::PNAlarmAckPDU::blockHeader, profinet::blockHeaderLenght, profinet::PNBlockHeader::blockLength, profinet::PNBlockHeader::blockType, profinet::PNBlockHeader::blockVersionHigh, profinet::PNBlockHeader::blockVersionLow, profinet::AlarmNotification::channelDiagnosis, profinet::AlarmEndpoint::deviceMac, endpoint, profinet::AlarmNotification::IsHighPriority(), profinet::PNAlarmAckPDU::kSize, lastUdpSrc, profinet::AlarmNotification::manufacturerSpecific, SendLayer2Ack(), SendUdpAck(), profinet::AlarmNotification::slotNumber, profinet::PNAlarmAckPDU::slotNumber, profinet::PNAlarmAckPDU::statusPNIO, profinet::AlarmNotification::submoduleDiagnosisState, profinet::AlarmNotification::subslotNumber, profinet::PNAlarmAckPDU::subslotNumber, profinet::PNBlockHeader::ToBytes(), profinet::PNAlarmAckPDU::ToBytes(), and profinet::AlarmEndpoint::transport.
Referenced by ProcessAlarm().
Here is the call graph for this function:
Here is the caller graph for this function:
|
private |
Send an AlarmAck-PDU over the Layer 2 transport.
| ackData | Serialized AlarmAck-PDU. |
| dstMac | Destination MAC address. |
| highPriority | Whether to use the high-priority frame ID. |
Definition at line 387 of file alarmListener.cpp.
References profinet::PNRTAHeader::ackSeqNum, profinet::PNRTAHeader::ADD_FLAGS_TACK, profinet::PNRTAHeader::ADD_FLAGS_WINDOW_1, profinet::PNRTAHeader::addFlags, profinet::PNRTAHeader::alarmDstEndpoint, profinet::PNRTAHeader::alarmSrcEndpoint, controllerMac, profinet::AlarmEndpoint::controllerRef, profinet::AlarmEndpoint::deviceRef, endpoint, profinet::ETHERTYPE_PROFINET, profinet::FRAME_ID_ALARM_HIGH, profinet::FRAME_ID_ALARM_LOW, l2Sock, profinet::LowByteMask, profinet::OneOctetShift, profinet::PNRTAHeader::pduType, recvSeqNum, profinet::PNRTAHeader::RTA_TYPE_DATA, sendSeqNum, profinet::PNRTAHeader::sendSeqNum, profinet::PNRTAHeader::ToBytes(), profinet::PNRTAHeader::variablePartLenght, and profinet::PNRTAHeader::VERSION_1.
Referenced by SendAck().
Here is the call graph for this function:
Here is the caller graph for this function:
|
private |
Send an AlarmAck-PDU over the UDP transport.
| ackData | Serialized AlarmAck-PDU. |
| dstAddr | Destination UDP address. |
Definition at line 436 of file alarmListener.cpp.
References udpFd.
Referenced by SendAck().
Here is the caller graph for this function:
|
overridevirtual |
Start the background listener (socket + thread).
No-op if already running. Throws PermissionDeniedError if a raw socket needs elevated privilege.
Implements profinet::IAlarmListener.
Definition at line 65 of file alarmListener.cpp.
References profinet::ALARM_UDP_PORT, endpoint, profinet::ETHERTYPE_PROFINET, profinet::AlarmEndpoint::interface, l2Sock, ListenLoop(), running, thread, profinet::AlarmEndpoint::transport, and udpFd.
Here is the call graph for this function:
|
overridevirtual |
Stop the listener.
Closes the socket (to unblock recv) and joins the thread.
Implements profinet::IAlarmListener.
Definition at line 118 of file alarmListener.cpp.
References l2Sock, running, thread, and udpFd.
Referenced by ~AlarmListener().
Here is the caller graph for this function:
|
friend |
Test fixture for callback behavior tests.
Definition at line 93 of file alarmListener.h.
|
friend |
Test fixture for multi-frame RTA integration tests.
Definition at line 90 of file alarmListener.h.
|
friend |
Test fixture for RTA transport regression tests.
Definition at line 87 of file alarmListener.h.
|
friend |
Test fixture for AlarmListener unit tests.
Definition at line 84 of file alarmListener.h.
|
private |
Registered callbacks invoked for successfully parsed alarms.
Access to this collection is protected by callbacksMutex. Callbacks are copied before invocation so application callback code executes without holding the mutex.
Definition at line 206 of file alarmListener.h.
Referenced by AddCallback(), ProcessAlarm(), and RemoveCallback().
|
mutableprivate |
Protects concurrent access to callbacks.
Definition at line 198 of file alarmListener.h.
Referenced by AddCallback(), ProcessAlarm(), and RemoveCallback().
|
private |
This host's MAC address.
Definition at line 189 of file alarmListener.h.
Referenced by SendLayer2Ack().
|
private |
Alarm endpoint configuration.
Definition at line 186 of file alarmListener.h.
Referenced by HandleLayer2Frame(), ListenLoop(), ProcessAlarm(), SendAck(), SendLayer2Ack(), and Start().
|
private |
Raw Ethernet transport used for Layer 2 alarm reception.
When null, Start() creates the production EthernetSocket. Unit tests can provide a MockRawEthernetSocket through the constructor.
Layer 2 path uses EthernetSocket; UDP path manages its own fd directly (needs bind-to-wildcard + recvfrom, which EthernetSocket / UdpSocket don't support – same rationale as RPCCon's CControl listener).
Definition at line 224 of file alarmListener.h.
Referenced by HandleLayer2Frame(), SendLayer2Ack(), Start(), and Stop().
|
private |
Address of the most recently received UDP alarm, for replying.
Definition at line 230 of file alarmListener.h.
Referenced by HandleUdpFrame(), and SendAck().
|
private |
Last received sequence number, for duplicate detection.
Definition at line 212 of file alarmListener.h.
Referenced by ProcessAlarm(), and SendLayer2Ack().
|
private |
Whether the listener thread should keep running.
Definition at line 192 of file alarmListener.h.
Referenced by HandleUdpFrame(), IsRunning(), ListenLoop(), Start(), and Stop().
|
private |
Sequence number for outgoing AlarmAck-PDUs.
Definition at line 209 of file alarmListener.h.
Referenced by SendLayer2Ack().
|
private |
Background thread receiving and processing alarms.
Definition at line 195 of file alarmListener.h.
|
private |
Socket file descriptor used for the UDP transport.
Definition at line 227 of file alarmListener.h.
Referenced by HandleUdpFrame(), SendUdpAck(), Start(), and Stop().