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
37#include <algorithm>
38#include <array>
39#include <cstdint>
40#include <stdexcept>
41#include <string>
42#include <vector>
43
44#include "profinet/indices.h"
45#include "profinet/util.h"
46#include "profinet/wire.h"
47
48namespace profinet
49{
50
52using Bytes = std::vector<std::uint8_t>;
53
55inline constexpr int blockHeaderLenght = 6;
56
57// =============================================================================
58// DCP - Discovery and Configuration Protocol
59// =============================================================================
60
63{
66
69
71 std::uint16_t type = 0;
72
75
79 static EthernetHeader Parse(const Bytes& data)
80 {
81 const int expectedEthernetHeaderSize = 14;
82 if (data.size() < expectedEthernetHeaderSize)
83 {
84 throw std::runtime_error("EthernetHeader: insufficient data");
85 }
86 wire::Reader r(data);
88 h.dst = r.Fixed<macAddressLength>();
89 h.src = r.Fixed<macAddressLength>();
90 h.type = r.U16();
91 h.payload = r.ReadBytes(r.Remaining());
92 return h;
93 }
94
97 [[nodiscard]] Bytes ToBytes() const
98 {
99 Bytes out;
100 wire::PutFixed(out, dst);
101 wire::PutFixed(out, src);
102 wire::PutU16(out, type);
103 out.insert(out.end(), payload.begin(), payload.end());
104 return out;
105 }
106};
107
110{
113
116
118 std::uint16_t tPid = 0;
119
121 std::uint16_t tCI = 0;
122
124 std::uint16_t type = 0;
125
128
132 static EthernetVLANHeader Parse(const Bytes& data)
133 {
134 const int expectedEthernetVLANHeaderSize = 14;
135
136 if (data.size() < expectedEthernetVLANHeaderSize)
137 {
138 throw std::runtime_error("EthernetVLANHeader: insufficient data");
139 }
140 wire::Reader r(data);
142 h.dst = r.Fixed<macAddressLength>();
143 h.src = r.Fixed<macAddressLength>();
144 h.tPid = r.U16();
145 h.tCI = r.U16();
146 h.type = r.U16();
147 h.payload = r.ReadBytes(r.Remaining());
148 return h;
149 }
150
153 [[nodiscard]] Bytes ToBytes() const
154 {
155 Bytes out;
156 wire::PutFixed(out, dst);
157 wire::PutFixed(out, src);
158 wire::PutU16(out, tPid);
159 wire::PutU16(out, tCI);
160 wire::PutU16(out, type);
161 out.insert(out.end(), payload.begin(), payload.end());
162 return out;
163 }
164};
165
168{
169 // NOLINTBEGIN(readability-identifier-naming)
171 static constexpr std::uint16_t ETHER_TYPE = 0x8892;
172
174 static constexpr std::uint8_t GET = 3;
175
177 static constexpr std::uint8_t SET = 4;
178
180 static constexpr std::uint8_t IDENTIFY = 5;
181
183 static constexpr std::uint8_t HELLO = 6;
184
186 static constexpr std::uint8_t REQUEST = 0;
187
189 static constexpr std::uint8_t RESPONSE = 1;
190
192 static constexpr std::uint8_t RESPONSE_UNSUPPORTED = 5;
193 // NOLINTEND(readability-identifier-naming)
194
196 std::uint16_t frameId = 0;
197
199 std::uint8_t serviceId = 0;
200
202 std::uint8_t serviceType = 0;
203
205 std::uint32_t xId = 0;
206
208 std::uint16_t respDelay = 0;
209
211 std::uint16_t length = 0;
212
215
217 static constexpr std::size_t kFixedSize = 12;
218
222 static PNDCPHeader Parse(const Bytes& data)
223 {
224 if (data.size() < kFixedSize)
225 {
226 throw std::runtime_error("PNDCPHeader: insufficient data");
227 }
228 wire::Reader r(data);
229 PNDCPHeader h;
230 h.frameId = r.U16();
231 h.serviceId = r.U8();
232 h.serviceType = r.U8();
233 h.xId = r.U32();
234 h.respDelay = r.U16();
235 h.length = r.U16();
236 h.payload = r.ReadBytes(r.Remaining());
237 return h;
238 }
239
242 [[nodiscard]] Bytes ToBytes() const
243 {
244 Bytes out;
245 wire::PutU16(out, frameId);
248 wire::PutU32(out, xId);
250 wire::PutU16(out, length);
251 out.insert(out.end(), payload.begin(), payload.end());
252 return out;
253 }
254};
255
258{
260 std::string address;
261
263 std::string netmask;
264
266 std::string gateway;
267};
268
271{
273 std::uint8_t option = 0;
274
276 std::uint8_t suboption = 0;
277
279 std::uint16_t length = 0;
280
283
285 static constexpr std::size_t kFixedSize = 4;
286
290 static PNDCPBlockRequest Parse(const Bytes& data)
291 {
292 if (data.size() < kFixedSize)
293 {
294 throw std::runtime_error("PNDCPBlockRequest: insufficient data");
295 }
296 wire::Reader r(data);
298 b.option = r.U8();
299 b.suboption = r.U8();
300 b.length = r.U16();
301 std::size_t avail = r.Remaining();
302 b.payload = r.ReadBytes(std::min<std::size_t>(b.length, avail));
303 return b;
304 }
305
308 [[nodiscard]] Bytes ToBytes() const
309 {
310 Bytes out;
311 wire::PutU8(out, option);
313 wire::PutU16(out, length);
314 out.insert(out.end(), payload.begin(), payload.end());
315 return out;
316 }
317
321 [[nodiscard]] IPConfiguration ParseIp() const
322 {
323 const int defaultIPConfigurationBlockLength = 12; // 3 (ip,mask,gw) x4 = 12
324 if (payload.size() < defaultIPConfigurationBlockLength)
325 {
326 throw std::runtime_error("PNDCPBlockRequest: short IP payload");
327 }
328 const int ipAddressIndex = 0;
329 const int netmaskIndex = 4;
330 const int gatewayIndex = 8;
331 return {
332 .address = String2Ip(std::span(payload).subspan<ipAddressIndex, 4>()),
333 .netmask = String2Ip(std::span(payload).subspan<netmaskIndex, 4>()),
334 .gateway = String2Ip(std::span(payload).subspan<gatewayIndex, 4>())};
335 }
336};
337
342{
344 std::uint8_t option = 0;
345
347 std::uint8_t suboption = 0;
348
350 std::uint16_t length = 0;
351
353 std::uint16_t status = 0;
354
357
358 // NOLINTBEGIN(readability-identifier-naming)
360 static constexpr std::pair<std::uint8_t, std::uint8_t> IP_MAC{1, 1};
361
363 static constexpr std::pair<std::uint8_t, std::uint8_t> IP_ADDRESS{1, 2};
364
366 static constexpr std::pair<std::uint8_t, std::uint8_t> IP_FULL_SUITE{1, 3};
367
369 static constexpr std::pair<std::uint8_t, std::uint8_t> DEVICE_TYPE{2, 1};
370
372 static constexpr std::pair<std::uint8_t, std::uint8_t> NAME_OF_STATION{2, 2};
373
375 static constexpr std::pair<std::uint8_t, std::uint8_t> DEVICE_ID{2, 3};
376
378 static constexpr std::pair<std::uint8_t, std::uint8_t> DEVICE_ROLE{2, 4};
379
381 static constexpr std::pair<std::uint8_t, std::uint8_t> DEVICE_OPTIONS{2, 5};
382
384 static constexpr std::pair<std::uint8_t, std::uint8_t> DEVICE_ALIAS{2, 6};
385
387 static constexpr std::pair<std::uint8_t, std::uint8_t> DEVICE_INSTANCE{2, 7};
388
390 static constexpr std::pair<std::uint8_t, std::uint8_t> DEVICE_OEM_ID{2, 8};
391
393 static constexpr std::pair<std::uint8_t, std::uint8_t> ALL{0xFF, 0xFF};
394 // NOLINTEND(readability-identifier-naming)
395
397 static constexpr std::size_t kFixedSize = 6;
398
402 static PNDCPBlock Parse(const Bytes& data)
403 {
404 if (data.size() < kFixedSize)
405 {
406 throw std::runtime_error("PNDCPBlock: insufficient data");
407 }
408 wire::Reader r(data);
409 PNDCPBlock b;
410 b.option = r.U8();
411 b.suboption = r.U8();
412 b.length = r.U16();
413 b.status = r.U16();
414 // payload_size_field="length", payload_offset=-2: payload length is
415 // `length - 2` (the 2 bytes already consumed by `status`).
416 std::size_t plSize = b.length >= 2 ? static_cast<std::size_t>(b.length - 2) : 0;
417 std::size_t avail = r.Remaining();
418 b.payload = r.ReadBytes(std::min(plSize, avail));
419 return b;
420 }
421
424 [[nodiscard]] Bytes ToBytes() const
425 {
426 Bytes out;
427 wire::PutU8(out, option);
429 wire::PutU16(out, length);
430 wire::PutU16(out, status);
431 out.insert(out.end(), payload.begin(), payload.end());
432 return out;
433 }
434
438 [[nodiscard]] IPConfiguration ParseIp() const
439 {
440 const int defaultIPConfigurationBlockLength = 12; // 3 (ip,mask,gw) x4 = 12
441 if (payload.size() < defaultIPConfigurationBlockLength)
442 {
443 throw std::runtime_error("PNDCPBlock: short IP payload");
444 }
445 const int ipAddressIndex = 0;
446 const int netmaskIndex = 4;
447 const int gatewayIndex = 8;
448 return {
449 .address = String2Ip(std::span(payload).subspan<ipAddressIndex, 4>()),
450 .netmask = String2Ip(std::span(payload).subspan<netmaskIndex, 4>()),
451 .gateway = String2Ip(std::span(payload).subspan<gatewayIndex, 4>())};
452 }
453};
454
455// =============================================================================
456// DCE/RPC - Remote Procedure Call
457// =============================================================================
458
460inline constexpr std::array<std::uint8_t, 12> kPnUuidSuffix = {
461 0x6C, 0x97, 0x11, 0xD1, 0x82, 0x71, 0x00, 0xA0, 0x24, 0x42, 0xDF, 0x7D};
462
465{
466 // NOLINTBEGIN(readability-identifier-naming)
468 static constexpr std::uint8_t REQUEST = 0x00;
469
471 static constexpr std::uint8_t PING = 0x01;
472
474 static constexpr std::uint8_t RESPONSE = 0x02;
475
477 static constexpr std::uint8_t FAULT = 0x03;
478
480 static constexpr std::uint8_t WORKING = 0x04;
481
483 static constexpr std::uint8_t PONG = 0x05;
484
486 static constexpr std::uint8_t REJECT = 0x06;
487
489 static constexpr std::uint8_t ACK = 0x07;
490
492 static constexpr std::uint8_t CANCEL = 0x08;
493
495 static constexpr std::uint8_t FRAG_ACK = 0x09;
496
498 static constexpr std::uint8_t CANCEL_ACK = 0x0A;
499
501 static constexpr std::uint16_t CONNECT = 0x00;
502
504 static constexpr std::uint16_t RELEASE = 0x01;
505
507 static constexpr std::uint16_t READ = 0x02;
508
510 static constexpr std::uint16_t WRITE = 0x03;
511
513 static constexpr std::uint16_t CONTROL = 0x04;
514
516 static constexpr std::uint16_t IMPLICIT_READ = 0x05;
517
518 // NOLINTEND(readability-identifier-naming)
519
521 std::uint8_t version = 4;
522
524 std::uint8_t packetType = 0;
525
527 std::uint8_t flags1 = 0;
528
530 std::uint8_t flags2 = 0;
531
533 std::array<std::uint8_t, 3> dataRepresentation{};
534
536 std::uint8_t serialNrHigh = 0;
537
539 std::array<std::uint8_t, uuidLenght> objectUuid{};
540
542 std::array<std::uint8_t, uuidLenght> interfaceUuid{};
543
545 std::array<std::uint8_t, uuidLenght> activityUuid{};
546
548 std::uint32_t serverBootTime = 0;
549
551 std::uint32_t interfaceVersion = 1;
552
554 std::uint32_t sequenceNumber = 0;
555
557 std::uint16_t operationNumber = 0;
558
560 std::uint16_t interfaceHint = 0xFFFF;
561
563 std::uint16_t activityHint = 0xFFFF;
564
566 std::uint16_t lengthOfBody = 0;
567
569 std::uint16_t fragmentNumber = 0;
570
572 std::uint8_t authenticationProtocol = 0;
573
575 std::uint8_t serialNrLow = 0;
576
579
581 static constexpr std::size_t kFixedSize = 80;
582
585 static std::array<std::uint8_t, uuidLenght> IfaceUuidDevice()
586 {
587 return PrefixedUuid(0x00, 0x01);
588 }
589
592 static std::array<std::uint8_t, uuidLenght> IfaceUuidController()
593 {
594 return PrefixedUuid(0x00, 0x02);
595 }
596
599 static std::array<std::uint8_t, uuidLenght> IfaceUuidSupervisor()
600 {
601 return PrefixedUuid(0x00, 0x03);
602 }
603
606 static std::array<std::uint8_t, uuidLenght> IfaceUuidParamserver()
607 {
608 return PrefixedUuid(0x00, 0x04);
609 }
610
614 static PNRPCHeader Parse(const Bytes& data)
615 {
616 if (data.size() < kFixedSize)
617 {
618 throw std::runtime_error("PNRPCHeader: insufficient data");
619 }
620 wire::Reader r(data);
621 PNRPCHeader h;
622 h.version = r.U8();
623 h.packetType = r.U8();
624 h.flags1 = r.U8();
625 h.flags2 = r.U8();
626 h.dataRepresentation = r.Fixed<3>();
627 h.serialNrHigh = r.U8();
628 h.objectUuid = r.Fixed<uuidLenght>();
631 h.serverBootTime = r.U32();
632 h.interfaceVersion = r.U32();
633 h.sequenceNumber = r.U32();
634 h.operationNumber = r.U16();
635 h.interfaceHint = r.U16();
636 h.activityHint = r.U16();
637 h.lengthOfBody = r.U16();
638 h.fragmentNumber = r.U16();
640 h.serialNrLow = r.U8();
641 h.payload = r.ReadBytes(r.Remaining());
642 return h;
643 }
644
647 [[nodiscard]] Bytes ToBytes() const
648 {
649 Bytes out;
650 wire::PutU8(out, version);
652 wire::PutU8(out, flags1);
653 wire::PutU8(out, flags2);
669 out.insert(out.end(), payload.begin(), payload.end());
670 return out;
671 }
672
673 private:
678 static std::array<std::uint8_t, uuidLenght> PrefixedUuid(std::uint8_t b2, std::uint8_t b3)
679 {
680 std::array<std::uint8_t, uuidLenght> u{};
681 u[0] = 0xDE;
682 u[1] = 0xA0;
683 u[2] = b2;
684 u[3] = b3;
685 std::ranges::copy(kPnUuidSuffix, u.begin() + 4);
686 return u;
687 }
688};
689
695{
697 std::uint32_t argsMaximumStatus = 0;
698
700 std::uint32_t argsLength = 0;
701
703 std::uint32_t maximumCount = 0;
704
706 std::uint32_t offset = 0;
707
709 std::uint32_t actualCount = 0;
710
713
715 static constexpr std::size_t kFixedSize = 20;
716
720 static PNNRDData Parse(const Bytes& data)
721 {
722 if (data.size() < kFixedSize)
723 {
724 throw std::runtime_error("PNNRDData: insufficient data");
725 }
726 wire::Reader r(data);
727 PNNRDData d;
728 d.argsMaximumStatus = r.U32();
729 d.argsLength = r.U32();
730 d.maximumCount = r.U32();
731 d.offset = r.U32();
732 d.actualCount = r.U32();
733 // Some devices' actual_count doesn't exactly match the remaining
734 // bytes (padding, etc.); take whichever is smaller, matching the
735 // defensive slicing rpc.py relies on when parsing responses.
736 std::size_t take = std::min<std::size_t>(d.actualCount, r.Remaining());
737 d.payload = r.ReadBytes(take);
738 return d;
739 }
740
743 [[nodiscard]] Bytes ToBytes() const
744 {
745 Bytes out;
749 wire::PutU32(out, offset);
751 out.insert(out.end(), payload.begin(), payload.end());
752 return out;
753 }
754};
755
758{
760 std::array<std::uint8_t, blockHeaderLenght> blockHeader{};
761
763 std::uint16_t sequenceNumber = 0;
764
766 std::array<std::uint8_t, uuidLenght> arUuid{};
767
769 std::uint32_t api = 0;
770
772 std::uint16_t slot = 0;
773
775 std::uint16_t subslot = 0;
776
778 std::uint16_t padding1 = 0;
779
781 std::uint16_t index = 0;
782
784 std::uint32_t length = 0;
785
787 std::array<std::uint8_t, uuidLenght> targetArUuid{};
788
790 std::array<std::uint8_t, 8> padding2{};
791
794
796 static constexpr std::size_t kFixedSize = 64;
797
801 static PNIODHeader Parse(const Bytes& data)
802 {
803 if (data.size() < kFixedSize)
804 {
805 throw std::runtime_error("PNIODHeader: insufficient data");
806 }
807 wire::Reader r(data);
808 PNIODHeader h;
810 h.sequenceNumber = r.U16();
811 h.arUuid = r.Fixed<uuidLenght>();
812 h.api = r.U32();
813 h.slot = r.U16();
814 h.subslot = r.U16();
815 h.padding1 = r.U16();
816 h.index = r.U16();
817 h.length = r.U32();
819 h.padding2 = r.Fixed<8>();
820 h.payload = r.ReadBytes(r.Remaining());
821 return h;
822 }
823
826 [[nodiscard]] Bytes ToBytes() const
827 {
828 Bytes out;
832 wire::PutU32(out, api);
833 wire::PutU16(out, slot);
834 wire::PutU16(out, subslot);
836 wire::PutU16(out, index);
837 wire::PutU32(out, length);
840 out.insert(out.end(), payload.begin(), payload.end());
841 return out;
842 }
843};
844
846{
847 // NOLINTBEGIN(readability-identifier-naming)
851
853 static constexpr std::uint16_t IODReadResponseHeader = 0x8009;
854
856 static constexpr std::uint16_t InM0 = 0x0020;
857
859 static constexpr std::uint16_t InM0FilterDataSubModul = 0x0030;
860
862 static constexpr std::uint16_t InM0FilterDataModul = 0x0031;
863
865 static constexpr std::uint16_t InM0FilterDataDevice = 0x0032;
866
868 static constexpr std::uint16_t DEFAULT_BLOCK_LENGTH = 60;
869 // NOLINTEND(readability-identifier-naming)
870
873
875 std::uint16_t blockLength = 0;
876
878 std::uint8_t blockVersionHigh = 1;
879
881 std::uint8_t blockVersionLow = 0;
882
884 static constexpr std::size_t kSize = 6;
885
889 static PNBlockHeader Parse(const Bytes& data)
890 {
891 if (data.size() < kSize)
892 {
893 throw std::runtime_error("PNBlockHeader: insufficient data");
894 }
895 wire::Reader r(data);
897 h.blockType = static_cast<BlockType>(r.U16());
898 h.blockLength = r.U16();
899 h.blockVersionHigh = r.U8();
900 h.blockVersionLow = r.U8();
901 return h;
902 }
903
906 [[nodiscard]] Bytes ToBytes() const
907 {
908 Bytes out;
909 wire::PutU16(out, static_cast<std::uint16_t>(blockType));
913 return out;
914 }
915};
916
919{
921 std::array<std::uint8_t, blockHeaderLenght> blockHeader{};
922
924 std::uint16_t arType = 0;
925
927 std::array<std::uint8_t, uuidLenght> arUuid{};
928
930 std::uint16_t sessionKey = 0;
931
934
936 std::array<std::uint8_t, uuidLenght> cmInitiatorObjectUuid{};
937
939 std::uint32_t arProperties = 0;
940
943
945 std::uint16_t initiatorUdpRtport = 0;
946
948 std::uint16_t stationNameLength = 0;
949
952
955
957 static constexpr std::size_t kFixedSize = 58;
958
962 static PNARBlockRequest Parse(const Bytes& data)
963 {
964 if (data.size() < kFixedSize)
965 {
966 throw std::runtime_error("PNARBlockRequest: insufficient data");
967 }
968 wire::Reader r(data);
971 b.arType = r.U16();
972 b.arUuid = r.Fixed<uuidLenght>();
973 b.sessionKey = r.U16();
976 b.arProperties = r.U32();
978 b.initiatorUdpRtport = r.U16();
979 b.stationNameLength = r.U16();
980 b.cmInitiatorStationName = r.ReadBytes(std::min<std::size_t>(b.stationNameLength, r.Remaining()));
981 b.payload = r.ReadBytes(r.Remaining());
982 return b;
983 }
984
987 [[nodiscard]] Bytes ToBytes() const
988 {
989 Bytes out;
991 wire::PutU16(out, arType);
1000 out.insert(out.end(), cmInitiatorStationName.begin(), cmInitiatorStationName.end());
1001 out.insert(out.end(), payload.begin(), payload.end());
1002 return out;
1003 }
1004};
1005
1008{
1010 std::array<std::uint8_t, blockHeaderLenght> blockHeader{};
1011
1013 std::uint16_t padding1 = 0;
1014
1016 std::array<std::uint8_t, uuidLenght> arUuid{};
1017
1019 std::uint16_t sessionKey = 0;
1020
1022 std::uint16_t padding2 = 0;
1023
1026
1028 std::uint16_t controlBlockProperties = 0;
1029
1031 static constexpr std::size_t kSize = 32;
1032
1036 static PNIODReleaseBlock Parse(const Bytes& data)
1037 {
1038 if (data.size() < kSize)
1039 {
1040 throw std::runtime_error("PNIODReleaseBlock: insufficient data");
1041 }
1042 wire::Reader r(data);
1045 b.padding1 = r.U16();
1046 b.arUuid = r.Fixed<uuidLenght>();
1047 b.sessionKey = r.U16();
1048 b.padding2 = r.U16();
1049 b.controlCommand = static_cast<ControlCommand>(r.U16());
1051 return b;
1052 }
1053
1056 [[nodiscard]] Bytes ToBytes() const
1057 {
1058 Bytes out;
1060 wire::PutU16(out, padding1);
1061 wire::PutFixed(out, arUuid);
1063 wire::PutU16(out, padding2);
1064 wire::PutU16(out, static_cast<std::uint16_t>(controlCommand));
1066 return out;
1067 }
1068};
1069
1070// =============================================================================
1071// I&M (Identification & Maintenance) Data
1072// =============================================================================
1073
1076{
1077 // NOLINTBEGIN(readability-identifier-naming)
1079 static constexpr std::uint16_t IDX = 0xAFF0;
1080 // NOLINTEND(readability-identifier-naming)
1081
1083 std::array<std::uint8_t, blockHeaderLenght> blockHeader{};
1084
1086 std::uint8_t vendorIdHigh = 0;
1087
1089 std::uint8_t vendorIdLow = 0;
1090
1092 std::string orderId;
1093
1095 std::string imSerialNumber;
1096
1098 std::uint16_t imHardwareRevision = 0;
1099
1101 std::uint8_t swRevisionPrefix = 0;
1102
1105
1107 std::uint8_t imSwRevisionBugFix = 0;
1108
1111
1113 std::uint16_t imRevisionCounter = 0;
1114
1116 std::uint16_t imProfileId = 0;
1117
1119 std::uint16_t imProfileSpecificType = 0;
1120
1122 std::uint16_t imVersion = 0;
1123
1125 std::uint16_t imSupported = 0;
1126
1128 static constexpr std::size_t kSize = 60;
1129
1132 [[nodiscard]] std::uint16_t VendorId() const
1133 {
1134 return static_cast<std::uint16_t>((vendorIdHigh << OneOctetShift) | vendorIdLow);
1135 }
1136
1140 static PNInM0 Parse(const Bytes& data)
1141 {
1142 if (data.size() < kSize)
1143 {
1144 throw std::runtime_error("PNInM0: insufficient data");
1145 }
1146 wire::Reader r(data);
1147 PNInM0 v;
1149 v.vendorIdHigh = r.U8();
1150 v.vendorIdLow = r.U8();
1151 auto oid = r.ReadBytes(20);
1152 v.orderId = DecodeBytes(oid);
1153 auto sn = r.ReadBytes(16);
1155 v.imHardwareRevision = r.U16();
1156 v.swRevisionPrefix = r.U8();
1158 v.imSwRevisionBugFix = r.U8();
1160 v.imRevisionCounter = r.U16();
1161 v.imProfileId = r.U16();
1162 v.imProfileSpecificType = r.U16();
1163 v.imVersion = r.U16();
1164 v.imSupported = r.U16();
1165 return v;
1166 }
1167
1173 bool operator==(const PNInM0&) const = default;
1174};
1175
1178{
1179 // NOLINTBEGIN(readability-identifier-naming)
1181 static constexpr std::uint16_t IDX = 0xAFF1;
1182 // NOLINTEND(readability-identifier-naming)
1183
1185 std::array<std::uint8_t, blockHeaderLenght> blockHeader{};
1186
1188 std::string imTagFunction;
1189
1191 std::string imTagLocation;
1192
1194 static constexpr std::size_t kSize = 60;
1195
1199 static PNInM1 Parse(const Bytes& data)
1200 {
1201 if (data.size() < kSize)
1202 {
1203 throw std::runtime_error("PNInM1: insufficient data");
1204 }
1205 wire::Reader r(data);
1206 PNInM1 v;
1210 return v;
1211 }
1217 bool operator==(const PNInM1&) const = default;
1218};
1219
1222{
1223 // NOLINTBEGIN(readability-identifier-naming)
1225 static constexpr std::uint16_t IDX = 0xAFF2;
1226 // NOLINTEND(readability-identifier-naming)
1227
1229 std::array<std::uint8_t, blockHeaderLenght> blockHeader{};
1230
1232 std::string imDate;
1233
1235 static constexpr std::size_t kSize = 22;
1236
1240 static PNInM2 Parse(const Bytes& data)
1241 {
1242 if (data.size() < kSize)
1243 {
1244 throw std::runtime_error("PNInM2: insufficient data");
1245 }
1246 wire::Reader r(data);
1247 PNInM2 v;
1249 v.imDate = DecodeBytes(r.ReadBytes(16));
1250 return v;
1251 }
1252
1258 bool operator==(const PNInM2&) const = default;
1259};
1260
1263{
1264 // NOLINTBEGIN(readability-identifier-naming)
1266 static constexpr std::uint16_t IDX = 0xAFF3;
1267 // NOLINTEND(readability-identifier-naming)
1268
1270 std::array<std::uint8_t, blockHeaderLenght> blockHeader{};
1271
1273 std::string imDescriptor;
1274
1276 static constexpr std::size_t kSize = 60;
1277
1281 static PNInM3 Parse(const Bytes& data)
1282 {
1283 if (data.size() < kSize)
1284 {
1285 throw std::runtime_error("PNInM3: insufficient data");
1286 }
1287 wire::Reader r(data);
1288 PNInM3 v;
1291 return v;
1292 }
1298 bool operator==(const PNInM3&) const = default;
1299};
1300
1303{
1304 // NOLINTBEGIN(readability-identifier-naming)
1306 static constexpr std::uint16_t IDX = 0xAFF4;
1307 // NOLINTEND(readability-identifier-naming)
1308
1310 std::array<std::uint8_t, blockHeaderLenght> blockHeader{};
1311
1313 std::array<std::uint8_t, 54> imSignature{};
1314
1316 static constexpr std::size_t kSize = 60;
1317
1321 static PNInM4 Parse(const Bytes& data)
1322 {
1323 if (data.size() < kSize)
1324 {
1325 throw std::runtime_error("PNInM4: insufficient data");
1326 }
1327 wire::Reader r(data);
1328 PNInM4 v;
1330 v.imSignature = r.Fixed<54>();
1331 return v;
1332 }
1338 bool operator==(const PNInM4&) const = default;
1339};
1340
1343{
1344 // NOLINTBEGIN(readability-identifier-naming)
1346 static constexpr std::uint16_t IDX = 0xAFF5;
1347 // NOLINTEND(readability-identifier-naming)
1348
1350 std::array<std::uint8_t, blockHeaderLenght> blockHeader{};
1351
1353 std::string imAnnotation;
1354
1356 static constexpr std::size_t kSize = 70;
1357
1361 static PNInM5 Parse(const Bytes& data)
1362 {
1363 if (data.size() < kSize)
1364 {
1365 throw std::runtime_error("PNInM5: insufficient data");
1366 }
1367 wire::Reader r(data);
1368 PNInM5 v;
1371 return v;
1372 }
1378 bool operator==(const PNInM5&) const = default;
1379};
1380
1385template <std::uint16_t Idx>
1387{
1388 // NOLINTBEGIN(readability-identifier-naming)
1390 static constexpr std::uint16_t IDX = Idx;
1391 // NOLINTEND(readability-identifier-naming)
1392
1394 std::array<std::uint8_t, blockHeaderLenght> blockHeader{};
1395
1398
1402 static PNInMReserved Parse(const Bytes& data)
1403 {
1404 if (data.size() < 6)
1405 {
1406 throw std::runtime_error("PNInMReserved: insufficient data");
1407 }
1408 wire::Reader r(data);
1409 PNInMReserved v;
1411 v.payload = r.ReadBytes(r.Remaining());
1412 return v;
1413 }
1414
1420 bool operator==(const PNInMReserved&) const = default;
1421};
1422
1443
1444// =============================================================================
1445// IOCR (IO Connection Relationship) Blocks
1446// =============================================================================
1447
1450{
1452 std::uint16_t slotNumber = 0;
1453
1455 std::uint16_t subslotNumber = 0;
1456
1458 std::uint16_t frameOffset = 0;
1459
1461 static constexpr std::size_t kSize = 6;
1462
1466 static IOCRAPIObject Parse(const Bytes& data)
1467 {
1468 if (data.size() < kSize)
1469 {
1470 throw std::runtime_error("IOCRAPIObject: insufficient data");
1471 }
1472 wire::Reader r(data);
1473 IOCRAPIObject o;
1474 o.slotNumber = r.U16();
1475 o.subslotNumber = r.U16();
1476 o.frameOffset = r.U16();
1477 return o;
1478 }
1479
1482 [[nodiscard]] Bytes ToBytes() const
1483 {
1484 Bytes out;
1488 return out;
1489 }
1490};
1491
1494{
1495 // NOLINTBEGIN(readability-identifier-naming)
1497 static constexpr std::uint16_t BLOCK_TYPE = 0x8102;
1498 // NOLINTEND(readability-identifier-naming)
1499
1501 std::array<std::uint8_t, blockHeaderLenght> blockHeader{};
1502
1504 std::uint16_t iocrType = 0;
1505
1507 std::uint16_t iocrReference = 0;
1508
1510 std::uint16_t frameId = 0;
1511
1513 static constexpr std::size_t kSize = 12;
1514
1518 static PNIOCRBlockRes Parse(const Bytes& data)
1519 {
1520 if (data.size() < kSize)
1521 {
1522 throw std::runtime_error("PNIOCRBlockRes: insufficient data");
1523 }
1524 wire::Reader r(data);
1527 b.iocrType = r.U16();
1528 b.iocrReference = r.U16();
1529 b.frameId = r.U16();
1530 return b;
1531 }
1532};
1533
1538{
1539 // NOLINTBEGIN(readability-identifier-naming)
1542 // NOLINTEND(readability-identifier-naming)
1543
1545 std::array<std::uint8_t, blockHeaderLenght> blockHeader{};
1546
1548 std::uint16_t iocrType = 0;
1549
1551 std::uint16_t iocrReference = 0;
1552
1555
1557 std::uint32_t iocrProperties = 0;
1558
1560 std::uint16_t dataLength = 0;
1561
1563 std::uint16_t frameId = 0;
1564
1566 std::uint16_t sendClockFactor = 32;
1567
1569 std::uint16_t reductionRatio = 1;
1570
1572 std::uint16_t phase = 1;
1573
1575 std::uint16_t sequence = 0;
1576
1578 std::uint32_t frameSendOffset = 0;
1579
1581 std::uint16_t watchdogFactor = 3;
1582
1584 std::uint16_t dataHoldFactor = 3;
1585
1587 std::uint16_t iocrTagHeader = 0xC000;
1588
1591
1593 std::uint16_t numberOfApis = 1;
1594
1596 static constexpr std::size_t kSize = 46;
1597
1602 [[nodiscard]] static PNIOCRBlockReqHeader Parse(const Bytes& data)
1603 {
1604 if (data.size() < kSize)
1605 {
1606 throw std::runtime_error(
1607 "IOCRBlockReq too short, insufficient data: " +
1608 std::to_string(data.size()) +
1609 " bytes, expected at least " +
1610 std::to_string(kSize));
1611 }
1612
1613 wire::Reader r(data);
1615
1617 b.iocrType = r.U16();
1618 b.iocrReference = r.U16();
1619 b.etherTypeLT = r.U16();
1620 b.iocrProperties = r.U32();
1621 b.dataLength = r.U16();
1622 b.frameId = r.U16();
1623 b.sendClockFactor = r.U16();
1624 b.reductionRatio = r.U16();
1625 b.phase = r.U16();
1626 b.sequence = r.U16();
1627 b.frameSendOffset = r.U32();
1628 b.watchdogFactor = r.U16();
1629 b.dataHoldFactor = r.U16();
1630 b.iocrTagHeader = r.U16();
1632 b.numberOfApis = r.U16();
1633
1634 return b;
1635 }
1636
1639 [[nodiscard]] Bytes ToBytes() const
1640 {
1641 Bytes out;
1643 wire::PutU16(out, iocrType);
1648 wire::PutU16(out, frameId);
1651 wire::PutU16(out, phase);
1652 wire::PutU16(out, sequence);
1659 return out;
1660 }
1661};
1662
1663// =============================================================================
1664// AlarmCR (Alarm Connection Relationship) Blocks
1665// =============================================================================
1666
1669{
1670 // NOLINTBEGIN(readability-identifier-naming)
1673
1675 static constexpr std::uint16_t DEFAULT_RTA_TIMEOUT_FACTOR = 1;
1676
1678 static constexpr std::uint16_t DEFAULT_RTA_RETRIES = 3;
1679
1681 static constexpr std::uint16_t DEFAULT_MAX_ALARM_DATA_LENGTH = 200;
1682
1684 static constexpr std::uint16_t DEFAULT_TAG_HEADER_HIGH = 0xC000;
1685
1687 static constexpr std::uint16_t DEFAULT_TAG_HEADER_LOW = 0xA000;
1688 // NOLINTEND(readability-identifier-naming)
1689
1691 std::array<std::uint8_t, blockHeaderLenght> blockHeader{};
1692
1694 std::uint16_t alarmCrType = 1;
1695
1697 std::uint16_t etherTypeLT = 0x8892;
1698
1700 std::uint32_t alarmCrProperties = 0;
1701
1704
1707
1709 std::uint16_t localAlarmReference = 0;
1710
1713
1716
1719
1721 static constexpr std::size_t kSize = 26;
1722
1725 [[nodiscard]] Bytes ToBytes() const
1726 {
1727 Bytes out;
1738 return out;
1739 }
1740};
1741
1744{
1745 // NOLINTBEGIN(readability-identifier-naming)
1747 static constexpr std::uint16_t BLOCK_TYPE = 0x8103;
1748 // NOLINTEND(readability-identifier-naming)
1749
1751 std::array<std::uint8_t, blockHeaderLenght> blockHeader{};
1752
1754 std::uint16_t alarmCrType = 0;
1755
1757 std::uint16_t localAlarmReference = 0;
1758
1760 std::uint16_t maxAlarmDataLength = 0;
1761
1763 static constexpr std::size_t kSize = 12;
1764
1768 static PNAlarmCRBlockRes Parse(const Bytes& data)
1769 {
1770 if (data.size() < kSize)
1771 {
1772 throw std::runtime_error("PNAlarmCRBlockRes: insufficient data");
1773 }
1774 wire::Reader r(data);
1777 b.alarmCrType = r.U16();
1778 b.localAlarmReference = r.U16();
1779 b.maxAlarmDataLength = r.U16();
1780 return b;
1781 }
1782};
1783
1784// =============================================================================
1785// Alarm Notification PDUs
1786// =============================================================================
1787
1790{
1791 // NOLINTBEGIN(readability-identifier-naming)
1793 static constexpr std::uint16_t BLOCK_ALARM_HIGH = 0x0001;
1794
1796 static constexpr std::uint16_t BLOCK_ALARM_LOW = 0x0002;
1797
1799 static constexpr std::uint16_t BLOCK_ALARM_ACK_HIGH = 0x8001;
1800
1802 static constexpr std::uint16_t BLOCK_ALARM_ACK_LOW = 0x8002;
1803 // NOLINTEND(readability-identifier-naming)
1804
1806 std::array<std::uint8_t, blockHeaderLenght> blockHeader{};
1807
1809 std::uint16_t alarmType = 0;
1810
1812 std::uint32_t api = 0;
1813
1815 std::uint16_t slotNumber = 0;
1816
1818 std::uint16_t subslotNumber = 0;
1819
1821 std::uint32_t moduleIdentNumber = 0;
1822
1824 std::uint32_t submoduleIdentNumber = 0;
1825
1827 std::uint16_t alarmSpecifier = 0;
1828
1831
1833 static constexpr std::size_t kFixedSize = 26;
1834
1839 {
1840 if (data.size() < kFixedSize)
1841 {
1842 throw std::runtime_error("PNAlarmNotificationPDU: insufficient data");
1843 }
1844 wire::Reader r(data);
1847 p.alarmType = r.U16();
1848 p.api = r.U32();
1849 p.slotNumber = r.U16();
1850 p.subslotNumber = r.U16();
1851 p.moduleIdentNumber = r.U32();
1852 p.submoduleIdentNumber = r.U32();
1853 p.alarmSpecifier = r.U16();
1854 p.payload = r.ReadBytes(r.Remaining());
1855 return p;
1856 }
1857};
1858
1861{
1863 std::array<std::uint8_t, blockHeaderLenght> blockHeader{};
1864
1867
1869 std::uint32_t api = 0;
1870
1872 std::uint16_t slotNumber = 0;
1873
1875 std::uint16_t subslotNumber = 0;
1876
1878 std::uint16_t alarmSpecifier = 0;
1879
1881 std::uint32_t statusPNIO = 0;
1882
1884 static constexpr std::size_t kSize = 22;
1885
1888 [[nodiscard]] Bytes ToBytes() const
1889 {
1890 Bytes out;
1892 wire::PutU16(out, static_cast<std::uint16_t>(alarmType));
1893 wire::PutU32(out, api);
1898 return out;
1899 }
1900};
1901
1904{
1905 // NOLINTBEGIN(readability-identifier-naming)
1907 static constexpr std::uint8_t RTA_TYPE_DATA = 0x01;
1908
1910 static constexpr std::uint8_t RTA_TYPE_NACK = 0x02;
1911
1913 static constexpr std::uint8_t RTA_TYPE_ACK = 0x03;
1914
1916 static constexpr std::uint8_t RTA_TYPE_ERR = 0x04;
1917
1919 static constexpr std::uint8_t VERSION_1 = 0x01;
1920
1922 static constexpr std::uint8_t VERSION_2 = 0x02;
1923
1925 static constexpr std::uint8_t ADD_FLAGS_WINDOW_1 = 0x01;
1926
1928 static constexpr std::uint8_t ADD_FLAGS_TACK = 0x10;
1929
1930 // NOLINTEND(readability-identifier-naming)
1931
1933 std::uint16_t alarmDstEndpoint = 0;
1934
1936 std::uint16_t alarmSrcEndpoint = 0;
1937
1939 std::uint8_t pduType = 0;
1940
1942 std::uint8_t addFlags = 0;
1943
1945 std::uint16_t sendSeqNum = 0;
1946
1948 std::uint16_t ackSeqNum = 0;
1949
1951 std::uint16_t variablePartLenght = 0;
1952
1955
1957 static constexpr std::size_t kFixedSize = 12;
1958
1962 static PNRTAHeader Parse(const Bytes& data)
1963 {
1964 if (data.size() < kFixedSize)
1965 {
1966 throw std::runtime_error("PNRTAHeader: insufficient data");
1967 }
1968 wire::Reader r(data);
1969 PNRTAHeader h;
1970 h.alarmDstEndpoint = r.U16();
1971 h.alarmSrcEndpoint = r.U16();
1972 h.pduType = r.U8();
1973 h.addFlags = r.U8();
1974 h.sendSeqNum = r.U16();
1975 h.ackSeqNum = r.U16();
1976 h.variablePartLenght = r.U16();
1977 h.payload = r.ReadBytes(r.Remaining());
1978 return h;
1979 }
1980
1983 [[nodiscard]] Bytes ToBytes() const
1984 {
1985 Bytes out;
1988 wire::PutU8(out, pduType);
1989 wire::PutU8(out, addFlags);
1991 wire::PutU16(out, ackSeqNum);
1993 out.insert(out.end(), payload.begin(), payload.end());
1994 return out;
1995 }
1996};
1997
1998// =============================================================================
1999// ExpectedSubmodule Blocks (0x0104)
2000// =============================================================================
2001
2004{
2006 std::uint16_t dataDescription = 0;
2007
2009 std::uint16_t submoduleDataLength = 0;
2010
2012 std::uint8_t lengthIocs = 0;
2013
2015 std::uint8_t lengthIops = 0;
2016
2018 static constexpr std::size_t kSize = 6;
2019
2022 [[nodiscard]] Bytes ToBytes() const
2023 {
2024 Bytes out;
2027 wire::PutU8(out, lengthIocs);
2028 wire::PutU8(out, lengthIops);
2029 return out;
2030 }
2031};
2032
2033// =============================================================================
2034// IOD Write/Read Request Blocks
2035// =============================================================================
2036
2039{
2040 // NOLINTBEGIN(readability-identifier-naming)
2042 static constexpr std::uint16_t BLOCK_TYPE = 0x0008;
2043 // NOLINTEND(readability-identifier-naming)
2044
2046 std::array<std::uint8_t, blockHeaderLenght> blockHeader{};
2047
2049 std::uint16_t seqNum = 0;
2050
2052 std::array<std::uint8_t, uuidLenght> arUuid{};
2053
2055 std::uint32_t api = 0;
2056
2058 std::uint16_t slot = 0;
2059
2061 std::uint16_t subslot = 0;
2062
2064 std::uint16_t padding = 0;
2065
2067 std::uint16_t index = 0;
2068
2070 std::uint32_t recordDataLength = 0;
2071
2073 std::array<std::uint8_t, 24> rwPadding{};
2074
2077
2079 static constexpr std::size_t kFixedSize = 64;
2080
2083 [[nodiscard]] Bytes ToBytes() const
2084 {
2085 Bytes out;
2087 wire::PutU16(out, seqNum);
2088 wire::PutFixed(out, arUuid);
2089 wire::PutU32(out, api);
2090 wire::PutU16(out, slot);
2091 wire::PutU16(out, subslot);
2092 wire::PutU16(out, padding);
2093 wire::PutU16(out, index);
2096 out.insert(out.end(), payload.begin(), payload.end());
2097 return out;
2098 }
2099};
2100
2103{
2104 // NOLINTBEGIN(readability-identifier-naming)
2106 static constexpr std::uint16_t BLOCK_TYPE = 0x8008;
2107 // NOLINTEND(readability-identifier-naming)
2108
2110 std::array<std::uint8_t, blockHeaderLenght> blockHeader{};
2111
2113 std::uint16_t seqNum = 0;
2114
2116 std::array<std::uint8_t, uuidLenght> arUuid{};
2117
2119 std::uint32_t api = 0;
2120
2122 std::uint16_t slot = 0;
2123
2125 std::uint16_t subslot = 0;
2126
2128 std::uint16_t padding = 0;
2129
2131 std::uint16_t index = 0;
2132
2134 std::uint32_t recordDataLength = 0;
2135
2137 std::uint16_t additionalValue1 = 0;
2138
2140 std::uint16_t additionalValue2 = 0;
2141
2143 std::uint32_t status = 0;
2144
2146 std::array<std::uint8_t, 16> rwPadding{};
2147
2149 static constexpr std::size_t kSize = 64;
2150
2154 static PNIODWriteRes Parse(const Bytes& data)
2155 {
2156 if (data.size() < kSize)
2157 {
2158 throw std::runtime_error("PNIODWriteRes: insufficient data");
2159 }
2160 wire::Reader r(data);
2161 PNIODWriteRes b;
2163 b.seqNum = r.U16();
2164 b.arUuid = r.Fixed<uuidLenght>();
2165 b.api = r.U32();
2166 b.slot = r.U16();
2167 b.subslot = r.U16();
2168 b.padding = r.U16();
2169 b.index = r.U16();
2170 b.recordDataLength = r.U32();
2171 b.additionalValue1 = r.U16();
2172 b.additionalValue2 = r.U16();
2173 b.status = r.U32();
2174 b.rwPadding = r.Fixed<16>();
2175 return b;
2176 }
2177};
2178
2179} // namespace profinet
Lightweight cursor for parsing a big-endian byte buffer without copies.
Definition wire.h:67
std::uint8_t U8()
Read and consume one byte.
Definition wire.h:125
std::uint32_t U32()
Read and consume a big-endian 32-bit value.
Definition wire.h:143
std::size_t Remaining() const
Number of bytes not yet consumed.
Definition wire.h:93
std::array< std::uint8_t, N > Fixed()
Read and consume a fixed-size byte array.
Definition wire.h:169
std::vector< std::uint8_t > ReadBytes(std::size_t n)
Read and consume a variable-length byte range.
Definition wire.h:157
std::uint16_t U16()
Read and consume a big-endian 16-bit value.
Definition wire.h:133
PROFINET record-data indices, block types, and protocol enumerations.
void PutU16(std::vector< std::uint8_t > &out, std::uint16_t v)
Append a 16-bit value to a buffer in big-endian order.
Definition wire.h:27
void PutU8(std::vector< std::uint8_t > &out, std::uint8_t v)
Append a single byte to a buffer.
Definition wire.h:19
void PutU32(std::vector< std::uint8_t > &out, std::uint32_t v)
Append a 32-bit value to a buffer in big-endian order.
Definition wire.h:36
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:58
BlockType
PROFINET block types.
Definition indices.h:91
@ IoCrRequest
IOCR block request.
@ Unknown
Unknown / Initialize value.
@ AlarmCrRequest
AlarmCR block request.
@ IoDataReadRequest
IOD read request block.
constexpr int uuidLenght
Constant lenght of a UUID.
Definition util.h:44
std::string String2Ip(std::span< const std::uint8_t > ipBytes)
Format raw IPv4 address bytes as a dotted string.
Definition util.cpp:214
std::array< std::uint8_t, macAddressLength > MacAddress
A 6-byte Ethernet MAC address.
Definition util.h:67
AlarmType
PROFINET Alarm Types used in AlarmNotification blocks.
Definition indices.h:344
@ Unknown
Unkown alarm.
ControlCommand
PROFINET IOD control command values.
Definition indices.h:60
@ Unknown
Unknown / Initialize value.
static constexpr int OneOctetShift
The bit-shift distance required to move data across a single octet.
Definition util.h:50
constexpr int macAddressLength
Constant lenght of a mac address.
Definition util.h:41
constexpr std::uint16_t PROFINET_ETHERTYPE
EtherType value identifying PROFINET frames (0x8892).
Definition util.h:32
std::vector< std::uint8_t > Bytes
Generic byte buffer alias used throughout the library for raw wire data.
Definition protocol.h:52
constexpr int blockHeaderLenght
Constant lenght of a blockHeader.
Definition protocol.h:55
constexpr std::array< std::uint8_t, 12 > kPnUuidSuffix
PROFINET UUID suffix, shared by all interface/object UUIDs.
Definition protocol.h:460
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:247
Plain (untagged) Ethernet II frame header.
Definition protocol.h:63
MacAddress src
Source MAC address.
Definition protocol.h:68
std::uint16_t type
EtherType field.
Definition protocol.h:71
static EthernetHeader Parse(const Bytes &data)
Parse an Ethernet header and payload from raw frame bytes.
Definition protocol.h:79
Bytes ToBytes() const
Serialize this header and its payload back to raw frame bytes.
Definition protocol.h:97
MacAddress dst
Destination MAC address.
Definition protocol.h:65
Bytes payload
Frame payload following the header.
Definition protocol.h:74
802.1Q VLAN-tagged Ethernet II frame header.
Definition protocol.h:110
Bytes ToBytes() const
Serialize this header and its payload back to raw frame bytes.
Definition protocol.h:153
std::uint16_t tPid
Tag Protocol Identifier (0x8100 for 802.1Q).
Definition protocol.h:118
MacAddress dst
Destination MAC address.
Definition protocol.h:112
Bytes payload
Frame payload following the header.
Definition protocol.h:127
static EthernetVLANHeader Parse(const Bytes &data)
Parse a VLAN-tagged Ethernet header and payload from raw frame bytes.
Definition protocol.h:132
std::uint16_t tCI
Tag Control Information (priority, DEI, VLAN ID).
Definition protocol.h:121
MacAddress src
Source MAC address.
Definition protocol.h:115
std::uint16_t type
Inner EtherType field.
Definition protocol.h:124
One slot/subslot's placement within an IOCR's cyclic data frame.
Definition protocol.h:1450
std::uint16_t frameOffset
Byte offset of this object's data within the cyclic frame.
Definition protocol.h:1458
std::uint16_t subslotNumber
Subslot number.
Definition protocol.h:1455
static constexpr std::size_t kSize
Size in bytes of this object.
Definition protocol.h:1461
Bytes ToBytes() const
Serialize this object back to raw bytes.
Definition protocol.h:1482
std::uint16_t slotNumber
Slot number.
Definition protocol.h:1452
static IOCRAPIObject Parse(const Bytes &data)
Parse an IOCR API object from raw bytes.
Definition protocol.h:1466
Decoded IPv4 address/netmask/gateway triple.
Definition protocol.h:258
std::string gateway
IPv4 default gateway.
Definition protocol.h:266
std::string netmask
IPv4 subnet mask, e.g. "255.255.255.0".
Definition protocol.h:263
std::string address
IPv4 address, e.g. "192.168.1.1".
Definition protocol.h:260
ARBlockReq: establishes an Application Relationship (sent in the CONNECT request).
Definition protocol.h:919
std::array< std::uint8_t, blockHeaderLenght > blockHeader
Nested 6-byte block header.
Definition protocol.h:921
static PNARBlockRequest Parse(const Bytes &data)
Parse an ARBlockReq from raw bytes.
Definition protocol.h:962
std::uint32_t arProperties
AR property flags (supervisor takeover, device access, etc.).
Definition protocol.h:939
std::uint16_t cmInitiatorActivityTimeoutFactor
Activity timeout factor for the initiator.
Definition protocol.h:942
MacAddress cmInitiatorMacAddress
MAC address of the initiating controller.
Definition protocol.h:933
std::uint16_t sessionKey
Session key chosen by the initiator.
Definition protocol.h:930
std::array< std::uint8_t, uuidLenght > arUuid
Unique AR UUID chosen by the initiator (controller).
Definition protocol.h:927
Bytes cmInitiatorStationName
Station name of the initiating controller (variable length).
Definition protocol.h:951
Bytes ToBytes() const
Serialize this block back to raw bytes.
Definition protocol.h:987
Bytes payload
Additional blocks following this one (IOCR/AlarmCR/ExpectedSubmodule).
Definition protocol.h:954
std::uint16_t arType
AR type (e.g. IOCARSingle, IOSAR).
Definition protocol.h:924
std::uint16_t initiatorUdpRtport
UDP port the initiator uses for real-time data.
Definition protocol.h:945
static constexpr std::size_t kFixedSize
Size in bytes of the fixed portion of this block.
Definition protocol.h:957
std::array< std::uint8_t, uuidLenght > cmInitiatorObjectUuid
Object UUID of the initiating controller.
Definition protocol.h:936
std::uint16_t stationNameLength
Length in bytes of CmInitiatorStationName.
Definition protocol.h:948
AlarmAck-PDU: acknowledges receipt of an AlarmNotification-PDU.
Definition protocol.h:1861
std::uint16_t alarmSpecifier
Alarm specifier flags echoed from the notification.
Definition protocol.h:1878
AlarmType alarmType
Alarm type being acknowledged.
Definition protocol.h:1866
std::uint16_t slotNumber
Slot number being acknowledged.
Definition protocol.h:1872
std::uint32_t statusPNIO
PNIO status code (0 = acknowledged OK).
Definition protocol.h:1881
std::uint16_t subslotNumber
Subslot number being acknowledged.
Definition protocol.h:1875
static constexpr std::size_t kSize
Size in bytes of this PDU.
Definition protocol.h:1884
std::array< std::uint8_t, blockHeaderLenght > blockHeader
Nested 6-byte block header.
Definition protocol.h:1863
std::uint32_t api
API number.
Definition protocol.h:1869
Bytes ToBytes() const
Serialize this PDU back to raw bytes.
Definition protocol.h:1888
AlarmCRBlockReq: requests establishment of the alarm connection (part of the CONNECT request).
Definition protocol.h:1669
static constexpr std::uint16_t DEFAULT_MAX_ALARM_DATA_LENGTH
Default maximum alarm data length in bytes.
Definition protocol.h:1681
std::array< std::uint8_t, blockHeaderLenght > blockHeader
Nested 6-byte block header.
Definition protocol.h:1691
static constexpr std::uint16_t DEFAULT_TAG_HEADER_LOW
Default low word of the alarm VLAN tag header.
Definition protocol.h:1687
static constexpr BlockType BLOCK_TYPE
Block type identifier for AlarmCRBlockReq.
Definition protocol.h:1672
Bytes ToBytes() const
Serialize this block back to raw bytes.
Definition protocol.h:1725
static constexpr std::uint16_t DEFAULT_TAG_HEADER_HIGH
Default high word of the alarm VLAN tag header.
Definition protocol.h:1684
std::uint16_t alarmCrType
Alarm CR type (always 1: Alarm).
Definition protocol.h:1694
std::uint16_t etherTypeLT
EtherType used for alarm frames (0x8892).
Definition protocol.h:1697
std::uint32_t alarmCrProperties
Alarm CR property flags (transport, priority).
Definition protocol.h:1700
static constexpr std::size_t kSize
Size in bytes of this block.
Definition protocol.h:1721
static constexpr std::uint16_t DEFAULT_RTA_RETRIES
Default number of RTA retries.
Definition protocol.h:1678
std::uint16_t localAlarmReference
Local alarm reference chosen by the controller.
Definition protocol.h:1709
std::uint16_t alarmCrTagHeaderHigh
High word of the alarm VLAN tag header.
Definition protocol.h:1715
std::uint16_t maxAlarmDataLength
Maximum alarm data length in bytes.
Definition protocol.h:1712
std::uint16_t alarmCrTagHeaderLow
Low word of the alarm VLAN tag header.
Definition protocol.h:1718
std::uint16_t rtaRetries
Number of RTA retransmission attempts.
Definition protocol.h:1706
std::uint16_t rtaTimeoutFactor
RTA (real-time acyclic) retransmission timeout factor.
Definition protocol.h:1703
static constexpr std::uint16_t DEFAULT_RTA_TIMEOUT_FACTOR
Default RTA timeout factor.
Definition protocol.h:1675
AlarmCRBlockRes: device's response confirming the alarm connection (part of the CONNECT response).
Definition protocol.h:1744
std::uint16_t alarmCrType
Alarm CR type (always 1: Alarm).
Definition protocol.h:1754
static constexpr std::uint16_t BLOCK_TYPE
Block type identifier for AlarmCRBlockRes.
Definition protocol.h:1747
std::array< std::uint8_t, blockHeaderLenght > blockHeader
Nested 6-byte block header.
Definition protocol.h:1751
std::uint16_t maxAlarmDataLength
Maximum alarm data length in bytes accepted by the device.
Definition protocol.h:1760
static constexpr std::size_t kSize
Size in bytes of this block.
Definition protocol.h:1763
std::uint16_t localAlarmReference
Local alarm reference assigned by the device.
Definition protocol.h:1757
static PNAlarmCRBlockRes Parse(const Bytes &data)
Parse an AlarmCRBlockRes from raw bytes.
Definition protocol.h:1768
AlarmNotification-PDU: carries a diagnosis/process/pull/plug/... alarm event.
Definition protocol.h:1790
std::uint16_t slotNumber
Slot number where the alarm originated.
Definition protocol.h:1815
std::uint32_t moduleIdentNumber
Module ident number of the affected module.
Definition protocol.h:1821
static constexpr std::uint16_t BLOCK_ALARM_HIGH
Block type: high-priority alarm notification.
Definition protocol.h:1793
static constexpr std::size_t kFixedSize
Size in bytes of the fixed portion of this PDU.
Definition protocol.h:1833
static constexpr std::uint16_t BLOCK_ALARM_ACK_LOW
Block type: low-priority alarm acknowledgement.
Definition protocol.h:1802
static constexpr std::uint16_t BLOCK_ALARM_ACK_HIGH
Block type: high-priority alarm acknowledgement.
Definition protocol.h:1799
static PNAlarmNotificationPDU Parse(const Bytes &data)
Parse an AlarmNotification-PDU from raw bytes.
Definition protocol.h:1838
std::array< std::uint8_t, blockHeaderLenght > blockHeader
Nested 6-byte block header.
Definition protocol.h:1806
std::uint32_t api
API number.
Definition protocol.h:1812
std::uint32_t submoduleIdentNumber
Submodule ident number of the affected submodule.
Definition protocol.h:1824
std::uint16_t subslotNumber
Subslot number where the alarm originated.
Definition protocol.h:1818
std::uint16_t alarmSpecifier
Alarm specifier flags (sequence number, channel diagnosis presence, etc.).
Definition protocol.h:1827
static constexpr std::uint16_t BLOCK_ALARM_LOW
Block type: low-priority alarm notification.
Definition protocol.h:1796
Bytes payload
Alarm item data (USI-dispatched; see alarms.h).
Definition protocol.h:1830
std::uint16_t alarmType
Alarm type (Diagnosis/Process/Pull/Plug/...).
Definition protocol.h:1809
static constexpr std::uint16_t InM0
Block type: I&M0.
Definition protocol.h:856
Bytes ToBytes() const
Serialize this header back to raw bytes.
Definition protocol.h:906
BlockType blockType
Block type identifier.
Definition protocol.h:872
static constexpr std::uint16_t DEFAULT_BLOCK_LENGTH
Default block length.
Definition protocol.h:868
static PNBlockHeader Parse(const Bytes &data)
Parse a block header from raw bytes.
Definition protocol.h:889
std::uint8_t blockVersionHigh
Block format major version.
Definition protocol.h:878
static constexpr std::uint16_t InM0FilterDataModul
Block type: I&M0 filter data (module level).
Definition protocol.h:862
std::uint8_t blockVersionLow
Block format minor version.
Definition protocol.h:881
std::uint16_t blockLength
Length in bytes of the block body (excludes Type/Length fields).
Definition protocol.h:875
static constexpr std::uint16_t InM0FilterDataDevice
Block type: I&M0 filter data (device level).
Definition protocol.h:865
static constexpr BlockType IODReadRequestHeader
Generic 6-byte PROFINET block header (Type + Length + Version).
Definition protocol.h:850
static constexpr std::uint16_t IODReadResponseHeader
Block type: IODReadResponseHeader.
Definition protocol.h:853
static constexpr std::size_t kSize
Size in bytes of this header.
Definition protocol.h:884
static constexpr std::uint16_t InM0FilterDataSubModul
Block type: I&M0 filter data (submodule level).
Definition protocol.h:859
DCP request block: Option(1) + SubOption(1) + Length(2) + payload(Length).
Definition protocol.h:271
std::uint16_t length
Length in bytes of Payload.
Definition protocol.h:279
IPConfiguration ParseIp() const
Interpret this block's payload as an IP configuration triple.
Definition protocol.h:321
std::uint8_t suboption
DCP suboption code.
Definition protocol.h:276
Bytes payload
Block payload.
Definition protocol.h:282
std::uint8_t option
DCP option code.
Definition protocol.h:273
Bytes ToBytes() const
Serialize this block back to raw bytes.
Definition protocol.h:308
static constexpr std::size_t kFixedSize
Size in bytes of the fixed portion of this block.
Definition protocol.h:285
static PNDCPBlockRequest Parse(const Bytes &data)
Parse a DCP request block from raw bytes.
Definition protocol.h:290
DCP response block: Option(1) + SubOption(1) + Length(2) + Status(2) + payload.
Definition protocol.h:342
static constexpr std::pair< std::uint8_t, std::uint8_t > DEVICE_ROLE
Block option/suboption: device role bitmask.
Definition protocol.h:378
std::uint16_t status
Per-block status/error code.
Definition protocol.h:353
std::uint8_t suboption
DCP suboption code.
Definition protocol.h:347
static constexpr std::pair< std::uint8_t, std::uint8_t > DEVICE_ID
Block option/suboption: vendor/device ID.
Definition protocol.h:375
static constexpr std::pair< std::uint8_t, std::uint8_t > IP_ADDRESS
Block option/suboption: IP address/netmask/gateway.
Definition protocol.h:363
static constexpr std::pair< std::uint8_t, std::uint8_t > NAME_OF_STATION
Block option/suboption: station name.
Definition protocol.h:372
static PNDCPBlock Parse(const Bytes &data)
Parse a DCP response block from raw bytes.
Definition protocol.h:402
static constexpr std::size_t kFixedSize
Size in bytes of the fixed portion of this block.
Definition protocol.h:397
std::uint8_t option
DCP option code.
Definition protocol.h:344
std::uint16_t length
Length in bytes of Status plus Payload (see class.
Definition protocol.h:350
static constexpr std::pair< std::uint8_t, std::uint8_t > DEVICE_OEM_ID
Block option/suboption: OEM vendor/device ID.
Definition protocol.h:390
IPConfiguration ParseIp() const
Interpret this block's payload as an IP configuration triple.
Definition protocol.h:438
static constexpr std::pair< std::uint8_t, std::uint8_t > DEVICE_OPTIONS
Block option/suboption: supported option list.
Definition protocol.h:381
static constexpr std::pair< std::uint8_t, std::uint8_t > IP_FULL_SUITE
Block option/suboption: full IP suite.
Definition protocol.h:366
static constexpr std::pair< std::uint8_t, std::uint8_t > ALL
Block option/suboption wildcard: all blocks.
Definition protocol.h:393
static constexpr std::pair< std::uint8_t, std::uint8_t > DEVICE_ALIAS
Block option/suboption: device alias name.
Definition protocol.h:384
static constexpr std::pair< std::uint8_t, std::uint8_t > DEVICE_INSTANCE
Block option/suboption: device instance.
Definition protocol.h:387
Bytes payload
Block payload (excludes Status).
Definition protocol.h:356
Bytes ToBytes() const
Serialize this block back to raw bytes.
Definition protocol.h:424
static constexpr std::pair< std::uint8_t, std::uint8_t > IP_MAC
Block option/suboption: IP/MAC address.
Definition protocol.h:360
static constexpr std::pair< std::uint8_t, std::uint8_t > DEVICE_TYPE
Block option/suboption: device type string.
Definition protocol.h:369
DCP (Discovery and Configuration Protocol) frame header.
Definition protocol.h:168
std::uint32_t xId
Transaction ID correlating requests and responses.
Definition protocol.h:205
Bytes ToBytes() const
Serialize this header and its block-list payload back to raw bytes.
Definition protocol.h:242
static constexpr std::uint8_t SET
Service ID: SET.
Definition protocol.h:177
std::uint16_t respDelay
Response delay factor (requests) or reserved (responses).
Definition protocol.h:208
std::uint16_t frameId
DCP frame ID identifying the service/multicast group.
Definition protocol.h:196
static PNDCPHeader Parse(const Bytes &data)
Parse a DCP header and block-list payload from raw bytes.
Definition protocol.h:222
static constexpr std::size_t kFixedSize
Size in bytes of the fixed portion of this header.
Definition protocol.h:217
std::uint16_t length
Length in bytes of the block list that follows.
Definition protocol.h:211
static constexpr std::uint8_t IDENTIFY
Service ID: IDENTIFY.
Definition protocol.h:180
std::uint8_t serviceType
DCP service type (REQUEST/RESPONSE/...).
Definition protocol.h:202
static constexpr std::uint8_t REQUEST
Service Type: REQUEST.
Definition protocol.h:186
static constexpr std::uint8_t HELLO
Service ID: HELLO.
Definition protocol.h:183
static constexpr std::uint8_t GET
Service ID: GET.
Definition protocol.h:174
std::uint8_t serviceId
DCP service ID (GET/SET/IDENTIFY/HELLO).
Definition protocol.h:199
static constexpr std::uint16_t ETHER_TYPE
EtherType used by DCP frames.
Definition protocol.h:171
static constexpr std::uint8_t RESPONSE_UNSUPPORTED
Service Type: RESPONSE (unsupported service).
Definition protocol.h:192
static constexpr std::uint8_t RESPONSE
Service Type: RESPONSE (success).
Definition protocol.h:189
Bytes payload
DCP block list payload.
Definition protocol.h:214
Describes one direction (input or output) of a submodule's cyclic data.
Definition protocol.h:2004
std::uint16_t dataDescription
Data direction: 1 = Input, 2 = Output.
Definition protocol.h:2006
Bytes ToBytes() const
Serialize this description back to raw bytes.
Definition protocol.h:2022
std::uint8_t lengthIops
Length in bytes of the IOPS (provider status) trailer.
Definition protocol.h:2015
std::uint16_t submoduleDataLength
Length in bytes of this direction's cyclic data.
Definition protocol.h:2009
static constexpr std::size_t kSize
Size in bytes of this description.
Definition protocol.h:2018
std::uint8_t lengthIocs
Length in bytes of the IOCS (consumer status) trailer.
Definition protocol.h:2012
IOCRBlockReq header: requests establishment of one IOCR (part of the CONNECT request).
Definition protocol.h:1538
static constexpr std::size_t kSize
Size in bytes of this header.
Definition protocol.h:1596
static constexpr BlockType BLOCK_TYPE
Block type identifier for IOCRBlockReq.
Definition protocol.h:1541
std::uint16_t frameId
Requested frame ID (device may reassign in its response).
Definition protocol.h:1563
MacAddress iocrMulticastMac
Multicast MAC address (used only for multicast IOCRs).
Definition protocol.h:1590
std::uint16_t dataLength
Total cyclic data length in bytes.
Definition protocol.h:1560
std::uint16_t sendClockFactor
Send clock base factor (31.25us units).
Definition protocol.h:1566
std::uint16_t dataHoldFactor
Data hold factor (how long to keep the last good frame's data).
Definition protocol.h:1584
std::uint16_t phase
Phase offset within the reduction ratio.
Definition protocol.h:1572
std::uint16_t iocrType
IOCR type (Input/Output/MulticastProvider/MulticastConsumer).
Definition protocol.h:1548
std::uint16_t watchdogFactor
Watchdog factor (missed-frame tolerance before a timeout fault).
Definition protocol.h:1581
std::uint16_t sequence
Sequence value (reserved, usually 0).
Definition protocol.h:1575
std::uint16_t numberOfApis
Number of API entries that follow this header.
Definition protocol.h:1593
std::uint16_t iocrReference
IOCR reference chosen by the controller.
Definition protocol.h:1551
std::uint16_t iocrTagHeader
VLAN tag header used for cyclic frames.
Definition protocol.h:1587
std::uint32_t iocrProperties
IOCR property flags (RT class, redundancy, etc.).
Definition protocol.h:1557
std::uint16_t etherTypeLT
EtherType used for cyclic frames (0x8892).
Definition protocol.h:1554
std::uint16_t reductionRatio
Reduction ratio relative to the send clock.
Definition protocol.h:1569
std::array< std::uint8_t, blockHeaderLenght > blockHeader
Nested 6-byte block header.
Definition protocol.h:1545
Bytes ToBytes() const
Serialize this header back to raw bytes.
Definition protocol.h:1639
static PNIOCRBlockReqHeader Parse(const Bytes &data)
Parse the fixed IOCRBlockReq header.
Definition protocol.h:1602
std::uint32_t frameSendOffset
Frame send offset within the cycle.
Definition protocol.h:1578
IOCRBlockRes: device's response confirming an IOCR (part of the CONNECT response).
Definition protocol.h:1494
static PNIOCRBlockRes Parse(const Bytes &data)
Parse an IOCRBlockRes from raw bytes.
Definition protocol.h:1518
std::array< std::uint8_t, blockHeaderLenght > blockHeader
Nested 6-byte block header.
Definition protocol.h:1501
std::uint16_t iocrReference
IOCR reference assigned by the controller.
Definition protocol.h:1507
static constexpr std::uint16_t BLOCK_TYPE
Block type identifier for IOCRBlockRes.
Definition protocol.h:1497
std::uint16_t frameId
Frame ID assigned by the device for this IOCR.
Definition protocol.h:1510
std::uint16_t iocrType
IOCR type (Input/Output/MulticastProvider/MulticastConsumer).
Definition protocol.h:1504
static constexpr std::size_t kSize
Size in bytes of this block.
Definition protocol.h:1513
IOD read/write request/response header (RPC body for READ/WRITE/IMPLICIT_READ).
Definition protocol.h:758
std::uint32_t api
API number.
Definition protocol.h:769
std::uint16_t slot
Slot number.
Definition protocol.h:772
Bytes ToBytes() const
Serialize this header and payload back to raw bytes.
Definition protocol.h:826
std::array< std::uint8_t, blockHeaderLenght > blockHeader
Nested 6-byte block header (type + length + version).
Definition protocol.h:760
static PNIODHeader Parse(const Bytes &data)
Parse an IOD header and payload from raw bytes.
Definition protocol.h:801
std::uint16_t sequenceNumber
Sequence number for tracking retries.
Definition protocol.h:763
static constexpr std::size_t kFixedSize
Size in bytes of the fixed portion of this header.
Definition protocol.h:796
std::array< std::uint8_t, 8 > padding2
Reserved/padding.
Definition protocol.h:790
std::uint16_t padding1
Reserved/padding.
Definition protocol.h:778
Bytes payload
Record data payload.
Definition protocol.h:793
std::uint16_t subslot
Subslot number.
Definition protocol.h:775
std::array< std::uint8_t, uuidLenght > targetArUuid
Target AR UUID for AR handover scenarios (usually zero).
Definition protocol.h:787
std::uint32_t length
Length in bytes of Payload.
Definition protocol.h:784
std::uint16_t index
Record data index being read or written.
Definition protocol.h:781
std::array< std::uint8_t, uuidLenght > arUuid
AR (Application Relationship) UUID this record belongs to.
Definition protocol.h:766
Control block used for Release/PrmBegin/PrmEnd/ApplicationReady/RTClass3 requests.
Definition protocol.h:1008
std::array< std::uint8_t, uuidLenght > arUuid
AR UUID this control operation applies to.
Definition protocol.h:1016
std::uint16_t controlBlockProperties
Control block property flags.
Definition protocol.h:1028
static constexpr std::size_t kSize
Size in bytes of this block.
Definition protocol.h:1031
std::uint16_t padding1
Reserved/padding.
Definition protocol.h:1013
static PNIODReleaseBlock Parse(const Bytes &data)
Parse a control block from raw bytes.
Definition protocol.h:1036
std::uint16_t sessionKey
Session key matching the AR.
Definition protocol.h:1019
ControlCommand controlCommand
Control command bitmask (PrmEnd/AppReady/Release/Done/...).
Definition protocol.h:1025
std::uint16_t padding2
Reserved/padding.
Definition protocol.h:1022
Bytes ToBytes() const
Serialize this block back to raw bytes.
Definition protocol.h:1056
std::array< std::uint8_t, blockHeaderLenght > blockHeader
Nested 6-byte block header.
Definition protocol.h:1010
IODWriteReqHeader: request header for writing a data record.
Definition protocol.h:2039
static constexpr std::uint16_t BLOCK_TYPE
Block type identifier for IODWriteReqHeader.
Definition protocol.h:2042
std::uint16_t seqNum
Sequence number for tracking retries.
Definition protocol.h:2049
std::uint16_t index
Record data index being written.
Definition protocol.h:2067
Bytes payload
Record data to write.
Definition protocol.h:2076
std::array< std::uint8_t, uuidLenght > arUuid
AR UUID this record belongs to.
Definition protocol.h:2052
std::array< std::uint8_t, 24 > rwPadding
Reserved/padding.
Definition protocol.h:2073
static constexpr std::size_t kFixedSize
Size in bytes of the fixed portion of this block.
Definition protocol.h:2079
std::uint32_t recordDataLength
Length in bytes of Payload.
Definition protocol.h:2070
std::uint16_t subslot
Subslot number.
Definition protocol.h:2061
std::uint16_t slot
Slot number.
Definition protocol.h:2058
std::array< std::uint8_t, blockHeaderLenght > blockHeader
Nested 6-byte block header.
Definition protocol.h:2046
std::uint32_t api
API number.
Definition protocol.h:2055
Bytes ToBytes() const
Serialize this block back to raw bytes.
Definition protocol.h:2083
std::uint16_t padding
Reserved/padding.
Definition protocol.h:2064
IODWriteResHeader: response header confirming (or rejecting) a data record write.
Definition protocol.h:2103
std::uint32_t recordDataLength
Length in bytes accepted by the device.
Definition protocol.h:2134
static constexpr std::uint16_t BLOCK_TYPE
Block type identifier for IODWriteResHeader.
Definition protocol.h:2106
std::uint16_t padding
Reserved/padding.
Definition protocol.h:2128
std::uint16_t slot
Slot number.
Definition protocol.h:2122
std::uint16_t seqNum
Sequence number echoed from the request.
Definition protocol.h:2113
std::uint16_t additionalValue1
Additional status value 1 (device-specific).
Definition protocol.h:2137
std::array< std::uint8_t, uuidLenght > arUuid
AR UUID this record belongs to.
Definition protocol.h:2116
std::uint16_t index
Record data index written.
Definition protocol.h:2131
static PNIODWriteRes Parse(const Bytes &data)
Parse an IODWriteResHeader from raw bytes.
Definition protocol.h:2154
std::uint32_t status
PNIO status code (0 = success).
Definition protocol.h:2143
std::uint16_t subslot
Subslot number.
Definition protocol.h:2125
static constexpr std::size_t kSize
Size in bytes of this block.
Definition protocol.h:2149
std::uint16_t additionalValue2
Additional status value 2 (device-specific).
Definition protocol.h:2140
std::array< std::uint8_t, blockHeaderLenght > blockHeader
Nested 6-byte block header.
Definition protocol.h:2110
std::array< std::uint8_t, 16 > rwPadding
Reserved/padding.
Definition protocol.h:2146
std::uint32_t api
API number.
Definition protocol.h:2119
I&M0: mandatory identification data (vendor, order ID, serial number, revisions).
Definition protocol.h:1076
std::uint16_t imProfileId
I&M profile ID.
Definition protocol.h:1116
std::uint16_t imHardwareRevision
Hardware revision number.
Definition protocol.h:1098
static constexpr std::size_t kSize
Size in bytes of this record.
Definition protocol.h:1128
std::uint8_t vendorIdHigh
High byte of the PROFINET vendor ID.
Definition protocol.h:1086
std::uint16_t imProfileSpecificType
I&M profile-specific type.
Definition protocol.h:1119
std::string imSerialNumber
Device serial number (16 chars).
Definition protocol.h:1095
std::uint16_t imSupported
Bitmask of which I&M1-I&M15 records this device supports.
Definition protocol.h:1125
std::uint8_t imSwRevisionBugFix
Bug fix revision digit.
Definition protocol.h:1107
static PNInM0 Parse(const Bytes &data)
Parse an I&M0 record from raw bytes.
Definition protocol.h:1140
std::array< std::uint8_t, blockHeaderLenght > blockHeader
Nested 6-byte block header.
Definition protocol.h:1083
std::uint16_t imVersion
I&M data structure version.
Definition protocol.h:1122
std::uint8_t swRevisionPrefix
Software revision prefix character (e.g. 'V', 'R', 'P', 'U', 'T').
Definition protocol.h:1101
std::uint16_t imRevisionCounter
Monotonically increasing revision counter.
Definition protocol.h:1113
std::uint8_t imSwRevisionFunctionalEnhancement
Functional enhancement revision digit.
Definition protocol.h:1104
std::uint16_t VendorId() const
Combine VendorIdHigh/VendorIdLow into a 16-bit vendor ID.
Definition protocol.h:1132
std::uint8_t imSwRevisionInternalChange
Internal change revision digit.
Definition protocol.h:1110
std::string orderId
Manufacturer-specific order/part number (20 chars).
Definition protocol.h:1092
static constexpr std::uint16_t IDX
Record data index for I&M0.
Definition protocol.h:1079
std::uint8_t vendorIdLow
Low byte of the PROFINET vendor ID.
Definition protocol.h:1089
bool operator==(const PNInM0 &) const =default
Compares two PNInM0 for equality.
I&M1: user-assigned tag function and location strings.
Definition protocol.h:1178
std::string imTagLocation
User-assigned installation location (22 chars).
Definition protocol.h:1191
static PNInM1 Parse(const Bytes &data)
Parse an I&M1 record from raw bytes.
Definition protocol.h:1199
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:1181
std::string imTagFunction
User-assigned function description (32 chars).
Definition protocol.h:1188
std::array< std::uint8_t, blockHeaderLenght > blockHeader
Nested 6-byte block header.
Definition protocol.h:1185
static constexpr std::size_t kSize
Size in bytes of this record.
Definition protocol.h:1194
I&M2: installation date.
Definition protocol.h:1222
static PNInM2 Parse(const Bytes &data)
Parse an I&M2 record from raw bytes.
Definition protocol.h:1240
std::array< std::uint8_t, blockHeaderLenght > blockHeader
Nested 6-byte block header.
Definition protocol.h:1229
std::string imDate
Installation date, "YYYY-MM-DD HH:MM" (16 chars).
Definition protocol.h:1232
bool operator==(const PNInM2 &) const =default
Compares two PNInM2 for equality.
static constexpr std::uint16_t IDX
Record data index for I&M2.
Definition protocol.h:1225
static constexpr std::size_t kSize
Size in bytes of this record.
Definition protocol.h:1235
I&M3: free-text descriptor.
Definition protocol.h:1263
static constexpr std::uint16_t IDX
Record data index for I&M3.
Definition protocol.h:1266
std::array< std::uint8_t, blockHeaderLenght > blockHeader
Nested 6-byte block header.
Definition protocol.h:1270
std::string imDescriptor
Free-text descriptor (54 chars).
Definition protocol.h:1273
static PNInM3 Parse(const Bytes &data)
Parse an I&M3 record from raw bytes.
Definition protocol.h:1281
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:1276
I&M4: PROFIsafe signature (binary, not text).
Definition protocol.h:1303
bool operator==(const PNInM4 &) const =default
Compares two PNInM4 for equality.
std::array< std::uint8_t, 54 > imSignature
PROFIsafe signature bytes.
Definition protocol.h:1313
static PNInM4 Parse(const Bytes &data)
Parse an I&M4 record from raw bytes.
Definition protocol.h:1321
static constexpr std::uint16_t IDX
Record data index for I&M4.
Definition protocol.h:1306
static constexpr std::size_t kSize
Size in bytes of this record.
Definition protocol.h:1316
std::array< std::uint8_t, blockHeaderLenght > blockHeader
Nested 6-byte block header.
Definition protocol.h:1310
I&M5: free-text annotation.
Definition protocol.h:1343
static PNInM5 Parse(const Bytes &data)
Parse an I&M5 record from raw bytes.
Definition protocol.h:1361
static constexpr std::uint16_t IDX
Record data index for I&M5.
Definition protocol.h:1346
std::string imAnnotation
Free-text annotation (64 chars).
Definition protocol.h:1353
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:1356
std::array< std::uint8_t, blockHeaderLenght > blockHeader
Nested 6-byte block header.
Definition protocol.h:1350
I&M6-I&M15: reserved for future use per IEC 61158-6-10.
Definition protocol.h:1387
Bytes payload
Opaque remaining payload.
Definition protocol.h:1397
bool operator==(const PNInMReserved &) const =default
Compares two PNInMReserved for equality.
std::array< std::uint8_t, blockHeaderLenght > blockHeader
Nested 6-byte block header.
Definition protocol.h:1394
static constexpr std::uint16_t IDX
Record data index for this reserved I&M slot.
Definition protocol.h:1390
static PNInMReserved Parse(const Bytes &data)
Parse a reserved I&M record from raw bytes.
Definition protocol.h:1402
NRD (Network Representation Data) wrapper carrying the actual IOD payload.
Definition protocol.h:695
Bytes payload
The wrapped IOD data.
Definition protocol.h:712
static PNNRDData Parse(const Bytes &data)
Parse an NRD wrapper and payload from raw bytes.
Definition protocol.h:720
Bytes ToBytes() const
Serialize this wrapper and payload back to raw bytes.
Definition protocol.h:743
std::uint32_t argsLength
Length in bytes of the arguments (usually equals ActualCount).
Definition protocol.h:700
std::uint32_t offset
Byte offset into the logical result (0 unless fragmented).
Definition protocol.h:706
std::uint32_t argsMaximumStatus
Maximum status/argument buffer size accepted by the caller.
Definition protocol.h:697
static constexpr std::size_t kFixedSize
Size in bytes of the fixed portion of this wrapper.
Definition protocol.h:715
std::uint32_t maximumCount
Maximum number of bytes the caller can accept.
Definition protocol.h:703
std::uint32_t actualCount
Actual length in bytes of Payload.
Definition protocol.h:709
DCE/RPC PDU header used to carry PROFINET connect/read/write/control requests.
Definition protocol.h:465
Bytes ToBytes() const
Serialize this header and body back to raw bytes.
Definition protocol.h:647
static constexpr std::uint8_t WORKING
Packet type: WORKING.
Definition protocol.h:480
std::array< std::uint8_t, 3 > dataRepresentation
Data representation format label.
Definition protocol.h:533
static constexpr std::uint16_t RELEASE
Operation number: RELEASE.
Definition protocol.h:504
std::uint16_t operationNumber
Operation number (CONNECT/RELEASE/READ/WRITE/CONTROL/IMPLICIT_READ).
Definition protocol.h:557
std::uint16_t fragmentNumber
Fragment number for fragmented PDUs.
Definition protocol.h:569
static constexpr std::size_t kFixedSize
Size in bytes of the fixed portion of this header.
Definition protocol.h:581
static std::array< std::uint8_t, uuidLenght > IfaceUuidParamserver()
Interface UUID identifying the Parameter Server role.
Definition protocol.h:606
std::uint16_t interfaceHint
Interface hint (0xFFFF if unused).
Definition protocol.h:560
static constexpr std::uint16_t READ
Operation number: READ.
Definition protocol.h:507
static constexpr std::uint8_t FRAG_ACK
Packet type: FRAG_ACK.
Definition protocol.h:495
std::uint8_t flags1
Packet flags, first byte.
Definition protocol.h:527
static PNRPCHeader Parse(const Bytes &data)
Parse an RPC header and body from raw bytes.
Definition protocol.h:614
std::uint8_t packetType
Packet type (REQUEST/RESPONSE/FAULT/...).
Definition protocol.h:524
static constexpr std::uint16_t WRITE
Operation number: WRITE.
Definition protocol.h:510
std::array< std::uint8_t, uuidLenght > interfaceUuid
Target interface UUID (identifies device/controller/supervisor role).
Definition protocol.h:542
std::uint8_t authenticationProtocol
Authentication protocol identifier (unused by PROFINET).
Definition protocol.h:572
std::uint8_t serialNrHigh
High byte of the serial number.
Definition protocol.h:536
static std::array< std::uint8_t, uuidLenght > IfaceUuidDevice()
Interface UUID identifying the IO-Device role.
Definition protocol.h:585
std::uint8_t serialNrLow
Low byte of the serial number.
Definition protocol.h:575
static constexpr std::uint8_t ACK
Packet type: ACK.
Definition protocol.h:489
static std::array< std::uint8_t, uuidLenght > IfaceUuidSupervisor()
Interface UUID identifying the IO-Supervisor role.
Definition protocol.h:599
std::uint32_t sequenceNumber
Sequence number within the activity.
Definition protocol.h:554
static constexpr std::uint8_t REJECT
Packet type: REJECT.
Definition protocol.h:486
static constexpr std::uint16_t CONNECT
Operation number: CONNECT.
Definition protocol.h:501
std::uint8_t version
DCE/RPC version (always 4 for PROFINET).
Definition protocol.h:521
static constexpr std::uint8_t CANCEL_ACK
Packet type: CANCEL_ACK.
Definition protocol.h:498
static constexpr std::uint8_t PONG
Packet type: PONG.
Definition protocol.h:483
static constexpr std::uint8_t PING
Packet type: PING.
Definition protocol.h:471
static constexpr std::uint8_t REQUEST
Packet type: REQUEST.
Definition protocol.h:468
static constexpr std::uint16_t CONTROL
Operation number: CONTROL.
Definition protocol.h:513
std::uint32_t serverBootTime
Server boot time counter.
Definition protocol.h:548
static constexpr std::uint8_t RESPONSE
Packet type: RESPONSE.
Definition protocol.h:474
std::uint8_t flags2
Packet flags, second byte.
Definition protocol.h:530
static constexpr std::uint16_t IMPLICIT_READ
Operation number: IMPLICIT_READ.
Definition protocol.h:516
Bytes payload
PDU body (NRD data for read/write/control, etc.).
Definition protocol.h:578
std::uint32_t interfaceVersion
Interface version.
Definition protocol.h:551
std::uint16_t activityHint
Activity hint (0xFFFF if unused).
Definition protocol.h:563
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:678
std::uint16_t lengthOfBody
Length in bytes of Payload.
Definition protocol.h:566
static std::array< std::uint8_t, uuidLenght > IfaceUuidController()
Interface UUID identifying the IO-Controller role.
Definition protocol.h:592
std::array< std::uint8_t, uuidLenght > objectUuid
Target object UUID.
Definition protocol.h:539
static constexpr std::uint8_t CANCEL
Packet type: CANCEL.
Definition protocol.h:492
static constexpr std::uint8_t FAULT
Packet type: FAULT.
Definition protocol.h:477
std::array< std::uint8_t, uuidLenght > activityUuid
Activity (call) UUID correlating request/response pairs.
Definition protocol.h:545
RTA-PDU Header - Real-Time Acyclic PDU for Layer 2 alarm transport.
Definition protocol.h:1904
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:1928
std::uint16_t sendSeqNum
Sender's sequence number for this PDU.
Definition protocol.h:1945
static constexpr std::uint8_t RTA_TYPE_ERR
PDU type: ERR.
Definition protocol.h:1916
std::uint16_t alarmSrcEndpoint
Source alarm endpoint (AlarmCR reference on the sender).
Definition protocol.h:1936
Bytes payload
RTA variable part (e.g. an AlarmNotification-PDU or AlarmAck-PDU).
Definition protocol.h:1954
static constexpr std::size_t kFixedSize
Size in bytes of the fixed portion of this header.
Definition protocol.h:1957
Bytes ToBytes() const
Serialize this header and variable part back to raw bytes.
Definition protocol.h:1983
static constexpr std::uint8_t VERSION_2
RTA protocol version 2.
Definition protocol.h:1922
std::uint16_t alarmDstEndpoint
Destination alarm endpoint (AlarmCR reference on the receiver).
Definition protocol.h:1933
static constexpr std::uint8_t RTA_TYPE_ACK
PDU type: ACK.
Definition protocol.h:1913
std::uint16_t variablePartLenght
Length in bytes of the variable part (Payload).
Definition protocol.h:1951
std::uint8_t addFlags
Additional flags (window size, TACK flag).
Definition protocol.h:1942
static PNRTAHeader Parse(const Bytes &data)
Parse an RTA header and variable part from raw bytes.
Definition protocol.h:1962
static constexpr std::uint8_t RTA_TYPE_DATA
PDU type: DATA.
Definition protocol.h:1907
static constexpr std::uint8_t ADD_FLAGS_WINDOW_1
RTA AddFlags bits: window size in bits 0-3.
Definition protocol.h:1925
static constexpr std::uint8_t VERSION_1
RTA protocol version 1.
Definition protocol.h:1919
static constexpr std::uint8_t RTA_TYPE_NACK
PDU type: NACK.
Definition protocol.h:1910
std::uint16_t ackSeqNum
Sequence number being acknowledged.
Definition protocol.h:1948
std::uint8_t pduType
PDU type and protocol version, packed as type(bits 4-7) + version(bits 0-3).
Definition protocol.h:1939
Declares Linux Ethernet, addressing, timing, and utility helpers used by the PROFINET stack.
Small helpers for reading/writing big-endian ("network order") integers to/from byte buffers....