PROFINET IO Controller Stack 1.0.0
Modern C++ implementation of a PROFINET IO Controller stack
Loading...
Searching...
No Matches
protocol.h
Go to the documentation of this file.
1
34
35#pragma once
36#define MAGIC_ENUM_RANGE_MIN 0
37#define MAGIC_ENUM_RANGE_MAX 255
38
39#include <algorithm>
40#include <array>
41#include <cstdint>
42#include <magic_enum.hpp>
43#include <stdexcept>
44#include <string>
45#include <vector>
46
47#include "profinet/indices.h"
48#include "profinet/util.h"
49#include "profinet/wire.h"
50
51namespace profinet
52{
53
55using Bytes = std::vector<std::uint8_t>;
56
58inline constexpr int blockHeaderLength = 6;
59
60// =============================================================================
61// DCP Constants
62// =============================================================================
64enum class DcpFrameId : std::uint16_t
65{
67 Unknown = 0x0000,
68
70 IdentifyRequest = 0xFEFE,
71
73 IdentifyResponse = 0xFEFF,
74
76 GetSet = 0xFEFD,
77
79 Hello = 0xFEFC,
80};
81
83enum class DcpServiceId : std::uint8_t
84{
86 Unknown = 0x00,
87
89 Get = 0x03,
90
92 Set = 0x04,
93
95 Identify = 0x05,
96
98 Hello = 0x06,
99};
100
102enum class DcpServiceType : std::uint8_t
103{
105 Request = 0x00,
106
108 ResponseSuccess = 0x01,
109
111 ResponseUnsupported = 0x05,
112};
113
115enum class DcpOption : std::uint8_t
116{
118 Unknown = 0x00,
119
121 Ip = 0x01,
122
124 Device = 0x02,
125
127 Dhcp = 0x03,
128
130 Reserved = 0x04,
131
133 Control = 0x05,
134
136 DeviceInitiative = 0x06,
137
139 Nme = 0x07,
140
142 All = 0xFF,
143};
144
146enum class DcpIpSuboption : std::uint8_t
147{
149 Unknown = 0x00,
150
152 Mac = 0x01,
153
155 IpParameter = 0x02,
156
158 FullIpSuite = 0x03,
159};
160
162enum class DcpDeviceSuboption : std::uint8_t
163{
165 Unknown = 0x00,
166
168 Type = 0x01,
169
171 Name = 0x02,
172
174 DeviceId = 0x03,
175
177 Role = 0x04,
178
180 Options = 0x05,
181
183 Alias = 0x06,
184
186 Instance = 0x07,
187
189 OemId = 0x08,
190
192 Rsi = 0x0A,
193};
194
196enum class DcpControlSuboption : std::uint8_t
197{
199 Unknown = 0x00,
200
202 Start = 0x01,
203
205 Stop = 0x02,
206
208 Signal = 0x03,
209
211 Response = 0x04,
212
214 FactoryReset = 0x05,
215
217 ResetToFactory = 0x06,
218};
219
221enum class DcpDhcpSuboption : std::uint8_t
222{
224 Unknown = 0x00,
225
227 Hostname = 0x0C,
228
230 VendorSpec = 0x2B,
231
233 ServerId = 0x36,
234
236 ParamReq = 0x37,
237
239 ClassId = 0x3C,
240
242 ClientId = 0x3D,
243
245 Fqdn = 0x51,
246
248 Uuid = 0x61,
249
251 Control = 0xFF
252};
253
255enum class DcpDeviceInitiativeSuboption : std::uint8_t
256{
258 Initiative = 0x01,
259};
260
262enum class DcpDeviceRole : std::uint8_t
263{
265 IoDevice = 0x01,
266
268 IoController = 0x02,
269
271 IoMultidevice = 0x04,
272
274 PnSupervisor = 0x08,
275};
276
278{
279 return static_cast<DcpDeviceRole>(static_cast<std::uint8_t>(lhs) | static_cast<std::uint8_t>(rhs));
280}
281
283{
284 return static_cast<DcpDeviceRole>(static_cast<std::uint8_t>(lhs) & static_cast<std::uint8_t>(rhs));
285}
286
288enum class DcpResetMode : std::uint16_t
289{
291 Communication = 0x0002,
292
294 Application = 0x0004,
295
297 Engineering = 0x0008,
298
300 AllData = 0x0010,
301
303 Device = 0x0020,
304
306 Factory = 0x0040,
307};
308
310{
311 return static_cast<DcpResetMode>(static_cast<std::uint16_t>(lhs) | static_cast<std::uint16_t>(rhs));
312}
313
315{
316 return static_cast<DcpResetMode>(static_cast<std::uint16_t>(lhs) & static_cast<std::uint16_t>(rhs));
317}
318
320enum class DcpDeviceInitiative : std::uint16_t
321{
323 NoHello = 0x0000,
324
326 IssueHello = 0x0001,
327};
328
330enum class DcpBlockError : std::uint8_t
331{
333 Ok = 0x00,
334
336 OptionUnsupported = 0x01,
337
340
342 SuboptionNotSet = 0x03,
343
345 Resource = 0x04,
346
348 SetNotPossible = 0x05,
349
351 InOperation = 0x06,
352};
353
355enum class DcpResponseCode : std::uint8_t
356{
358 NoError = 0x00,
359
361 OptionNotSupported = 0x01,
362
365
367 SuboptionNotSet = 0x03,
368
370 ResourceError = 0x04,
371
373 SetNotPossible = 0x05,
374
377};
378
380enum class DcpResetQualifier : std::uint16_t
381{
383 Unknown = 0x0000,
384
386 ApplicationData = 0x0002,
387
390
392 CommunicationParameter = 0x0004,
393
396
398 EngineeringParameter = 0x0006,
399
402
404 AllStoredData = 0x0008,
405
407 AllStoredDataAlternate = 0x0009,
408
411
414
416 ToFactory = 0x0010,
417
419 ToFactoryAlternate = 0x0011,
420
422 Restore = 0x0012,
423
425 RestoreAlternate = 0x0013,
426};
427
429enum class DcpBlockQualifier : std::uint16_t
430{
432 Temporary = 0x0000,
433
435 Permanent = 0x0001,
436};
437
439enum class DcpIpBlockInfo : std::uint16_t
440{
442 NotSet = 0x0000,
443
445 Set = 0x0001,
446
448 SetByDhcp = 0x0002,
449
451 NotSetConflict = 0x0080,
452
454 SetConflict = 0x0081,
455
457 SetByDhcpConflict = 0x0082,
458};
459// =============================================================================
460// DCP - Discovery and Configuration Protocol
461// =============================================================================
462
465{
468
470 std::uint8_t suboption;
471
472 // constexpr bool operator==(const DcpBlockKey&) const = default;
474 constexpr auto operator<=>(const DcpBlockKey&) const = default;
475};
476
479{
482
485
487 std::uint16_t type = 0;
488
491
495 static EthernetHeader Parse(const Bytes& data)
496 {
497 const int expectedEthernetHeaderSize = 14;
498 if (data.size() < expectedEthernetHeaderSize)
499 {
500 throw std::runtime_error("EthernetHeader: insufficient data");
501 }
502 wire::Reader r(data);
504 h.dst = r.Fixed<macAddressLength>();
505 h.src = r.Fixed<macAddressLength>();
506 h.type = r.U16();
507 h.payload = r.ReadBytes(r.Remaining());
508 return h;
509 }
510
513 [[nodiscard]] Bytes ToBytes() const
514 {
515 Bytes out;
516 wire::PutFixed(out, dst);
517 wire::PutFixed(out, src);
518 wire::PutU16(out, type);
519 out.insert(out.end(), payload.begin(), payload.end());
520 return out;
521 }
522};
523
526{
529
532
534 std::uint16_t tPid = 0;
535
537 std::uint16_t tCI = 0;
538
540 std::uint16_t type = 0;
541
544
548 static EthernetVLANHeader Parse(const Bytes& data)
549 {
550 const int expectedEthernetVLANHeaderSize = 18;
551
552 if (data.size() < expectedEthernetVLANHeaderSize)
553 {
554 throw std::runtime_error("EthernetVLANHeader: insufficient data");
555 }
556 wire::Reader r(data);
558 h.dst = r.Fixed<macAddressLength>();
559 h.src = r.Fixed<macAddressLength>();
560 h.tPid = r.U16();
561 h.tCI = r.U16();
562 h.type = r.U16();
563 h.payload = r.ReadBytes(r.Remaining());
564 return h;
565 }
566
569 [[nodiscard]] Bytes ToBytes() const
570 {
571 Bytes out;
572 wire::PutFixed(out, dst);
573 wire::PutFixed(out, src);
574 wire::PutU16(out, tPid);
575 wire::PutU16(out, tCI);
576 wire::PutU16(out, type);
577 out.insert(out.end(), payload.begin(), payload.end());
578 return out;
579 }
580};
581
584{
585 // NOLINTBEGIN(readability-identifier-naming)
587 static constexpr std::uint16_t ETHER_TYPE = 0x8892;
588 // NOLINTEND(readability-identifier-naming)
589
592
595
598
600 std::uint32_t xId = 0;
601
603 std::uint16_t respDelay = 0;
604
606 std::uint16_t length = 0;
607
610
612 static constexpr std::size_t kFixedSize = 12;
613
617 static PNDCPHeader Parse(const Bytes& data)
618 {
619 if (data.size() < kFixedSize)
620 {
621 throw std::runtime_error("PNDCPHeader: insufficient data");
622 }
623 wire::Reader r(data);
624 PNDCPHeader h;
625 h.frameId = static_cast<DcpFrameId>(r.U16());
626 h.serviceId = static_cast<DcpServiceId>(r.U8());
627 h.serviceType = static_cast<DcpServiceType>(r.U8());
628 h.xId = r.U32();
629 h.respDelay = r.U16();
630 h.length = r.U16();
631 h.payload = r.ReadBytes(r.Remaining());
632 return h;
633 }
634
637 [[nodiscard]] Bytes ToBytes() const
638 {
639 Bytes out;
640 wire::PutU16(out, static_cast<std::uint16_t>(frameId));
641 wire::PutU8(out, static_cast<std::uint8_t>(serviceId));
642 wire::PutU8(out, static_cast<std::uint8_t>(serviceType));
643 wire::PutU32(out, xId);
645 wire::PutU16(out, length);
646 out.insert(out.end(), payload.begin(), payload.end());
647 return out;
648 }
649};
650
653{
655 std::string address;
656
658 std::string netmask;
659
661 std::string gateway;
662};
663
666{
669
671 // DcpControlSuboption suboption = DcpControlSuboption::Unknown;
672 std::uint8_t suboption = 0;
673
675 std::uint16_t length = 0;
676
679
681 static constexpr std::size_t kFixedSize = 4;
682
686 static PNDCPBlockRequest Parse(const Bytes& data)
687 {
688 if (data.size() < kFixedSize)
689 {
690 throw std::runtime_error("PNDCPBlockRequest: insufficient data");
691 }
692 wire::Reader r(data);
694 b.option = static_cast<DcpOption>(r.U8());
695 b.suboption = r.U8();
696 b.length = r.U16();
697 std::size_t avail = r.Remaining();
698 b.payload = r.ReadBytes(std::min<std::size_t>(b.length, avail));
699 return b;
700 }
701
704 [[nodiscard]] Bytes ToBytes() const
705 {
706 Bytes out;
707 wire::PutU8(out, static_cast<std::uint8_t>(option));
709 wire::PutU16(out, length);
710 out.insert(out.end(), payload.begin(), payload.end());
711 return out;
712 }
713
717 [[nodiscard]] IPConfiguration ParseIp() const
718 {
719 const int defaultIPConfigurationBlockLength = 12; // 3 (ip,mask,gw) x4 = 12
720 if (payload.size() < defaultIPConfigurationBlockLength)
721 {
722 throw std::runtime_error("PNDCPBlockRequest: short IP payload");
723 }
724 const int ipAddressIndex = 0;
725 const int netmaskIndex = 4;
726 const int gatewayIndex = 8;
727 return {
728 .address = String2Ip(std::span(payload).subspan<ipAddressIndex, 4>()),
729 .netmask = String2Ip(std::span(payload).subspan<netmaskIndex, 4>()),
730 .gateway = String2Ip(std::span(payload).subspan<gatewayIndex, 4>())};
731 }
732};
733
737{
739 std::uint8_t option = 0;
740
742 std::uint8_t suboption = 0;
743
745 std::uint16_t length = 0;
746
748 std::uint16_t status = 0;
749
752
753 // NOLINTBEGIN(readability-identifier-naming)
755 static constexpr std::pair<std::uint8_t, std::uint8_t> IP_MAC{1, 1};
756
758 static constexpr std::pair<std::uint8_t, std::uint8_t> IP_ADDRESS{1, 2};
759
761 static constexpr std::pair<std::uint8_t, std::uint8_t> IP_FULL_SUITE{1, 3};
762
764 static constexpr std::pair<std::uint8_t, std::uint8_t> DEVICE_TYPE{2, 1};
765
767 static constexpr std::pair<std::uint8_t, std::uint8_t> NAME_OF_STATION{2, 2};
768
770 static constexpr std::pair<std::uint8_t, std::uint8_t> DEVICE_ID{2, 3};
771
773 static constexpr std::pair<std::uint8_t, std::uint8_t> DEVICE_ROLE{2, 4};
774
776 static constexpr std::pair<std::uint8_t, std::uint8_t> DEVICE_OPTIONS{2, 5};
777
779 static constexpr std::pair<std::uint8_t, std::uint8_t> DEVICE_ALIAS{2, 6};
780
782 static constexpr std::pair<std::uint8_t, std::uint8_t> DEVICE_INSTANCE{2, 7};
783
785 static constexpr std::pair<std::uint8_t, std::uint8_t> DEVICE_OEM_ID{2, 8};
786
788 static constexpr std::pair<std::uint8_t, std::uint8_t> ALL{0xFF, 0xFF};
789 // NOLINTEND(readability-identifier-naming)
790
792 static constexpr std::size_t kFixedSize = 6;
793
797 static PNDCPBlock Parse(const Bytes& data)
798 {
799 if (data.size() < kFixedSize)
800 {
801 throw std::runtime_error("PNDCPBlock: insufficient data");
802 }
803 wire::Reader r(data);
804 PNDCPBlock b;
805 b.option = r.U8();
806 b.suboption = r.U8();
807 b.length = r.U16();
808 b.status = r.U16();
809 // payload_size_field="length", payload_offset=-2: payload length is
810 // `length - 2` (the 2 bytes already consumed by `status`).
811 std::size_t plSize = b.length >= 2 ? static_cast<std::size_t>(b.length - 2) : 0;
812 std::size_t avail = r.Remaining();
813 b.payload = r.ReadBytes(std::min(plSize, avail));
814 return b;
815 }
816
819 [[nodiscard]] Bytes ToBytes() const
820 {
821 Bytes out;
822 wire::PutU8(out, option);
824 wire::PutU16(out, length);
825 wire::PutU16(out, status);
826 out.insert(out.end(), payload.begin(), payload.end());
827 return out;
828 }
829
833 [[nodiscard]] IPConfiguration ParseIp() const
834 {
835 const int defaultIPConfigurationBlockLength = 12; // 3 (ip,mask,gw) x4 = 12
836 if (payload.size() < defaultIPConfigurationBlockLength)
837 {
838 throw std::runtime_error("PNDCPBlock: short IP payload");
839 }
840 const int ipAddressIndex = 0;
841 const int netmaskIndex = 4;
842 const int gatewayIndex = 8;
843 return {
844 .address = String2Ip(std::span(payload).subspan<ipAddressIndex, 4>()),
845 .netmask = String2Ip(std::span(payload).subspan<netmaskIndex, 4>()),
846 .gateway = String2Ip(std::span(payload).subspan<gatewayIndex, 4>())};
847 }
848};
849
850// =============================================================================
851// DCE/RPC - Remote Procedure Call
852// =============================================================================
853
855inline constexpr std::array<std::uint8_t, 12> kPnUuidSuffix = {
856 0x6C, 0x97, 0x11, 0xD1, 0x82, 0x71, 0x00, 0xA0, 0x24, 0x42, 0xDF, 0x7D};
857
860{
861 // NOLINTBEGIN(readability-identifier-naming)
863 static constexpr std::uint8_t REQUEST = 0x00;
864
866 static constexpr std::uint8_t PING = 0x01;
867
869 static constexpr std::uint8_t RESPONSE = 0x02;
870
872 static constexpr std::uint8_t FAULT = 0x03;
873
875 static constexpr std::uint8_t WORKING = 0x04;
876
878 static constexpr std::uint8_t PONG = 0x05;
879
881 static constexpr std::uint8_t REJECT = 0x06;
882
884 static constexpr std::uint8_t ACK = 0x07;
885
887 static constexpr std::uint8_t CANCEL = 0x08;
888
890 static constexpr std::uint8_t FRAG_ACK = 0x09;
891
893 static constexpr std::uint8_t CANCEL_ACK = 0x0A;
894
896 static constexpr std::uint16_t CONNECT = 0x00;
897
899 static constexpr std::uint16_t RELEASE = 0x01;
900
902 static constexpr std::uint16_t READ = 0x02;
903
905 static constexpr std::uint16_t WRITE = 0x03;
906
908 static constexpr std::uint16_t CONTROL = 0x04;
909
911 static constexpr std::uint16_t IMPLICIT_READ = 0x05;
912
913 // NOLINTEND(readability-identifier-naming)
914
915 static constexpr std::uint16_t defaultInterfaceHint = 0xFFFF;
916 static constexpr std::uint16_t defaultActivityHint = 0xFFFF;
917
919 std::uint8_t version = 4;
920
922 std::uint8_t packetType = 0;
923
925 std::uint8_t flags1 = 0;
926
928 std::uint8_t flags2 = 0;
929
931 std::array<std::uint8_t, 3> dataRepresentation{};
932
934 std::uint8_t serialNrHigh = 0;
935
937 std::array<std::uint8_t, uuidLenght> objectUuid{};
938
940 std::array<std::uint8_t, uuidLenght> interfaceUuid{};
941
943 std::array<std::uint8_t, uuidLenght> activityUuid{};
944
946 std::uint32_t serverBootTime = 0;
947
949 std::uint32_t interfaceVersion = 1;
950
952 std::uint32_t sequenceNumber = 0;
953
955 std::uint16_t operationNumber = 0;
956
958 std::uint16_t interfaceHint = 0xFFFF;
959
961 std::uint16_t activityHint = 0xFFFF;
962
964 std::uint16_t lengthOfBody = 0;
965
967 std::uint16_t fragmentNumber = 0;
968
970 std::uint8_t authenticationProtocol = 0;
971
973 std::uint8_t serialNrLow = 0;
974
977
979 static constexpr std::size_t kFixedSize = 80;
980
983 static std::array<std::uint8_t, uuidLenght> IfaceUuidDevice()
984 {
985 return PrefixedUuid(0x00, 0x01);
986 }
987
990 static std::array<std::uint8_t, uuidLenght> IfaceUuidController()
991 {
992 return PrefixedUuid(0x00, 0x02);
993 }
994
997 static std::array<std::uint8_t, uuidLenght> IfaceUuidSupervisor()
998 {
999 return PrefixedUuid(0x00, 0x03);
1000 }
1001
1004 static std::array<std::uint8_t, uuidLenght> IfaceUuidParamserver()
1005 {
1006 return PrefixedUuid(0x00, 0x04);
1007 }
1008
1012 static PNRPCHeader Parse(const Bytes& data)
1013 {
1014 if (data.size() < kFixedSize)
1015 {
1016 throw std::runtime_error("PNRPCHeader: insufficient data");
1017 }
1018 wire::Reader r(data);
1019 PNRPCHeader h;
1020 h.version = r.U8();
1021 h.packetType = r.U8();
1022 h.flags1 = r.U8();
1023 h.flags2 = r.U8();
1024 h.dataRepresentation = r.Fixed<3>();
1025 h.serialNrHigh = r.U8();
1026 h.objectUuid = r.Fixed<uuidLenght>();
1028 h.activityUuid = r.Fixed<uuidLenght>();
1029 h.serverBootTime = r.U32();
1030 h.interfaceVersion = r.U32();
1031 h.sequenceNumber = r.U32();
1032 h.operationNumber = r.U16();
1033 h.interfaceHint = r.U16();
1034 h.activityHint = r.U16();
1035 h.lengthOfBody = r.U16();
1036 h.fragmentNumber = r.U16();
1037 h.authenticationProtocol = r.U8();
1038 h.serialNrLow = r.U8();
1039 h.payload = r.ReadBytes(r.Remaining());
1040 return h;
1041 }
1042
1045 [[nodiscard]] Bytes ToBytes() const
1046 {
1047 Bytes out;
1048
1049 // bool isLittleEndian = dataRepresentation[0] & 0x10;
1050
1051 // auto putFieldU32 = [&](std::uint32_t value)
1052 // {
1053 // if (isLittleEndian)
1054 // {
1055 // wire::PutLittleEndian(out, value);
1056 // }
1057 // else
1058 // {
1059 // wire::PutBigEndian(out, value);
1060 // }
1061 // };
1062 // auto putFieldU16 = [&](std::uint16_t value)
1063 // {
1064 // if (isLittleEndian)
1065 // {
1066 // wire::PutLittleEndian(out, value);
1067 // }
1068 // else
1069 // {
1070 // wire::PutBigEndian(out, value);
1071 // }
1072 // };
1073
1074 wire::PutU8(out, version);
1075 wire::PutU8(out, packetType);
1076 wire::PutU8(out, flags1);
1077 wire::PutU8(out, flags2);
1083
1092
1093 // putFieldU32(serverBootTime); // server_boot_time
1094 // putFieldU32(interfaceVersion);
1095 // putFieldU32(sequenceNumber);
1096 // putFieldU16(operationNumber);
1097 // putFieldU16(interfaceHint); // interface_hint
1098 // putFieldU16(activityHint); // activity_hint
1099 // putFieldU16(lengthOfBody);
1100 // putFieldU16(fragmentNumber); // fragment_number
1103 out.insert(out.end(), payload.begin(), payload.end());
1104 return out;
1105 }
1106
1107 private:
1112 static std::array<std::uint8_t, uuidLenght> PrefixedUuid(std::uint8_t b2, std::uint8_t b3)
1113 {
1114 std::array<std::uint8_t, uuidLenght> u{};
1115 u[0] = 0xDE;
1116 u[1] = 0xA0;
1117 u[2] = b2;
1118 u[3] = b3;
1119 std::ranges::copy(kPnUuidSuffix, u.begin() + 4);
1120 return u;
1121 }
1122};
1123
1128{
1130 std::uint32_t argsMaximumStatus = 0;
1131
1133 std::uint32_t argsLength = 0;
1134
1136 std::uint32_t maximumCount = 0;
1137
1139 std::uint32_t offset = 0;
1140
1142 std::uint32_t actualCount = 0;
1143
1146
1148 static constexpr std::size_t kFixedSize = 20;
1149
1153 static PNNRDData Parse(const Bytes& data)
1154 {
1155 if (data.size() < kFixedSize)
1156 {
1157 throw std::runtime_error("PNNRDData: insufficient data");
1158 }
1159 wire::Reader r(data);
1160 PNNRDData d;
1161 d.argsMaximumStatus = r.U32();
1162 d.argsLength = r.U32();
1163 d.maximumCount = r.U32();
1164 d.offset = r.U32();
1165 d.actualCount = r.U32();
1166 // Some devices' actual_count doesn't exactly match the remaining
1167 // bytes (padding, etc.); take whichever is smaller
1168 std::size_t take = std::min<std::size_t>(d.actualCount, r.Remaining());
1169 d.payload = r.ReadBytes(take);
1170 return d;
1171 }
1172
1175 [[nodiscard]] Bytes ToBytes() const
1176 {
1177 Bytes out;
1181 wire::PutU32(out, offset);
1183 out.insert(out.end(), payload.begin(), payload.end());
1184 return out;
1185 }
1186};
1187
1190{
1193 static constexpr std::uint16_t kContolCommandOffset = 28U;
1194
1196 std::array<std::uint8_t, blockHeaderLength> blockHeader{};
1197
1199 std::uint16_t sequenceNumber = 0;
1200
1202 std::array<std::uint8_t, uuidLenght> arUuid{};
1203
1205 std::uint32_t api = 0;
1206
1208 std::uint16_t slot = 0;
1209
1211 std::uint16_t subslot = 0;
1212
1214 std::uint16_t padding1 = 0;
1215
1217 std::uint16_t index = 0;
1218
1220 std::uint32_t length = 0;
1221
1223 std::array<std::uint8_t, uuidLenght> targetArUuid{};
1224
1226 std::array<std::uint8_t, 8> padding2{};
1227
1230
1232 static constexpr std::size_t kFixedSize = 64;
1233
1237 static PNIODHeader Parse(const Bytes& data)
1238 {
1239 if (data.size() < kFixedSize)
1240 {
1241 throw std::runtime_error("PNIODHeader: insufficient data");
1242 }
1243 wire::Reader r(data);
1244 PNIODHeader h;
1246 h.sequenceNumber = r.U16();
1247 h.arUuid = r.Fixed<uuidLenght>();
1248 h.api = r.U32();
1249 h.slot = r.U16();
1250 h.subslot = r.U16();
1251 h.padding1 = r.U16();
1252 h.index = r.U16();
1253 h.length = r.U32();
1254 h.targetArUuid = r.Fixed<uuidLenght>();
1255 h.padding2 = r.Fixed<8>();
1256 h.payload = r.ReadBytes(r.Remaining());
1257 return h;
1258 }
1259
1262 [[nodiscard]] Bytes ToBytes() const
1263 {
1264 Bytes out;
1267 wire::PutFixed(out, arUuid);
1268 wire::PutU32(out, api);
1269 wire::PutU16(out, slot);
1270 wire::PutU16(out, subslot);
1271 wire::PutU16(out, padding1);
1272 wire::PutU16(out, index);
1273 wire::PutU32(out, length);
1276 out.insert(out.end(), payload.begin(), payload.end());
1277 return out;
1278 }
1279};
1280
1282{
1283 // NOLINTBEGIN(readability-identifier-naming)
1287
1289 static constexpr std::uint16_t IODReadResponseHeader = 0x8009;
1290
1292 static constexpr std::uint16_t InM0 = 0x0020;
1293
1295 static constexpr std::uint16_t InM0FilterDataSubModul = 0x0030;
1296
1298 static constexpr std::uint16_t InM0FilterDataModul = 0x0031;
1299
1301 static constexpr std::uint16_t InM0FilterDataDevice = 0x0032;
1302
1304 static constexpr std::uint16_t DEFAULT_BLOCK_LENGTH = 60;
1305 // NOLINTEND(readability-identifier-naming)
1306
1309
1311 std::uint16_t blockLength = 0;
1312
1314 std::uint16_t blockVersion = 0x0100;
1315
1317 std::uint8_t blockVersionHigh = 1;
1318
1320 std::uint8_t blockVersionLow = 0;
1321
1323 static constexpr std::size_t kSize = sizeof(std::uint16_t) + sizeof(std::uint16_t) + (2 * sizeof(std::uint8_t));
1324
1328 static PNBlockHeader Parse(const Bytes& data)
1329 {
1330 if (data.size() < kSize)
1331 {
1332 throw std::runtime_error("PNBlockHeader: insufficient data");
1333 }
1334 wire::Reader r(data);
1335 PNBlockHeader h;
1336 h.blockType = static_cast<BlockType>(r.U16());
1337 h.blockLength = r.U16();
1338 h.blockVersionHigh = r.U8();
1339 h.blockVersionLow = r.U8();
1340 r.SkipTo(4);
1341 h.blockVersion = r.U16();
1342 return h;
1343 }
1344
1347 [[nodiscard]] Bytes ToBytes() const
1348 {
1349 Bytes out;
1350 wire::PutU16(out, static_cast<std::uint16_t>(blockType));
1354 return out;
1355 }
1356};
1357
1360{
1362 std::array<std::uint8_t, blockHeaderLength> blockHeader{};
1363
1365 std::uint16_t arType = 0;
1366
1368 std::array<std::uint8_t, uuidLenght> arUuid{};
1369
1371 std::uint16_t sessionKey = 0;
1372
1375
1377 std::array<std::uint8_t, uuidLenght> cmInitiatorObjectUuid{};
1378
1380 std::uint32_t arProperties = 0;
1381
1384
1386 std::uint16_t initiatorUdpRtport = 0;
1387
1389 std::uint16_t stationNameLength = 0;
1390
1393
1396
1398 static constexpr std::size_t kFixedSize = 58;
1399
1403 static PNARBlockRequest Parse(const Bytes& data)
1404 {
1405 if (data.size() < kFixedSize)
1406 {
1407 throw std::runtime_error("PNARBlockRequest: insufficient data");
1408 }
1409 wire::Reader r(data);
1412 b.arType = r.U16();
1413 b.arUuid = r.Fixed<uuidLenght>();
1414 b.sessionKey = r.U16();
1417 b.arProperties = r.U32();
1419 b.initiatorUdpRtport = r.U16();
1420 b.stationNameLength = r.U16();
1421 b.cmInitiatorStationName = r.ReadBytes(std::min<std::size_t>(b.stationNameLength, r.Remaining()));
1422 b.payload = r.ReadBytes(r.Remaining());
1423 return b;
1424 }
1425
1428 [[nodiscard]] Bytes ToBytes() const
1429 {
1430 Bytes out;
1432 wire::PutU16(out, arType);
1433 wire::PutFixed(out, arUuid);
1441 out.insert(out.end(), cmInitiatorStationName.begin(), cmInitiatorStationName.end());
1442 out.insert(out.end(), payload.begin(), payload.end());
1443 return out;
1444 }
1445};
1446
1449{
1451 std::array<std::uint8_t, blockHeaderLength> blockHeader{};
1452
1454 std::uint16_t padding1 = 0;
1455
1457 std::array<std::uint8_t, uuidLenght> arUuid{};
1458
1460 std::uint16_t sessionKey = 0;
1461
1463 std::uint16_t padding2 = 0;
1464
1467
1469 std::uint16_t controlBlockProperties = 0;
1470
1472 static constexpr std::size_t kSize = 32;
1473
1477 static PNIODReleaseBlock Parse(const Bytes& data)
1478 {
1479 if (data.size() < kSize)
1480 {
1481 throw std::runtime_error("PNIODReleaseBlock: insufficient data");
1482 }
1483 wire::Reader r(data);
1486 b.padding1 = r.U16();
1487 b.arUuid = r.Fixed<uuidLenght>();
1488 b.sessionKey = r.U16();
1489 b.padding2 = r.U16();
1490 b.controlCommand = static_cast<ControlCommand>(r.U16());
1492 return b;
1493 }
1494
1497 [[nodiscard]] Bytes ToBytes() const
1498 {
1499 Bytes out;
1501 wire::PutU16(out, padding1);
1502 wire::PutFixed(out, arUuid);
1504 wire::PutU16(out, padding2);
1505 wire::PutU16(out, static_cast<std::uint16_t>(controlCommand));
1507 return out;
1508 }
1509};
1510
1511// =============================================================================
1512// I&M (Identification & Maintenance) Data
1513// =============================================================================
1514
1517{
1518 // NOLINTBEGIN(readability-identifier-naming)
1520 static constexpr std::uint16_t IDX = 0xAFF0;
1521 // NOLINTEND(readability-identifier-naming)
1522
1524 std::array<std::uint8_t, blockHeaderLength> blockHeader{};
1525
1527 std::uint16_t vendorId = 0;
1528
1529 // /// @brief High byte of the PROFINET vendor ID.
1530 // std::uint8_t vendorIdHigh = 0;
1531
1532 // /// @brief Low byte of the PROFINET vendor ID.
1533 // std::uint8_t vendorIdLow = 0;
1534
1536 std::string orderId;
1537
1539 std::string imSerialNumber;
1540
1542 std::uint16_t imHardwareRevision = 0;
1543
1545 std::uint8_t swRevisionPrefix = 0;
1546
1549
1551 std::uint8_t imSwRevisionBugFix = 0;
1552
1555
1557 std::uint16_t imRevisionCounter = 0;
1558
1560 std::uint16_t imProfileId = 0;
1561
1563 std::uint16_t imProfileSpecificType = 0;
1564
1566 std::uint16_t imVersion = 0;
1567
1569 std::uint16_t imSupported = 0;
1570
1572 static constexpr std::size_t kSize = 60;
1573
1576 [[nodiscard]] std::uint16_t VendorId() const
1577 {
1578 return vendorId;
1579 }
1580
1584 static PNInM0 Parse(const Bytes& data)
1585 {
1586 if (data.size() < kSize)
1587 {
1588 throw std::runtime_error("PNInM0: insufficient data");
1589 }
1590 wire::Reader r(data);
1591 PNInM0 v;
1593 // v.vendorIdHigh = r.U8();
1594 // v.vendorIdLow = r.U8();
1595 v.vendorId = r.U16();
1596
1597 auto oid = r.ReadBytes(20);
1598 v.orderId = DecodeBytes(oid);
1599 auto sn = r.ReadBytes(16);
1601 v.imHardwareRevision = r.U16();
1602 v.swRevisionPrefix = r.U8();
1604 v.imSwRevisionBugFix = r.U8();
1606 v.imRevisionCounter = r.U16();
1607 v.imProfileId = r.U16();
1608 v.imProfileSpecificType = r.U16();
1609 v.imVersion = r.U16();
1610 v.imSupported = r.U16();
1611 return v;
1612 }
1613
1619 bool operator==(const PNInM0&) const = default;
1620};
1621
1624{
1625 // NOLINTBEGIN(readability-identifier-naming)
1627 static constexpr std::uint16_t IDX = 0xAFF1;
1628 // NOLINTEND(readability-identifier-naming)
1629
1631 std::array<std::uint8_t, blockHeaderLength> blockHeader{};
1632
1634 std::string imTagFunction;
1635
1637 std::string imTagLocation;
1638
1640 static constexpr std::size_t kSize = 60;
1641
1645 static PNInM1 Parse(const Bytes& data)
1646 {
1647 if (data.size() < kSize)
1648 {
1649 throw std::runtime_error("PNInM1: insufficient data");
1650 }
1651 wire::Reader r(data);
1652 PNInM1 v;
1656 return v;
1657 }
1663 bool operator==(const PNInM1&) const = default;
1664};
1665
1668{
1669 // NOLINTBEGIN(readability-identifier-naming)
1671 static constexpr std::uint16_t IDX = 0xAFF2;
1672 // NOLINTEND(readability-identifier-naming)
1673
1675 std::array<std::uint8_t, blockHeaderLength> blockHeader{};
1676
1678 std::string imDate;
1679
1681 static constexpr std::size_t kSize = 22;
1682
1686 static PNInM2 Parse(const Bytes& data)
1687 {
1688 if (data.size() < kSize)
1689 {
1690 throw std::runtime_error("PNInM2: insufficient data");
1691 }
1692 wire::Reader r(data);
1693 PNInM2 v;
1695 v.imDate = DecodeBytes(r.ReadBytes(16));
1696 return v;
1697 }
1698
1704 bool operator==(const PNInM2&) const = default;
1705};
1706
1709{
1710 // NOLINTBEGIN(readability-identifier-naming)
1712 static constexpr std::uint16_t IDX = 0xAFF3;
1713 // NOLINTEND(readability-identifier-naming)
1714
1716 std::array<std::uint8_t, blockHeaderLength> blockHeader{};
1717
1719 std::string imDescriptor;
1720
1722 static constexpr std::size_t kSize = 60;
1723
1727 static PNInM3 Parse(const Bytes& data)
1728 {
1729 if (data.size() < kSize)
1730 {
1731 throw std::runtime_error("PNInM3: insufficient data");
1732 }
1733 wire::Reader r(data);
1734 PNInM3 v;
1737 return v;
1738 }
1744 bool operator==(const PNInM3&) const = default;
1745};
1746
1749{
1750 // NOLINTBEGIN(readability-identifier-naming)
1752 static constexpr std::uint16_t IDX = 0xAFF4;
1753 // NOLINTEND(readability-identifier-naming)
1754
1756 std::array<std::uint8_t, blockHeaderLength> blockHeader{};
1757
1759 std::array<std::uint8_t, 54> imSignature{};
1760
1762 static constexpr std::size_t kSize = 60;
1763
1767 static PNInM4 Parse(const Bytes& data)
1768 {
1769 if (data.size() < kSize)
1770 {
1771 throw std::runtime_error("PNInM4: insufficient data");
1772 }
1773 wire::Reader r(data);
1774 PNInM4 v;
1776 v.imSignature = r.Fixed<54>();
1777 return v;
1778 }
1784 bool operator==(const PNInM4&) const = default;
1785};
1786
1789{
1790 // NOLINTBEGIN(readability-identifier-naming)
1792 static constexpr std::uint16_t IDX = 0xAFF5;
1793 // NOLINTEND(readability-identifier-naming)
1794
1796 std::array<std::uint8_t, blockHeaderLength> blockHeader{};
1797
1799 std::string imAnnotation;
1800
1802 static constexpr std::size_t kSize = 70;
1803
1807 static PNInM5 Parse(const Bytes& data)
1808 {
1809 if (data.size() < kSize)
1810 {
1811 throw std::runtime_error("PNInM5: insufficient data");
1812 }
1813 wire::Reader r(data);
1814 PNInM5 v;
1817 return v;
1818 }
1824 bool operator==(const PNInM5&) const = default;
1825};
1826
1831template <std::uint16_t Idx>
1833{
1834 // NOLINTBEGIN(readability-identifier-naming)
1836 static constexpr std::uint16_t IDX = Idx;
1837 // NOLINTEND(readability-identifier-naming)
1838
1840 std::array<std::uint8_t, blockHeaderLength> blockHeader{};
1841
1844
1848 static PNInMReserved Parse(const Bytes& data)
1849 {
1850 if (data.size() < 6)
1851 {
1852 throw std::runtime_error("PNInMReserved: insufficient data");
1853 }
1854 wire::Reader r(data);
1855 PNInMReserved v;
1857 v.payload = r.ReadBytes(r.Remaining());
1858 return v;
1859 }
1860
1866 bool operator==(const PNInMReserved&) const = default;
1867};
1868
1889
1890// =============================================================================
1891// IOCR (IO Connection Relationship) Blocks
1892// =============================================================================
1893
1896{
1898 std::uint16_t slotNumber = 0;
1899
1901 std::uint16_t subslotNumber = 0;
1902
1904 std::uint16_t frameOffset = 0;
1905
1907 static constexpr std::size_t kSize = 6;
1908
1912 static IOCRAPIObject Parse(const Bytes& data)
1913 {
1914 if (data.size() < kSize)
1915 {
1916 throw std::runtime_error("IOCRAPIObject: insufficient data");
1917 }
1918 wire::Reader r(data);
1919 IOCRAPIObject o;
1920 o.slotNumber = r.U16();
1921 o.subslotNumber = r.U16();
1922 o.frameOffset = r.U16();
1923 return o;
1924 }
1925
1928 [[nodiscard]] Bytes ToBytes() const
1929 {
1930 Bytes out;
1934 return out;
1935 }
1936};
1937
1940{
1941 // NOLINTBEGIN(readability-identifier-naming)
1943 static constexpr std::uint16_t BLOCK_TYPE = 0x8102;
1944 // NOLINTEND(readability-identifier-naming)
1945
1947 std::array<std::uint8_t, blockHeaderLength> blockHeader{};
1948
1950 std::uint16_t iocrType = 0;
1951
1953 std::uint16_t iocrReference = 0;
1954
1956 std::uint16_t frameId = 0;
1957
1959 static constexpr std::size_t kSize = 12;
1960
1964 static PNIOCRBlockRes Parse(const Bytes& data)
1965 {
1966 if (data.size() < kSize)
1967 {
1968 throw std::runtime_error("PNIOCRBlockRes: insufficient data");
1969 }
1970 wire::Reader r(data);
1973 b.iocrType = r.U16();
1974 b.iocrReference = r.U16();
1975 b.frameId = r.U16();
1976 return b;
1977 }
1978};
1979
1984{
1985 // NOLINTBEGIN(readability-identifier-naming)
1988 // NOLINTEND(readability-identifier-naming)
1989
1991 std::array<std::uint8_t, blockHeaderLength> blockHeader{};
1992
1994 std::uint16_t iocrType = 0;
1995
1997 std::uint16_t iocrReference = 0;
1998
2001
2003 std::uint32_t iocrProperties = 0;
2004
2006 std::uint16_t dataLength = 0;
2007
2009 std::uint16_t frameId = 0;
2010
2012 std::uint16_t sendClockFactor = 32;
2013
2015 std::uint16_t reductionRatio = 1;
2016
2018 std::uint16_t phase = 1;
2019
2021 std::uint16_t sequence = 0;
2022
2024 std::uint32_t frameSendOffset = 0;
2025
2027 std::uint16_t watchdogFactor = 3;
2028
2030 std::uint16_t dataHoldFactor = 3;
2031
2033 std::uint16_t iocrTagHeader = 0xC000;
2034
2037
2039 std::uint16_t numberOfApis = 1;
2040
2042 static constexpr std::size_t kSize = 46;
2043
2048 [[nodiscard]] static PNIOCRBlockReqHeader Parse(const Bytes& data)
2049 {
2050 if (data.size() < kSize)
2051 {
2052 throw std::runtime_error(
2053 "IOCRBlockReq too short, insufficient data: " +
2054 std::to_string(data.size()) +
2055 " bytes, expected at least " +
2056 std::to_string(kSize));
2057 }
2058
2059 wire::Reader r(data);
2061
2063 b.iocrType = r.U16();
2064 b.iocrReference = r.U16();
2065 b.etherTypeLT = r.U16();
2066 b.iocrProperties = r.U32();
2067 b.dataLength = r.U16();
2068 b.frameId = r.U16();
2069 b.sendClockFactor = r.U16();
2070 b.reductionRatio = r.U16();
2071 b.phase = r.U16();
2072 b.sequence = r.U16();
2073 b.frameSendOffset = r.U32();
2074 b.watchdogFactor = r.U16();
2075 b.dataHoldFactor = r.U16();
2076 b.iocrTagHeader = r.U16();
2078 b.numberOfApis = r.U16();
2079
2080 return b;
2081 }
2082
2085 [[nodiscard]] Bytes ToBytes() const
2086 {
2087 Bytes out;
2089 wire::PutU16(out, iocrType);
2094 wire::PutU16(out, frameId);
2097 wire::PutU16(out, phase);
2098 wire::PutU16(out, sequence);
2105 return out;
2106 }
2107};
2108
2109// =============================================================================
2110// AlarmCR (Alarm Connection Relationship) Blocks
2111// =============================================================================
2112
2115{
2116 // NOLINTBEGIN(readability-identifier-naming)
2119
2121 static constexpr std::uint16_t DEFAULT_RTA_TIMEOUT_FACTOR = 1;
2122
2124 static constexpr std::uint16_t DEFAULT_RTA_RETRIES = 3;
2125
2127 static constexpr std::uint16_t DEFAULT_MAX_ALARM_DATA_LENGTH = 200;
2128
2130 static constexpr std::uint16_t DEFAULT_TAG_HEADER_HIGH = 0xC000;
2131
2133 static constexpr std::uint16_t DEFAULT_TAG_HEADER_LOW = 0xA000;
2134 // NOLINTEND(readability-identifier-naming)
2135
2137 std::array<std::uint8_t, blockHeaderLength> blockHeader{};
2138
2140 std::uint16_t alarmCrType = 1;
2141
2143 std::uint16_t etherTypeLT = 0x8892;
2144
2146 std::uint32_t alarmCrProperties = 0;
2147
2150
2153
2155 std::uint16_t localAlarmReference = 0;
2156
2159
2162
2165
2167 static constexpr std::size_t kSize = 26;
2168
2172 static PNAlarmCRBlockReq Parse(const Bytes& data)
2173 {
2174 if (data.size() < kSize)
2175 {
2176 throw std::runtime_error("PNAlarmCRBlockReq: insufficient data");
2177 }
2178
2179 wire::Reader r(data);
2182 b.alarmCrType = r.U16();
2183 b.etherTypeLT = r.U16();
2184 b.alarmCrProperties = r.U32();
2185 b.rtaTimeoutFactor = r.U16();
2186 b.rtaRetries = r.U16();
2187 b.localAlarmReference = r.U16();
2188 b.maxAlarmDataLength = r.U16();
2189 b.alarmCrTagHeaderHigh = r.U16();
2190 b.alarmCrTagHeaderLow = r.U16();
2191
2192 return b;
2193 }
2194
2197 [[nodiscard]] Bytes ToBytes() const
2198 {
2199 Bytes out;
2210 return out;
2211 }
2212};
2213
2216{
2217 // NOLINTBEGIN(readability-identifier-naming)
2219 static constexpr std::uint16_t BLOCK_TYPE = 0x8103;
2220 // NOLINTEND(readability-identifier-naming)
2221
2223 std::array<std::uint8_t, blockHeaderLength> blockHeader{};
2224
2226 std::uint16_t alarmCrType = 0;
2227
2229 std::uint16_t localAlarmReference = 0;
2230
2232 std::uint16_t maxAlarmDataLength = 0;
2233
2235 static constexpr std::size_t kSize = 12;
2236
2240 static PNAlarmCRBlockRes Parse(const Bytes& data)
2241 {
2242 if (data.size() < kSize)
2243 {
2244 throw std::runtime_error("PNAlarmCRBlockRes: insufficient data");
2245 }
2246 wire::Reader r(data);
2249 b.alarmCrType = r.U16();
2250 b.localAlarmReference = r.U16();
2251 b.maxAlarmDataLength = r.U16();
2252 return b;
2253 }
2254
2257 [[nodiscard]] Bytes ToBytes() const
2258 {
2259 Bytes out;
2260
2265
2266 return out;
2267 }
2268};
2269
2270// =============================================================================
2271// Alarm Notification PDUs
2272// =============================================================================
2273
2276{
2277 // NOLINTBEGIN(readability-identifier-naming)
2279 static constexpr std::uint16_t BLOCK_ALARM_HIGH = 0x0001;
2280
2282 static constexpr std::uint16_t BLOCK_ALARM_LOW = 0x0002;
2283
2285 static constexpr std::uint16_t BLOCK_ALARM_ACK_HIGH = 0x8001;
2286
2288 static constexpr std::uint16_t BLOCK_ALARM_ACK_LOW = 0x8002;
2289 // NOLINTEND(readability-identifier-naming)
2290
2292 std::array<std::uint8_t, blockHeaderLength> blockHeader{};
2293
2295 std::uint16_t alarmType = 0;
2296
2298 std::uint32_t api = 0;
2299
2301 std::uint16_t slotNumber = 0;
2302
2304 std::uint16_t subslotNumber = 0;
2305
2307 std::uint32_t moduleIdentNumber = 0;
2308
2310 std::uint32_t submoduleIdentNumber = 0;
2311
2313 std::uint16_t alarmSpecifier = 0;
2314
2317
2319 static constexpr std::size_t kFixedSize = 26;
2320
2325 {
2326 if (data.size() < kFixedSize)
2327 {
2328 throw std::runtime_error("PNAlarmNotificationPDU: insufficient data");
2329 }
2330 wire::Reader r(data);
2333 p.alarmType = r.U16();
2334 p.api = r.U32();
2335 p.slotNumber = r.U16();
2336 p.subslotNumber = r.U16();
2337 p.moduleIdentNumber = r.U32();
2338 p.submoduleIdentNumber = r.U32();
2339 p.alarmSpecifier = r.U16();
2340 p.payload = r.ReadBytes(r.Remaining());
2341 return p;
2342 }
2343};
2344
2347{
2349 std::array<std::uint8_t, blockHeaderLength> blockHeader{};
2350
2353
2355 std::uint32_t api = 0;
2356
2358 std::uint16_t slotNumber = 0;
2359
2361 std::uint16_t subslotNumber = 0;
2362
2364 std::uint16_t alarmSpecifier = 0;
2365
2367 std::uint32_t statusPNIO = 0;
2368
2370 static constexpr std::size_t kSize = 22;
2371
2374 [[nodiscard]] Bytes ToBytes() const
2375 {
2376 Bytes out;
2378 wire::PutU16(out, static_cast<std::uint16_t>(alarmType));
2379 wire::PutU32(out, api);
2384 return out;
2385 }
2386};
2387
2390{
2391 // NOLINTBEGIN(readability-identifier-naming)
2393 static constexpr std::uint8_t RTA_TYPE_DATA = 0x01;
2394
2396 static constexpr std::uint8_t RTA_TYPE_NACK = 0x02;
2397
2399 static constexpr std::uint8_t RTA_TYPE_ACK = 0x03;
2400
2402 static constexpr std::uint8_t RTA_TYPE_ERR = 0x04;
2403
2405 static constexpr std::uint8_t VERSION_1 = 0x01;
2406
2408 static constexpr std::uint8_t VERSION_2 = 0x02;
2409
2411 static constexpr std::uint8_t ADD_FLAGS_WINDOW_1 = 0x01;
2412
2414 static constexpr std::uint8_t ADD_FLAGS_TACK = 0x10;
2415
2416 // NOLINTEND(readability-identifier-naming)
2417
2419 std::uint16_t alarmDstEndpoint = 0;
2420
2422 std::uint16_t alarmSrcEndpoint = 0;
2423
2425 std::uint8_t pduType = 0;
2426
2428 std::uint8_t addFlags = 0;
2429
2431 std::uint16_t sendSeqNum = 0;
2432
2434 std::uint16_t ackSeqNum = 0;
2435
2437 std::uint16_t variablePartLenght = 0;
2438
2441
2443 static constexpr std::size_t kFixedSize = 12;
2444
2448 static PNRTAHeader Parse(const Bytes& data)
2449 {
2450 if (data.size() < kFixedSize)
2451 {
2452 throw std::runtime_error("PNRTAHeader: insufficient data");
2453 }
2454 wire::Reader r(data);
2455 PNRTAHeader h;
2456 h.alarmDstEndpoint = r.U16();
2457 h.alarmSrcEndpoint = r.U16();
2458 h.pduType = r.U8();
2459 h.addFlags = r.U8();
2460 h.sendSeqNum = r.U16();
2461 h.ackSeqNum = r.U16();
2462 h.variablePartLenght = r.U16();
2463 h.payload = r.ReadBytes(r.Remaining());
2464 return h;
2465 }
2466
2469 [[nodiscard]] Bytes ToBytes() const
2470 {
2471 Bytes out;
2474 wire::PutU8(out, pduType);
2475 wire::PutU8(out, addFlags);
2477 wire::PutU16(out, ackSeqNum);
2479 out.insert(out.end(), payload.begin(), payload.end());
2480 return out;
2481 }
2482};
2484enum class RtaErrorClass : std::uint8_t
2485{
2487 Reserved = 0x00,
2488
2490 SequenceNumber = 0x01,
2491
2493 Abort = 0x02,
2494
2496 Extended = 0x03,
2497
2499 Obsoleted = 0x04,
2500
2502 UserSpecific = 0x05,
2503};
2504
2506enum class RtaErrorReason : std::uint8_t
2507{
2508 Reserved = 0x00,
2509 SequenceNumber = 0x01,
2510
2511 InstanceClosed = 0x02,
2512 ArOutOfMemory = 0x03,
2515 ArCmiTimeout = 0x06,
2516 ArAlarmOpenFailed = 0x07,
2519 ArAlarmDataTooLong = 0x0A,
2520 ArAlarmIndError = 0x0B,
2522 ArAbortRequest = 0x0D,
2523 ArRerunAbortsExisting = 0x0E,
2524 ArReleaseIndReceived = 0x0F,
2525 ArDeviceDeactivated = 0x10,
2526 ArRemoved = 0x11,
2527 ArProtocolViolation = 0x12,
2528 ArNameResolutionError = 0x13,
2529 ArRpcBindError = 0x14,
2530 ArRpcConnectError = 0x15,
2531 ArRpcReadError = 0x16,
2532 ArRpcWriteError = 0x17,
2533 ArRpcControlError = 0x18,
2534 ArForbiddenPullPlug = 0x19,
2535 ArApRemoved = 0x1A,
2536 ArLinkDown = 0x1B,
2538 NotSynchronized = 0x1D,
2539 WrongTopology = 0x1E,
2540 DcpStationNameChanged = 0x1F,
2543 NoIrdataRecordYet = 0x22,
2544 Pdev = 0x23,
2546 IpSuiteChanged = 0x25,
2547 IocarSrRdhtExpired = 0x26,
2551 IocarSrMtotExpired = 0x2A,
2555
2556 UserAbort = 0xFF,
2557};
2558
2571{
2574
2576 std::uint32_t statusPnio = 0;
2577
2579 std::uint8_t errorCode = 0;
2580
2582 std::uint8_t errorDecode = 0;
2583
2585 std::uint8_t errorCode1 = 0;
2586
2588 std::uint8_t errorCode2 = 0;
2589
2592
2595
2598 [[nodiscard]] RtaErrorClass ErrorClass() const
2599 {
2600 return kind;
2601 }
2602
2605 [[nodiscard]] bool IsRtaProtocolError() const
2606 {
2607 return errorCode == 0xCFU &&
2608 errorDecode == 0x81U &&
2609 errorCode1 == 0xFDU;
2610 }
2611
2614 [[nodiscard]] bool IsSequenceNumberError() const
2615 {
2616 return IsRtaProtocolError() &&
2617 errorCode2 == 0x01U;
2618 }
2619
2622 [[nodiscard]] bool IsAbort() const
2623 {
2624 return IsRtaProtocolError() &&
2625 errorCode2 >= 0x02U &&
2626 errorCode2 <= 0x25U;
2627 }
2628
2631 [[nodiscard]] bool IsExtended() const
2632 {
2633 return IsRtaProtocolError() &&
2634 errorCode2 >= 0x26U &&
2635 errorCode2 <= 0x2CU;
2636 }
2637
2640 [[nodiscard]] bool IsObsoleted() const
2641 {
2642 return IsRtaProtocolError() &&
2643 errorCode2 == 0x2DU;
2644 }
2645
2648 [[nodiscard]] bool IsUserAbort() const
2649 {
2650 return IsRtaProtocolError() &&
2651 errorCode2 == 0xFFU;
2652 }
2653
2656 [[nodiscard]] std::string ReasonName() const;
2657
2662
2666 static RtaErrorClass ClassifyRtaError(std::uint8_t errorCode2);
2667
2672};
2673
2680[[nodiscard]] inline RtaError ParseRtaError(const PNRTAHeader& header)
2681{
2682 const auto rtaType = static_cast<std::uint8_t>(header.pduType & 0x0FU);
2683
2684 if (rtaType != PNRTAHeader::RTA_TYPE_ERR)
2685 {
2686 throw std::invalid_argument("RTA PDU is not ERR-RTA");
2687 }
2688
2689 if (header.variablePartLenght != 4U)
2690 {
2691 throw std::invalid_argument("RTA ERR-PDU variable part must be 4 bytes");
2692 }
2693
2694 if (header.payload.size() < header.variablePartLenght)
2695 {
2696 throw std::invalid_argument("Truncated RTA ERR-PDU payload");
2697 }
2698
2699 RtaError result;
2700 result.header = header;
2701
2702 result.errorCode = header.payload[0];
2703 result.errorDecode = header.payload[1];
2704 result.errorCode1 = header.payload[2];
2705 result.errorCode2 = header.payload[3];
2706
2707 result.statusPnio =
2708 (static_cast<std::uint32_t>(result.errorCode) << 24U) |
2709 (static_cast<std::uint32_t>(result.errorDecode) << 16U) |
2710 (static_cast<std::uint32_t>(result.errorCode1) << 8U) |
2711 static_cast<std::uint32_t>(result.errorCode2);
2714 return result;
2715}
2716
2722[[nodiscard]] inline RtaError ParseRtaError(const Bytes& data)
2723{
2724 return ParseRtaError(PNRTAHeader::Parse(data));
2725}
2726
2727// =============================================================================
2728// ExpectedSubmodule Blocks (0x0104)
2729// =============================================================================
2730
2733{
2735 std::uint16_t dataDescription = 0;
2736
2738 std::uint16_t submoduleDataLength = 0;
2739
2741 std::uint8_t lengthIocs = 0;
2742
2744 std::uint8_t lengthIops = 0;
2745
2747 static constexpr std::size_t kSize = 6;
2748
2751 [[nodiscard]] Bytes ToBytes() const
2752 {
2753 Bytes out;
2756 wire::PutU8(out, lengthIocs);
2757 wire::PutU8(out, lengthIops);
2758 return out;
2759 }
2760};
2761
2762// =============================================================================
2763// IOD Write/Read Request Blocks
2764// =============================================================================
2765
2768{
2769 // NOLINTBEGIN(readability-identifier-naming)
2771 static constexpr std::uint16_t BLOCK_TYPE = 0x0008;
2772 // NOLINTEND(readability-identifier-naming)
2773
2775 std::array<std::uint8_t, blockHeaderLength> blockHeader{};
2776
2778 std::uint16_t seqNum = 0;
2779
2781 std::array<std::uint8_t, uuidLenght> arUuid{};
2782
2784 std::uint32_t api = 0;
2785
2787 std::uint16_t slot = 0;
2788
2790 std::uint16_t subslot = 0;
2791
2793 std::uint16_t padding = 0;
2794
2796 std::uint16_t index = 0;
2797
2799 std::uint32_t recordDataLength = 0;
2800
2802 std::array<std::uint8_t, 24> rwPadding{};
2803
2806
2808 static constexpr std::size_t kFixedSize = 64;
2809
2812 [[nodiscard]] Bytes ToBytes() const
2813 {
2814 Bytes out;
2816 wire::PutU16(out, seqNum);
2817 wire::PutFixed(out, arUuid);
2818 wire::PutU32(out, api);
2819 wire::PutU16(out, slot);
2820 wire::PutU16(out, subslot);
2821 wire::PutU16(out, padding);
2822 wire::PutU16(out, index);
2825 out.insert(out.end(), payload.begin(), payload.end());
2826 return out;
2827 }
2828};
2829
2832{
2833 // NOLINTBEGIN(readability-identifier-naming)
2835 static constexpr std::uint16_t BLOCK_TYPE = 0x8008;
2836 // NOLINTEND(readability-identifier-naming)
2837
2839 std::array<std::uint8_t, blockHeaderLength> blockHeader{};
2840
2842 std::uint16_t seqNum = 0;
2843
2845 std::array<std::uint8_t, uuidLenght> arUuid{};
2846
2848 std::uint32_t api = 0;
2849
2851 std::uint16_t slot = 0;
2852
2854 std::uint16_t subslot = 0;
2855
2857 std::uint16_t padding = 0;
2858
2860 std::uint16_t index = 0;
2861
2863 std::uint32_t recordDataLength = 0;
2864
2866 std::uint16_t additionalValue1 = 0;
2867
2869 std::uint16_t additionalValue2 = 0;
2870
2872 std::uint32_t status = 0;
2873
2875 std::array<std::uint8_t, 16> rwPadding{};
2876
2878 static constexpr std::size_t kSize = 64;
2879
2883 static PNIODWriteRes Parse(const Bytes& data)
2884 {
2885 if (data.size() < kSize)
2886 {
2887 throw std::runtime_error("PNIODWriteRes: insufficient data");
2888 }
2889 wire::Reader r(data);
2890 PNIODWriteRes b;
2892 b.seqNum = r.U16();
2893 b.arUuid = r.Fixed<uuidLenght>();
2894 b.api = r.U32();
2895 b.slot = r.U16();
2896 b.subslot = r.U16();
2897 b.padding = r.U16();
2898 b.index = r.U16();
2899 b.recordDataLength = r.U32();
2900 b.additionalValue1 = r.U16();
2901 b.additionalValue2 = r.U16();
2902 b.status = r.U32();
2903 b.rwPadding = r.Fixed<16>();
2904 return b;
2905 }
2906};
2907
2908} // namespace profinet
Lightweight cursor for parsing a big-endian byte buffer without copies.
Definition wire.h:192
std::uint8_t U8()
Read and consume one byte.
Definition wire.h:250
std::uint32_t U32()
Read and consume a big-endian 32-bit value.
Definition wire.h:268
std::size_t Remaining() const
Number of bytes not yet consumed.
Definition wire.h:218
std::array< std::uint8_t, N > Fixed()
Read and consume a fixed-size byte array.
Definition wire.h:316
void SkipTo(std::size_t offset)
Move the read position to an absolute byte offset.
Definition wire.h:343
std::vector< std::uint8_t > ReadBytes(std::size_t n)
Read and consume a variable-length byte range.
Definition wire.h:304
std::uint16_t U16()
Read and consume a big-endian 16-bit value.
Definition wire.h:258
PROFINET record-data indices, block types, and protocol enumerations.
void PutFixed(std::vector< std::uint8_t > &out, const std::array< std::uint8_t, N > &data)
Append a fixed-size byte array to a buffer.
Definition wire.h:124
void PutU8(std::vector< std::uint8_t > &out, std::uint8_t value)
Append a single byte to a buffer.
Definition wire.h:89
void PutU16(std::vector< std::uint8_t > &out, std::uint16_t value)
Append a 16-bit value to a buffer in big-endian order.
Definition wire.h:97
void PutU32(std::vector< std::uint8_t > &out, std::uint32_t value)
Append a 32-bit value to a buffer in big-endian order.
Definition wire.h:105
constexpr AlarmNotificationBitmask operator&(AlarmNotificationBitmask lhs, AlarmNotificationBitmask rhs) noexcept
Bitwise AND operator for intersecting two AlarmNotificationBitmask values.
Definition alarms.h:480
DcpBlockQualifier
DCP block qualifier values.
Definition protocol.h:430
@ Temporary
Change applies until the next power cycle only.
@ Permanent
Change is persisted permanently.
DcpIpSuboption
DCP IP suboptions.
Definition protocol.h:147
@ FullIpSuite
Full IP suite.
@ IpParameter
IP address, subnet mask and gateway.
BlockType
PROFINET block types.
Definition indices.h:89
@ IoCrRequest
IOCR block request.
@ AlarmCrRequest
AlarmCR block request.
@ IoDataReadRequest
IOD read request block.
DcpDeviceInitiativeSuboption
DCP DeviceInitiative suboptions.
Definition protocol.h:256
@ Initiative
Device-initiative setting.
DcpDhcpSuboption
DCP DHCP suboptions.
Definition protocol.h:222
@ Fqdn
Fully qualified domain name.
@ ClassId
Class identifier.
@ ParamReq
Parameter request list.
@ ServerId
Server identifier.
@ ClientId
Client identifier.
@ VendorSpec
Vendor-specific option.
constexpr int uuidLenght
Constant lenght of a UUID.
Definition util.h:40
DcpControlSuboption
DCP Control suboptions.
Definition protocol.h:197
@ Signal
Signal / flash LEDs.
@ Response
Control response.
@ ResetToFactory
Reset to factory.
constexpr int blockHeaderLength
Constant lenght of a blockHeader.
Definition protocol.h:58
DcpBlockError
DCP block-level SET response errors.
Definition protocol.h:331
@ SetNotPossible
SET not possible for local reasons.
@ OptionUnsupported
Option not supported.
@ SuboptionUnsupported
Suboption not supported or no dataset available.
@ SuboptionNotSet
Suboption not set.
@ InOperation
SET not possible because the device is in operation.
std::string String2Ip(std::span< const std::uint8_t > ipBytes)
Format raw IPv4 address bytes as a dotted string.
Definition util.cpp:206
std::array< std::uint8_t, macAddressLength > MacAddress
A 6-byte Ethernet MAC address.
Definition util.h:48
AlarmType
PROFINET Alarm Types used in AlarmNotification blocks.
Definition indices.h:382
DcpResetMode
Reset mode bitmask.
Definition protocol.h:289
@ Communication
Reset communication parameters.
@ Factory
Reset to factory defaults.
@ AllData
Reset all stored data.
@ Engineering
Reset engineering parameters.
RtaErrorReason
Exact current PROFINET RTA ErrorCode2 values.
Definition protocol.h:2507
constexpr AlarmNotificationBitmask operator|(AlarmNotificationBitmask lhs, AlarmNotificationBitmask rhs) noexcept
Bitwise OR operator for combining two AlarmNotificationBitmask values.
Definition alarms.h:471
RtaError ParseRtaError(const PNRTAHeader &header)
Parse an RTA ERR-PDU from an already parsed RTA header.
Definition protocol.h:2680
ControlCommand
PROFINET IOD control command values.
Definition indices.h:61
constexpr int macAddressLength
Constant lenght of a mac address.
Definition util.h:37
DcpFrameId
PROFINET DCP frame identifiers.
Definition protocol.h:65
@ IdentifyResponse
DCP Identify response.
@ IdentifyRequest
DCP Identify request.
@ GetSet
DCP GET/SET request or response.
@ Unknown
Not set / initialize value.
@ Hello
DCP Hello announcement.
DcpOption
DCP options.
Definition protocol.h:116
@ Nme
Network Management.
@ Unknown
Not set / initialize value.
@ All
Wildcard: all options.
@ DeviceInitiative
Device initiative.
@ Device
Device identification.
@ Ip
IP configuration.
constexpr std::uint16_t PROFINET_ETHERTYPE
EtherType value identifying PROFINET frames (0x8892).
Definition util.h:30
DcpDeviceSuboption
DCP Device suboptions.
Definition protocol.h:163
@ Rsi
Reverse Status Indication.
@ OemId
OEM vendor/device ID.
@ DeviceId
Vendor and device ID.
@ Instance
Device instance.
@ Options
Supported options.
DcpDeviceInitiative
DCP device-initiative values.
Definition protocol.h:321
@ NoHello
Device does not issue DCP-Hello after power-on.
@ IssueHello
Device issues DCP-Hello after power-on.
RtaErrorClass
Classification of an RTA protocol error reason.
Definition protocol.h:2485
@ UserSpecific
User-specific RTA abort.
@ SequenceNumber
Error coordinating RTA sequence numbers.
@ Abort
RTA error that aborts the application relation.
@ Obsoleted
Obsoleted reason code.
@ Extended
Additional AR/IOCARSR/PDEV RTA reason defined by PROFINET.
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
@ ToFactory
Reset to factory defaults.
@ Restore
Reset and restore from backup.
@ ApplicationData
Reset application data.
@ EngineeringParameterAlternate
Alternative engineering-parameter reset qualifier.
@ RestoreAlternate
Alternative reset-and-restore qualifier.
@ EngineeringParameter
Reset engineering parameters.
@ CommunicationParameterAlternate
Alternative communication-parameter reset qualifier.
@ EngineeringParameterExtendedAlternate
Alternative reset qualifier associated with engineering parameters.
@ ToFactoryAlternate
Alternative reset-to-factory qualifier.
@ AllStoredData
Reset all stored data.
@ CommunicationParameter
Reset communication parameters.
@ ApplicationDataAlternate
Alternative application-data reset qualifier.
@ AllStoredDataAlternate
Alternative all-stored-data reset qualifier.
@ EngineeringParameterExtended
Alternative reset qualifier associated with engineering parameters.
DcpServiceId
DCP service identifiers.
Definition protocol.h:84
@ Unknown
Not set / initialize value.
@ Identify
IDENTIFY service.
DcpServiceType
DCP service types.
Definition protocol.h:103
@ ResponseUnsupported
Service unsupported response.
@ ResponseSuccess
Successful response.
DcpIpBlockInfo
PROFINET DCP IP block status values. IP block status flags (IEC 61158-6-10 IPBlockInfo).
Definition protocol.h:440
@ NotSetConflict
IP address not set; address conflict detected.
@ SetByDhcp
IP address set via DHCP.
@ SetConflict
IP address set statically; address conflict detected.
@ SetByDhcpConflict
IP address set via DHCP; address conflict detected.
@ NotSet
IP address not set.
@ Resource
Resource error.
@ Application
Application error.
constexpr std::array< std::uint8_t, 12 > kPnUuidSuffix
PROFINET UUID suffix, shared by all interface/object UUIDs.
Definition protocol.h:855
DcpDeviceRole
Device role bitmask.
Definition protocol.h:263
@ PnSupervisor
PN-Supervisor.
@ IoController
IO-Controller.
@ IoMultidevice
IO-Multidevice.
std::string DecodeBytes(const std::uint8_t *data, std::size_t len)
Decode bytes to a UTF-8 string, stripping trailing NUL bytes.
Definition util.cpp:246
DcpResponseCode
DCP GET/SET response codes.
Definition protocol.h:356
@ InOperationSetNotPossible
SET not possible while device is in operation.
@ ResourceError
Resource error.
@ SuboptionNotSupported
Suboption not supported or no dataset available.
@ OptionNotSupported
Option not supported.
Identifies a PROFINET DCP block by option and suboption.
Definition protocol.h:465
constexpr auto operator<=>(const DcpBlockKey &) const =default
Compares DCP block keys lexicographically.
std::uint8_t suboption
DCP suboption code.
Definition protocol.h:470
DcpOption option
DCP option.
Definition protocol.h:467
Plain (untagged) Ethernet II frame header.
Definition protocol.h:479
MacAddress src
Source MAC address.
Definition protocol.h:484
std::uint16_t type
EtherType field.
Definition protocol.h:487
static EthernetHeader Parse(const Bytes &data)
Parse an Ethernet header and payload from raw frame bytes.
Definition protocol.h:495
Bytes ToBytes() const
Serialize this header and its payload back to raw frame bytes.
Definition protocol.h:513
MacAddress dst
Destination MAC address.
Definition protocol.h:481
Bytes payload
Frame payload following the header.
Definition protocol.h:490
802.1Q VLAN-tagged Ethernet II frame header.
Definition protocol.h:526
Bytes ToBytes() const
Serialize this header and its payload back to raw frame bytes.
Definition protocol.h:569
std::uint16_t tPid
Tag Protocol Identifier (0x8100 for 802.1Q).
Definition protocol.h:534
MacAddress dst
Destination MAC address.
Definition protocol.h:528
Bytes payload
Frame payload following the header.
Definition protocol.h:543
static EthernetVLANHeader Parse(const Bytes &data)
Parse a VLAN-tagged Ethernet header and payload from raw frame bytes.
Definition protocol.h:548
std::uint16_t tCI
Tag Control Information (priority, DEI, VLAN ID).
Definition protocol.h:537
MacAddress src
Source MAC address.
Definition protocol.h:531
std::uint16_t type
Inner EtherType field.
Definition protocol.h:540
One slot/subslot's placement within an IOCR's cyclic data frame.
Definition protocol.h:1896
std::uint16_t frameOffset
Byte offset of this object's data within the cyclic frame.
Definition protocol.h:1904
std::uint16_t subslotNumber
Subslot number.
Definition protocol.h:1901
static constexpr std::size_t kSize
Size in bytes of this object.
Definition protocol.h:1907
Bytes ToBytes() const
Serialize this object back to raw bytes.
Definition protocol.h:1928
std::uint16_t slotNumber
Slot number.
Definition protocol.h:1898
static IOCRAPIObject Parse(const Bytes &data)
Parse an IOCR API object from raw bytes.
Definition protocol.h:1912
Decoded IPv4 address/netmask/gateway triple.
Definition protocol.h:653
std::string gateway
IPv4 default gateway.
Definition protocol.h:661
std::string netmask
IPv4 subnet mask, e.g. "255.255.255.0".
Definition protocol.h:658
std::string address
IPv4 address, e.g. "192.168.1.1".
Definition protocol.h:655
ARBlockReq: establishes an Application Relationship (sent in the CONNECT request).
Definition protocol.h:1360
static PNARBlockRequest Parse(const Bytes &data)
Parse an ARBlockReq from raw bytes.
Definition protocol.h:1403
std::uint32_t arProperties
AR property flags (supervisor takeover, device access, etc.).
Definition protocol.h:1380
std::uint16_t cmInitiatorActivityTimeoutFactor
Activity timeout factor for the initiator.
Definition protocol.h:1383
MacAddress cmInitiatorMacAddress
MAC address of the initiating controller.
Definition protocol.h:1374
std::uint16_t sessionKey
Session key chosen by the initiator.
Definition protocol.h:1371
std::array< std::uint8_t, uuidLenght > arUuid
Unique AR UUID chosen by the initiator (controller).
Definition protocol.h:1368
Bytes cmInitiatorStationName
Station name of the initiating controller (variable length).
Definition protocol.h:1392
Bytes ToBytes() const
Serialize this block back to raw bytes.
Definition protocol.h:1428
Bytes payload
Additional blocks following this one (IOCR/AlarmCR/ExpectedSubmodule).
Definition protocol.h:1395
std::uint16_t arType
AR type (e.g. IOCARSingle, IOSAR).
Definition protocol.h:1365
std::uint16_t initiatorUdpRtport
UDP port the initiator uses for real-time data.
Definition protocol.h:1386
static constexpr std::size_t kFixedSize
Size in bytes of the fixed portion of this block.
Definition protocol.h:1398
std::array< std::uint8_t, blockHeaderLength > blockHeader
Nested 6-byte block header.
Definition protocol.h:1362
std::array< std::uint8_t, uuidLenght > cmInitiatorObjectUuid
Object UUID of the initiating controller.
Definition protocol.h:1377
std::uint16_t stationNameLength
Length in bytes of CmInitiatorStationName.
Definition protocol.h:1389
AlarmAck-PDU: acknowledges receipt of an AlarmNotification-PDU.
Definition protocol.h:2347
std::uint16_t alarmSpecifier
Alarm specifier flags echoed from the notification.
Definition protocol.h:2364
AlarmType alarmType
Alarm type being acknowledged.
Definition protocol.h:2352
std::uint16_t slotNumber
Slot number being acknowledged.
Definition protocol.h:2358
std::array< std::uint8_t, blockHeaderLength > blockHeader
Nested 6-byte block header.
Definition protocol.h:2349
std::uint32_t statusPNIO
PNIO status code (0 = acknowledged OK).
Definition protocol.h:2367
std::uint16_t subslotNumber
Subslot number being acknowledged.
Definition protocol.h:2361
static constexpr std::size_t kSize
Size in bytes of this PDU.
Definition protocol.h:2370
std::uint32_t api
API number.
Definition protocol.h:2355
Bytes ToBytes() const
Serialize this PDU back to raw bytes.
Definition protocol.h:2374
AlarmCRBlockReq: requests establishment of the alarm connection (part of the CONNECT request).
Definition protocol.h:2115
static constexpr std::uint16_t DEFAULT_MAX_ALARM_DATA_LENGTH
Default maximum alarm data length in bytes.
Definition protocol.h:2127
static constexpr std::uint16_t DEFAULT_TAG_HEADER_LOW
Default low word of the alarm VLAN tag header.
Definition protocol.h:2133
static constexpr BlockType BLOCK_TYPE
Block type identifier for AlarmCRBlockReq.
Definition protocol.h:2118
static PNAlarmCRBlockReq Parse(const Bytes &data)
Parse an AlarmCRBlockReq from raw bytes.
Definition protocol.h:2172
Bytes ToBytes() const
Serialize this block back to raw bytes.
Definition protocol.h:2197
static constexpr std::uint16_t DEFAULT_TAG_HEADER_HIGH
Default high word of the alarm VLAN tag header.
Definition protocol.h:2130
std::uint16_t alarmCrType
Alarm CR type (always 1: Alarm).
Definition protocol.h:2140
std::uint16_t etherTypeLT
EtherType used for alarm frames (0x8892).
Definition protocol.h:2143
std::uint32_t alarmCrProperties
Alarm CR property flags (transport, priority).
Definition protocol.h:2146
static constexpr std::size_t kSize
Size in bytes of this block.
Definition protocol.h:2167
static constexpr std::uint16_t DEFAULT_RTA_RETRIES
Default number of RTA retries.
Definition protocol.h:2124
std::uint16_t localAlarmReference
Local alarm reference chosen by the controller.
Definition protocol.h:2155
std::uint16_t alarmCrTagHeaderHigh
High word of the alarm VLAN tag header.
Definition protocol.h:2161
std::array< std::uint8_t, blockHeaderLength > blockHeader
Nested 6-byte block header.
Definition protocol.h:2137
std::uint16_t maxAlarmDataLength
Maximum alarm data length in bytes.
Definition protocol.h:2158
std::uint16_t alarmCrTagHeaderLow
Low word of the alarm VLAN tag header.
Definition protocol.h:2164
std::uint16_t rtaRetries
Number of RTA retransmission attempts.
Definition protocol.h:2152
std::uint16_t rtaTimeoutFactor
RTA (real-time acyclic) retransmission timeout factor.
Definition protocol.h:2149
static constexpr std::uint16_t DEFAULT_RTA_TIMEOUT_FACTOR
Default RTA timeout factor.
Definition protocol.h:2121
AlarmCRBlockRes: device's response confirming the alarm connection (part of the CONNECT response).
Definition protocol.h:2216
Bytes ToBytes() const
Serialize this block back to raw bytes.
Definition protocol.h:2257
std::uint16_t alarmCrType
Alarm CR type (always 1: Alarm).
Definition protocol.h:2226
std::array< std::uint8_t, blockHeaderLength > blockHeader
Nested 6-byte block header.
Definition protocol.h:2223
static constexpr std::uint16_t BLOCK_TYPE
Block type identifier for AlarmCRBlockRes.
Definition protocol.h:2219
std::uint16_t maxAlarmDataLength
Maximum alarm data length in bytes accepted by the device.
Definition protocol.h:2232
static constexpr std::size_t kSize
Size in bytes of this block.
Definition protocol.h:2235
std::uint16_t localAlarmReference
Local alarm reference assigned by the device.
Definition protocol.h:2229
static PNAlarmCRBlockRes Parse(const Bytes &data)
Parse an AlarmCRBlockRes from raw bytes.
Definition protocol.h:2240
AlarmNotification-PDU: carries a diagnosis/process/pull/plug/... alarm event.
Definition protocol.h:2276
std::uint16_t slotNumber
Slot number where the alarm originated.
Definition protocol.h:2301
std::uint32_t moduleIdentNumber
Module ident number of the affected module.
Definition protocol.h:2307
static constexpr std::uint16_t BLOCK_ALARM_HIGH
Block type: high-priority alarm notification.
Definition protocol.h:2279
std::array< std::uint8_t, blockHeaderLength > blockHeader
Nested 6-byte block header.
Definition protocol.h:2292
static constexpr std::size_t kFixedSize
Size in bytes of the fixed portion of this PDU.
Definition protocol.h:2319
static constexpr std::uint16_t BLOCK_ALARM_ACK_LOW
Block type: low-priority alarm acknowledgement.
Definition protocol.h:2288
static constexpr std::uint16_t BLOCK_ALARM_ACK_HIGH
Block type: high-priority alarm acknowledgement.
Definition protocol.h:2285
static PNAlarmNotificationPDU Parse(const Bytes &data)
Parse an AlarmNotification-PDU from raw bytes.
Definition protocol.h:2324
std::uint32_t api
API number.
Definition protocol.h:2298
std::uint32_t submoduleIdentNumber
Submodule ident number of the affected submodule.
Definition protocol.h:2310
std::uint16_t subslotNumber
Subslot number where the alarm originated.
Definition protocol.h:2304
std::uint16_t alarmSpecifier
Alarm specifier flags (sequence number, channel diagnosis presence, etc.).
Definition protocol.h:2313
static constexpr std::uint16_t BLOCK_ALARM_LOW
Block type: low-priority alarm notification.
Definition protocol.h:2282
Bytes payload
Alarm item data (USI-dispatched; see alarms.h).
Definition protocol.h:2316
std::uint16_t alarmType
Alarm type (Diagnosis/Process/Pull/Plug/...).
Definition protocol.h:2295
static constexpr std::uint16_t InM0
Block type: I&M0.
Definition protocol.h:1292
Bytes ToBytes() const
Serialize this header back to raw bytes.
Definition protocol.h:1347
BlockType blockType
Block type identifier.
Definition protocol.h:1308
static constexpr std::uint16_t DEFAULT_BLOCK_LENGTH
Default block length.
Definition protocol.h:1304
static PNBlockHeader Parse(const Bytes &data)
Parse a block header from raw bytes.
Definition protocol.h:1328
std::uint8_t blockVersionHigh
Block format major version.
Definition protocol.h:1317
static constexpr std::uint16_t InM0FilterDataModul
Block type: I&M0 filter data (module level).
Definition protocol.h:1298
std::uint8_t blockVersionLow
Block format minor version.
Definition protocol.h:1320
std::uint16_t blockLength
Length in bytes of the block body (excludes Type/Length fields).
Definition protocol.h:1311
std::uint16_t blockVersion
Block format version.
Definition protocol.h:1314
static constexpr std::uint16_t InM0FilterDataDevice
Block type: I&M0 filter data (device level).
Definition protocol.h:1301
static constexpr BlockType IODReadRequestHeader
Generic 6-byte PROFINET block header (Type + Length + Version).
Definition protocol.h:1286
static constexpr std::uint16_t IODReadResponseHeader
Block type: IODReadResponseHeader.
Definition protocol.h:1289
static constexpr std::size_t kSize
Size in bytes of this header.
Definition protocol.h:1323
static constexpr std::uint16_t InM0FilterDataSubModul
Block type: I&M0 filter data (submodule level).
Definition protocol.h:1295
DCP request block: Option(1) + SubOption(1) + Length(2) + payload(Length).
Definition protocol.h:666
std::uint16_t length
Length in bytes of Payload.
Definition protocol.h:675
IPConfiguration ParseIp() const
Interpret this block's payload as an IP configuration triple.
Definition protocol.h:717
std::uint8_t suboption
DCP suboption code.
Definition protocol.h:672
Bytes payload
Block payload.
Definition protocol.h:678
DcpOption option
DCP option code.
Definition protocol.h:668
Bytes ToBytes() const
Serialize this block back to raw bytes.
Definition protocol.h:704
static constexpr std::size_t kFixedSize
Size in bytes of the fixed portion of this block.
Definition protocol.h:681
static PNDCPBlockRequest Parse(const Bytes &data)
Parse a DCP request block from raw bytes.
Definition protocol.h:686
DCP response block: Option(1) + SubOption(1) + Length(2) + Status(2) + payload.
Definition protocol.h:737
static constexpr std::pair< std::uint8_t, std::uint8_t > DEVICE_ROLE
Block option/suboption: device role bitmask.
Definition protocol.h:773
std::uint16_t status
Per-block status/error code.
Definition protocol.h:748
std::uint8_t suboption
DCP suboption code.
Definition protocol.h:742
static constexpr std::pair< std::uint8_t, std::uint8_t > DEVICE_ID
Block option/suboption: vendor/device ID.
Definition protocol.h:770
static constexpr std::pair< std::uint8_t, std::uint8_t > IP_ADDRESS
Block option/suboption: IP address/netmask/gateway.
Definition protocol.h:758
static constexpr std::pair< std::uint8_t, std::uint8_t > NAME_OF_STATION
Block option/suboption: station name.
Definition protocol.h:767
static PNDCPBlock Parse(const Bytes &data)
Parse a DCP response block from raw bytes.
Definition protocol.h:797
static constexpr std::size_t kFixedSize
Size in bytes of the fixed portion of this block.
Definition protocol.h:792
std::uint8_t option
DCP option code.
Definition protocol.h:739
std::uint16_t length
Length in bytes of Status plus Payload (see class.
Definition protocol.h:745
static constexpr std::pair< std::uint8_t, std::uint8_t > DEVICE_OEM_ID
Block option/suboption: OEM vendor/device ID.
Definition protocol.h:785
IPConfiguration ParseIp() const
Interpret this block's payload as an IP configuration triple.
Definition protocol.h:833
static constexpr std::pair< std::uint8_t, std::uint8_t > DEVICE_OPTIONS
Block option/suboption: supported option list.
Definition protocol.h:776
static constexpr std::pair< std::uint8_t, std::uint8_t > IP_FULL_SUITE
Block option/suboption: full IP suite.
Definition protocol.h:761
static constexpr std::pair< std::uint8_t, std::uint8_t > ALL
Block option/suboption wildcard: all blocks.
Definition protocol.h:788
static constexpr std::pair< std::uint8_t, std::uint8_t > DEVICE_ALIAS
Block option/suboption: device alias name.
Definition protocol.h:779
static constexpr std::pair< std::uint8_t, std::uint8_t > DEVICE_INSTANCE
Block option/suboption: device instance.
Definition protocol.h:782
Bytes payload
Block payload (excludes Status).
Definition protocol.h:751
Bytes ToBytes() const
Serialize this block back to raw bytes.
Definition protocol.h:819
static constexpr std::pair< std::uint8_t, std::uint8_t > IP_MAC
Block option/suboption: IP/MAC address.
Definition protocol.h:755
static constexpr std::pair< std::uint8_t, std::uint8_t > DEVICE_TYPE
Block option/suboption: device type string.
Definition protocol.h:764
DCP (Discovery and Configuration Protocol) frame header.
Definition protocol.h:584
std::uint32_t xId
Transaction ID correlating requests and responses.
Definition protocol.h:600
Bytes ToBytes() const
Serialize this header and its block-list payload back to raw bytes.
Definition protocol.h:637
std::uint16_t respDelay
Response delay factor (requests) or reserved (responses).
Definition protocol.h:603
static PNDCPHeader Parse(const Bytes &data)
Parse a DCP header and block-list payload from raw bytes.
Definition protocol.h:617
DcpFrameId frameId
DCP frame ID identifying the service/multicast group.
Definition protocol.h:591
static constexpr std::size_t kFixedSize
Size in bytes of the fixed portion of this header.
Definition protocol.h:612
std::uint16_t length
Length in bytes of the block list that follows.
Definition protocol.h:606
DcpServiceId serviceId
DCP service ID (GET/SET/IDENTIFY/HELLO).
Definition protocol.h:594
DcpServiceType serviceType
DCP service type (REQUEST/RESPONSE/...).
Definition protocol.h:597
static constexpr std::uint16_t ETHER_TYPE
EtherType used by DCP frames.
Definition protocol.h:587
Bytes payload
DCP block list payload.
Definition protocol.h:609
Describes one direction (input or output) of a submodule's cyclic data.
Definition protocol.h:2733
std::uint16_t dataDescription
Data direction: 1 = Input, 2 = Output.
Definition protocol.h:2735
Bytes ToBytes() const
Serialize this description back to raw bytes.
Definition protocol.h:2751
std::uint8_t lengthIops
Length in bytes of the IOPS (provider status) trailer.
Definition protocol.h:2744
std::uint16_t submoduleDataLength
Length in bytes of this direction's cyclic data.
Definition protocol.h:2738
static constexpr std::size_t kSize
Size in bytes of this description.
Definition protocol.h:2747
std::uint8_t lengthIocs
Length in bytes of the IOCS (consumer status) trailer.
Definition protocol.h:2741
IOCRBlockReq header: requests establishment of one IOCR (part of the CONNECT request).
Definition protocol.h:1984
static constexpr std::size_t kSize
Size in bytes of this header.
Definition protocol.h:2042
static constexpr BlockType BLOCK_TYPE
Block type identifier for IOCRBlockReq.
Definition protocol.h:1987
std::uint16_t frameId
Requested frame ID (device may reassign in its response).
Definition protocol.h:2009
MacAddress iocrMulticastMac
Multicast MAC address (used only for multicast IOCRs).
Definition protocol.h:2036
std::uint16_t dataLength
Total cyclic data length in bytes.
Definition protocol.h:2006
std::uint16_t sendClockFactor
Send clock base factor (31.25us units).
Definition protocol.h:2012
std::uint16_t dataHoldFactor
Data hold factor (how long to keep the last good frame's data).
Definition protocol.h:2030
std::uint16_t phase
Phase offset within the reduction ratio.
Definition protocol.h:2018
std::uint16_t iocrType
IOCR type (Input/Output/MulticastProvider/MulticastConsumer).
Definition protocol.h:1994
std::uint16_t watchdogFactor
Watchdog factor (missed-frame tolerance before a timeout fault).
Definition protocol.h:2027
std::uint16_t sequence
Sequence value (reserved, usually 0).
Definition protocol.h:2021
std::uint16_t numberOfApis
Number of API entries that follow this header.
Definition protocol.h:2039
std::uint16_t iocrReference
IOCR reference chosen by the controller.
Definition protocol.h:1997
std::uint16_t iocrTagHeader
VLAN tag header used for cyclic frames.
Definition protocol.h:2033
std::uint32_t iocrProperties
IOCR property flags (RT class, redundancy, etc.).
Definition protocol.h:2003
std::uint16_t etherTypeLT
EtherType used for cyclic frames (0x8892).
Definition protocol.h:2000
std::array< std::uint8_t, blockHeaderLength > blockHeader
Nested 6-byte block header.
Definition protocol.h:1991
std::uint16_t reductionRatio
Reduction ratio relative to the send clock.
Definition protocol.h:2015
Bytes ToBytes() const
Serialize this header back to raw bytes.
Definition protocol.h:2085
static PNIOCRBlockReqHeader Parse(const Bytes &data)
Parse the fixed IOCRBlockReq header.
Definition protocol.h:2048
std::uint32_t frameSendOffset
Frame send offset within the cycle.
Definition protocol.h:2024
IOCRBlockRes: device's response confirming an IOCR (part of the CONNECT response).
Definition protocol.h:1940
std::array< std::uint8_t, blockHeaderLength > blockHeader
Nested 6-byte block header.
Definition protocol.h:1947
static PNIOCRBlockRes Parse(const Bytes &data)
Parse an IOCRBlockRes from raw bytes.
Definition protocol.h:1964
std::uint16_t iocrReference
IOCR reference assigned by the controller.
Definition protocol.h:1953
static constexpr std::uint16_t BLOCK_TYPE
Block type identifier for IOCRBlockRes.
Definition protocol.h:1943
std::uint16_t frameId
Frame ID assigned by the device for this IOCR.
Definition protocol.h:1956
std::uint16_t iocrType
IOCR type (Input/Output/MulticastProvider/MulticastConsumer).
Definition protocol.h:1950
static constexpr std::size_t kSize
Size in bytes of this block.
Definition protocol.h:1959
IOD read/write request/response header (RPC body for READ/WRITE/IMPLICIT_READ).
Definition protocol.h:1190
std::uint32_t api
API number.
Definition protocol.h:1205
std::uint16_t slot
Slot number.
Definition protocol.h:1208
std::array< std::uint8_t, blockHeaderLength > blockHeader
Nested 6-byte block header (type + length + version).
Definition protocol.h:1196
Bytes ToBytes() const
Serialize this header and payload back to raw bytes.
Definition protocol.h:1262
static PNIODHeader Parse(const Bytes &data)
Parse an IOD header and payload from raw bytes.
Definition protocol.h:1237
std::uint16_t sequenceNumber
Sequence number for tracking retries.
Definition protocol.h:1199
static constexpr std::size_t kFixedSize
Size in bytes of the fixed portion of this header.
Definition protocol.h:1232
std::array< std::uint8_t, 8 > padding2
Reserved/padding.
Definition protocol.h:1226
std::uint16_t padding1
Reserved/padding.
Definition protocol.h:1214
static constexpr std::uint16_t kContolCommandOffset
ControlCommand is located at offset 28 inside PNIODControlBlockReq (Block Header: 6 bytes + ARUUID: 1...
Definition protocol.h:1193
Bytes payload
Record data payload.
Definition protocol.h:1229
std::uint16_t subslot
Subslot number.
Definition protocol.h:1211
std::array< std::uint8_t, uuidLenght > targetArUuid
Target AR UUID for AR handover scenarios (usually zero).
Definition protocol.h:1223
std::uint32_t length
Length in bytes of Payload.
Definition protocol.h:1220
std::uint16_t index
Record data index being read or written.
Definition protocol.h:1217
std::array< std::uint8_t, uuidLenght > arUuid
AR (Application Relationship) UUID this record belongs to.
Definition protocol.h:1202
Control block used for Release/PrmBegin/PrmEnd/ApplicationReady/RTClass3 requests.
Definition protocol.h:1449
std::array< std::uint8_t, uuidLenght > arUuid
AR UUID this control operation applies to.
Definition protocol.h:1457
std::uint16_t controlBlockProperties
Control block property flags.
Definition protocol.h:1469
static constexpr std::size_t kSize
Size in bytes of this block.
Definition protocol.h:1472
std::uint16_t padding1
Reserved/padding.
Definition protocol.h:1454
static PNIODReleaseBlock Parse(const Bytes &data)
Parse a control block from raw bytes.
Definition protocol.h:1477
std::uint16_t sessionKey
Session key matching the AR.
Definition protocol.h:1460
std::array< std::uint8_t, blockHeaderLength > blockHeader
Nested 6-byte block header.
Definition protocol.h:1451
ControlCommand controlCommand
Control command bitmask (PrmEnd/AppReady/Release/Done/...).
Definition protocol.h:1466
std::uint16_t padding2
Reserved/padding.
Definition protocol.h:1463
Bytes ToBytes() const
Serialize this block back to raw bytes.
Definition protocol.h:1497
IODWriteReqHeader: request header for writing a data record.
Definition protocol.h:2768
static constexpr std::uint16_t BLOCK_TYPE
Block type identifier for IODWriteReqHeader.
Definition protocol.h:2771
std::uint16_t seqNum
Sequence number for tracking retries.
Definition protocol.h:2778
std::uint16_t index
Record data index being written.
Definition protocol.h:2796
Bytes payload
Record data to write.
Definition protocol.h:2805
std::array< std::uint8_t, uuidLenght > arUuid
AR UUID this record belongs to.
Definition protocol.h:2781
std::array< std::uint8_t, 24 > rwPadding
Reserved/padding.
Definition protocol.h:2802
static constexpr std::size_t kFixedSize
Size in bytes of the fixed portion of this block.
Definition protocol.h:2808
std::uint32_t recordDataLength
Length in bytes of Payload.
Definition protocol.h:2799
std::uint16_t subslot
Subslot number.
Definition protocol.h:2790
std::uint16_t slot
Slot number.
Definition protocol.h:2787
std::array< std::uint8_t, blockHeaderLength > blockHeader
Nested 6-byte block header.
Definition protocol.h:2775
std::uint32_t api
API number.
Definition protocol.h:2784
Bytes ToBytes() const
Serialize this block back to raw bytes.
Definition protocol.h:2812
std::uint16_t padding
Reserved/padding.
Definition protocol.h:2793
IODWriteResHeader: response header confirming (or rejecting) a data record write.
Definition protocol.h:2832
std::array< std::uint8_t, blockHeaderLength > blockHeader
Nested 6-byte block header.
Definition protocol.h:2839
std::uint32_t recordDataLength
Length in bytes accepted by the device.
Definition protocol.h:2863
static constexpr std::uint16_t BLOCK_TYPE
Block type identifier for IODWriteResHeader.
Definition protocol.h:2835
std::uint16_t padding
Reserved/padding.
Definition protocol.h:2857
std::uint16_t slot
Slot number.
Definition protocol.h:2851
std::uint16_t seqNum
Sequence number echoed from the request.
Definition protocol.h:2842
std::uint16_t additionalValue1
Additional status value 1 (device-specific).
Definition protocol.h:2866
std::array< std::uint8_t, uuidLenght > arUuid
AR UUID this record belongs to.
Definition protocol.h:2845
std::uint16_t index
Record data index written.
Definition protocol.h:2860
static PNIODWriteRes Parse(const Bytes &data)
Parse an IODWriteResHeader from raw bytes.
Definition protocol.h:2883
std::uint32_t status
PNIO status code (0 = success).
Definition protocol.h:2872
std::uint16_t subslot
Subslot number.
Definition protocol.h:2854
static constexpr std::size_t kSize
Size in bytes of this block.
Definition protocol.h:2878
std::uint16_t additionalValue2
Additional status value 2 (device-specific).
Definition protocol.h:2869
std::array< std::uint8_t, 16 > rwPadding
Reserved/padding.
Definition protocol.h:2875
std::uint32_t api
API number.
Definition protocol.h:2848
I&M0: mandatory identification data (vendor, order ID, serial number, revisions).
Definition protocol.h:1517
std::uint16_t imProfileId
I&M profile ID.
Definition protocol.h:1560
std::uint16_t imHardwareRevision
Hardware revision number.
Definition protocol.h:1542
static constexpr std::size_t kSize
Size in bytes of this record.
Definition protocol.h:1572
std::uint16_t imProfileSpecificType
I&M profile-specific type.
Definition protocol.h:1563
std::string imSerialNumber
Device serial number (16 chars).
Definition protocol.h:1539
std::uint16_t imSupported
Bitmask of which I&M1-I&M15 records this device supports.
Definition protocol.h:1569
std::uint8_t imSwRevisionBugFix
Bug fix revision digit.
Definition protocol.h:1551
static PNInM0 Parse(const Bytes &data)
Parse an I&M0 record from raw bytes.
Definition protocol.h:1584
std::uint16_t imVersion
I&M data structure version.
Definition protocol.h:1566
std::uint8_t swRevisionPrefix
Software revision prefix character (e.g. 'V', 'R', 'P', 'U', 'T').
Definition protocol.h:1545
std::uint16_t imRevisionCounter
Monotonically increasing revision counter.
Definition protocol.h:1557
std::uint8_t imSwRevisionFunctionalEnhancement
Functional enhancement revision digit.
Definition protocol.h:1548
std::uint16_t VendorId() const
Combine VendorIdHigh/VendorIdLow into a 16-bit vendor ID.
Definition protocol.h:1576
std::uint8_t imSwRevisionInternalChange
Internal change revision digit.
Definition protocol.h:1554
std::uint16_t vendorId
The PROFINET vendor ID.
Definition protocol.h:1527
std::string orderId
Manufacturer-specific order/part number (20 chars).
Definition protocol.h:1536
static constexpr std::uint16_t IDX
Record data index for I&M0.
Definition protocol.h:1520
std::array< std::uint8_t, blockHeaderLength > blockHeader
Nested 6-byte block header.
Definition protocol.h:1524
bool operator==(const PNInM0 &) const =default
Compares two PNInM0 for equality.
I&M1: user-assigned tag function and location strings.
Definition protocol.h:1624
std::string imTagLocation
User-assigned installation location (22 chars).
Definition protocol.h:1637
static PNInM1 Parse(const Bytes &data)
Parse an I&M1 record from raw bytes.
Definition protocol.h:1645
std::array< std::uint8_t, blockHeaderLength > blockHeader
Nested 6-byte block header.
Definition protocol.h:1631
bool operator==(const PNInM1 &) const =default
Compares two PNInM1 for equality.
static constexpr std::uint16_t IDX
Record data index for I&M1.
Definition protocol.h:1627
std::string imTagFunction
User-assigned function description (32 chars).
Definition protocol.h:1634
static constexpr std::size_t kSize
Size in bytes of this record.
Definition protocol.h:1640
I&M2: installation date.
Definition protocol.h:1668
static PNInM2 Parse(const Bytes &data)
Parse an I&M2 record from raw bytes.
Definition protocol.h:1686
std::string imDate
Installation date, "YYYY-MM-DD HH:MM" (16 chars).
Definition protocol.h:1678
bool operator==(const PNInM2 &) const =default
Compares two PNInM2 for equality.
std::array< std::uint8_t, blockHeaderLength > blockHeader
Nested 6-byte block header.
Definition protocol.h:1675
static constexpr std::uint16_t IDX
Record data index for I&M2.
Definition protocol.h:1671
static constexpr std::size_t kSize
Size in bytes of this record.
Definition protocol.h:1681
I&M3: free-text descriptor.
Definition protocol.h:1709
static constexpr std::uint16_t IDX
Record data index for I&M3.
Definition protocol.h:1712
std::array< std::uint8_t, blockHeaderLength > blockHeader
Nested 6-byte block header.
Definition protocol.h:1716
std::string imDescriptor
Free-text descriptor (54 chars).
Definition protocol.h:1719
static PNInM3 Parse(const Bytes &data)
Parse an I&M3 record from raw bytes.
Definition protocol.h:1727
bool operator==(const PNInM3 &) const =default
Compares two PNInM3 for equality.
static constexpr std::size_t kSize
Size in bytes of this record.
Definition protocol.h:1722
I&M4: PROFIsafe signature (binary, not text).
Definition protocol.h:1749
bool operator==(const PNInM4 &) const =default
Compares two PNInM4 for equality.
std::array< std::uint8_t, 54 > imSignature
PROFIsafe signature bytes.
Definition protocol.h:1759
static PNInM4 Parse(const Bytes &data)
Parse an I&M4 record from raw bytes.
Definition protocol.h:1767
static constexpr std::uint16_t IDX
Record data index for I&M4.
Definition protocol.h:1752
static constexpr std::size_t kSize
Size in bytes of this record.
Definition protocol.h:1762
std::array< std::uint8_t, blockHeaderLength > blockHeader
Nested 6-byte block header.
Definition protocol.h:1756
I&M5: free-text annotation.
Definition protocol.h:1789
std::array< std::uint8_t, blockHeaderLength > blockHeader
Nested 6-byte block header.
Definition protocol.h:1796
static PNInM5 Parse(const Bytes &data)
Parse an I&M5 record from raw bytes.
Definition protocol.h:1807
static constexpr std::uint16_t IDX
Record data index for I&M5.
Definition protocol.h:1792
std::string imAnnotation
Free-text annotation (64 chars).
Definition protocol.h:1799
bool operator==(const PNInM5 &) const =default
Compares two PNInM5 for equality.
static constexpr std::size_t kSize
Size in bytes of this record.
Definition protocol.h:1802
I&M6-I&M15: reserved for future use per IEC 61158-6-10.
Definition protocol.h:1833
Bytes payload
Opaque remaining payload.
Definition protocol.h:1843
bool operator==(const PNInMReserved &) const =default
Compares two PNInMReserved for equality.
static constexpr std::uint16_t IDX
Record data index for this reserved I&M slot.
Definition protocol.h:1836
std::array< std::uint8_t, blockHeaderLength > blockHeader
Nested 6-byte block header.
Definition protocol.h:1840
static PNInMReserved Parse(const Bytes &data)
Parse a reserved I&M record from raw bytes.
Definition protocol.h:1848
NRD (Network Representation Data) wrapper carrying the actual IOD payload.
Definition protocol.h:1128
Bytes payload
The wrapped IOD data.
Definition protocol.h:1145
static PNNRDData Parse(const Bytes &data)
Parse an NRD wrapper and payload from raw bytes.
Definition protocol.h:1153
Bytes ToBytes() const
Serialize this wrapper and payload back to raw bytes.
Definition protocol.h:1175
std::uint32_t argsLength
Length in bytes of the arguments (usually equals ActualCount).
Definition protocol.h:1133
std::uint32_t offset
Byte offset into the logical result (0 unless fragmented).
Definition protocol.h:1139
std::uint32_t argsMaximumStatus
Maximum status/argument buffer size accepted by the caller.
Definition protocol.h:1130
static constexpr std::size_t kFixedSize
Size in bytes of the fixed portion of this wrapper.
Definition protocol.h:1148
std::uint32_t maximumCount
Maximum number of bytes the caller can accept.
Definition protocol.h:1136
std::uint32_t actualCount
Actual length in bytes of Payload.
Definition protocol.h:1142
DCE/RPC PDU header used to carry PROFINET connect/read/write/control requests.
Definition protocol.h:860
Bytes ToBytes() const
Serialize this header and body back to raw bytes.
Definition protocol.h:1045
static constexpr std::uint8_t WORKING
Packet type: WORKING.
Definition protocol.h:875
static constexpr std::uint16_t defaultInterfaceHint
Definition protocol.h:915
std::array< std::uint8_t, 3 > dataRepresentation
Data representation format label.
Definition protocol.h:931
static constexpr std::uint16_t RELEASE
Operation number: RELEASE.
Definition protocol.h:899
std::uint16_t operationNumber
Operation number (CONNECT/RELEASE/READ/WRITE/CONTROL/IMPLICIT_READ).
Definition protocol.h:955
std::uint16_t fragmentNumber
Fragment number for fragmented PDUs.
Definition protocol.h:967
static constexpr std::size_t kFixedSize
Size in bytes of the fixed portion of this header.
Definition protocol.h:979
static std::array< std::uint8_t, uuidLenght > IfaceUuidParamserver()
Interface UUID identifying the Parameter Server role.
Definition protocol.h:1004
std::uint16_t interfaceHint
Interface hint (0xFFFF if unused).
Definition protocol.h:958
static constexpr std::uint16_t READ
Operation number: READ.
Definition protocol.h:902
static constexpr std::uint8_t FRAG_ACK
Packet type: FRAG_ACK.
Definition protocol.h:890
std::uint8_t flags1
Packet flags, first byte.
Definition protocol.h:925
static constexpr std::uint16_t defaultActivityHint
Definition protocol.h:916
static PNRPCHeader Parse(const Bytes &data)
Parse an RPC header and body from raw bytes.
Definition protocol.h:1012
std::uint8_t packetType
Packet type (REQUEST/RESPONSE/FAULT/...).
Definition protocol.h:922
static constexpr std::uint16_t WRITE
Operation number: WRITE.
Definition protocol.h:905
std::array< std::uint8_t, uuidLenght > interfaceUuid
Target interface UUID (identifies device/controller/supervisor role).
Definition protocol.h:940
std::uint8_t authenticationProtocol
Authentication protocol identifier (unused by PROFINET).
Definition protocol.h:970
std::uint8_t serialNrHigh
High byte of the serial number.
Definition protocol.h:934
static std::array< std::uint8_t, uuidLenght > IfaceUuidDevice()
Interface UUID identifying the IO-Device role.
Definition protocol.h:983
std::uint8_t serialNrLow
Low byte of the serial number.
Definition protocol.h:973
static constexpr std::uint8_t ACK
Packet type: ACK.
Definition protocol.h:884
static std::array< std::uint8_t, uuidLenght > IfaceUuidSupervisor()
Interface UUID identifying the IO-Supervisor role.
Definition protocol.h:997
std::uint32_t sequenceNumber
Sequence number within the activity.
Definition protocol.h:952
static constexpr std::uint8_t REJECT
Packet type: REJECT.
Definition protocol.h:881
static constexpr std::uint16_t CONNECT
Operation number: CONNECT.
Definition protocol.h:896
std::uint8_t version
DCE/RPC version (always 4 for PROFINET).
Definition protocol.h:919
static constexpr std::uint8_t CANCEL_ACK
Packet type: CANCEL_ACK.
Definition protocol.h:893
static constexpr std::uint8_t PONG
Packet type: PONG.
Definition protocol.h:878
static constexpr std::uint8_t PING
Packet type: PING.
Definition protocol.h:866
static constexpr std::uint8_t REQUEST
Packet type: REQUEST.
Definition protocol.h:863
static constexpr std::uint16_t CONTROL
Operation number: CONTROL.
Definition protocol.h:908
std::uint32_t serverBootTime
Server boot time counter.
Definition protocol.h:946
static constexpr std::uint8_t RESPONSE
Packet type: RESPONSE.
Definition protocol.h:869
std::uint8_t flags2
Packet flags, second byte.
Definition protocol.h:928
static constexpr std::uint16_t IMPLICIT_READ
Operation number: IMPLICIT_READ.
Definition protocol.h:911
Bytes payload
PDU body (NRD data for read/write/control, etc.).
Definition protocol.h:976
std::uint32_t interfaceVersion
Interface version.
Definition protocol.h:949
std::uint16_t activityHint
Activity hint (0xFFFF if unused).
Definition protocol.h:961
static std::array< std::uint8_t, uuidLenght > PrefixedUuid(std::uint8_t b2, std::uint8_t b3)
Build a 16-byte PROFINET interface/object UUID from its two distinguishing bytes.
Definition protocol.h:1112
std::uint16_t lengthOfBody
Length in bytes of Payload.
Definition protocol.h:964
static std::array< std::uint8_t, uuidLenght > IfaceUuidController()
Interface UUID identifying the IO-Controller role.
Definition protocol.h:990
std::array< std::uint8_t, uuidLenght > objectUuid
Target object UUID.
Definition protocol.h:937
static constexpr std::uint8_t CANCEL
Packet type: CANCEL.
Definition protocol.h:887
static constexpr std::uint8_t FAULT
Packet type: FAULT.
Definition protocol.h:872
std::array< std::uint8_t, uuidLenght > activityUuid
Activity (call) UUID correlating request/response pairs.
Definition protocol.h:943
RTA-PDU Header - Real-Time Acyclic PDU for Layer 2 alarm transport.
Definition protocol.h:2390
static constexpr std::uint8_t ADD_FLAGS_TACK
TACK(transport ack request) in bit 4(IEC 61158-6-10; cf. p-net pf_put_alarm_fixed)
Definition protocol.h:2414
std::uint16_t sendSeqNum
Sender's sequence number for this PDU.
Definition protocol.h:2431
static constexpr std::uint8_t RTA_TYPE_ERR
PDU type: ERR.
Definition protocol.h:2402
std::uint16_t alarmSrcEndpoint
Source alarm endpoint (AlarmCR reference on the sender).
Definition protocol.h:2422
Bytes payload
RTA variable part (e.g. an AlarmNotification-PDU or AlarmAck-PDU).
Definition protocol.h:2440
static constexpr std::size_t kFixedSize
Size in bytes of the fixed portion of this header.
Definition protocol.h:2443
Bytes ToBytes() const
Serialize this header and variable part back to raw bytes.
Definition protocol.h:2469
static constexpr std::uint8_t VERSION_2
RTA protocol version 2.
Definition protocol.h:2408
std::uint16_t alarmDstEndpoint
Destination alarm endpoint (AlarmCR reference on the receiver).
Definition protocol.h:2419
static constexpr std::uint8_t RTA_TYPE_ACK
PDU type: ACK.
Definition protocol.h:2399
std::uint16_t variablePartLenght
Length in bytes of the variable part (Payload).
Definition protocol.h:2437
std::uint8_t addFlags
Additional flags (window size, TACK flag).
Definition protocol.h:2428
static PNRTAHeader Parse(const Bytes &data)
Parse an RTA header and variable part from raw bytes.
Definition protocol.h:2448
static constexpr std::uint8_t RTA_TYPE_DATA
PDU type: DATA.
Definition protocol.h:2393
static constexpr std::uint8_t ADD_FLAGS_WINDOW_1
RTA AddFlags bits: window size in bits 0-3.
Definition protocol.h:2411
static constexpr std::uint8_t VERSION_1
RTA protocol version 1.
Definition protocol.h:2405
static constexpr std::uint8_t RTA_TYPE_NACK
PDU type: NACK.
Definition protocol.h:2396
std::uint16_t ackSeqNum
Sequence number being acknowledged.
Definition protocol.h:2434
std::uint8_t pduType
PDU type and protocol version, packed as type(bits 4-7) + version(bits 0-3).
Definition protocol.h:2425
Decoded PROFINET RTA ERR-PDU.
Definition protocol.h:2571
std::uint8_t errorCode1
PNIO ErrorCode1 byte.
Definition protocol.h:2585
static RtaErrorReason ClassifyRtaErrorReason(std::uint8_t errorCode2)
Return the decoded RTA reason.
Definition alarms.cpp:347
static RtaErrorClass ClassifyRtaError(std::uint8_t errorCode2)
Return the decoded RTA reason.
Definition alarms.cpp:496
bool IsUserAbort() const
Whether this is the user-specific RTA abort.
Definition protocol.h:2648
bool IsObsoleted() const
Whether this reason code is obsolete.
Definition protocol.h:2640
RtaErrorClass kind
Decoded RTA class.
Definition protocol.h:2594
RtaErrorClass ErrorClass() const
Classify the ErrorCode2 reason.
Definition protocol.h:2598
RtaErrorReason reason
Decoded RTA reason.
Definition protocol.h:2591
bool IsSequenceNumberError() const
Whether this is RTA sequence-number coordination failure.
Definition protocol.h:2614
bool IsRtaProtocolError() const
Whether the status belongs to the RTA protocol-error class.
Definition protocol.h:2605
static RtaErrorClass ClassifyRtaError(RtaErrorReason reason)
Return the decoded RTA reason.
PNRTAHeader header
Complete RTA header associated with this error.
Definition protocol.h:2573
std::string ReasonName() const
Return the decoded RTA reason name.
Definition alarms.cpp:563
std::uint8_t errorCode2
PNIO ErrorCode2 byte.
Definition protocol.h:2588
bool IsAbort() const
Whether this reason is an RTA abort reason.
Definition protocol.h:2622
bool IsExtended() const
Whether the reason is one of the later extended RTA reasons.
Definition protocol.h:2631
std::uint8_t errorDecode
PNIO ErrorDecode byte.
Definition protocol.h:2582
std::uint32_t statusPnio
Raw four-byte PNIO status value.
Definition protocol.h:2576
std::uint8_t errorCode
PNIO ErrorCode byte.
Definition protocol.h:2579
Declares Linux Ethernet, addressing, timing, and utility helpers used by the PROFINET stack.
Generic helpers for reading and writing integer and byte data in big- and little-endian wire formats.