PROFINET IO Controller Stack 1.0.0
Modern C++ implementation of a PROFINET IO Controller stack
Loading...
Searching...
No Matches
exceptions.cpp
Go to the documentation of this file.
1
3
4// Ported from profinet-py's profinet/exceptions.py
6
7#include <cstdio>
8#include <map>
9
10#include "profinet/util.h"
11
12namespace profinet
13{
14
15std::string GetErrorDecodeName(const ErrorDecode errorDecodeName)
16{
17 switch (errorDecodeName)
18 {
20 return "PNIO Connection Management";
21
23 return "PNIO Read/Write";
24
26 return "PNIO";
27
28 default:
29 return "Unknown (" +
30 Hex2(static_cast<std::uint8_t>(errorDecodeName)) +
31 ")";
32 }
33}
34
35std::string GetPnioRwErrorCode1Name(const PnioRwErrorCode1 errorCodeRw1)
36{
37 switch (errorCodeRw1)
38 {
40 return "Invalid Index";
41
43 return "Write Length Error";
44
46 return "Resource Error";
47
49 return "Access Error";
50
52 return "Application Error";
53
54 default:
55 return "Unknown (" +
56 Hex2(static_cast<std::uint8_t>(errorCodeRw1)) +
57 ")";
58 }
59}
60
61std::string GetPnioCmErrorCode1Name(const PnioCmErrorCode1 errorCodeCm1)
62{
63 switch (errorCodeCm1)
64 {
66 return "AR Block";
67
69 return "IOCR Block";
70
72 return "Alarm CR Block";
73
75 return "Expected Submodule Block";
76
78 return "Module Difference Block";
79
81 return "AR RPC Block";
82
84 return "IR Info Block";
85
87 return "SR Info Block";
88
90 return "ARFSU Block";
91
93 return "IOD Control Request";
94
96 return "IOD Control Response";
97
99 return "AR Block Response";
100
102 return "IOCR Block Response";
103
105 return "Alarm CR Block Response";
106
108 return "Module Difference Block Response";
109
111 return "AR Server Block Response";
112
114 return "Parameter Server";
115
117 return "Connection Management Control";
118
120 return "Connection Management Device";
121
123 return "Connection Management RPC";
124
126 return "Faulty Record Data";
127
129 return "Faulty Application Relation";
130
132 return "Faulty Block Structure";
133
134 default:
135 return "Unknown (" +
136 Hex2(static_cast<std::uint8_t>(errorCodeCm1)) +
137 ")";
138 }
139}
140
142{
143 switch (errorCode2)
144 {
146 return "Index not supported";
147
149 return "Index exists but has not been written";
150
151 default:
152 return "Unknown Error (" +
153 Hex2(static_cast<std::uint8_t>(errorCode2)) +
154 ")";
155 }
156}
157
159{
160 switch (errorCode2)
161 {
163 return "Write length error";
164
166 return "Write data is too short";
167
169 return "Write data is too long";
170
172 return "Write access denied (write protected)";
173
174 default:
175 return "Unknown Error (" +
176 Hex2(static_cast<std::uint8_t>(errorCode2)) +
177 ")";
178 }
179}
180
182{
183 switch (errorCode2)
184 {
186 return "Resource not available";
187
189 return "Invalid slot number";
190
192 return "Invalid subslot number";
193
195 return "Module has no data";
196
197 default:
198 return "Unknown Error (" +
199 Hex2(static_cast<std::uint8_t>(errorCode2)) +
200 ")";
201 }
202}
203
205{
206 switch (errorCode2)
207 {
209 return "Access denied (invalid area)";
210
212 return "Access denied";
213
215 return "Access denied (invalid range)";
216
218 return "Access denied (invalid state for access)";
219
221 return "Access denied (local control)";
222
223 default:
224 return "Unknown Error (" +
225 Hex2(static_cast<std::uint8_t>(errorCode2)) +
226 ")";
227 }
228}
229
231{
232 switch (errorCode2)
233 {
235 return "Read error";
236
238 return "Write error";
239
241 return "Module failure";
242
244 return "Resource busy";
245
247 return "Version conflict";
248
250 return "Invalid API number";
251
253 return "Backup not allowed";
254
256 return "Alarm pending";
257
258 default:
259 return "Unknown Error (" +
260 Hex2(static_cast<std::uint8_t>(errorCode2)) +
261 ")";
262 }
263}
264
265std::string GetPnioErrorCode1Name(const PnioErrorCode1 errorCode1)
266{
267 switch (errorCode1)
268 {
270 return "RMPM";
271
273 return "PrmServer";
274
275 default:
276 return "Unknown(" +
277 Hex2(static_cast<std::uint8_t>(errorCode1)) +
278 ")";
279 }
280}
281
282std::string GetPnioErrorMessage(const PnioRmpmErrorCode2 errorCode2)
283{
284 switch (errorCode2)
285 {
287 return "Invalid arguments length";
288
290 return "Unknown blocks in request";
291
293 return "Required IOCR block missing";
294
296 return "Wrong AlarmCR block count";
297
299 return "Out of AR resources";
300
301 default:
302 return "Unknown Error (" +
303 Hex2(static_cast<std::uint8_t>(errorCode2)) +
304 ")";
305 }
306}
307
308std::string GetPnioErrorMessage(const PnioPrmServerErrorCode2 errorCode2)
309{
310 switch (errorCode2)
311 {
313 return "Parameter server state conflict";
314
315 default:
316 return "Unknown Error (" +
317 Hex2(static_cast<std::uint8_t>(errorCode2)) +
318 ")";
319 }
320}
321
322std::string GetPnioRwErrorMessage(const PnioRwErrorCode1 errorCode1, const std::uint8_t errorCode2)
323{
324 switch (errorCode1)
325 {
327 {
328 const auto errCode2 = static_cast<PnioRwInvalidIndexErrorCode2>(errorCode2);
329 return GetPnioRwErrorMessage(errCode2);
330 }
332 {
333 const auto errCode2 = static_cast<PnioRwWriteLengthErrorCode2>(errorCode2);
334 return GetPnioRwErrorMessage(errCode2);
335 }
337 {
338 const auto errCode2 = static_cast<PnioRwResourceErrorCode2>(errorCode2);
339 return GetPnioRwErrorMessage(errCode2);
340 }
342 {
343 const auto errCode2 = static_cast<PnioRwAccessErrorCode2>(errorCode2);
344 return GetPnioRwErrorMessage(errCode2);
345 }
347 {
348 const auto errCode2 = static_cast<PnioRwApplicationErrorCode2>(errorCode2);
349 return GetPnioRwErrorMessage(errCode2);
350 }
351 }
352
353 return "Unknown Error (" + Hex2(errorCode2) + ")";
354}
355
356std::string GetPnioCmErrorMessage(const PnioCmArErrorCode2 errorCode2)
357{
358 switch (errorCode2)
359 {
361 return "Invalid AR type";
362
364 return "AR already active";
365
367 return "Out of AR resources";
368
370 return "Out of provider resources";
371
373 return "Out of consumer resources";
374
376 return "Out of alarm resources";
377
379 return "Out of memory";
380
382 return "Invalid session key";
383
385 return "AR UUID conflict";
386
387 default:
388 return "Unknown Error (" +
389 Hex2(static_cast<std::uint8_t>(errorCode2)) +
390 ")";
391 }
392}
393
394std::string GetPnioCmErrorMessage(const PnioCmIocrErrorCode2 errorCode2)
395{
396 switch (errorCode2)
397 {
399 return "Invalid IOCR type";
400
402 return "Out of IOCR resources";
403
405 return "Invalid frame ID";
406
408 return "Invalid RT class";
409
411 return "Invalid IO data length";
412
414 return "Cycle time conflict";
415
417 return "Watchdog configuration error";
418
419 default:
420 return "Unknown Error (" +
421 Hex2(static_cast<std::uint8_t>(errorCode2)) +
422 ")";
423 }
424}
425
427{
428 switch (errorCode2)
429 {
431 return "Invalid AlarmCR type";
432
434 return "Out of AlarmCR resources";
435
436 default:
437 return "Unknown Error (" +
438 Hex2(static_cast<std::uint8_t>(errorCode2)) +
439 ")";
440 }
441}
442
444{
445 switch (errorCode2)
446 {
448 return "Invalid slot number";
449
451 return "Invalid subslot number";
452
454 return "Wrong module identification number";
455
457 return "Wrong submodule identification number";
458
460 return "IO data length mismatch";
461
462 default:
463 return "Unknown Error (" +
464 Hex2(static_cast<std::uint8_t>(errorCode2)) +
465 ")";
466 }
467}
468
470{
471 switch (errorCode2)
472 {
474 return "Device state conflict";
475
477 return "Connection resource unavailable";
478
480 return "Device already owned";
481
483 return "AR set aborted";
484
485 default:
486 return "Unknown Error (" +
487 Hex2(static_cast<std::uint8_t>(errorCode2)) +
488 ")";
489 }
490}
491
493{
494 switch (errorCode2)
495 {
497 return "Faulty block structure";
498
499 default:
500 return "Unknown Error (" +
501 Hex2(static_cast<std::uint8_t>(errorCode2)) +
502 ")";
503 }
504}
505
506PNIOError PNIOError::FromBytes(std::span<const std::uint8_t, 4> data)
507{
508 // Expliciet benoemde indices in lowerCamelCase om te voldoen aan je stijlrichtlijn
509 static constexpr std::size_t idxErrorCode = 0;
510 static constexpr std::size_t idxErrorDecode = 1;
511 static constexpr std::size_t idxErrorCode1 = 2;
512 static constexpr std::size_t idxErrorCode2 = 3;
513
514 // We gebruiken .at() of directe span-indexering; Clang-Tidy staat dit toe
515 // omdat de grootte (4) compile-time gegarandeerd is via de span-template.
516 return CreateFromCodes(data[idxErrorCode],
517 data[idxErrorDecode],
518 data[idxErrorCode1],
519 data[idxErrorCode2]);
520}
521
522PNIOError PNIOError::FromArgsStatus(std::uint32_t argsStatus)
523{
524 // args_status was parsed as big-endian from little-endian wire bytes by
525 // the caller, so byte-swap it back to Hilscher-style ordering, exactly
526 // as the Python implementation does.
527 const std::uint32_t swapped = ((argsStatus & LowByteMask) << ThreeOctetsShift) | (((argsStatus >> OneOctetShift) & LowByteMask) << TwoOctetsShift) |
528 (((argsStatus >> TwoOctetsShift) & LowByteMask) << OneOctetShift) | ((argsStatus >> ThreeOctetsShift) & LowByteMask);
529
530 const std::uint8_t errorCode = (swapped >> ThreeOctetsShift) & LowByteMask;
531 const std::uint8_t errorDecode = (swapped >> TwoOctetsShift) & LowByteMask;
532 const std::uint8_t errorCode1 = (swapped >> OneOctetShift) & LowByteMask;
533 const std::uint8_t errorCode2 = swapped & LowByteMask;
534
536}
537
538std::string DecodePnioCmError(const std::uint8_t& errorCode1, const std::uint8_t& errorCode2)
539{
540 const auto code1 = static_cast<PnioCmErrorCode1>(errorCode1);
541
542 switch (code1)
543 {
545 return GetPnioCmErrorMessage(PnioCmArErrorCode2{static_cast<std::uint8_t>(errorCode2)});
546
548 return GetPnioCmErrorMessage(PnioCmArErrorCode2{static_cast<std::uint8_t>(errorCode2)}) + " (in response)";
549
551 return GetPnioCmErrorMessage(PnioCmIocrErrorCode2{static_cast<std::uint8_t>(errorCode2)});
552
554 return GetPnioCmErrorMessage(PnioCmIocrErrorCode2{static_cast<std::uint8_t>(errorCode2)}) + " (in response)";
555
557 return GetPnioCmErrorMessage(PnioCmAlarmCrErrorCode2{static_cast<std::uint8_t>(errorCode2)});
558
560 return GetPnioCmErrorMessage(PnioCmAlarmCrErrorCode2{static_cast<std::uint8_t>(errorCode2)}) + " (in response)";
561
563 return GetPnioCmErrorMessage(PnioCmExpectedSubmoduleErrorCode2{static_cast<std::uint8_t>(errorCode2)});
564
566 return GetPnioCmErrorMessage(PnioCmDeviceErrorCode2{static_cast<std::uint8_t>(errorCode2)});
567
569 return GetPnioCmErrorMessage(PnioCmFaultyBlockErrorCode2{static_cast<std::uint8_t>(errorCode2)});
570
571 default:
572 return "Unknown CM error in " + GetPnioCmErrorCode1Name(code1);
573 }
574}
575std::string DecodePnioError(const std::uint8_t& errorCode1, const std::uint8_t& errorCode2)
576{
577 const auto code1 = static_cast<PnioErrorCode1>(errorCode1);
578
579 switch (code1)
580 {
582 return GetPnioErrorMessage(PnioRmpmErrorCode2{static_cast<std::uint8_t>(errorCode2)});
583
585 return GetPnioErrorMessage(PnioPrmServerErrorCode2{static_cast<std::uint8_t>(errorCode2)});
586
587 default:
588 return "Unknown PNIO error";
589 }
590}
591std::string DecodePnioRWError(const std::uint8_t& errorCode1, const std::uint8_t& errorCode2)
592{
593 const auto code1 = static_cast<PnioRwErrorCode1>(errorCode1);
594
595 switch (code1)
596 {
598 return GetPnioRwErrorMessage(PnioRwInvalidIndexErrorCode2{static_cast<std::uint8_t>(errorCode2)});
599
601 return GetPnioRwErrorMessage(PnioRwWriteLengthErrorCode2{static_cast<std::uint8_t>(errorCode2)});
602
604 return GetPnioRwErrorMessage(PnioRwResourceErrorCode2{static_cast<std::uint8_t>(errorCode2)});
605
607 return GetPnioRwErrorMessage(PnioRwAccessErrorCode2{static_cast<std::uint8_t>(errorCode2)});
608
610 return GetPnioRwErrorMessage(PnioRwApplicationErrorCode2{static_cast<std::uint8_t>(errorCode2)});
611
612 default:
613 return "Unknown PNIORW error";
614 }
615}
616
618 const std::uint8_t errorCode,
619 const std::uint8_t errorDecode,
620 const std::uint8_t errorCode1,
621 const std::uint8_t errorCode2)
622{
623 std::string message;
624
625 const auto decode = static_cast<ErrorDecode>(errorDecode);
626
627 switch (decode)
628 {
631 break;
634 break;
637 break;
638 default:
639 message = "Unknown error (Decode=" +
641 ")";
642 break;
643 }
644
645 return {message, errorCode, errorDecode, errorCode1, errorCode2};
646}
647std::string PNIOError::BlockName() const
648{
649 if (!IsCmError())
650 {
651 return "";
652 }
653
655 static_cast<PnioCmErrorCode1>(errorCode1));
656}
657} // namespace profinet
PNIO application error with error codes.
Definition exceptions.h:692
std::uint8_t errorCode1
Raw ErrorCode1 byte (category / block type).
Definition exceptions.h:701
static PNIOError CreateFromCodes(std::uint8_t errorCode, std::uint8_t errorDecode, std::uint8_t errorCode1, std::uint8_t errorCode2)
std::uint8_t errorCode
Raw ErrorCode byte (see class-level.
Definition exceptions.h:695
std::uint8_t errorDecode
Raw ErrorDecode byte; selects which ErrorCode1/ErrorCode2 table applies.
Definition exceptions.h:698
std::string BlockName() const
Human-readable name of the PNIO-CM block referenced by ErrorCode1.
bool IsCmError() const
Whether this error came from the PNIO-CM (connection management) table.
Definition exceptions.h:738
static PNIOError FromBytes(std::span< const std::uint8_t, 4 > data)
Create a PNIOError from a raw 4-byte error status.
std::uint8_t errorCode2
Raw ErrorCode2 byte (specific error within the category).
Definition exceptions.h:704
static PNIOError FromArgsStatus(std::uint32_t argsStatus)
Create a PNIOError from the little-endian ArgsStatus field carried in a DCE/RPC PDU.
Declares exceptions and error types used by the PROFINET IO controller stack.
std::string Hex2(std::uint8_t value)
Format an 8-bit unsigned integer as a 2-digit hexadecimal string.
Definition util.cpp:68
std::string GetPnioRwErrorCode1Name(PnioRwErrorCode1 errorCodeRw1)
Get the human-readable name for a PNIORW ErrorCode1.
PnioCmErrorCode1
PNIO-CM ErrorCode1 values.
Definition exceptions.h:76
@ ArServerResponse
ARServerBlock response.
@ Iocr
IOCRBlock request.
@ CmCtl
Connection management control.
@ IodControlResponse
IODControl response.
@ PrmServer
Parameter server.
@ FaultyRecord
Faulty record data.
@ AlarmCr
AlarmCRBlock request.
@ CmRpc
Connection management RPC.
@ IodControlRequest
IODControl request.
@ ModuleDiff
ModuleDiffBlock.
@ Ar
ARBlock request.
@ ArResponse
ARBlock response.
@ CmDev
Connection management device.
@ ExpectedSubmodule
ExpectedSubmoduleBlock request.
@ IocrResponse
IOCRBlock response.
@ AlarmCrResponse
AlarmCRBlock response.
@ FaultyBlock
Faulty block structure.
@ FaultyAr
Faulty application relation.
@ ModuleDiffResponse
ModuleDiffBlock response.
PnioRwWriteLengthErrorCode2
PNIORW WriteLength ErrorCode2 values.
Definition exceptions.h:174
@ WriteProtected
Write access is denied because the data is write protected.
@ DataTooLong
Write data is too long.
@ WriteLengthError
General write length error.
@ DataTooShort
Write data is too short.
std::string DecodePnioCmError(const std::uint8_t &errorCode1, const std::uint8_t &errorCode2)
ErrorDecode
PROFINET error decode values.
Definition exceptions.h:22
@ Pnio
General PNIO error.
@ PnioRw
PNIO read/write error.
@ PnioCm
PNIO connection management error.
std::string GetPnioErrorMessage(PnioRmpmErrorCode2 errorCode2)
Get the human-readable message for an RMPM ErrorCode2.
std::string GetPnioCmErrorCode1Name(PnioCmErrorCode1 errorCodeCm1)
Get the human-readable name for a PNIO-CM ErrorCode1.
PnioPrmServerErrorCode2
PNIO Parameter Server ErrorCode2 values.
Definition exceptions.h:499
@ StateConflict
The parameter server is in an invalid state for the requested operation.
PnioRwAccessErrorCode2
PNIORW Access ErrorCode2 values.
Definition exceptions.h:220
@ InvalidArea
Access denied because the area is invalid.
@ LocalControl
Access denied because of local control.
@ InvalidState
Access denied because the device is in an invalid state.
@ InvalidRange
Access denied because the range is invalid.
std::string GetPnioRwErrorMessage(PnioRwInvalidIndexErrorCode2 errorCode2)
Get the human-readable message for an InvalidIndex error.
std::string GetPnioErrorCode1Name(PnioErrorCode1 errorCode1)
Get the human-readable name of a PNIO ErrorCode1.
std::string DecodePnioError(const std::uint8_t &errorCode1, const std::uint8_t &errorCode2)
PnioErrorCode1
PNIO ErrorCode1 values.
Definition exceptions.h:448
@ PrmServer
Parameter server error.
@ Rmpm
Runtime parameter and module management (RMPM) error.
PnioCmIocrErrorCode2
PNIO-CM IOCR ErrorCode2 values.
Definition exceptions.h:320
@ NoIocrResources
No IOCR resources are available.
@ InvalidIocrType
Invalid IOCR type.
@ InvalidIoDataLength
The IO data length is invalid.
@ CycleTimeConflict
A cycle time conflict occurred.
@ InvalidFrameId
The frame ID is invalid.
@ WatchdogConfigurationError
The watchdog configuration is invalid.
@ InvalidRtClass
The RT class is invalid.
static constexpr int OneOctetShift
The bit-shift distance required to move data across a single octet.
Definition util.h:50
static constexpr int ThreeOctetsShift
The bit-shift distance required to move data across three octets.
Definition util.h:56
static constexpr int TwoOctetsShift
The bit-shift distance required to move data across two octets.
Definition util.h:53
PnioRmpmErrorCode2
PNIO RMPM ErrorCode2 values.
Definition exceptions.h:469
@ WrongAlarmCrBlockCount
The number of AlarmCR blocks is incorrect.
@ RequiredIocrBlockMissing
A required IOCR block is missing.
@ OutOfArResources
No application relation resources are available.
@ InvalidArgumentsLength
Invalid arguments length.
@ UnknownBlocksInRequest
Unknown blocks were found in the request.
PnioRwInvalidIndexErrorCode2
PNIORW InvalidIndex ErrorCode2 values.
Definition exceptions.h:157
@ IndexNotWritten
Index exists but has not been written.
@ IndexNotSupported
Index is not supported.
std::string DecodePnioRWError(const std::uint8_t &errorCode1, const std::uint8_t &errorCode2)
PnioRwResourceErrorCode2
PNIORW Resource ErrorCode2 values.
Definition exceptions.h:197
@ ModuleHasNoData
Module has no data.
@ InvalidSlot
Slot number is invalid.
@ ResourceNotAvailable
Resource is not available.
@ InvalidSubslot
Subslot number is invalid.
PnioCmExpectedSubmoduleErrorCode2
PNIO-CM Expected Submodule ErrorCode2 values.
Definition exceptions.h:374
@ IoDataLengthMismatch
IO data length does not match the expected length.
@ WrongModuleIdentNumber
Module identification number does not match.
@ WrongSubmoduleIdentNumber
Submodule identification number does not match.
static constexpr std::uint8_t LowByteMask
Bitmask used to isolate the lowest significant byte (8 bits) of a larger integer.
Definition util.h:59
PnioCmAlarmCrErrorCode2
PNIO-CM Alarm CR ErrorCode2 values.
Definition exceptions.h:353
@ NoAlarmCrResources
No Alarm CR resources are available.
@ InvalidAlarmCrType
Invalid Alarm CR type.
std::string GetPnioCmErrorMessage(PnioCmArErrorCode2 errorCode2)
Get the human-readable message for a PNIO-CM AR error.
PnioRwErrorCode1
PNIO read/write ErrorCode1 values.
Definition exceptions.h:46
@ WriteLength
Write length error.
@ Resource
Resource error.
@ Application
Application error.
@ InvalidIndex
Invalid or unsupported index.
PnioCmDeviceErrorCode2
PNIO-CM Device ErrorCode2 values.
Definition exceptions.h:404
@ ConnectionResourceUnavailable
No connection management resources are available.
@ DeviceStateConflict
Device state conflict.
@ ArSetAborted
The application relation set was aborted.
@ AlreadyOwned
The device is already owned.
std::string GetErrorDecodeName(ErrorDecode errorDecodeName)
Get the human-readable name for an ErrorDecode value.
PnioCmArErrorCode2
PNIO-CM AR ErrorCode2 values.
Definition exceptions.h:281
@ InvalidSessionKey
The session key is invalid.
@ NoAlarmResources
No alarm resources are available.
@ NoConsumerResources
No consumer resources are available.
@ InvalidArType
Invalid AR type.
@ ArAlreadyActive
AR is already active.
@ NoMemory
No memory is available.
@ NoArResources
No AR resources are available.
@ NoProviderResources
No provider resources are available.
@ ArUuidConflict
The AR UUID conflicts with an existing AR.
PnioRwApplicationErrorCode2
PNIORW Application ErrorCode2 values.
Definition exceptions.h:246
@ AlarmPending
An alarm is pending.
@ BackupNotAllowed
Backup is not allowed.
@ InvalidApi
API number is invalid.
PnioCmFaultyBlockErrorCode2
PNIO-CM Faulty Block ErrorCode2 values.
Definition exceptions.h:430
@ FaultyBlockStructure
Faulty block structure.
Declares Linux Ethernet, addressing, timing, and utility helpers used by the PROFINET stack.