33#include <libxml/parser.h>
34#include <libxml/tree.h>
35#include <libxml/xpath.h>
36#include <libxml/xpathInternals.h>
58 xmlDocPtr
doc =
nullptr;
68struct XPathContextGuard
70 xmlXPathContextPtr
ctx =
nullptr;
75 xmlXPathFreeContext(
ctx);
80struct XPathObjectGuard
82 xmlXPathObjectPtr
obj =
nullptr;
87 xmlXPathFreeObject(
obj);
98std::string EscapeXPathLiteral(
const std::string& s)
104 if (s.find(
'\'') == std::string::npos)
106 return "'" + s +
"'";
108 std::ostringstream oss;
120 oss <<
"'" << cur <<
"'";
136 oss <<
"'" << cur <<
"'";
144std::vector<xmlNodePtr> XPathFind(xmlXPathContextPtr
ctx, xmlNodePtr node,
const std::string& expr)
146 xmlXPathContextPtr currentCtx =
ctx;
147 xmlNodePtr savedNode = currentCtx->node;
150 currentCtx->node = node;
153 XPathObjectGuard guard;
154 guard.obj = xmlXPathEvalExpression(
reinterpret_cast<const xmlChar*
>(expr.c_str()), currentCtx);
155 currentCtx->node = savedNode;
157 std::vector<xmlNodePtr> result;
158 if ((guard.obj ==
nullptr) || (guard.obj->nodesetval ==
nullptr))
162 for (
int i = 0; i < guard.obj->nodesetval->nodeNr; ++i)
164 result.push_back(guard.obj->nodesetval->nodeTab[i]);
170xmlNodePtr FindFirst(xmlXPathContextPtr
ctx, xmlNodePtr node,
const std::string& tag)
172 auto results = XPathFind(
ctx, node,
".//*[local-name()='" + tag +
"']");
173 return results.empty() ? nullptr : results.front();
177std::vector<xmlNodePtr> FindAll(xmlXPathContextPtr
ctx, xmlNodePtr node,
const std::string& tag)
179 return XPathFind(
ctx, node,
".//*[local-name()='" + tag +
"']");
183std::vector<xmlNodePtr> FindChildren(xmlXPathContextPtr
ctx, xmlNodePtr node,
const std::string& tag)
185 return XPathFind(
ctx, node,
"./*[local-name()='" + tag +
"']");
188std::string GetAttr(xmlNodePtr node,
const std::string& name,
const std::string& Default =
"")
194 xmlChar* val = xmlGetProp(node,
reinterpret_cast<const xmlChar*
>(name.c_str()));
199 std::string result(
reinterpret_cast<const char*
>(val));
204std::optional<std::string> GetAttrOpt(xmlNodePtr node,
const std::string& name)
210 xmlChar* val = xmlGetProp(node,
reinterpret_cast<const xmlChar*
>(name.c_str()));
215 std::string result(
reinterpret_cast<const char*
>(val));
225bool ParseBool(
const std::optional<std::string>& spec,
const bool defaultValue =
false)
231 std::string str = *spec;
234 str.erase(str.begin(), std::ranges::find_if(str, [](
unsigned char ch)
236 return !std::isspace(ch);
240 str.erase(std::ranges::find_if(std::views::reverse(str), [](
unsigned char ch)
242 return !std::isspace(ch);
261 std::ranges::transform(str, str.begin(), [](
unsigned char c)
263 return static_cast<char>(std::tolower(c));
279std::uint32_t ParseInt(
const std::optional<std::string>& spec)
285 const std::string& s = *spec;
291 if (s.size() > 3 && s[0] ==
'#' && s[1] ==
'1' && s[2] ==
'6' && s[3] ==
'#')
293 return static_cast<std::uint32_t
>(std::stoul(s.substr(4),
nullptr, 16));
295 if (s.size() > 2 && s[0] ==
'0' && (s[1] ==
'x' || s[1] ==
'X'))
297 return static_cast<std::uint32_t
>(std::stoul(s.substr(2),
nullptr, 16));
301 return static_cast<std::uint32_t
>(std::stoul(s,
nullptr, 10));
303 catch (
const std::exception&)
316void ParseBitDataItems(xmlXPathContextPtr
ctx, xmlNodePtr dataItemNode, GSDMLDataItem& dataItem,
const std::map<std::string, std::string>& textTable)
318 dataItem.useAsBits = ParseBool(GetAttrOpt(dataItemNode,
"UseAsBits"));
320 for (
auto* bitNode : FindChildren(
ctx, dataItemNode,
"BitDataItem"))
322 GSDMLBitDataItem bit;
324 const auto bitOffset = GetAttrOpt(bitNode,
"BitOffset");
325 if (!bitOffset.has_value())
327 throw std::invalid_argument(
"GSDML BitDataItem is missing BitOffset");
330 bit.bitOffset =
static_cast<std::size_t
>(ParseInt(bitOffset));
331 bit.textId = GetAttr(bitNode,
"TextId");
333 const auto bitCount =
static_cast<std::size_t
>(dataItem.length) * 8U;
335 if (bit.bitOffset >= bitCount)
337 throw std::invalid_argument(
338 "GSDML BitDataItem offset is outside its DataItem");
340 const auto textIt = textTable.find(bit.textId);
342 bit.name = (textIt != textTable.end())
346 dataItem.bitDataItems.push_back(std::move(bit));
351 if (!dataItem.bitDataItems.empty())
353 dataItem.useAsBits =
true;
355 if (!dataItem.textId.empty())
357 const auto textIt = textTable.find(dataItem.textId);
359 if (textIt != textTable.end())
361 dataItem.name = textIt->second;
365 dataItem.name = dataItem.textId;
371std::vector<int> ParseSlotSpec(
const std::optional<std::string>& spec)
373 std::vector<int> result;
374 if (!spec || spec->empty())
379 std::string s = *spec;
380 std::ranges::replace(s,
',',
' ');
381 std::istringstream iss(s);
385 auto dotdot = part.find(
"..");
386 if (dotdot != std::string::npos)
388 int start = std::stoi(part.substr(0, dotdot));
389 int end = std::stoi(part.substr(dotdot + 2));
390 for (
int i = start; i <= end; ++i)
397 result.push_back(std::stoi(part));
405const std::map<std::string, int>& TypeSizeTable()
407 static const std::map<std::string, int> table = {
424 {
"TimeDifference", 4},
425 {
"F_MessageTrailer4Byte", 4},
426 {
"F_MessageTrailer5Byte", 5},
431int DataItemLength(
const std::string& dataType,
const std::optional<std::string>& lengthAttr)
433 if (dataType ==
"OctetString" || dataType ==
"VisibleString")
435 return lengthAttr ?
static_cast<int>(ParseInt(lengthAttr)) : 0;
437 auto it = TypeSizeTable().find(dataType);
438 return it != TypeSizeTable().end() ? it->second : 1;
446std::map<std::string, std::string> BuildTextTable(xmlXPathContextPtr
ctx, xmlNodePtr root)
448 std::map<std::string, std::string> table;
449 for (
auto* textNode : FindAll(
ctx, root,
"Text"))
451 auto id = GetAttrOpt(textNode,
"TextId");
452 auto value = GetAttrOpt(textNode,
"Value");
462std::string ResolveName(xmlXPathContextPtr
ctx, xmlNodePtr parent,
const std::map<std::string, std::string>& textTable,
463 const std::string& fallback)
465 xmlNodePtr nameNode = FindFirst(
ctx, parent,
"Name");
466 if (nameNode ==
nullptr)
471 if (
auto textId = GetAttrOpt(nameNode,
"TextId"))
473 auto it = textTable.find(*textId);
474 if (it != textTable.end())
479 if (
auto value = GetAttrOpt(nameNode,
"Value"))
487std::string ResolveInfoText(xmlXPathContextPtr
ctx, xmlNodePtr parent,
const std::map<std::string, std::string>& textTable,
488 const std::string& fallback)
490 xmlNodePtr infoTextNode = FindFirst(
ctx, parent,
"InfoText");
491 if (infoTextNode ==
nullptr)
496 if (
auto textId = GetAttrOpt(infoTextNode,
"TextId"))
498 auto it = textTable.find(*textId);
499 if (it != textTable.end())
504 if (
auto value = GetAttrOpt(infoTextNode,
"Value"))
512std::string ResolveVendorName(xmlXPathContextPtr
ctx, xmlNodePtr parent,
const std::map<std::string, std::string>& textTable,
513 const std::string& fallback)
515 xmlNodePtr vendorNameNode = FindFirst(
ctx, parent,
"VendorName");
516 if (vendorNameNode ==
nullptr)
521 if (
auto textId = GetAttrOpt(vendorNameNode,
"TextId"))
523 auto it = textTable.find(*textId);
524 if (it != textTable.end())
529 if (
auto value = GetAttrOpt(vendorNameNode,
"Value"))
536rpc::StartupMode ParseStartupMode(
const std::optional<std::string>& mode,
char delimiter =
';')
538 if (mode.has_value() && mode->find(
"Advanced") != std::string::npos)
546std::vector<std::uint16_t> ParseStringRanges(std::optional<std::string_view> input)
548 std::vector<std::uint16_t> result;
549 if (!input.has_value())
554 for (
auto word : input.value() | std::ranges::views::split(
' '))
562 std::string_view sv{word.begin(), word.end()};
564 auto [ptr, ec] = std::from_chars(sv.data(), sv.data() + sv.size(), val);
565 if (ec == std::errc{})
567 result.push_back(val);
577GSDMLSubmodule ParseSubmoduleNode(xmlXPathContextPtr
ctx, xmlNodePtr submoduleNode,
const std::map<std::string, std::string>& textTable)
580 sm.id = GetAttr(submoduleNode,
"ID");
581 sm.submoduleIdentNumber = ParseInt(GetAttrOpt(submoduleNode,
"SubmoduleIdentNumber"));
582 sm.name = ResolveName(
ctx, submoduleNode, textTable, sm.id);
583 sm.allowedSubslots = ParseSlotSpec(GetAttrOpt(submoduleNode,
"AllowedInSubslots"));
584 sm.fixedSubslots = ParseSlotSpec(GetAttrOpt(submoduleNode,
"FixedInSubslots"));
585 sm.usedSubslots = ParseSlotSpec(GetAttrOpt(submoduleNode,
"UsedInSubslots"));
587 xmlNodePtr ioData = FindFirst(
ctx, submoduleNode,
"IOData");
588 if (ioData !=
nullptr)
590 for (
auto* input : FindChildren(
ctx, ioData,
"Input"))
592 for (
auto* item : FindChildren(
ctx, input,
"DataItem"))
595 di.dataType = GetAttr(item,
"DataType");
596 di.textId = GetAttr(item,
"TextId");
597 di.length = DataItemLength(di.dataType, GetAttrOpt(item,
"Length"));
598 di.byteOffset = sm.inputLength;
599 ParseBitDataItems(
ctx, item, di, textTable);
601 sm.inputLength += di.length;
602 sm.inputItems.push_back(di);
605 for (
auto* output : FindChildren(
ctx, ioData,
"Output"))
607 for (
auto* item : FindChildren(
ctx, output,
"DataItem"))
610 di.dataType = GetAttr(item,
"DataType");
611 di.textId = GetAttr(item,
"TextId");
612 di.length = DataItemLength(di.dataType, GetAttrOpt(item,
"Length"));
613 di.byteOffset = sm.inputLength;
614 ParseBitDataItems(
ctx, item, di, textTable);
616 sm.outputLength += di.length;
617 sm.outputItems.push_back(di);
633 auto it =
modules.find(moduleId);
634 return it !=
modules.end() ? &it->second :
nullptr;
730 std::vector<rpc::IOSlot> slots;
745 slot.
subslot =
static_cast<std::uint16_t
>(i + 1);
751 slots.push_back(slot);
771 slots.push_back(slot);
780 const auto inlineIt =
module.submodules.find(submoduleId);
784 return &inlineIt->second;
789 return ref.submoduleId == submoduleId;
804 auto isModuleAllowedInSlot = [&](
const std::string& moduleId,
int slotNumber)
806 bool hasRestrictions =
false;
810 if (ref.moduleId != moduleId)
815 if (!ref.allowedSlots.empty())
817 hasRestrictions =
true;
819 if (std::ranges::find(
821 slotNumber) != ref.allowedSlots.end())
827 if (std::ranges::find(
829 slotNumber) != ref.fixedSlots.end())
834 if (std::ranges::find(
836 slotNumber) != ref.usedSlots.end())
842 return !hasRestrictions;
847 auto validateSubslot = [&](
const GSDMLModule& module,
const std::string& submoduleId,
int subslotNumber)
851 return ref.submoduleId == submoduleId;
859 if (!refIt->allowedSubslots.empty() &&
860 std::ranges::find(refIt->allowedSubslots, subslotNumber) == refIt->allowedSubslots.end())
862 throw std::invalid_argument(
"Submodule '" + submoduleId +
"' is not allowed in subslot " + std::to_string(subslotNumber) +
" of module '" + module.
id +
"'");
868 auto addModuleSubmodule = [&](
int slotNumber,
const std::string& moduleId,
int subslotNumber,
const std::string& submoduleId)
872 if (module ==
nullptr)
874 throw std::invalid_argument(
"Unknown module ID: " + moduleId);
889 if (!isModuleAllowedInSlot(moduleId, slotNumber))
891 throw std::invalid_argument(
"Module '" + moduleId +
"' is not allowed in slot " + std::to_string(slotNumber));
894 validateSubslot(*module, submoduleId, subslotNumber);
896 const GSDMLSubmodule* submodule = resolveSubmodule(*module, submoduleId);
898 if (submodule ==
nullptr)
900 throw std::invalid_argument(
"Unknown submodule ID '" + submoduleId +
"' in module '" + moduleId +
"'");
933 ioSlot.
slot =
static_cast<std::uint16_t
>(slotNumber);
934 ioSlot.
subslot =
static_cast<std::uint16_t
>(subslotNumber);
940 slots.push_back(ioSlot);
946 if (!plugged.empty())
948 for (
const auto& [slotNumber, moduleId, subslotNumber, submoduleId] : plugged)
1012 const GSDMLModule*
module = FindModule(moduleRef.moduleId);
1014 if (module ==
nullptr)
1016 throw std::invalid_argument(
"Unknown referenced module ID: " + moduleRef.moduleId);
1019 std::vector<int> selectedSlots;
1021 if (!moduleRef.fixedSlots.empty())
1023 selectedSlots = moduleRef.fixedSlots;
1025 else if (!moduleRef.usedSlots.empty())
1027 selectedSlots = moduleRef.usedSlots;
1035 for (
const int slotNumber : selectedSlots)
1043 for (
const auto& submoduleRef :
module->submoduleReferences)
1045 std::vector<int> selectedSubslots;
1047 if (!submoduleRef.fixedSubslots.empty())
1049 selectedSubslots = submoduleRef.fixedSubslots;
1051 else if (!submoduleRef.usedSubslots.empty())
1053 selectedSubslots = submoduleRef.usedSubslots;
1060 for (
const int subslotNumber : selectedSubslots)
1066 submoduleRef.submoduleId);
1077 for (
const auto& [submoduleId, submodule] :
module->submodules)
1079 std::vector<int> selectedSubslots;
1081 if (!submodule.fixedSubslots.empty())
1083 selectedSubslots = submodule.fixedSubslots;
1085 else if (!submodule.usedSubslots.empty())
1087 selectedSubslots = submodule.usedSubslots;
1093 selectedSubslots = {1};
1096 for (
const int subslotNumber : selectedSubslots)
1116 XmlDocGuard docGuard;
1117 docGuard.doc = xmlReadMemory(xml.data(),
static_cast<int>(xml.size()),
"gsdml.xml",
nullptr,
1118 XML_PARSE_NOBLANKS);
1119 if (docGuard.doc ==
nullptr)
1121 throw std::runtime_error(
"Failed to parse GSDML: not well-formed XML");
1124 xmlNodePtr root = xmlDocGetRootElement(docGuard.doc);
1125 if (root ==
nullptr)
1127 throw std::runtime_error(
"Failed to parse GSDML: empty document");
1130 XPathContextGuard ctxGuard;
1131 ctxGuard.ctx = xmlXPathNewContext(docGuard.doc);
1132 if (ctxGuard.ctx ==
nullptr)
1134 throw std::runtime_error(
"Failed to create XPath context");
1136 xmlXPathContextPtr
ctx = ctxGuard.ctx;
1140 xmlNodePtr primaryLanguageSection = FindFirst(
ctx, root,
"PrimaryLanguage");
1142 std::map<std::string, std::string> textTable;
1143 if (primaryLanguageSection ==
nullptr)
1145 textTable = BuildTextTable(
ctx, root);
1149 textTable = BuildTextTable(
ctx, primaryLanguageSection);
1152 xmlNodePtr deviceIdentity = FindFirst(
ctx, root,
"DeviceIdentity");
1153 if (deviceIdentity ==
nullptr)
1159 device.
vendorId =
static_cast<std::uint16_t
>(ParseInt(GetAttrOpt(deviceIdentity,
"VendorID")));
1160 device.
deviceId =
static_cast<std::uint16_t
>(ParseInt(GetAttrOpt(deviceIdentity,
"DeviceID")));
1161 device.
vendorName = ResolveName(
ctx, deviceIdentity, textTable,
"");
1164 device.
vendorName = ResolveVendorName(
ctx, deviceIdentity, textTable,
"");
1167 xmlNodePtr deviceFunction = FindFirst(
ctx, root,
"DeviceFunction");
1168 device.
deviceName = (deviceFunction !=
nullptr) ? ResolveName(
ctx, deviceFunction, textTable,
"") : device.
vendorName;
1171 xmlNodePtr dap = FindFirst(
ctx, root,
"DeviceAccessPointItem");
1178 xmlNodePtr dapModuleInfo = FindFirst(
ctx, dap,
"ModuleInfo");
1179 if (dapModuleInfo !=
nullptr)
1188 device.
dapSlots = ParseSlotSpec(GetAttrOpt(dap,
"PhysicalSlots"));
1190 xmlNodePtr sysList = FindFirst(
ctx, dap,
"SystemDefinedSubmoduleList");
1191 if (sysList !=
nullptr)
1193 for (
auto* subNode : FindChildren(
ctx, sysList,
"InterfaceSubmoduleItem"))
1198 sys.
subslot =
static_cast<std::uint16_t
>(ParseInt(GetAttrOpt(subNode,
"SubslotNumber")));
1201 xmlNodePtr moduleInfo = FindFirst(
ctx, subNode,
"ModuleInfo");
1202 if (moduleInfo !=
nullptr)
1204 sys.
moduleName = ResolveName(
ctx, moduleInfo, textTable,
"");
1212 xmlNodePtr applicationRelations = FindFirst(
ctx, subNode,
"ApplicationRelations");
1213 if (applicationRelations !=
nullptr)
1217 xmlNodePtr timingProperties = FindFirst(
ctx, applicationRelations,
"TimingProperties");
1218 if (timingProperties !=
nullptr)
1227 for (
auto* subNode : FindChildren(
ctx, sysList,
"PortSubmoduleItem"))
1232 sys.
subslot =
static_cast<std::uint16_t
>(ParseInt(GetAttrOpt(subNode,
"SubslotNumber")));
1235 xmlNodePtr moduleInfo = FindFirst(
ctx, subNode,
"ModuleInfo");
1236 if (moduleInfo !=
nullptr)
1238 sys.
moduleName = ResolveName(
ctx, moduleInfo, textTable,
"");
1250 xmlNodePtr dapVsl = FindFirst(
ctx, dap,
"VirtualSubmoduleList");
1251 if (dapVsl !=
nullptr)
1259 for (
auto* subNode : FindChildren(
ctx, dapVsl,
"VirtualSubmoduleItem"))
1282 device.
modules[dapModule.
id] = std::move(dapModule);
1287 xmlNodePtr moduleList = FindFirst(
ctx, root,
"ModuleList");
1288 if (moduleList !=
nullptr)
1290 for (
auto* moduleNode : FindChildren(
ctx, moduleList,
"ModuleItem"))
1293 mod.
id = GetAttr(moduleNode,
"ID");
1295 mod.
name = ResolveName(
ctx, moduleNode, textTable, mod.
id);
1296 mod.
physicalSubslots = ParseSlotSpec(GetAttrOpt(moduleNode,
"PhysicalSubslots"));
1298 xmlNodePtr vsl = FindFirst(
ctx, moduleNode,
"VirtualSubmoduleList");
1301 for (
auto* subNode : FindChildren(
ctx, vsl,
"VirtualSubmoduleItem"))
1314 xmlNodePtr usableSubmodules = FindFirst(
ctx, moduleNode,
"UseableSubmodules");
1316 if (usableSubmodules !=
nullptr)
1318 for (
auto* refNode : FindChildren(
ctx, usableSubmodules,
"SubmoduleItemRef"))
1321 ref.
submoduleId = GetAttr(refNode,
"SubmoduleItemTarget");
1322 ref.
allowedSubslots = ParseSlotSpec(GetAttrOpt(refNode,
"AllowedInSubslots"));
1323 ref.
fixedSubslots = ParseSlotSpec(GetAttrOpt(refNode,
"FixedInSubslots"));
1324 ref.
usedSubslots = ParseSlotSpec(GetAttrOpt(refNode,
"UsedInSubslots"));
1329 device.
modules[mod.
id] = std::move(mod);
1342 xmlNodePtr submoduleList = FindFirst(
ctx, root,
"SubmoduleList");
1344 if (submoduleList !=
nullptr)
1346 for (
auto* submoduleNode :
1347 FindChildren(
ctx, submoduleList,
"SubmoduleItem"))
1350 ParseSubmoduleNode(
ctx, submoduleNode, textTable);
1352 device.
submodules[submodule.
id] = std::move(submodule);
1358 xmlNodePtr useList = FindFirst(
ctx, (dap !=
nullptr) ? dap : root,
"UseableModules");
1359 if (useList !=
nullptr)
1361 for (
auto* useNode : FindChildren(
ctx, useList,
"ModuleItemRef"))
1368 ref.
moduleId = GetAttr(useNode,
"ModuleItemTarget");
1369 ref.
allowedSlots = ParseSlotSpec(GetAttrOpt(useNode,
"AllowedInSlots"));
1370 ref.
fixedSlots = ParseSlotSpec(GetAttrOpt(useNode,
"FixedInSlots"));
1371 ref.
usedSlots = ParseSlotSpec(GetAttrOpt(useNode,
"UsedInSlots"));
1377 xmlNodePtr fixedList = FindFirst(
ctx, (dap !=
nullptr) ? dap : root,
"PredefinedPnioModules");
1378 if (fixedList !=
nullptr)
1380 for (
auto* fixedNode : FindChildren(
ctx, fixedList,
"PnioModuleItemRef"))
1383 ref.
moduleId = GetAttr(fixedNode,
"ModuleItemTarget");
1384 ref.
fixedSlots = ParseSlotSpec(GetAttrOpt(fixedNode,
"FixedInSlots"));
1400 XmlDocGuard docGuard;
1401 docGuard.doc = xmlReadFile(path.c_str(),
nullptr, XML_PARSE_NOBLANKS);
1402 if (docGuard.doc ==
nullptr)
1404 throw std::runtime_error(
"Failed to open or parse GSDML file: " + path);
1410 xmlChar* buf =
nullptr;
1412 xmlDocDumpMemory(docGuard.doc, &buf, &size);
1413 std::string xml(
reinterpret_cast<const char*
>(buf),
static_cast<std::size_t
>(size));
Declares the GSDML parser and PROFINET device-description data model.
GSDMLDevice ParseGsdmlString(const std::string &xml)
Parse GSDML content already held in memory.
GSDMLDevice ParseGsdml(const std::string &path)
Parse a GSDML file into a GSDMLDevice.
Complete parsed GSDML device profile.
std::string vendorName
Vendor name from the GSDML's DeviceIdentity.
std::string dapModuleInfo
The device access point's own (built-in) module info text.
std::map< std::string, GSDMLModule > modules
Every module declared in the GSDML's ModuleList, keyed by GSDML ID.
std::vector< GSDMLModuleReference > moduleReferences
Modules referenced by the DAP's UseableModules list.
std::vector< GSDMLSubmodule > dapSubmodules
DAP virtual submodules.
std::uint16_t vendorId
PROFINET vendor ID from the GSDML's DeviceIdentity (VendorID attribute).
rpc::ApplicationRelations applicationRelations
std::uint32_t dapSubmoduleIdentNumber
The device access point's own (built-in) submodule ident number.
const GSDMLSubmodule * FindSubmodule(const std::string &submoduleId) const
Look up a globally defined submodule.
std::vector< GSDMLSystemSubmodule > systemSubmodules
System-defined submodules built into the DAP (e.g. interface, port 1).
std::vector< rpc::IOSlot > BuildIoSlots(const std::vector< std::tuple< int, std::string, int, std::string > > &plugged={}) const
Build I/O slot descriptions from the parsed GSDML configuration.
std::uint16_t deviceId
PROFINET device ID from the GSDML's DeviceIdentity (DeviceID attribute).
std::uint32_t dapModuleIdentNumber
The device access point's own module ident number.
std::map< std::string, GSDMLSubmodule > submodules
Every globally defined SubmoduleItem, keyed by GSDML ID.
std::string dapModuleName
The device access point's own (built-in) module name.
std::string deviceName
Device name from the GSDML's DeviceIdentity / DeviceFunction.
const GSDMLModule * FindModule(const std::string &moduleId) const
Look up a module by its GSDML ID.
std::vector< int > dapSlots
Slot numbers where the DAP may be fixed/plugged (from UseableModules/PlugSlots).
std::string dapModuleId
The device access point's own (built-in) identifier to matchs with the submodule.
Reference describing how a module may be used by the DAP.
std::string moduleId
Referenced ModuleItem ID.
std::vector< int > usedSlots
Slots where the module is currently used/preselected.
std::vector< int > allowedSlots
Slots where the module is allowed.
std::vector< int > fixedSlots
Slots where the module is fixed.
A GSDML module definition (ModuleItem), possibly offering multiple virtual submodules.
std::string id
GSDML ID attribute (used to resolve ModuleItemTarget references).
std::vector< GSDMLSubmoduleReference > submoduleReferences
References to globally defined SubmoduleItem definitions.
std::map< std::string, GSDMLSubmodule > submodules
Virtual submodules this module offers, keyed by their GSDML ID.
std::string name
Human-readable module name (from the GSDML's Name/TextId, resolved via ExternalTextList).
std::vector< int > physicalSubslots
Physical subslots supported by this module.
std::uint32_t moduleIdentNumber
Module ident number (hex value from the GSDML, parsed to an integer).
Reference to a submodule that may be used by a module.
std::vector< int > usedSubslots
Subslots where this submodule is currently used/preselected.
std::vector< int > allowedSubslots
Subslots where this submodule is allowed.
std::vector< int > fixedSubslots
Subslots where this submodule is fixed.
std::string submoduleId
Referenced SubmoduleItem ID.
A GSDML virtual submodule definition (VirtualSubmoduleItem).
std::uint32_t submoduleIdentNumber
Submodule ident number (hex value from the GSDML, parsed to an integer).
std::string id
GSDML ID attribute (used to resolve VirtualSubmoduleItemTarget references).
int outputLength
Total output data length in bytes (sum of Output DataItems).
int inputLength
Total input data length in bytes (sum of Input DataItems).
A GSDML system-defined submodule (e.g. built into the DAP: interface, port).
std::string moduleName
Referenced ModuleItem name.
std::uint16_t subslot
Subslot this submodule occupies.
std::uint32_t submoduleIdentNumber
Submodule ident number.
std::vector< std::uint16_t > reductionRatioTimingProperties
std::vector< std::uint16_t > sendClockTimingProperties
One slot/subslot's expected module configuration and IO data sizes.
std::uint16_t inputLength
Expected input data length in bytes (0 if no input data).
std::uint16_t slot
Slot number.
std::uint16_t outputLength
Expected output data length in bytes (0 if no output data).
std::uint32_t moduleIdent
Expected module ident number.
std::uint32_t submoduleIdent
Expected submodule ident number.
std::uint16_t subslot
Subslot number.