17#include <gtest/gtest.h>
42std::filesystem::path FindGsdmlFile(
const std::string& fileName)
44 const std::vector<std::filesystem::path> candidates = {
52 for (
const auto& candidate : candidates)
54 if (std::filesystem::exists(candidate))
60 ADD_FAILURE() <<
"Unable to locate GSDML fixture '" << fileName <<
"'";
71GSDMLDevice ParseAumaGsdml()
73 const auto path = FindGsdmlFile(
"GSDML-V2.42-AUMA-SGX-20220920.xml");
90GSDMLDevice ParsePhoenixGsdml()
92 const auto path = FindGsdmlFile(
"GSDML-V2.45-Phoenix Contact-AXC F 1252-20250813.xml");
107const rpc::IOSlot* FindSlot(
const std::vector<rpc::IOSlot>& slots,
108 std::uint16_t slotNumber)
110 for (
const auto& slot : slots)
112 if (slot.slot == slotNumber)
127const rpc::IOSlot* FindSlot(
const std::vector<rpc::IOSlot>& slots,
128 std::uint16_t slotNumber,
129 std::uint16_t subslotNumber)
131 for (
const auto& slot : slots)
133 if ((slot.slot == slotNumber) && (slot.subslot == subslotNumber))
151 auma = ParseAumaGsdml();
165 EXPECT_EQ(auma.vendorId, 0x013F);
166 EXPECT_EQ(auma.deviceId, 0x0002);
167 EXPECT_EQ(auma.dapModuleIdentNumber, 0x80010000U);
173 EXPECT_EQ(phoenix.vendorId, 0x00B0);
174 EXPECT_EQ(phoenix.deviceId, 0x0193);
175 EXPECT_EQ(phoenix.dapModuleIdentNumber, 0x00000300U);
181 EXPECT_EQ(auma.vendorId, 0x013F);
187 EXPECT_EQ(auma.deviceId, 0x0002);
193 ASSERT_NE(auma.dapModuleIdentNumber, 0U);
194 EXPECT_EQ(auma.dapModuleIdentNumber, 0x80010000U);
195 EXPECT_EQ(auma.dapSubmoduleIdentNumber, 0x00000001U);
196 EXPECT_EQ(auma.dapSlots, (std::vector<int>{0, 1, 2}));
202 const auto*
module = auma.FindModule("ID_MODULE_ADI_IN_0");
204 ASSERT_NE(module,
nullptr);
205 EXPECT_EQ(module->moduleIdentNumber, 0x00008000U);
206 EXPECT_EQ(module->submodules.size(), 1U);
212 const auto*
module = auma.FindModule("ID_MODULE_ADI_OUT_0");
214 ASSERT_NE(module,
nullptr);
215 EXPECT_EQ(module->moduleIdentNumber, 0x00008100U);
216 EXPECT_EQ(module->submodules.size(), 1U);
222 const auto*
module = auma.FindModule("ID_MODULE_ADI_IN_0");
224 ASSERT_NE(module,
nullptr);
226 const auto submodule =
module->submodules.find("ID_SUBMOD_ADI_IN_0");
228 ASSERT_NE(submodule, module->submodules.end());
229 EXPECT_EQ(submodule->second.inputLength, 34);
230 EXPECT_EQ(submodule->second.outputLength, 0);
236 const auto*
module = auma.FindModule("ID_MODULE_ADI_OUT_0");
238 ASSERT_NE(module,
nullptr);
240 const auto submodule =
module->submodules.find("ID_SUBMOD_ADI_OUT_0");
242 ASSERT_NE(submodule, module->submodules.end());
243 EXPECT_EQ(submodule->second.inputLength, 0);
244 EXPECT_EQ(submodule->second.outputLength, 16);
250 const auto*
module = auma.FindModule("ID_MODULE_ADI_IN_0");
252 ASSERT_NE(module,
nullptr);
254 const auto submodule =
module->submodules.find("ID_SUBMOD_ADI_IN_0");
256 ASSERT_NE(submodule, module->submodules.end());
257 EXPECT_EQ(submodule->second.submoduleIdentNumber, 0x00002200U);
263 const auto*
module = auma.FindModule("ID_MODULE_ADI_OUT_0");
265 ASSERT_NE(module,
nullptr);
267 const auto submodule =
module->submodules.find("ID_SUBMOD_ADI_OUT_0");
269 ASSERT_NE(submodule, module->submodules.end());
270 EXPECT_EQ(submodule->second.submoduleIdentNumber, 0x10001000U);
276 const auto slots = auma.BuildIoSlots();
278 const auto* status = FindSlot(slots, 1, 1);
279 const auto* control = FindSlot(slots, 2, 1);
281 ASSERT_NE(status,
nullptr);
282 ASSERT_NE(control,
nullptr);
284 EXPECT_EQ(status->inputLength, 34);
285 EXPECT_EQ(status->outputLength, 0);
287 EXPECT_EQ(control->inputLength, 0);
288 EXPECT_EQ(control->outputLength, 16);
294 const auto slots = auma.BuildIoSlots();
296 const auto* status = FindSlot(slots, 1, 1);
297 const auto* control = FindSlot(slots, 2, 1);
299 ASSERT_NE(status,
nullptr);
300 ASSERT_NE(control,
nullptr);
302 EXPECT_EQ(status->outputLength, 0);
303 EXPECT_EQ(control->outputLength, 16);
309 const auto slots = auma.BuildIoSlots();
311 const auto* status = FindSlot(slots, 1, 1);
312 const auto* control = FindSlot(slots, 2, 1);
314 ASSERT_NE(status,
nullptr);
315 ASSERT_NE(control,
nullptr);
317 EXPECT_EQ(status->moduleIdent, 0x00008000U);
318 EXPECT_EQ(status->submoduleIdent, 0x00002200U);
320 EXPECT_EQ(control->moduleIdent, 0x00008100U);
321 EXPECT_EQ(control->submoduleIdent, 0x10001000U);
327 const auto*
module = phoenix.FindModule("PNSlot1");
329 ASSERT_NE(module,
nullptr);
330 EXPECT_EQ(module->moduleIdentNumber, 0x00000001U);
336 EXPECT_EQ(phoenix.dapModuleIdentNumber, 0x00000300U);
337 EXPECT_EQ(phoenix.dapSubmoduleIdentNumber, 0x00000001U);
343 const auto slots = phoenix.BuildIoSlots();
345 ASSERT_EQ(slots.size(), 4U);
347 const auto* dap = FindSlot(slots, 0, 1);
348 const auto*
interface = FindSlot(slots, 0, 0x8000);
349 const auto* port = FindSlot(slots, 0, 0x8001);
350 const auto* io = FindSlot(slots, 1, 1);
352 ASSERT_NE(dap,
nullptr);
353 ASSERT_NE(interface,
nullptr);
354 ASSERT_NE(port,
nullptr);
355 ASSERT_NE(io,
nullptr);
357 EXPECT_EQ(dap->moduleIdent, phoenix.dapModuleIdentNumber);
358 EXPECT_EQ(dap->submoduleIdent, phoenix.dapSubmoduleIdentNumber);
360 EXPECT_EQ(interface->submoduleIdent, 0x00000002U);
361 EXPECT_EQ(port->submoduleIdent, 0x00000003U);
363 EXPECT_EQ(io->moduleIdent, 0x00000001U);
364 EXPECT_EQ(io->submoduleIdent, 0x00000001U);
370 const auto slots = phoenix.BuildIoSlots();
372 const auto* slot = FindSlot(slots, 1, 1);
374 ASSERT_NE(slot,
nullptr);
376 EXPECT_EQ(slot->moduleIdent, 0x00000001U);
377 EXPECT_EQ(slot->submoduleIdent, 0x00000001U);
378 EXPECT_EQ(slot->inputLength, 512);
379 EXPECT_EQ(slot->outputLength, 512);
386 const auto*
module = phoenix.FindModule("PNSlot1");
388 ASSERT_NE(module,
nullptr);
389 ASSERT_EQ(module->submoduleReferences.size(), 9U);
391 const auto* submodule = phoenix.FindSubmodule(
"PNIO512512");
393 ASSERT_NE(submodule,
nullptr);
395 EXPECT_EQ(submodule->submoduleIdentNumber, 0x00000001U);
396 EXPECT_EQ(submodule->inputLength, 512);
397 EXPECT_EQ(submodule->outputLength, 512);
404 const auto*
module = phoenix.FindModule("PNSlot1");
406 ASSERT_NE(module,
nullptr);
408 bool foundUsedSubslot =
false;
410 for (
const auto& reference :
module->submoduleReferences)
412 if (reference.submoduleId == "PNIO512512")
414 foundUsedSubslot = true;
416 EXPECT_EQ(reference.allowedSubslots, (std::vector<int>{1}));
417 EXPECT_EQ(reference.fixedSubslots, std::vector<int>{});
418 EXPECT_EQ(reference.usedSubslots, (std::vector<int>{1}));
422 EXPECT_TRUE(foundUsedSubslot);
429 EXPECT_EQ(phoenix.applicationRelations.numberOfAr, 3U);
431 EXPECT_EQ(phoenix.applicationRelations.sendClockTimingProperties,
432 (std::vector<std::uint16_t>{32}));
434 EXPECT_EQ(phoenix.applicationRelations.reductionRatioTimingProperties,
435 (std::vector<std::uint16_t>{
436 1, 2, 4, 8, 16, 32, 64, 128, 256, 512}));
439 phoenix.applicationRelations.startupMode,
440 rpc::StartupMode::Advanced);
447 const auto slots = phoenix.BuildIoSlots();
449 const auto* slot = FindSlot(slots, 0, 1);
451 ASSERT_NE(slot,
nullptr);
453 EXPECT_EQ(slot->moduleIdent, phoenix.dapModuleIdentNumber);
454 EXPECT_EQ(slot->submoduleIdent, phoenix.dapSubmoduleIdentNumber);
455 EXPECT_EQ(slot->inputLength, 0U);
456 EXPECT_EQ(slot->outputLength, 0U);
463 const auto slots = phoenix.BuildIoSlots();
465 const auto* slot = FindSlot(slots, 0, 0x8000);
467 ASSERT_NE(slot,
nullptr);
469 EXPECT_EQ(slot->submoduleIdent, 0x00000002U);
470 EXPECT_EQ(slot->inputLength, 0U);
471 EXPECT_EQ(slot->outputLength, 0U);
478 const auto slots = phoenix.BuildIoSlots();
480 const auto* slot = FindSlot(slots, 0, 0x8001);
482 ASSERT_NE(slot,
nullptr);
484 EXPECT_EQ(slot->submoduleIdent, 0x00000003U);
485 EXPECT_EQ(slot->inputLength, 0U);
486 EXPECT_EQ(slot->outputLength, 0U);
493 const auto slots = phoenix.BuildIoSlots(
494 {{1,
"PNSlot1", 1,
"PNIO0202"}});
496 const auto* slot = FindSlot(slots, 1, 1);
498 ASSERT_NE(slot,
nullptr);
500 EXPECT_EQ(slot->moduleIdent, 0x00000001U);
501 EXPECT_EQ(slot->submoduleIdent, 0x00000009U);
502 EXPECT_EQ(slot->inputLength, 2U);
503 EXPECT_EQ(slot->outputLength, 2U);
511 phoenix.BuildIoSlots(
512 {{2,
"PNSlot1", 1,
"PNIO0202"}}),
513 std::invalid_argument);
521 phoenix.BuildIoSlots(
522 {{1,
"DOES_NOT_EXIST", 1,
"PNIO0202"}}),
523 std::invalid_argument);
531 phoenix.BuildIoSlots(
532 {{1,
"PNSlot1", 1,
"DOES_NOT_EXIST"}}),
533 std::invalid_argument);
541 phoenix.BuildIoSlots(
542 {{1,
"PNSlot1", 2,
"PNIO0202"}}),
543 std::invalid_argument);
550 const auto first = phoenix.BuildIoSlots();
551 const auto second = phoenix.BuildIoSlots();
553 ASSERT_EQ(first.size(), second.size());
555 for (std::size_t index = 0; index < first.size(); ++index)
557 EXPECT_EQ(first[index].slot, second[index].slot);
558 EXPECT_EQ(first[index].subslot, second[index].subslot);
559 EXPECT_EQ(first[index].moduleIdent, second[index].moduleIdent);
560 EXPECT_EQ(first[index].submoduleIdent, second[index].submoduleIdent);
561 EXPECT_EQ(first[index].inputLength, second[index].inputLength);
562 EXPECT_EQ(first[index].outputLength, second[index].outputLength);
570 for (
const auto& [moduleId, module] : auma.modules)
574 for (
const auto& [submoduleId, submodule] :
module.submodules)
580 for (
const auto& item : submodule.inputItems)
585 EXPECT_EQ(
length, submodule.inputLength)
586 <<
"Module '" <<
module.id
587 << "', submodule '" << submodule.id << "'";
596 for (
const auto& [moduleId, module] : auma.modules)
600 for (
const auto& [submoduleId, submodule] :
module.submodules)
606 for (
const auto& item : submodule.outputItems)
611 EXPECT_EQ(
length, submodule.outputLength)
612 <<
"Module '" <<
module.id
613 << "', submodule '" << submodule.id << "'";
622 for (
const auto& [submoduleId, submodule] : phoenix.submodules)
628 for (
const auto& item : submodule.inputItems)
633 EXPECT_EQ(
length, submodule.inputLength)
634 <<
"Submodule '" << submodule.id <<
"'";
642 for (
const auto& [submoduleId, submodule] : phoenix.submodules)
648 for (
const auto& item : submodule.outputItems)
653 EXPECT_EQ(
length, submodule.outputLength)
654 <<
"Submodule '" << submodule.id <<
"'";
661 const auto slots = auma.BuildIoSlots();
663 const auto* dap = FindSlot(slots, 0, 1);
664 const auto* input = FindSlot(slots, 1, 1);
665 const auto* output = FindSlot(slots, 2, 1);
667 ASSERT_NE(dap,
nullptr);
668 ASSERT_NE(input,
nullptr);
669 ASSERT_NE(output,
nullptr);
671 EXPECT_EQ(dap->moduleIdent, auma.dapModuleIdentNumber);
672 EXPECT_EQ(dap->submoduleIdent, auma.dapSubmoduleIdentNumber);
674 EXPECT_EQ(input->moduleIdent, 0x00008000U);
675 EXPECT_EQ(input->submoduleIdent, 0x00002200U);
676 EXPECT_EQ(input->inputLength, 34U);
677 EXPECT_EQ(input->outputLength, 0U);
679 EXPECT_EQ(output->moduleIdent, 0x00008100U);
680 EXPECT_EQ(output->submoduleIdent, 0x10001000U);
681 EXPECT_EQ(output->inputLength, 0U);
682 EXPECT_EQ(output->outputLength, 16U);
688 const auto vendorId = auma.vendorId;
689 const auto deviceId = auma.deviceId;
690 const auto moduleCount = auma.modules.size();
691 const auto submoduleCount = auma.submodules.size();
693 const auto first = auma.BuildIoSlots();
694 const auto second = auma.BuildIoSlots();
696 EXPECT_EQ(vendorId, auma.vendorId);
697 EXPECT_EQ(deviceId, auma.deviceId);
698 EXPECT_EQ(moduleCount, auma.modules.size());
699 EXPECT_EQ(submoduleCount, auma.submodules.size());
701 ASSERT_EQ(first.size(), second.size());
703 for (std::size_t index = 0; index < first.size(); ++index)
705 EXPECT_EQ(first[index].slot, second[index].slot);
706 EXPECT_EQ(first[index].subslot, second[index].subslot);
707 EXPECT_EQ(first[index].moduleIdent, second[index].moduleIdent);
708 EXPECT_EQ(first[index].submoduleIdent, second[index].submoduleIdent);
709 EXPECT_EQ(first[index].inputLength, second[index].inputLength);
710 EXPECT_EQ(first[index].outputLength, second[index].outputLength);
718 const auto* inputModule = auma.FindModule(
"ID_MODULE_ADI_IN_0");
719 const auto* outputModule = auma.FindModule(
"ID_MODULE_ADI_OUT_0");
721 ASSERT_NE(inputModule,
nullptr);
722 ASSERT_NE(outputModule,
nullptr);
725 inputModule->submodules.find(
"ID_SUBMOD_ADI_IN_0");
726 const auto outputIt =
727 outputModule->submodules.find(
"ID_SUBMOD_ADI_OUT_0");
729 ASSERT_NE(inputIt, inputModule->submodules.end());
730 ASSERT_NE(outputIt, outputModule->submodules.end());
732 const auto slots = auma.BuildIoSlots();
734 const auto* input = FindSlot(slots, 1, 1);
735 const auto* output = FindSlot(slots, 2, 1);
737 ASSERT_NE(input,
nullptr);
738 ASSERT_NE(output,
nullptr);
740 EXPECT_EQ(input->inputLength, inputIt->second.inputLength);
741 EXPECT_EQ(input->outputLength, inputIt->second.outputLength);
743 EXPECT_EQ(output->inputLength, outputIt->second.inputLength);
744 EXPECT_EQ(output->outputLength, outputIt->second.outputLength);
751 const auto firstPath =
752 FindGsdmlFile(
"GSDML-V2.42-AUMA-SGX-20220920.xml");
754 ASSERT_FALSE(firstPath.empty());
756 const auto first =
ParseGsdml(firstPath.string());
757 const auto second =
ParseGsdml(firstPath.string());
759 EXPECT_EQ(first.vendorId, second.vendorId);
760 EXPECT_EQ(first.deviceId, second.deviceId);
761 EXPECT_EQ(first.dapModuleId, second.dapModuleId);
762 EXPECT_EQ(first.dapModuleIdentNumber, second.dapModuleIdentNumber);
763 EXPECT_EQ(first.dapSubmoduleIdentNumber, second.dapSubmoduleIdentNumber);
764 EXPECT_EQ(first.modules.size(), second.modules.size());
765 EXPECT_EQ(first.submodules.size(), second.submodules.size());
770 const auto slots = auma.BuildIoSlots();
771 const auto numberOfIoSlotEntries = slots.size();
772 ASSERT_EQ(numberOfIoSlotEntries, 9U);
788 ASSERT_NE(FindSlot(slots, 0, 0x0001),
nullptr);
789 ASSERT_NE(FindSlot(slots, 0, 0x0002),
nullptr);
790 ASSERT_NE(FindSlot(slots, 0, 0x0003),
nullptr);
791 ASSERT_NE(FindSlot(slots, 0, 0x0004),
nullptr);
792 ASSERT_NE(FindSlot(slots, 0, 0x8000),
nullptr);
793 ASSERT_NE(FindSlot(slots, 0, 0x8001),
nullptr);
794 ASSERT_NE(FindSlot(slots, 0, 0x8002),
nullptr);
800 ASSERT_NE(FindSlot(slots, 1, 1),
nullptr);
801 ASSERT_NE(FindSlot(slots, 2, 1),
nullptr);
807 const auto slots = auma.BuildIoSlots();
809 const auto* status = FindSlot(slots, 1, 1);
810 const auto* control = FindSlot(slots, 2, 1);
812 ASSERT_NE(status,
nullptr);
813 ASSERT_NE(control,
nullptr);
815 EXPECT_EQ(status->inputLength, 34U);
816 EXPECT_EQ(status->outputLength, 0U);
818 EXPECT_EQ(control->inputLength, 0U);
819 EXPECT_EQ(control->outputLength, 16U);
828bool Contains(
const std::vector<int>& values,
const int value)
830 return std::ranges::find(values, value) != values.end();
844 if (signal.
moduleId == device.dapModuleId)
849 const auto*
module = device.FindModule(signal.moduleId);
850 if (module ==
nullptr)
855 const auto inlineIt =
module->submodules.find(signal.submoduleId);
856 if (inlineIt != module->submodules.end())
858 return &inlineIt->second;
869const rpc::IOSlot* FindSignalIoSlot(
const std::vector<rpc::IOSlot>& slots,
const profinet::io::IoSignal& signal)
871 for (
const auto& slot : slots)
888 EXPECT_GT(catalog.Size(), 0U);
889 EXPECT_GT(catalog.Sensors().size(), 0U);
890 EXPECT_GT(catalog.Actuators().size(), 0U);
892 for (
const auto& signal : catalog.Sensors())
896 EXPECT_FALSE(signal.
name.empty());
901 for (
const auto& signal : catalog.Actuators())
905 EXPECT_FALSE(signal.
name.empty());
916 ASSERT_GT(catalog.Sensors().size(), 0U);
918 for (
const auto& signal : catalog.Sensors())
920 if (signal.
moduleId !=
"ID_MODULE_ADI_IN_0")
925 EXPECT_EQ(signal.
submoduleId,
"ID_SUBMOD_ADI_IN_0");
938 ASSERT_GT(catalog.Actuators().size(), 0U);
940 for (
const auto& signal : catalog.Actuators())
942 if (signal.
moduleId !=
"ID_MODULE_ADI_OUT_0")
947 EXPECT_EQ(signal.
submoduleId,
"ID_SUBMOD_ADI_OUT_0");
960 for (
const auto& signal : catalog.Sensors())
962 const auto* submodule = FindSignalSubmodule(auma, signal);
964 ASSERT_NE(submodule,
nullptr)
965 <<
"Unable to resolve sensor submodule '" << signal.
submoduleId <<
"'";
969 static_cast<std::size_t
>(submodule->inputLength))
970 <<
"Signal '" << signal.
name <<
"' exceeds input process-data length";
973 for (
const auto& signal : catalog.Actuators())
975 const auto* submodule = FindSignalSubmodule(auma, signal);
977 ASSERT_NE(submodule,
nullptr)
978 <<
"Unable to resolve actuator submodule '" << signal.
submoduleId <<
"'";
981 EXPECT_LE(signal.
byteOffset + signal.
byteLength,
static_cast<std::size_t
>(submodule->outputLength))
982 <<
"Signal '" << signal.
name <<
"' exceeds output process-data length";
991 for (
const auto& signal : catalog.Sensors())
994 <<
"Reserved sensor signal exposed: '" << signal.
name <<
"'";
997 for (
const auto& signal : catalog.Actuators())
1000 <<
"Reserved actuator signal exposed: '" << signal.
name <<
"'";
1009 ASSERT_GT(catalog.Size(), 0U);
1011 for (
const auto& signal : catalog.Sensors())
1015 <<
"' for signal '" << signal.
name <<
"'";
1018 for (
const auto& signal : catalog.Actuators())
1021 <<
"Unsupported actuator DataType '" << signal.
gsdmlDataType
1022 <<
"' for signal '" << signal.
name <<
"'";
1031 EXPECT_GT(catalog.Size(), 0U);
1033 for (
const auto& signal : catalog.Sensors())
1035 EXPECT_FALSE(signal.
name.empty());
1040 for (
const auto& signal : catalog.Actuators())
1042 EXPECT_FALSE(signal.
name.empty());
1053 for (
const auto& signal : catalog.Sensors())
1058 for (
const auto& signal : catalog.Actuators())
1067 const auto slots = auma.BuildIoSlots();
1069 const auto* status = FindSlot(slots, 1, 1);
1070 const auto* control = FindSlot(slots, 2, 1);
1072 ASSERT_NE(status,
nullptr);
1073 ASSERT_NE(control,
nullptr);
1075 for (
const auto& signal : catalog.Sensors())
1077 if (signal.
moduleId !=
"ID_MODULE_ADI_IN_0")
1086 static_cast<std::size_t
>(status->inputLength));
1089 for (
const auto& signal : catalog.Actuators())
1091 if (signal.
moduleId !=
"ID_MODULE_ADI_OUT_0")
1100 static_cast<std::size_t
>(control->outputLength));
1106 const auto*
module = auma.FindModule("ID_MODULE_ADI_IN_0");
1108 ASSERT_NE(module,
nullptr);
1110 const auto it =
module->submodules.find("ID_SUBMOD_ADI_IN_0");
1112 ASSERT_NE(it, module->submodules.end());
1114 const auto& items = it->second.inputItems;
1116 ASSERT_GE(items.size(), 1U);
1118 const auto& log = items[0];
1120 EXPECT_EQ(log.textId,
"T_ID_LOG");
1121 EXPECT_EQ(log.dataType,
"Unsigned8");
1122 EXPECT_EQ(log.length, 1);
1123 EXPECT_TRUE(log.useAsBits);
1125 ASSERT_EQ(log.bitDataItems.size(), 8U);
1127 for (std::size_t index = 0; index < log.bitDataItems.size(); ++index)
1129 EXPECT_EQ(log.bitDataItems[index].bitOffset, index);
1131 log.bitDataItems[index].textId,
1132 "T_ID_LOG_" + std::to_string(index));
1141 std::vector<const profinet::io::IoSignal*> logBits;
1143 for (
const auto& signal : catalog.Sensors())
1147 logBits.push_back(&signal);
1151 ASSERT_EQ(logBits.size(), 8U);
1153 std::ranges::sort(logBits, [](
const auto* lhs,
const auto* rhs)
1155 return lhs->bitOffset < rhs->bitOffset;
1158 for (std::size_t index = 0; index < logBits.size(); ++index)
1160 const auto& signal = *logBits[index];
1163 EXPECT_EQ(signal.
textId,
"T_ID_LOG_" + std::to_string(index));
1173 const auto catalog =
1176 std::vector<const profinet::io::IoSignal*> commandBits;
1178 for (
const auto& signal : catalog.Actuators())
1182 commandBits.push_back(&signal);
1186 ASSERT_EQ(commandBits.size(), 5U);
1188 std::ranges::sort(commandBits, [](
const auto* lhs,
const auto* rhs)
1190 return lhs->bitOffset < rhs->bitOffset;
1193 for (std::size_t index = 0;
1194 index < commandBits.size();
1197 const auto& signal = *commandBits[index];
Defines the GSDML-derived logical process-data signal catalogue.
GoogleTest fixture for real vendor GSDML regression tests.
GSDMLDevice phoenix
Parsed Phoenix APLC.
void SetUp() override
Parse the AUMA GSDML once before each test.
GSDMLDevice auma
Parsed AUMA SGx device.
static IoSignalCatalog FromGsdml(const gsdml::GSDMLDevice &device)
Build a signal catalogue from a parsed GSDML device.
Declares the GSDML parser and PROFINET device-description data model.
GSDMLDevice ParseGsdml(const std::string &path)
Parse a GSDML file into a GSDMLDevice.
TEST_F(GsdmlRealDeviceTest, ParsesAumaGsdml)
bool IsReservedSignal(std::string_view textId, std::string_view name) noexcept
Determine whether a DataItem should be hidden from the normal signal catalogue.
@ Boolean
Boolean value, represented by the connector as 0.0 or 1.0.
@ Unsupported
Data for which this catalogue does not define a numeric double representation.
std::filesystem::path GetExecutableDirectory()
Retrieves the absolute directory path of the currently running executable.
Complete parsed GSDML device profile.
Describes one logical process-data signal available from a GSDML device.
bool IsSensor() const noexcept
Returns whether this signal is an input/sensor.
bool IsActuator() const noexcept
Returns whether this signal is an output/actuator.
std::uint32_t moduleIdentNumber
Module ident number of the containing module.
std::size_t byteLength
Size of the GSDML DataItem in bytes.
bool IsBitSignal() const noexcept
Returns whether this signal represents one BitDataItem.
std::string gsdmlDataType
GSDML DataType string.
std::size_t bitOffset
Bit offset within the containing DataItem.
std::size_t parentDataItemByteOffset
Byte offset of the parent DataItem.
std::string textId
Original GSDML TextId.
std::string submoduleId
GSDML submodule identifier containing the signal.
std::vector< int > possibleSubslots
Subslots in which the containing submodule may occur, when known.
std::string parentDataItemTextId
TextId of the parent DataItem.
std::uint32_t submoduleIdentNumber
Submodule ident number of the containing submodule.
std::size_t byteOffset
Byte offset within the submodule's input or output process-data area.
IoSignalValueType valueType
Logical value category inferred from gsdmlDataType.
std::string name
Current display name of the signal.
std::vector< int > possibleSlots
Slots in which the containing module may occur, when known.
std::string moduleId
GSDML module identifier containing the signal.
TEST_F(AlarmItemTest, ParseChannelDiagnosis)