PROFINET IO Controller Stack 1.0.0
Modern C++ implementation of a PROFINET IO Controller stack
Loading...
Searching...
No Matches
profinet::AlarmListener Class Reference

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).
 
AlarmListeneroperator= (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< IRawEthernetSocketl2Sock
 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.
 

Detailed Description

Background listener for PROFINET alarm notifications.

Example:

AlarmEndpoint ep{ifname, controller_ref, device_ref, device_mac};
AlarmListener listener(ep, my_mac);
listener.AddCallback([](const AlarmNotification& n) {
std::cout << n.AlarmTypeName() << " at " << n.Location() << "\n";
});
listener.Start();
// ...
listener.Stop();
Background listener for PROFINET alarm notifications.
Alarm endpoint configuration.
Complete parsed AlarmNotification PDU: header fields + parsed items.
Definition alarms.h:358
std::string Location() const
Location string identifying where the alarm originated.
Definition alarms.cpp:281
std::string AlarmTypeName() const
Human-readable name for AlarmType.
Definition alarms.h:420

Definition at line 80 of file alarmListener.h.

Constructor & Destructor Documentation

◆ AlarmListener() [1/2]

profinet::AlarmListener::AlarmListener ( AlarmEndpoint  endpoint,
std::optional< MacAddress controllerMac = std::nullopt,
std::unique_ptr< IRawEthernetSocket l2Socket = nullptr 
)
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.

Parameters
endpointAlarm endpoint configuration.
controllerMacThis host's MAC address (required for the Layer 2 transport).
l2SocketOptional Layer 2 Ethernet transport. When omitted, Start() creates the production EthernetSocket.

Definition at line 17 of file alarmListener.cpp.

◆ ~AlarmListener()

profinet::AlarmListener::~AlarmListener ( )
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:

◆ AlarmListener() [2/2]

profinet::AlarmListener::AlarmListener ( const AlarmListener )
delete

Not copyable (owns a socket and background thread).

Member Function Documentation

◆ AddCallback()

void profinet::AlarmListener::AddCallback ( std::function< void(const AlarmNotification &)>  callback)
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.

Parameters
callbackInvoked from the listener thread for each successfully parsed alarm.

Implements profinet::IAlarmListener.

Definition at line 31 of file alarmListener.cpp.

References callbacks, and callbacksMutex.

◆ HandleLayer2Frame()

void profinet::AlarmListener::HandleLayer2Frame ( )
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:

◆ HandleUdpFrame()

void profinet::AlarmListener::HandleUdpFrame ( )
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:

◆ IsRunning()

bool profinet::AlarmListener::IsRunning ( ) const
inlineoverridevirtual

Whether the listener thread is currently running.

Returns
True if Start() has been called and Stop() has not.

Implements profinet::IAlarmListener.

Definition at line 148 of file alarmListener.h.

References running.

◆ ListenLoop()

void profinet::AlarmListener::ListenLoop ( )
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:

◆ operator=()

AlarmListener & profinet::AlarmListener::operator= ( const AlarmListener )
delete

Not copyable (owns a socket and background thread).

◆ ProcessAlarm()

void profinet::AlarmListener::ProcessAlarm ( const Bytes payload,
std::optional< bool >  highPriority,
std::optional< MacAddress srcMac 
)
private

Parse an alarm payload and dispatch it to registered callbacks.

Parameters
payloadRaw alarm notification payload.
highPriorityWhether this arrived on the high-priority path, if known.
srcMacSender'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:

◆ RemoveCallback()

void profinet::AlarmListener::RemoveCallback ( std::function< void(const AlarmNotification &)>  callback)
overridevirtual

Remove a registered callback.

Parameters
callbackPreviously registered callback to remove.

Implements profinet::IAlarmListener.

Definition at line 41 of file alarmListener.cpp.

References callbacks, and callbacksMutex.

◆ SendAck()

void profinet::AlarmListener::SendAck ( const AlarmNotification alarm,
std::optional< MacAddress srcMac 
)
private

Build and send an AlarmAck-PDU for a received notification.

Parameters
alarmThe notification being acknowledged.
srcMacSender'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:

◆ SendLayer2Ack()

void profinet::AlarmListener::SendLayer2Ack ( const Bytes ackData,
const MacAddress dstMac,
bool  highPriority 
)
private

Send an AlarmAck-PDU over the Layer 2 transport.

Parameters
ackDataSerialized AlarmAck-PDU.
dstMacDestination MAC address.
highPriorityWhether 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:

◆ SendUdpAck()

void profinet::AlarmListener::SendUdpAck ( const Bytes ackData,
const sockaddr_in &  dstAddr 
) const
private

Send an AlarmAck-PDU over the UDP transport.

Parameters
ackDataSerialized AlarmAck-PDU.
dstAddrDestination UDP address.

Definition at line 436 of file alarmListener.cpp.

References udpFd.

Referenced by SendAck().

+ Here is the caller graph for this function:

◆ Start()

void profinet::AlarmListener::Start ( )
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:

◆ Stop()

void profinet::AlarmListener::Stop ( )
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:

Friends And Related Symbol Documentation

◆ AlarmListenerCallbackTest

friend class AlarmListenerCallbackTest
friend

Test fixture for callback behavior tests.

Definition at line 93 of file alarmListener.h.

◆ AlarmListenerRtaIntegrationTest

friend class AlarmListenerRtaIntegrationTest
friend

Test fixture for multi-frame RTA integration tests.

Definition at line 90 of file alarmListener.h.

◆ AlarmListenerRtaTest

friend class AlarmListenerRtaTest
friend

Test fixture for RTA transport regression tests.

Definition at line 87 of file alarmListener.h.

◆ AlarmListenerTests

friend class AlarmListenerTests
friend

Test fixture for AlarmListener unit tests.

Definition at line 84 of file alarmListener.h.

Member Data Documentation

◆ callbacks

std::vector<std::function<void(const AlarmNotification&)> > profinet::AlarmListener::callbacks
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().

◆ callbacksMutex

std::mutex profinet::AlarmListener::callbacksMutex
mutableprivate

Protects concurrent access to callbacks.

Definition at line 198 of file alarmListener.h.

Referenced by AddCallback(), ProcessAlarm(), and RemoveCallback().

◆ controllerMac

MacAddress profinet::AlarmListener::controllerMac {}
private

This host's MAC address.

Definition at line 189 of file alarmListener.h.

Referenced by SendLayer2Ack().

◆ endpoint

AlarmEndpoint profinet::AlarmListener::endpoint
private

Alarm endpoint configuration.

Definition at line 186 of file alarmListener.h.

Referenced by HandleLayer2Frame(), ListenLoop(), ProcessAlarm(), SendAck(), SendLayer2Ack(), and Start().

◆ l2Sock

std::unique_ptr<IRawEthernetSocket> profinet::AlarmListener::l2Sock
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().

◆ lastUdpSrc

std::optional<sockaddr_in> profinet::AlarmListener::lastUdpSrc
private

Address of the most recently received UDP alarm, for replying.

Definition at line 230 of file alarmListener.h.

Referenced by HandleUdpFrame(), and SendAck().

◆ recvSeqNum

std::uint16_t profinet::AlarmListener::recvSeqNum = 0
private

Last received sequence number, for duplicate detection.

Definition at line 212 of file alarmListener.h.

Referenced by ProcessAlarm(), and SendLayer2Ack().

◆ running

std::atomic<bool> profinet::AlarmListener::running {false}
private

Whether the listener thread should keep running.

Definition at line 192 of file alarmListener.h.

Referenced by HandleUdpFrame(), IsRunning(), ListenLoop(), Start(), and Stop().

◆ sendSeqNum

std::uint16_t profinet::AlarmListener::sendSeqNum = 0
private

Sequence number for outgoing AlarmAck-PDUs.

Definition at line 209 of file alarmListener.h.

Referenced by SendLayer2Ack().

◆ thread

std::thread profinet::AlarmListener::thread
private

Background thread receiving and processing alarms.

Definition at line 195 of file alarmListener.h.

Referenced by Start(), and Stop().

◆ udpFd

int profinet::AlarmListener::udpFd = -1
private

Socket file descriptor used for the UDP transport.

Definition at line 227 of file alarmListener.h.

Referenced by HandleUdpFrame(), SendUdpAck(), Start(), and Stop().


The documentation for this class was generated from the following files: