PROFINET IO Controller Stack 1.0.0
Modern C++ implementation of a PROFINET IO Controller stack
Loading...
Searching...
No Matches
device.h
Go to the documentation of this file.
1
33#pragma once
34
35#include <functional>
36#include <map>
37#include <memory>
38#include <optional>
39#include <string>
40#include <vector>
41
43#include "profinet/alarms.h"
44#include "profinet/blocks.h"
45#include "profinet/cyclic.h"
46#include "profinet/dcp.h"
47#include "profinet/diagnosis.h"
48#include "profinet/protocol.h"
49#include "profinet/rpc.h"
50#include "profinet/rt.h"
51#include "profinet/util.h"
52
54{
55
62std::optional<MacAddress> ParseMac(const std::string& macStr);
63
67bool IsMacAddress(const std::string& identifier);
68
69// =============================================================================
70// Data Classes
71// =============================================================================
72
75{
77 std::uint16_t slot = 0;
78
80 std::uint16_t subslot = 0;
81
83 std::uint16_t index = 0;
84
87
89 std::uint32_t api = 0;
90};
91
96{
98 std::string name;
99
101 std::string ip;
102
104 std::string mac;
105
107 std::uint16_t vendorId = 0;
108
110 std::uint16_t deviceId = 0;
111
113 std::string deviceType;
114
116 std::string netmask;
117
119 std::string gateway;
120
122 std::vector<std::string> deviceRoles;
123
125 std::string vendorName;
126
128 std::optional<PNInM0> im0;
129
131 std::optional<blocks::PDRealData> topology;
132
134 std::string annotation;
135
138 [[nodiscard]] std::string SerialNumber() const;
139
142 [[nodiscard]] std::string OrderId() const;
143
146 [[nodiscard]] std::uint16_t HardwareRevision() const;
147
150 [[nodiscard]] std::string SoftwareRevision() const;
151};
152
153// =============================================================================
154// ProfinetDevice
155// =============================================================================
156
168{
169 public:
180 double timeoutSec = 5.0,
181 std::unique_ptr<rpc::IRPCCon> rpc = nullptr, std::unique_ptr<IAlarmListener> alarmListener = nullptr);
182
185
188
191
194
198
199 // =========================================================================
200 // Discovery factory methods
201 // =========================================================================
202
210 static ProfinetDevice Discover(const std::string& identifier, const std::string& interface,
211 double timeoutSec = 10.0);
212
220 static ProfinetDevice FromIp(const std::string& ip, const std::string& interface, double timeoutSec = 10.0);
221
228 double timeoutSec = 5.0);
229
230 // =========================================================================
231 // Connection management
232 // =========================================================================
233
238 void Connect();
239
242 void Disconnect();
243
246 void Close();
247
250 [[nodiscard]] bool IsConnected() const
251 {
252 return connected;
253 }
254
255 // =========================================================================
256 // Device info
257 // =========================================================================
258
261 [[nodiscard]] const std::string& Name() const
262 {
263 return info.name;
264 }
265
268 [[nodiscard]] const std::string& Ip() const
269 {
270 return info.ip;
271 }
272
275 [[nodiscard]] std::string Mac() const
276 {
277 return info.mac;
278 }
279
286 DeviceInfo GetInfo(bool includeTopology = false);
287
288 // =========================================================================
289 // Read/write operations
290 // =========================================================================
291
299 Bytes Read(std::uint16_t slot, std::uint16_t subslot, std::uint16_t index, std::uint32_t api = 0);
300
330 Bytes ReadImplicit(std::uint16_t slot, std::uint16_t subslot, std::uint16_t index, std::uint32_t api = 0);
331
339 void Write(std::uint16_t slot, std::uint16_t subslot, std::uint16_t index, const Bytes& data,
340 std::uint32_t api = 0);
341
345 std::vector<blocks::WriteMultipleResult> WriteMultiple(const std::vector<WriteItem>& writes);
346
347 // =========================================================================
348 // I&M record convenience methods
349 // =========================================================================
350
355 PNInM0 ReadIm0(std::uint16_t slot = 0, std::uint16_t subslot = 1);
356
361 PNInM1 ReadIm1(std::uint16_t slot = 0, std::uint16_t subslot = 1);
362
367 PNInM2 ReadIm2(std::uint16_t slot = 0, std::uint16_t subslot = 1);
368
373 PNInM3 ReadIm3(std::uint16_t slot = 0, std::uint16_t subslot = 1);
374
379 PNInM4 ReadIm4(std::uint16_t slot = 0, std::uint16_t subslot = 1);
380
385 PNInM5 ReadIm5(std::uint16_t slot = 0, std::uint16_t subslot = 1);
386
391 rpc::AllIM ReadAllIm(std::uint16_t slot = 0, std::uint16_t subslot = 1);
392
400 void WriteIm1(const std::string& tagFunction, const std::string& tagLocation, std::uint16_t slot = 0,
401 std::uint16_t subslot = 1);
402
408 void WriteIm2(const std::string& date, std::uint16_t slot = 0, std::uint16_t subslot = 1);
409
415 void WriteIm3(const std::string& descriptor, std::uint16_t slot = 0, std::uint16_t subslot = 1);
416
417 // =========================================================================
418 // Configuration & diagnosis
419 // =========================================================================
420
424
430 diagnosis::DiagnosisData ReadDiagnosis(std::uint16_t slot = 0, std::uint16_t subslot = 0,
431 std::uint16_t index = 0xF000);
432
435 std::map<std::uint16_t, diagnosis::DiagnosisData> ReadAllDiagnosis();
436
439 std::vector<blocks::SlotInfo> DiscoverSlots();
440
444
445 // =========================================================================
446 // Alarm reading
447 // =========================================================================
448
456 std::optional<AlarmNotification> ReadAlarm(std::uint16_t slot = 0, std::uint16_t subslot = 0,
457 std::uint16_t index = 0x800C);
458
463 void OnAlarm(std::function<void(const AlarmNotification&)> callback);
464
472 void StartAlarmListener();
473
476 void StopAlarmListener();
477
480 [[nodiscard]] bool AlarmListenerRunning() const;
481
482 // =========================================================================
483 // Cyclic IO
484 // =========================================================================
485
496 std::unique_ptr<cyclic::ICyclicController> StartCyclic(const rpc::IOCRSetup& iocrSetup,
497 int maxConsecutiveTimeouts = 3,
498 std::unique_ptr<cyclic::ICyclicController> controller = nullptr);
499
500 // =========================================================================
501 // Utility
502 // =========================================================================
503
508 std::map<std::uint16_t, rpc::IndexProbeResult> EnumerateIndices(std::uint16_t slot = 0,
509 std::uint16_t subslot = 1);
510
513 [[nodiscard]] std::string ToString() const;
514
515 private:
519
538 void ReleaseAr(rpc::IRPCCon& releaseRpc);
539
542
544 std::string interface;
545
548
550 double timeout;
551
553 std::unique_ptr<rpc::IRPCCon> rpc;
554
556 bool connected = false;
557
559 std::unique_ptr<IAlarmListener> alarmListener;
560
562 std::vector<std::function<void(const AlarmNotification&)>> alarmCallbacks;
563};
564
565// =============================================================================
566// Scan
567// =============================================================================
568
574std::vector<ProfinetDevice> Scan(const std::string& interface = "eth0", double timeoutSec = 3.0);
575
581std::map<std::string, DeviceInfo> ScanDict(const std::string& interface = "eth0", double timeoutSec = 3.0);
582
583} // namespace profinet::device
Declares the PROFINET RTA alarm listener and AlarmAck transmission support.
Declares PROFINET alarm, diagnosis, maintenance, and USI payload types and parsers.
Declares PROFINET IO connection-management block structures and wire serialization.
Parsed PROFINET device information from a DCP response.
Definition dcp.h:426
std::string name
Station name.
Definition dcp.h:440
std::string mac
Device's MAC address, formatted as a string.
Definition dcp.h:434
std::string ip
IPv4 address, or "0.0.0.0" if unset.
Definition dcp.h:443
High-level PROFINET device interface.
Definition device.h:168
std::string ToString() const
Human-readable summary of this device, for logging/debugging.
Definition device.cpp:703
PNInM0 ReadIm0(std::uint16_t slot=0, std::uint16_t subslot=1)
Read I&M0 (mandatory identification data).
Definition device.cpp:488
std::string Mac() const
The device's MAC address.
Definition device.h:275
rpc::AllIM ReadAllIm(std::uint16_t slot=0, std::uint16_t subslot=1)
Read all I&M records the device supports.
Definition device.cpp:512
void ReleaseAr(rpc::IRPCCon &releaseRpc)
Release a PROFINET Application Relationship.
Definition device.cpp:338
blocks::ModuleDiffBlock ReadModuleDiff()
Read and parse the device's ModuleDiffBlock.
Definition device.cpp:571
~ProfinetDevice()
Close() the connection and release resources.
Definition device.cpp:226
static ProfinetDevice Discover(const std::string &identifier, const std::string &interface, double timeoutSec=10.0)
Discover a device by station name or MAC address.
Definition device.cpp:231
std::map< std::uint16_t, rpc::IndexProbeResult > EnumerateIndices(std::uint16_t slot=0, std::uint16_t subslot=1)
Probe standard indices and report which are readable/empty/erroring.
Definition device.cpp:697
std::vector< blocks::WriteMultipleResult > WriteMultiple(const std::vector< WriteItem > &writes)
Write multiple records atomically.
Definition device.cpp:476
PNInM5 ReadIm5(std::uint16_t slot=0, std::uint16_t subslot=1)
Read I&M5 (free-text annotation).
Definition device.cpp:508
std::string interface
Network interface name in use.
Definition device.h:544
void StopAlarmListener()
Stop the alarm listener.
Definition device.cpp:655
PNInM4 ReadIm4(std::uint16_t slot=0, std::uint16_t subslot=1)
Read I&M4 (PROFIsafe signature).
Definition device.cpp:504
blocks::PDRealData ReadTopology()
Read the device's physical topology.
Definition device.cpp:592
void StartAlarmListener()
Start the background alarm listener.
Definition device.cpp:625
void WriteIm1(const std::string &tagFunction, const std::string &tagLocation, std::uint16_t slot=0, std::uint16_t subslot=1)
Write I&M1 (tag function + location).
Definition device.cpp:517
std::unique_ptr< IAlarmListener > alarmListener
Background alarm listener, created lazily by StartAlarmListener().
Definition device.h:559
void OnAlarm(std::function< void(const AlarmNotification &)> callback)
Register a callback for alarm notifications.
Definition device.cpp:616
void WriteIm3(const std::string &descriptor, std::uint16_t slot=0, std::uint16_t subslot=1)
Write I&M3 (free-text descriptor).
Definition device.cpp:555
void Write(std::uint16_t slot, std::uint16_t subslot, std::uint16_t index, const Bytes &data, std::uint32_t api=0)
Write a raw record.
Definition device.cpp:469
ProfinetDevice(ProfinetDevice &&)=default
Move-construct, transferring ownership of the connection.
PNInM2 ReadIm2(std::uint16_t slot=0, std::uint16_t subslot=1)
Read I&M2 (installation date).
Definition device.cpp:496
Bytes ReadImplicit(std::uint16_t slot, std::uint16_t subslot, std::uint16_t index, std::uint32_t api=0)
Read a record using the AR-less Read Implicit service.
Definition device.cpp:444
std::unique_ptr< rpc::IRPCCon > rpc
Underlying RPC connection, created lazily on first use.
Definition device.h:553
void Close()
Stop the alarm listener (if running) and fully close the RPC connection.
Definition device.cpp:323
bool connected
Whether the AR is currently established.
Definition device.h:556
ProfinetDevice & operator=(const ProfinetDevice &)=delete
Not copyable (owns an RPC connection and alarm listener).
PNInM1 ReadIm1(std::uint16_t slot=0, std::uint16_t subslot=1)
Read I&M1 (tag function/location).
Definition device.cpp:492
diagnosis::DiagnosisData ReadDiagnosis(std::uint16_t slot=0, std::uint16_t subslot=0, std::uint16_t index=0xF000)
Read and parse diagnosis data at the given location/index.
Definition device.cpp:576
void Connect()
Establish the AR.
Definition device.cpp:289
const std::string & Ip() const
The device's IPv4 address.
Definition device.h:268
ProfinetDevice(const ProfinetDevice &)=delete
Not copyable (owns an RPC connection and alarm listener).
Bytes Read(std::uint16_t slot, std::uint16_t subslot, std::uint16_t index, std::uint32_t api=0)
Read a raw record.
Definition device.cpp:427
void WriteIm2(const std::string &date, std::uint16_t slot=0, std::uint16_t subslot=1)
Write I&M2 (installation date).
Definition device.cpp:539
static ProfinetDevice FromDcpInfo(dcp::DCPDeviceDescription info, const std::string &interface, double timeoutSec=5.0)
Wrap an already-discovered DCPDeviceDescription.
Definition device.cpp:281
ProfinetDevice & operator=(ProfinetDevice &&)=default
Move-assign, transferring ownership of the connection.
std::unique_ptr< cyclic::ICyclicController > StartCyclic(const rpc::IOCRSetup &iocrSetup, int maxConsecutiveTimeouts=3, std::unique_ptr< cyclic::ICyclicController > controller=nullptr)
Establish cyclic IO end-to-end.
Definition device.cpp:670
std::vector< blocks::SlotInfo > DiscoverSlots()
List the device's populated slots.
Definition device.cpp:587
PNInM3 ReadIm3(std::uint16_t slot=0, std::uint16_t subslot=1)
Read I&M3 (free-text descriptor).
Definition device.cpp:500
std::optional< AlarmNotification > ReadAlarm(std::uint16_t slot=0, std::uint16_t subslot=0, std::uint16_t index=0x800C)
Attempt to read an alarm notification at the given location.
Definition device.cpp:597
MacAddress srcMac
This host's MAC address.
Definition device.h:547
static ProfinetDevice FromIp(const std::string &ip, const std::string &interface, double timeoutSec=10.0)
Discover a device by IP address.
Definition device.cpp:262
bool IsConnected() const
Whether the AR is currently established.
Definition device.h:250
void Disconnect()
Gracefully disconnect (sends Release).
Definition device.cpp:314
bool AlarmListenerRunning() const
Whether the alarm listener is currently running.
Definition device.cpp:664
double timeout
Default RPC response timeout in seconds.
Definition device.h:550
std::vector< std::function< void(const AlarmNotification &)> > alarmCallbacks
Callbacks registered via OnAlarm(), applied to alarmListener once started.
Definition device.h:562
rpc::IRPCCon & EnsureConnected()
Return the underlying RPCCon, connecting first if necessary.
Definition device.cpp:362
const std::string & Name() const
The device's station name.
Definition device.h:261
DeviceInfo GetInfo(bool includeTopology=false)
Gather a complete device information summary.
Definition device.cpp:371
dcp::DCPDeviceDescription info
DCP-discovered description of this device.
Definition device.h:541
std::map< std::uint16_t, diagnosis::DiagnosisData > ReadAllDiagnosis()
Read diagnosis from all standard diagnosis indices.
Definition device.cpp:582
Abstract interface for a PROFINET RPC connection.
Definition IRPCCon.h:50
Declares the PROFINET RTC1 cyclic IO controller and process-data exchange API.
PROFINET DCP discovery and device configuration interface.
PROFINET diagnosis data structures, error decoding, and parsers.
bool IsMacAddress(const std::string &identifier)
Whether a string parses as a MAC address.
Definition device.cpp:173
std::optional< MacAddress > ParseMac(const std::string &macStr)
Parse a MAC address string in any common separator style.
Definition device.cpp:57
std::map< std::string, DeviceInfo > ScanDict(const std::string &interface="eth0", double timeoutSec=3.0)
Scan the network and return a name -> DeviceInfo map.
Definition device.cpp:731
std::vector< ProfinetDevice > Scan(const std::string &interface="eth0", double timeoutSec=3.0)
Scan the network for PROFINET devices via DCP Identify.
Definition device.cpp:713
std::array< std::uint8_t, macAddressLength > MacAddress
A 6-byte Ethernet MAC address.
Definition util.h:67
std::vector< std::uint8_t > Bytes
Generic byte buffer alias used throughout the library for raw wire data.
Definition protocol.h:52
PROFINET protocol wire-format structures and serialization helpers.
PROFINET DCE/RPC protocol structures and IO-Device connection API.
Declares PROFINET RT_CLASS_1 cyclic frame and IOCR data structures.
Complete parsed AlarmNotification PDU: header fields + parsed items.
Definition alarms.h:358
I&M0: mandatory identification data (vendor, order ID, serial number, revisions).
Definition protocol.h:1076
I&M1: user-assigned tag function and location strings.
Definition protocol.h:1178
I&M2: installation date.
Definition protocol.h:1222
I&M3: free-text descriptor.
Definition protocol.h:1263
I&M4: PROFIsafe signature (binary, not text).
Definition protocol.h:1303
I&M5: free-text annotation.
Definition protocol.h:1343
Parsed ModuleDiffBlock (0x8104).
Definition blocks.h:415
Parsed PDRealData (0xF841) structure.
Definition blocks.h:221
Complete device information summary.
Definition device.h:96
std::uint16_t deviceId
PROFINET device ID (from DCP).
Definition device.h:110
std::string name
Station name (from DCP).
Definition device.h:98
std::string deviceType
Device type string (from DCP).
Definition device.h:113
std::string netmask
IPv4 subnet mask (from DCP).
Definition device.h:116
std::string annotation
Device model, if the EPM endpoint advertised one.
Definition device.h:134
std::string mac
MAC address, formatted as a string (from DCP).
Definition device.h:104
std::string SerialNumber() const
Serial number from I&M0, trimmed.
Definition device.cpp:182
std::vector< std::string > deviceRoles
Decoded device role names (from DCP).
Definition device.h:122
std::string vendorName
Human-readable vendor name (from DCP).
Definition device.h:125
std::optional< PNInM0 > im0
I&M0 identification data, if it was read successfully.
Definition device.h:128
std::string gateway
IPv4 default gateway (from DCP).
Definition device.h:119
std::uint16_t vendorId
PROFINET vendor ID (from DCP).
Definition device.h:107
std::uint16_t HardwareRevision() const
Hardware revision from I&M0.
Definition device.cpp:190
std::string OrderId() const
Order ID from I&M0, trimmed.
Definition device.cpp:186
std::string ip
IPv4 address (from DCP).
Definition device.h:101
std::string SoftwareRevision() const
Software revision string from I&M0.
Definition device.cpp:195
std::optional< blocks::PDRealData > topology
Physical topology, if it was read successfully.
Definition device.h:131
A single write operation for ProfinetDevice::WriteMultiple().
Definition device.h:75
std::uint16_t subslot
Subslot number.
Definition device.h:80
std::uint16_t index
Record data index to write.
Definition device.h:83
std::uint32_t api
API number.
Definition device.h:89
Bytes data
Record data to write.
Definition device.h:86
std::uint16_t slot
Slot number.
Definition device.h:77
Complete diagnosis data for one slot/subslot.
Definition diagnosis.h:282
All I&M records a device supports, read in one call.
Definition rpcTypes.h:227
Configuration for establishing cyclic IO alongside an AR.
Definition rpcTypes.h:134
Declares Linux Ethernet, addressing, timing, and utility helpers used by the PROFINET stack.