57 .blockLength =
static_cast<std::uint16_t
>((data[offset + 2] <<
OneOctetShift) | data[offset + 3])};
72std::array<std::uint8_t, uuidLenght>
StringToUuidBytes(
const std::string& uuidStr);
119std::vector<EPMEndpoint>
EpmLookup(asio::io_context& ioContext,
const std::string& ip, std::uint16_t port =
RPC_PORT,
121 std::optional<std::string> interfaceFilter = std::nullopt);
134 const std::string& name,
187 std::optional<ConnectResult>
Connect(std::optional<MacAddress>
srcMac = std::nullopt,
188 bool withAlarmCr =
false,
189 std::optional<IOCRSetup>
iocrSetup = std::nullopt)
override;
198 PNIODHeader Read(std::uint32_t api, std::uint16_t slot, std::uint16_t subslot, std::uint16_t idx)
override;
206 PNIODHeader ReadImplicit(std::uint32_t api, std::uint16_t slot, std::uint16_t subslot, std::uint16_t idx)
override;
214 void Write(std::uint32_t api, std::uint16_t slot, std::uint16_t subslot, std::uint16_t idx,
215 const Bytes& data)
override;
222 std::vector<blocks::WriteMultipleResult>
WriteMultiple(
const std::vector<WriteItem>& writes)
override;
229 Bytes ReadRaw(std::uint16_t idx, std::uint16_t slot = 0, std::uint16_t subslot = 1);
235 PNInM0 ReadIm0(std::uint16_t slot = 0, std::uint16_t subslot = 1)
override;
241 PNInM1 ReadIm1(std::uint16_t slot = 0, std::uint16_t subslot = 1)
override;
247 PNInM2 ReadIm2(std::uint16_t slot = 0, std::uint16_t subslot = 1)
override;
253 PNInM3 ReadIm3(std::uint16_t slot = 0, std::uint16_t subslot = 1)
override;
259 PNInM4 ReadIm4(std::uint16_t slot = 0, std::uint16_t subslot = 1)
override;
265 PNInM5 ReadIm5(std::uint16_t slot = 0, std::uint16_t subslot = 1)
override;
271 PNInM6 ReadIm6(std::uint16_t slot = 0, std::uint16_t subslot = 1)
override;
277 PNInM7 ReadIm7(std::uint16_t slot = 0, std::uint16_t subslot = 1)
override;
283 PNInM8 ReadIm8(std::uint16_t slot = 0, std::uint16_t subslot = 1)
override;
289 PNInM9 ReadIm9(std::uint16_t slot = 0, std::uint16_t subslot = 1)
override;
295 PNInM10 ReadIm10(std::uint16_t slot = 0, std::uint16_t subslot = 1)
override;
301 PNInM11 ReadIm11(std::uint16_t slot = 0, std::uint16_t subslot = 1)
override;
307 PNInM12 ReadIm12(std::uint16_t slot = 0, std::uint16_t subslot = 1)
override;
313 PNInM13 ReadIm13(std::uint16_t slot = 0, std::uint16_t subslot = 1)
override;
319 PNInM14 ReadIm14(std::uint16_t slot = 0, std::uint16_t subslot = 1)
override;
325 PNInM15 ReadIm15(std::uint16_t slot = 0, std::uint16_t subslot = 1)
override;
331 AllIM ReadAllIm(std::uint16_t slot = 0, std::uint16_t subslot = 1)
override;
351 std::uint16_t index = 0xF000)
override;
356 std::map<std::uint16_t, diagnosis::DiagnosisData>
ReadAllDiagnosis()
override;
372 std::pair<blocks::PDRealData, blocks::RealIdentificationData>
DiscoverTopology()
override;
382 std::uint16_t slot = 0, std::uint16_t subslot = 1,
383 std::optional<std::vector<std::uint16_t>> customIndices = std::nullopt)
override;
412 void Close() noexcept override;
430 [[nodiscard]]
const std::array<std::uint8_t, uuidLenght>&
ArUuid()
const
536 const
Bytes& subBlocks = {});
545 std::array<std::uint8_t, uuidLenght>
arUuid{};
Interface for PROFINET IO-Device RPC connections.
Declares PROFINET IO connection-management block structures and wire serialization.
A minimal RAII wrapper around a Linux AF_PACKET raw socket bound to an interface.
Parsed PROFINET device information from a DCP response.
Abstract interface for a PROFINET RPC connection.
Connection to a PROFINET IO-Device: establishes an AR (Application Relationship) and performs acyclic...
PNInM13 ReadIm13(std::uint16_t slot=0, std::uint16_t subslot=1) override
Read I&M13 (reserved).
PNInM0 ReadIm0(std::uint16_t slot=0, std::uint16_t subslot=1) override
Read I&M0 (mandatory identification data).
static std::uint16_t ParseIocrResponse(const Bytes &responseData, int iocrType)
Parse an IOCRBlockRes from a CONNECT response.
int DeviceAlarmRef() const override
Device's local alarm reference, from AlarmCRBlockRes.
int iocrRefCounter
Counter used to allocate unique IOCR references.
std::uint32_t sequenceNumber
Monotonically increasing RPC sequence number.
blocks::PDRealData ReadPdRealData() override
Read and parse the device's PDRealData (physical topology).
static Bytes BuildUnifiedExpectedSubmoduleBlock(const IOCRSetup &setup)
std::array< std::uint8_t, uuidLenght > arUuid
AR UUID for this connection.
blocks::ModuleDiffBlock ReadModuleDiff() override
Read and parse the device's ModuleDiffBlock.
PNInM2 ReadIm2(std::uint16_t slot=0, std::uint16_t subslot=1) override
Read I&M2 (installation date).
RPCCon(RPCCon &&)=delete
Deleted move constructor to prevent moving instances of this class.
asio::io_context & IoContext() override
Returns the underlying Asio I/O context.
Bytes BuildAlarmCrBlock(int transport=0, int priority=0) const
Build an AlarmCRBlockReq for inclusion in the CONNECT request.
static Bytes BuildIocrBlock(int iocrType, int iocrReference, const IOCRSetup &setup)
Build an IOCRBlockReq (header + API object list) for the CONNECT request.
double timeout
Default RPC response timeout in seconds.
PNInM8 ReadIm8(std::uint16_t slot=0, std::uint16_t subslot=1) override
Read I&M8 (reserved).
std::array< std::uint8_t, uuidLenght > localObjectUuid
This controller's own object UUID.
~RPCCon()
Disconnect (best-effort) and close the underlying sockets.
static PNNRDData CreateNrd(const Bytes &payload)
Wrap a payload in an NRD (Network Representation Data) header.
PNInM4 ReadIm4(std::uint16_t slot=0, std::uint16_t subslot=1) override
Read I&M4 (PROFIsafe signature).
PNInM15 ReadIm15(std::uint16_t slot=0, std::uint16_t subslot=1) override
Read I&M15 (reserved).
std::uint16_t SessionKey() const
The session key for this connection.
bool HasAlarmCr() const override
Whether an AlarmCR was successfully established.
AllIM ReadAllIm(std::uint16_t slot=0, std::uint16_t subslot=1) override
Read all I&M records a device supports.
std::vector< blocks::SlotInfo > DiscoverSlots() override
Convenience accessor for ReadRealIdentificationData().Slots.
friend class RpcTest
FRIEND_CLASS declaration granting access to the specific test case for validating CreateRpc.
static int ParseAlarmCrResponse(const Bytes &responseData)
Parse the AlarmCRBlockRes from a CONNECT response.
Bytes PrmEnd() override
Send PrmEnd (end of the parameterization phase).
const dcp::DCPDeviceDescription & Info() const override
The device this connection targets.
PNInM6 ReadIm6(std::uint16_t slot=0, std::uint16_t subslot=1) override
Read I&M6 (reserved).
static Bytes BuildExpectedSubmoduleBlock(const IOCRSetup &setup)
Build an ExpectedSubmoduleBlockReq for the CONNECT request.
Bytes SendControl(BlockType blockType, ControlCommand controlCommand, bool waitResponse=true, const Bytes &subBlocks={})
Send a CONTROL operation and optionally wait for its response.
void Disconnect() override
Send Release to terminate the AR.
RPCCon(const RPCCon &)=delete
Not copyable because the connection owns non-copyable Asio sockets.
int deviceAlarmRef
Device's local alarm reference, if an AlarmCR was established.
PNInM11 ReadIm11(std::uint16_t slot=0, std::uint16_t subslot=1) override
Read I&M11 (reserved).
std::pair< blocks::PDRealData, blocks::RealIdentificationData > DiscoverTopology() override
Read both PDRealData and RealIdentificationData in one call.
RPCCon & operator=(RPCCon &&)=delete
Deleted move assignment operator to prevent moving instances of this class.
std::array< std::uint8_t, uuidLenght > remoteObjectUuid
The target device's object UUID.
dcp::DCPDeviceDescription info
DCP-discovered description of the target device.
RPCCon & operator=(const RPCCon &)=delete
Not copyable because the connection owns non-copyable Asio sockets.
std::uint16_t LocalAlarmRef() const override
Controller's own local alarm reference.
diagnosis::DiagnosisData ReadDiagnosis(std::uint16_t slot=0, std::uint16_t subslot=0, std::uint16_t index=0xF000) override
Read and parse diagnosis data at the given location/index.
asio::io_context ioContext
Asio execution context used by the RPC transport.
PNInM14 ReadIm14(std::uint16_t slot=0, std::uint16_t subslot=1) override
Read I&M14 (reserved).
void Close() noexcept override
Disconnect() and close the underlying sockets.
std::unique_ptr< RpcTransport > rpcTransport
PNInM12 ReadIm12(std::uint16_t slot=0, std::uint16_t subslot=1) override
Read I&M12 (reserved).
int inputIocrRef
IOCR reference for the input (device -> controller) IOCR.
bool IsConnected() const override
Whether the AR is currently established.
std::optional< MacAddress > srcMac
Source MAC address used to establish the AR.
std::map< std::uint16_t, diagnosis::DiagnosisData > ReadAllDiagnosis() override
Read diagnosis from all standard diagnosis indices.
std::map< std::uint16_t, IndexProbeResult > EnumerateIndices(std::uint16_t slot=0, std::uint16_t subslot=1, std::optional< std::vector< std::uint16_t > > customIndices=std::nullopt) override
Probe a set of indices and report which are readable/empty/erroring.
bool alarmCrEnabled
Whether an AlarmCR was successfully established.
std::chrono::steady_clock::time_point liveMonotonic
Timestamp of the last successful RPC exchange, for CONNECTION_TIMEOUT tracking.
void CheckTimeout()
Reconnect if the AR has been idle longer than CONNECTION_TIMEOUT.
Bytes PrmBegin() override
Send PrmBegin (start of the parameterization phase).
int outputIocrRef
IOCR reference for the output (controller -> device) IOCR.
std::uint16_t outputFrameId
Frame ID assigned to the output IOCR.
PNInM5 ReadIm5(std::uint16_t slot=0, std::uint16_t subslot=1) override
Read I&M5 (free-text annotation).
PNInM9 ReadIm9(std::uint16_t slot=0, std::uint16_t subslot=1) override
Read I&M9 (reserved).
std::uint16_t alarmRef
Controller's own local alarm reference.
PNInM10 ReadIm10(std::uint16_t slot=0, std::uint16_t subslot=1) override
Read I&M10 (reserved).
PNInM3 ReadIm3(std::uint16_t slot=0, std::uint16_t subslot=1) override
Read I&M3 (free-text descriptor).
std::uint16_t inputFrameId
Frame ID assigned to the input IOCR.
std::unique_ptr< RpcTransport > ccontrolTransport
blocks::RealIdentificationData ReadRealIdentificationData() override
Read and parse the device's RealIdentificationData (logical structure).
void CloseSockets() noexcept
Close the RPC and CControl UDP sockets.
std::optional< ConnectResult > Connect(std::optional< MacAddress > srcMac=std::nullopt, bool withAlarmCr=false, std::optional< IOCRSetup > iocrSetup=std::nullopt) override
Establish (or re-establish) the AR with the device.
PNInM1 ReadIm1(std::uint16_t slot=0, std::uint16_t subslot=1) override
Read I&M1 (tag function/location).
PNIODHeader Read(std::uint32_t api, std::uint16_t slot, std::uint16_t subslot, std::uint16_t idx) override
Read a data record via slot/subslot/index (AR must be connected).
void Write(std::uint32_t api, std::uint16_t slot, std::uint16_t subslot, std::uint16_t idx, const Bytes &data) override
Write a data record via slot/subslot/index (AR must be connected).
std::uint16_t sessionKey
Session key for this connection.
PNRPCHeader CreateRpc(std::uint16_t operation, const Bytes &nrd)
Build an RPC header for the given operation and NRD body.
Bytes ReadRaw(std::uint16_t idx, std::uint16_t slot=0, std::uint16_t subslot=1)
Read a raw record payload by index (convenience wrapper over Read()).
PNRPCHeader SendReceive(const PNRPCHeader &request)
Send an RPC request and synchronously wait for its response.
PNInM7 ReadIm7(std::uint16_t slot=0, std::uint16_t subslot=1) override
Read I&M7 (reserved).
Bytes ReadyForRtClass3() override
Send ReadyForRTClass3 (isochronous real-time readiness).
std::vector< blocks::WriteMultipleResult > WriteMultiple(const std::vector< WriteItem > &writes) override
Write multiple records atomically via IODWriteMultipleReq (0xE040).
bool live
Whether the AR is currently established.
const std::array< std::uint8_t, uuidLenght > & ArUuid() const
The AR UUID for this connection.
PNIODHeader ReadImplicit(std::uint32_t api, std::uint16_t slot, std::uint16_t subslot, std::uint16_t idx) override
Read a data record without an established AR.
std::optional< IOCRSetup > iocrSetup
Cyclic IO configuration used for the current AR, if any.
std::array< std::uint8_t, uuidLenght > activityUuid
Activity UUID for the current RPC exchange.
PROFINET DCP discovery and device configuration interface.
PROFINET diagnosis data structures, error decoding, and parsers.
Declares exceptions and error types used by the PROFINET IO controller stack.
PROFINET record-data indices, block types, and protocol enumerations.
std::string UuidBytesToString(const std::array< std::uint8_t, uuidLenght > &data)
Format a 16-byte DCE/RPC UUID as a canonical string.
constexpr double DEFAULT_TIMEOUT
Default RPC response timeout in seconds.
constexpr std::uint16_t RPC_PORT
PROFINET IO RPC port (34964).
dcp::DCPDeviceDescription GetStationInfo(const EthernetSocket &sock, const MacAddress &src, const std::string &name, int timeoutSec=static_cast< int >(DEFAULT_TIMEOUT *2))
Resolve a device by PROFINET station name via DCP.
BlockHeaderView PeekBlockHeader(const Bytes &data, std::size_t offset)
std::vector< EPMEndpoint > EpmLookup(asio::io_context &ioContext, const std::string &ip, std::uint16_t port=RPC_PORT, double timeoutSec=DEFAULT_TIMEOUT, std::optional< std::string > interfaceFilter=std::nullopt)
Query a device's Endpoint Mapper for available RPC endpoints.
std::array< std::uint8_t, uuidLenght > StringToUuidBytes(const std::string &uuidStr)
Parse a canonical UUID string into 16 raw DCE/RPC UUID bytes.
BlockType
PROFINET block types.
std::array< std::uint8_t, macAddressLength > MacAddress
A 6-byte Ethernet MAC address.
ControlCommand
PROFINET IOD control command values.
@ ApplicationReady
Application Ready command.
static constexpr int OneOctetShift
The bit-shift distance required to move data across a single octet.
std::vector< std::uint8_t > Bytes
Generic byte buffer alias used throughout the library for raw wire data.
PROFINET protocol wire-format structures and serialization helpers.
UDP transport abstraction for PROFINET DCE/RPC.
Shared data types used by the PROFINET DCE/RPC layer.
I&M0: mandatory identification data (vendor, order ID, serial number, revisions).
I&M1: user-assigned tag function and location strings.
I&M3: free-text descriptor.
I&M4: PROFIsafe signature (binary, not text).
I&M5: free-text annotation.
I&M6-I&M15: reserved for future use per IEC 61158-6-10.
NRD (Network Representation Data) wrapper carrying the actual IOD payload.
Parsed ModuleDiffBlock (0x8104).
Parsed PDRealData (0xF841) structure.
Parsed RealIdentificationData (0xF000/0x0013) structure.
Complete diagnosis data for one slot/subslot.
All I&M records a device supports, read in one call.
One RPC endpoint advertised by a device's Endpoint Mapper.
std::string protocol
Transport protocol, e.g. "ncadg_ip_udp".
std::uint16_t interfaceVersionMinor
Minor version of the interface.
std::string ipAddress
IPv4 address the endpoint listens on.
std::uint16_t port
UDP/TCP port the endpoint listens on.
std::uint16_t interfaceVersionMajor
Major version of the interface.
std::string annotation
Free-text annotation supplied by the device (e.g. a model name).
std::string InterfaceName() const
Human-readable interface name.
std::string objectUuid
Object UUID this endpoint entry is registered under.
std::string interfaceUuid
Interface UUID this endpoint serves.
Configuration for establishing cyclic IO alongside an AR.
Configuration options for an RPC connection.
Declares Linux Ethernet, addressing, timing, and utility helpers used by the PROFINET stack.