PROFINET IO Controller Stack 1.0.0
Modern C++ implementation of a PROFINET IO Controller stack
Loading...
Searching...
No Matches
dcp.h
Go to the documentation of this file.
1
31
32#pragma once
33
34#include <chrono>
35#include <cstdint>
36#include <functional>
37#include <map>
38#include <optional>
39#include <string>
40#include <utility>
41#include <vector>
42
44#include "profinet/protocol.h"
45#include "profinet/util.h"
46
48{
49// NOLINTBEGIN(readability-identifier-naming)
50// =============================================================================
51// Constants
52// =============================================================================
53
55inline const std::string DCP_MULTICAST_MAC = "01:0e:cf:00:00:00";
57inline const std::string DCP_HELLO_MULTICAST_MAC = "01:0e:cf:00:00:01";
58
60inline constexpr std::size_t DCP_MAX_NAME_LENGTH = 240;
61
63inline constexpr std::uint16_t DEFAULT_TIMEOUT = 5;
64inline constexpr std::uint16_t DEFAULT_THREAD_SLEEP_MS = 2000;
66inline constexpr std::uint16_t DEFAULT_RESPONSE_TIMEOUT = 20;
68inline constexpr std::uint16_t DEFAULT_HELLO_TIMEOUT = 10;
70inline constexpr std::uint16_t DEFAULT_RESPONSE_DELAY_FACTOR = 0x0080; // 128
72inline constexpr std::uint16_t FLASH_DURATION_MS = 3000;
73
75inline constexpr std::uint16_t blockNameVendorRangeMin = 0x80;
77inline constexpr std::uint16_t blockNameVendorRangeMax = 0xFF;
78
80inline constexpr std::uint16_t DCP_IP_CONFLICT_BIT = 0x0080;
82inline constexpr std::uint16_t DCP_IP_DHCP_BIT = 0x0002;
83// NOLINTEND(readability-identifier-naming)
84
88std::vector<std::string> DecodeDeviceRole(std::uint8_t roleByte);
89
93std::string DeviceRoleName(DcpDeviceRole role);
94
99std::string GetBlockName(std::uint16_t option, std::uint8_t suboption);
100
105std::string GetBlockName(DcpOption option, std::uint8_t suboption);
106
112
118
124
130
136
141
149DcpBlockError RecvSetResponse(IRawEthernetSocket& sock, const MacAddress& srcMac, int timeoutSec);
150
152
156std::string GetDcpResponseCodeName(DcpResponseCode value);
157
161std::string GetResetQualifierName(std::uint16_t qualifier);
162
166std::string GetResetQualifierName(DcpResetQualifier qualifier);
167
171std::string GetIPBlockInfoName(DcpIpBlockInfo info);
172
176bool HasConflict(DcpIpBlockInfo info);
177
181bool IsDhcp(DcpIpBlockInfo info);
182
187
192
195{
198
200 std::string suboptionName;
201
203 std::vector<std::uint8_t> rawData;
204
206 std::optional<std::string> hostname;
207
209 std::optional<std::vector<std::uint8_t>> clientId;
210
212 std::optional<std::vector<std::uint8_t>> vendorSpecific;
213
215 std::optional<std::string> fqdn;
216
218 std::optional<std::string> uuid;
219
224 static DCPDHCPBlock Parse(DcpDhcpSuboption suboption, const std::vector<std::uint8_t>& data);
225};
226
228// using BlockKey = std::pair<std::uint8_t, std::uint8_t>;
230
231constexpr DcpBlockKey MakeBlockKey(std::uint16_t option, std::uint8_t suboption)
232{
233 return {.option = static_cast<DcpOption>(option), .suboption = suboption};
234}
235
237{
238 return {.option = option, .suboption = suboption};
239}
240
242{
243 return {.option = option, .suboption = static_cast<std::uint8_t>(suboption)};
244}
245
247{
248 return {.option = option, .suboption = static_cast<std::uint8_t>(suboption)};
249}
250
252{
253 return {.option = option, .suboption = static_cast<std::uint8_t>(suboption)};
254}
255
257{
258 return {.option = option, .suboption = static_cast<std::uint8_t>(suboption)};
259}
260
262{
263 return {.option = option, .suboption = static_cast<std::uint8_t>(suboption)};
264}
265
268{
269 public:
273 DCPDeviceDescription(const MacAddress& mac, const std::map<BlockKey, std::vector<std::uint8_t>>& blocks);
274
276 std::string mac;
277
279 std::string deviceType;
280
282 std::string name;
283
285 std::string ip = "0.0.0.0";
286
288 std::string netmask = "0.0.0.0";
289
291 std::string gateway = "0.0.0.0";
292
295
297 bool ipConflict = false;
298
300 bool ipSetByDhcp = false;
301
303 std::uint16_t vendorId = 0;
304
306 std::uint8_t vendorHigh = 0;
307
309 std::uint8_t vendorLow = 0;
310
312 std::uint16_t deviceId = 0;
313
315 std::uint8_t deviceHigh = 0;
316
318 std::uint8_t deviceLow = 0;
319
321 std::uint8_t deviceRole = 0;
322
324 std::vector<std::string> deviceRoles;
325
327 std::pair<std::uint8_t, std::uint8_t> deviceInstance{0, 0};
328
330 std::string aliasName;
331
333 std::vector<BlockKey> supportedOptions;
334
336 std::vector<DCPDHCPBlock> dhcpBlocks;
337
339 // std::uint16_t deviceInitiative = 0;
341
343 bool issuesHello = false;
344
346 std::map<BlockKey, std::vector<std::uint8_t>> rawBlocks;
347
350 [[nodiscard]] std::uint16_t VendorId() const
351 {
352 return vendorId;
353 }
354
357 [[nodiscard]] std::uint16_t DeviceId() const
358 {
359 return deviceId;
360 }
361
364 [[nodiscard]] std::string VendorName() const;
365
368 [[nodiscard]] std::string ToString() const;
369};
370
371// =============================================================================
372// DCP Operations
373// =============================================================================
399 const MacAddress& src,
400 const std::string& param,
401 const std::string& value,
402 bool permanent);
403
418[[nodiscard]] Bytes BuildDcpSignalRequest(const MacAddress& dst, const MacAddress& src);
419
422const std::map<std::string, BlockKey>& Params();
423
432std::optional<std::vector<std::uint8_t>> GetParam(IRawEthernetSocket& sock, const MacAddress& src,
433 const std::string& target, const std::string& param,
434 int timeoutSec = DEFAULT_TIMEOUT);
435
450bool SetParam(IRawEthernetSocket& sock, const MacAddress& src, const std::string& target,
451 const std::string& param, const std::string& value, int timeoutSec = DEFAULT_TIMEOUT, bool permanent = false, int threadSleepMs = DEFAULT_THREAD_SLEEP_MS);
452
464bool SetIp(IRawEthernetSocket& sock, const MacAddress& src, const std::string& target,
465 const std::string& ip, const std::string& netmask, const std::string& gateway,
466 bool permanent = false, int timeoutSec = DEFAULT_TIMEOUT, int threadSleepMs = DEFAULT_THREAD_SLEEP_MS);
467
472void SendDiscover(IRawEthernetSocket& sock, const MacAddress& src, std::uint16_t responseDelay = DEFAULT_RESPONSE_DELAY_FACTOR);
473
479void SendRequest(IRawEthernetSocket& sock, const MacAddress& src, BlockKey blockType,
480 const std::vector<std::uint8_t>& value);
481
483using ResponseMap = std::map<MacAddress, std::map<BlockKey, std::vector<std::uint8_t>>>;
484
492ResponseMap ReadResponse(IRawEthernetSocket& sock, const MacAddress& myMac, double timeoutSec = DEFAULT_RESPONSE_TIMEOUT,
493 bool once = false, std::optional<std::uint32_t> expectedXid = std::nullopt);
494
504void SendHello(IRawEthernetSocket& sock, const MacAddress& src, const std::string& stationName,
505 const std::string& ip = "0.0.0.0", const std::string& netmask = "0.0.0.0",
506 const std::string& gateway = "0.0.0.0", std::pair<std::uint16_t, std::uint16_t> deviceId = {0, 0},
508
515std::vector<DCPDeviceDescription> ReceiveHello(
516 IRawEthernetSocket& sock, const MacAddress& myMac, double timeoutSec = DEFAULT_HELLO_TIMEOUT,
517 const std::function<void(const DCPDeviceDescription&)>& callback = nullptr);
518
527bool SignalDevice(IRawEthernetSocket& sock, const MacAddress& src, const std::string& target,
528 int durationMs = FLASH_DURATION_MS, double timeoutSec = DEFAULT_TIMEOUT);
529
539 const MacAddress& src,
540 const std::string& target,
542 double timeoutSec = DEFAULT_TIMEOUT);
543
544} // namespace profinet::dcp
Abstraction for sending and receiving raw Ethernet frames.
Abstract interface for raw Ethernet frame transport.
Parsed PROFINET device information from a DCP response.
Definition dcp.h:268
std::pair< std::uint8_t, std::uint8_t > deviceInstance
Device instance (high, low) pair.
Definition dcp.h:327
bool ipConflict
Whether an IP address conflict was detected.
Definition dcp.h:297
std::uint8_t vendorLow
Low byte of the PROFINET vendor ID.
Definition dcp.h:309
std::string netmask
IPv4 subnet mask, or "0.0.0.0" if unset.
Definition dcp.h:288
std::string ToString() const
Multi-line human-readable summary of this device.
Definition dcp.cpp:751
std::string name
Station name.
Definition dcp.h:282
std::uint8_t vendorHigh
High byte of the PROFINET vendor ID.
Definition dcp.h:306
std::uint8_t deviceLow
Low byte of the PROFINET device ID.
Definition dcp.h:318
std::uint16_t VendorId() const
Combine VendorHigh/VendorLow into a 16-bit vendor ID.
Definition dcp.h:350
DcpIpBlockInfo ipBlockInfo
IP block info flags (see IPBlockInfo).
Definition dcp.h:294
std::uint8_t deviceRole
Raw device role bitmask.
Definition dcp.h:321
std::string gateway
IPv4 default gateway, or "0.0.0.0" if unset.
Definition dcp.h:291
std::uint16_t DeviceId() const
Combine DeviceHigh/DeviceLow into a 16-bit device ID.
Definition dcp.h:357
std::string aliasName
Device alias name, if set.
Definition dcp.h:330
std::uint16_t vendorId
The PROFINET vendor ID.
Definition dcp.h:303
std::map< BlockKey, std::vector< std::uint8_t > > rawBlocks
Any parsed blocks not covered by the named fields above.
Definition dcp.h:346
DcpDeviceInitiative deviceInitiative
Raw device-initiative value (see DeviceInitiative).
Definition dcp.h:340
std::vector< BlockKey > supportedOptions
List of (option, suboption) blocks the device supports.
Definition dcp.h:333
bool issuesHello
Whether the device issues a DCP-Hello after power-on.
Definition dcp.h:343
std::uint8_t deviceHigh
High byte of the PROFINET device ID.
Definition dcp.h:315
std::string VendorName() const
Look up the vendor name for this device's vendor ID.
Definition dcp.cpp:746
std::string mac
Device's MAC address, formatted as a string.
Definition dcp.h:276
std::string ip
IPv4 address, or "0.0.0.0" if unset.
Definition dcp.h:285
bool ipSetByDhcp
Whether the IP address was assigned via DHCP.
Definition dcp.h:300
std::uint16_t deviceId
The PROFINET device ID.
Definition dcp.h:312
std::vector< DCPDHCPBlock > dhcpBlocks
Parsed DHCP blocks from the response, if any.
Definition dcp.h:336
std::vector< std::string > deviceRoles
Decoded device role names (see DecodeDeviceRole()).
Definition dcp.h:324
std::string deviceType
Device type string (e.g. model name).
Definition dcp.h:279
bool HasConflict(DcpIpBlockInfo info)
Whether an address conflict was detected.
Definition dcp.cpp:424
void SendDiscover(IRawEthernetSocket &sock, const MacAddress &src, std::uint16_t responseDelay=DEFAULT_RESPONSE_DELAY_FACTOR)
Send a DCP Identify multicast request to discover all devices on the segment.
Definition dcp.cpp:1173
std::optional< std::vector< std::uint8_t > > GetParam(IRawEthernetSocket &sock, const MacAddress &src, const std::string &target, const std::string &param, int timeoutSec=DEFAULT_TIMEOUT)
Read a named parameter from a device.
Definition dcp.cpp:1005
Bytes BuildSetParamRequest(const MacAddress &dst, const MacAddress &src, const std::string &param, const std::string &value, bool permanent)
Build a serialized DCP SET request for a named parameter.
Definition dcp.cpp:883
std::string GetResetQualifierName(std::uint16_t qualifier)
Get the human-readable name for a reset qualifier value.
Definition dcp.cpp:447
void SendHello(IRawEthernetSocket &sock, const MacAddress &src, const std::string &stationName, const std::string &ip="0.0.0.0", const std::string &netmask="0.0.0.0", const std::string &gateway="0.0.0.0", std::pair< std::uint16_t, std::uint16_t > deviceId={0, 0}, DcpDeviceRole deviceRole=DcpDeviceRole::IoDevice)
Send a DCP Hello multicast announcement (device self-announce after power-on).
Definition dcp.cpp:1342
Bytes BuildDcpSignalRequest(const MacAddress &dst, const MacAddress &src)
Build a serialized DCP Signal request.
Definition dcp.cpp:937
bool SetIp(IRawEthernetSocket &sock, const MacAddress &src, const std::string &target, const std::string &ip, const std::string &netmask, const std::string &gateway, bool permanent=false, int timeoutSec=DEFAULT_TIMEOUT, int threadSleepMs=DEFAULT_THREAD_SLEEP_MS)
Set a device's IP configuration via DCP.
Definition dcp.cpp:1120
const std::map< std::string, BlockKey > & Params()
Table of supported parameter names, mapping to their (option, suboption).
Definition dcp.cpp:590
std::string DeviceRoleName(DcpDeviceRole role)
Get the human-readable name of a DCP device role.
Definition dcp.cpp:118
bool SignalDevice(IRawEthernetSocket &sock, const MacAddress &src, const std::string &target, int durationMs=FLASH_DURATION_MS, double timeoutSec=DEFAULT_TIMEOUT)
Flash a device's identification LEDs.
Definition dcp.cpp:1519
constexpr DcpBlockKey MakeBlockKey(std::uint16_t option, std::uint8_t suboption)
Definition dcp.h:231
constexpr std::uint16_t DEFAULT_RESPONSE_DELAY_FACTOR
Default dcp response delay factor.
Definition dcp.h:70
DcpBlockKey BlockKey
(option, suboption) key identifying a DCP block.
Definition dcp.h:229
DcpBlockError RecvSetResponse(IRawEthernetSocket &sock, const MacAddress &srcMac, int timeoutSec)
Receive and parse a DCP SET response, filtering out unrelated frames.
Definition dcp.cpp:253
std::string GetDeviceInitiativeName(DcpDeviceInitiative value)
Definition dcp.cpp:488
std::string GetDcpBlockQualifierDescription(DcpBlockQualifier qualifier)
Get the human-readable description of a DCP block qualifier.
Definition dcp.cpp:434
constexpr std::uint16_t DCP_IP_DHCP_BIT
Bit mask indicating DHCP bit is set.
Definition dcp.h:82
constexpr std::uint16_t FLASH_DURATION_MS
Default flash duration of the leds.
Definition dcp.h:72
bool IsDhcp(DcpIpBlockInfo info)
Whether the address was assigned via DHCP.
Definition dcp.cpp:429
constexpr std::uint16_t DEFAULT_HELLO_TIMEOUT
Default HELLO timeout.
Definition dcp.h:68
constexpr std::uint16_t blockNameVendorRangeMin
Default flash duration of the leds.
Definition dcp.h:75
constexpr std::uint16_t DEFAULT_TIMEOUT
Default timeout.
Definition dcp.h:63
constexpr std::uint16_t blockNameVendorRangeMax
Default flash duration of the leds.
Definition dcp.h:77
void SendRequest(IRawEthernetSocket &sock, const MacAddress &src, BlockKey blockType, const std::vector< std::uint8_t > &value)
Send a DCP Identify request filtered to a specific (option, suboption).
Definition dcp.cpp:1195
const std::string DCP_MULTICAST_MAC
DCP Identify/Get/Set multicast destination MAC.
Definition dcp.h:55
const std::string DCP_HELLO_MULTICAST_MAC
DCP Hello multicast destination MAC.
Definition dcp.h:57
std::string GetIPBlockInfoName(DcpIpBlockInfo info)
Get the human-readable name for an IP block info value.
Definition dcp.cpp:402
std::vector< std::string > DecodeDeviceRole(std::uint8_t roleByte)
Decode a device role bitmask into a list of role names.
Definition dcp.cpp:97
std::map< MacAddress, std::map< BlockKey, std::vector< std::uint8_t > > > ResponseMap
Result of ReadResponse(): MAC address -> parsed (option,suboption) -> payload blocks.
Definition dcp.h:483
std::string GetBlockName(std::uint16_t option, std::uint8_t suboption)
Get the human-readable name for a (option, suboption) DCP block.
Definition dcp.cpp:196
ResponseMap ReadResponse(IRawEthernetSocket &sock, const MacAddress &myMac, double timeoutSec=DEFAULT_RESPONSE_TIMEOUT, bool once=false, std::optional< std::uint32_t > expectedXid=std::nullopt)
Read and parse DCP Identify responses.
Definition dcp.cpp:1218
constexpr std::uint16_t DEFAULT_RESPONSE_TIMEOUT
Default response timeout. How long to keep listening for responses.
Definition dcp.h:66
constexpr std::uint16_t DCP_IP_CONFLICT_BIT
Bit mask indicating an IP address conflict.
Definition dcp.h:80
std::string GetDcpBlockErrorDescription(DcpBlockError error)
Get the human-readable name for a DCP SET block-level error code.
Definition dcp.cpp:524
constexpr std::uint16_t DEFAULT_THREAD_SLEEP_MS
Definition dcp.h:64
std::string GetDcpResponseCodeName(DcpResponseCode value)
Get the human-readable name for a device-response value.
Definition dcp.cpp:501
bool SetParam(IRawEthernetSocket &sock, const MacAddress &src, const std::string &target, const std::string &param, const std::string &value, int timeoutSec=DEFAULT_TIMEOUT, bool permanent=false, int threadSleepMs=DEFAULT_THREAD_SLEEP_MS)
Write a named parameter to a device.
Definition dcp.cpp:1096
DcpBlockError ParseSetResponse(const Bytes &data)
Parses the raw byte response payload received from a SET operation.
Definition dcp.cpp:319
std::vector< DCPDeviceDescription > ReceiveHello(IRawEthernetSocket &sock, const MacAddress &myMac, double timeoutSec=DEFAULT_HELLO_TIMEOUT, const std::function< void(const DCPDeviceDescription &)> &callback=nullptr)
Listen for DCP Hello announcements from other devices.
Definition dcp.cpp:1424
constexpr std::size_t DCP_MAX_NAME_LENGTH
Maximum allowed length in bytes for a station name.
Definition dcp.h:60
DcpBlockQualifier
DCP block qualifier values.
Definition protocol.h:430
DcpIpSuboption
DCP IP suboptions.
Definition protocol.h:147
DcpDeviceInitiativeSuboption
DCP DeviceInitiative suboptions.
Definition protocol.h:256
DcpDhcpSuboption
DCP DHCP suboptions.
Definition protocol.h:222
@ Unknown
Not set / initialize value.
DcpControlSuboption
DCP Control suboptions.
Definition protocol.h:197
@ ResetToFactory
Reset to factory.
DcpBlockError
DCP block-level SET response errors.
Definition protocol.h:331
std::array< std::uint8_t, macAddressLength > MacAddress
A 6-byte Ethernet MAC address.
Definition util.h:48
DcpResetMode
Reset mode bitmask.
Definition protocol.h:289
@ Communication
Reset communication parameters.
DcpOption
DCP options.
Definition protocol.h:116
DcpDeviceSuboption
DCP Device suboptions.
Definition protocol.h:163
DcpDeviceInitiative
DCP device-initiative values.
Definition protocol.h:321
@ NoHello
Device does not issue DCP-Hello after power-on.
std::vector< std::uint8_t > Bytes
Generic byte buffer alias used throughout the library for raw wire data.
Definition protocol.h:55
DcpResetQualifier
Reset qualifier values for ResetToFactory().
Definition protocol.h:381
DcpIpBlockInfo
PROFINET DCP IP block status values. IP block status flags (IEC 61158-6-10 IPBlockInfo).
Definition protocol.h:440
@ NotSet
IP address not set.
DcpDeviceRole
Device role bitmask.
Definition protocol.h:263
DcpResponseCode
DCP GET/SET response codes.
Definition protocol.h:356
PROFINET protocol wire-format structures and serialization helpers.
asio::error_code error
Identifies a PROFINET DCP block by option and suboption.
Definition protocol.h:465
DcpOption option
DCP option.
Definition protocol.h:467
Parsed DHCP block from a DCP response.
Definition dcp.h:195
std::optional< std::string > fqdn
Decoded fully qualified domain name, if this is an FQDN suboption.
Definition dcp.h:215
std::vector< std::uint8_t > rawData
Raw, undecoded block payload.
Definition dcp.h:203
DcpDhcpSuboption suboption
DHCP suboption code.
Definition dcp.h:197
std::optional< std::vector< std::uint8_t > > vendorSpecific
Decoded vendor-specific data, if this is a VendorSpec suboption.
Definition dcp.h:212
std::optional< std::string > hostname
Decoded hostname, if this is a Hostname suboption.
Definition dcp.h:206
static DCPDHCPBlock Parse(DcpDhcpSuboption suboption, const std::vector< std::uint8_t > &data)
Parse a DHCP suboption's payload into a DCPDHCPBlock.
Definition dcp.cpp:553
std::string suboptionName
Human-readable name of the suboption.
Definition dcp.h:200
std::optional< std::vector< std::uint8_t > > clientId
Decoded client ID, if this is a ClientID suboption.
Definition dcp.h:209
std::optional< std::string > uuid
Decoded UUID string, if this is a UUID suboption.
Definition dcp.h:218
std::uint8_t suboption
Definition test_dcp.cpp:390
DcpOption option
Definition test_dcp.cpp:389
Declares Linux Ethernet, addressing, timing, and utility helpers used by the PROFINET stack.