落档: 2026-08-14 · 审计范围: Darra_Profinet_Slave 全仓只读审计(不改代码)
任务: GSDML 规范在线核对 + TIA Portal 可导入性确认
判据基准: ① 在线规范与 PI 官方资料(来源见第 2 节) ② 仓库内西门子官方真实样例
其他参考\GSDML-V2.34-#Siemens-PLC200smart_CPU SR20-20260811-045916.xml
③ 在线下载的 5 家厂商真实 TIA 导入级 GSDML(Lenze / ABB / Anybus-HMS / KUKA / 西门子,见第 3 节)
实测方法: 将当前 GsdmlWriter.cs(2026-08-13 22:07 版)复制到临时目录独立编译,
按默认工程参数真跑 Generate()(对仓库零写入),输出与规范/样例逐节对照。
1. 结论速览
| 问题 | 结论 |
|---|
| 当前导出物能被 TIA 导入吗? | 格式层 (XSD) 合规, 大概率能导入, 但有 3 个硬门槛风险必须先处理 |
| 门槛一 (P1 阻断风险) | 建议文件名不合 TIA 命名规则: 当前 GSDML-V2.4-Darra-Darra-PNET-IO-Device-1-0.xml 在日期位置放了 "1-0" 而非 yyyymmdd。TIA GSD 管理器对文件名有硬校验(见 §4·8, Siemens LT500 案例: 日期位置出现额外字符 → "Checker couldn't check Gsd file" 拒装) |
| 门槛二 (P1 兼容风险) | PNIO_Version="V2.4" + schema 引用 V2.4 XSD → 要求 TIA V17+; P-Net 栈实际实现的是 V2.3x 级特性 (RT_CLASS_1 + LLDP_NoD)。TIA V14-V16 用户会报 "XSD file not found" |
| 门槛三 (P1 身份风险) | VendorID=0x0001 已注册给 Acromag (PI 厂商注册表 v373, 2026-01-27)。TIA 导入本身不拒(schema 合法 + 已注册),但设备身份归属错误 + 与真 Acromag 同 VendorID+DeviceID 的 GSDML 存在"相同设备标识已安装"冲突风险。正式发布前必须向 PI 申请本司 VendorID |
| 格式争议裁决 | SubslotNumber/FixedInSubslots/FixedInSlots/AllowedInSlots = 双格式属性(XSD 双 pattern,十进制与 0x 均合法)。西门子/Lenze/ABB/Anybus/KUKA 五家真实 TIA 导入文件全部用十进制。当前 writer 输出 hex 0x8000 合法可导入,但 writer 内四处注释声称"十进制会被 TIA 拒绝"与事实相反,是错误注释(与仓库 docs\GSDML_十六进制属性规范.md 第 2 节"项目口径=十进制"也冲突) |
| 其余 8 类核对项 | 全部符合(详见 §5 对照表) |
2. 规范权威来源清单
2.1 官方入口(本环境 WebFetch 直连被网络策略阻断,作为权威定位列出)
| 来源 | URL | 说明 |
|---|
| PI 官方 GSDML 规范下载页 | https://www.profibus.com/download/gsdml-specification | GSDML Specification V2.3x/V2.4x + XSD schema(需注册下载) |
| PI 厂商 ID (VendorID) 注册页 | https://www.profibus.com/products/vendor-id | 申请本司 VendorID 的唯一渠道 |
| Siemens GSDML Getting Started V1.10 | https://cache.industry.siemens.com/dl/files/371/31410371/att_1299730/v1/GSDML_Getting_Started_V1_10.pdf | schema 引用格式 (xsi:schemaLocation)、官方资料获取途径 |
2.2 在线核对实际引用来源(本审计经 WebSearch/curl 取到的原文)
| # | 结论用途 | 来源 URL |
|---|
| S1 | VendorID 0x0001 = Acromag(PI 注册表 v373, 2026-01-27; 表头注明 "Vendor data maintained by PI International") | https://github.com/f0rw4rd/profinet-py/blob/master/profinet/vendors.py |
| S2 | TIA 文件名硬校验: 必须 GSDML-Vx.y-<厂商>-<设备族>-<yyyymmdd>[hhmmss].xml; 日期后只允许 hhmmss, 多出的 _1 报 "After the vendor and device family name, only a release date in the format 'yyyymmdd'..." | https://support.industry.siemens.com/forum/ww/pt/posts/install-lt500-gsdml-file-gsdml-v2-43-sitrans-lt500-0b19-20240617-1-xml/329974/ |
| S3 | "Checker couldn't check Gsd file" = 文件名违反命名规范; 合法例 GSDML-V2.35-HMS-CompactCom-40-PIR-20191210.xml; GSDML V2.4 需 TIA V17+ (XSD file not found = 工具内置 XSD 低于文件版本) | https://support.hms-networks.com/hc/en-us/articles/9912450786578 |
| S4 | 接口子槽 0x8000 / 端口 0x8001 语义 (0x8i00 / 0x8ipp); 西门子官方导出 SubslotNumber 十进制 32768/32769 | https://infosys.beckhoff.com/content/1033/tf6271_tc3_profinet_rt_controller/9340465675.html |
| S5 | 真实 GSDML 中 FixedInSubslots="0x8000"/"0x8001" hex 写法存在(Siemens/Honeywell 案例, 证明双格式共存于实盘) | https://www.ad.siemens.com.cn/service/answer/solve_342668_1267.html |
| S6 | 站名规则: 仅 a-z 0-9 - .; 段长 1-63; 总长 1-240; 禁首字符数字; 禁 port-xyz 形态; 禁 IP 形态 → DNS 语法错误 (TCPP0004) | https://engineer.plcnext.help/2023.6_en/TCPP0004DnsSyntax.htm |
| S7 | GSDML 总览 / VendorID+DeviceID 唯一标识设备; 文件名不要乱改 (缓存绑定) | https://scadaprotocols.com/profinet-gsd-gsdml-files-explained/ |
| S8 | TIA 导入流程与常见失败: schema 版本超工具支持 / 重复 GSD / 缓存未清 | https://industrialmonitordirect.com/blogs/knowledgebase/resolving-fanuc-r-30ib-plus-profinet-gsdml-errors-in-tia-portal |
| S9 | DataItem/OctetString/Channel 语义参考 (OPC UA for PROFINET GSD 通用模型) | https://reference.opcfoundation.org/PNGSDGM/v100/docs/6.3 |
2.3 在线下载的真实厂商 GSDML 对照样本(本审计实测取证)
| 厂商 | 文件 | 来源 |
|---|
| 西门子 (TIA 官方导出) | GSDML-V2.34, VendorID 0x002A | 仓库 其他参考\(本审计基准) |
| Lenze | GSDML-V2.34/V2.35/V2.43, VendorID 0x0106 | github.com/siahtirilab/GSD_GSDML_Siemens |
| ABB Robotics | GSDML-V2.35 OmniCore, VendorID 0x03B0 | github.com/FLo-ABB/GSDML_ABB_ROBOTS |
| Anybus (HMS) | GSDML-V2.34 PNET, VendorID 0x010C | 同上 |
| KUKA | GSDML-V2.33 KRC4, VendorID 0x019B | github.com/seb711/Profinet-Controller-Simu |
3. 在线核对: 八大项规范裁决
① 必须 0x 十六进制的属性(十进制 = schema 非法)
| 属性 | 格式 | 取证 |
|---|
VendorID | 0x + 1~4 位 hex | 西门子 0x002A; Lenze 0x0106; ABB 0x03B0; KUKA 0x019B |
DeviceID | 0x + 1~4 位 hex | 同上 (0x0119 / 0x17A0 / 0x0002 / 0x0300) |
ModuleIdentNumber | 0x + 1~8 位 hex(厂商惯例恒 8 位) | 西门子 0x80000201; Lenze 0x0000c520(小写 hex 合法, 证 XSD [0-9A-Fa-f] 大小写不敏感) |
SubmoduleIdentNumber | 0x + 1~8 位 hex(惯例 8 位; 西门子接口/端口用 3 位 0xf00/0xf01) | 西门子 L39/L70/L75; KUKA 0x00008000 |
当前 writer 输出: 全部符合(Hex16/Hex32 恒 8 位)。
② 双格式属性(十进制与 0x hex 均 XSD 合法, 均被 TIA 接受)
XSD SlotNumber 型为双 pattern(十进制 [0-9]{1,5} 与 0x[0-9A-Fa-f]{1,4} 均收)。三方取证:
- 西门子官方 TIA 导出:
SubslotNumber="32768"/"32769"、FixedInSubslots="1"、FixedInSlots="1" — 全十进制。
- Lenze / ABB / Anybus / KUKA 真实文件: 同样全十进制(Anybus
FixedInSubslots="1" ×16)。
- pnio-validator 开源解析器(
richenapedro/pnio-validator gsdml_parser.py L108-115)注释明写 "Parse decimal or hex int strings like '0x1234' or '4660'" — 两种形态都存在于实盘 GSDML。
- Siemens/Honeywell 案例 (S5) 证实 hex
FixedInSubslots="0x8000" 写法亦存在于真实文件。
| 属性 | 裁决 | 项目口径(仓库 docs\GSDML_十六进制属性规范.md 第 2 节) |
|---|
SubslotNumber | 双格式 | 十进制(接口 32768 / 端口 32769) |
FixedInSlots | 双格式 | 十进制 |
FixedInSubslots | 双格式 | 十进制 |
AllowedInSlots / UsedInSlots / UsedAsPlugInSlots | 双格式 | 十进制 |
当前 writer 输出: SubslotNumber="0x8000"/"0x8001"、FixedInSubslots="0x1"(hex)— 合法可导入, 但与项目口径(十进制)不符; writer 注释声称"十进制会被 TIA 拒绝"为错误注释(见 R2)。
③ 必须十进制的属性(0x 形式 = schema 非法)
PhysicalSlots(可区间 0..N)、ObjectUUID_LocalIndex、MinDeviceInterval、SendClock(31.25µs 时基, 1 ms=32)、ReductionRatio、NumberOfAR、MaxInputLength/MaxOutputLength/MaxDataLength、DataItem Length、MAUTypes/MAUTypeItem Value、MaxSupportedRecordSize、ResetToFactoryModes、Writeable_IM_Records。
取证: 西门子 MinDeviceInterval="128" SendClock="32" MAUTypes="16"; Lenze MAUTypes="16 15 11 10"; ABB MinDeviceInterval="256"。
当前 writer 输出: 全部符合(MAUTypes="16" 十进制 = 100BASE-TX 全双工, 对齐西门子)。
④ DAP 结构要求
DeviceAccessPointItem 必需子元素顺序: ModuleInfo → (可选 CertificationInfo) → (可选 SubslotList) → IOConfigData → (可选 UseableModules) → (可选 VirtualSubmoduleList) → SystemDefinedSubmoduleList; 系统子模块 InterfaceSubmoduleItem 用 SubmoduleIdentNumber 0x00008000 + SubslotNumber 32768(0x8000), PortSubmoduleItem 用 0x00008001 + 32769(0x8001)。SubslotList 中接口/端口条目按 0x8000/0x8001 序。
当前 writer 输出: 全部符合(顺序、ID、标识号、文本引用、SupportedRT_Classes="RT_CLASS_1"、ApplicationRelations StartupMode="Advanced;Legacy" + NumberOfAR="1"、TimingProperties SendClock=32 + ReductionRatio="1"、MAUTypeList 全部对齐西门子样例)。
⑤ ModuleIdentNumber 格式
0x + hex, 惯例固定 8 位(XSD 1~8 位)。当前输出 0x00000001(DAP 与模块同值 0x00000001 — 注意 DAP 与 ModuleItem 标识号相同虽 XSD 不拒, 但厂商惯例 DAP 与模块用不同号段(西门子 DAP 0x80000201 vs 模块各自; Lenze DAP 0x0000c520 vs 模块 0x1EC10001)— 属 P3 建议, 非阻断)。
⑥ VendorID 注册状态
- 0x0001 = Acromag(已注册)(S1, PI 注册表 v373 2026-01-27:
1: "Acromag")。
- TIA GSD 安装器对 VendorID 只做 schema 格式校验, 不做 PI 注册库比对 — 未注册/借用的 VendorID 不阻断安装(S7/S8 的失败案例均为名称/IP 不匹配、schema 版本、文件名、重复 GSD 四类, 无"未注册 VendorID 拒装")。
- 但 0x0001 属 Acromag → ① 设备在 TIA 中身份归属错误; ② 若客户机已装 Acromag 且 DeviceID=0x0001 的 GSDML, 安装时报"相同设备标识已存在"; ③ 运行时 I&M0 对照工程时会显示为 Acromag 设备。
- 仓库 GUI 校验层已按用户 2026-08-09 裁定拒绝 0x0000(
ValidationService.ValidateVendorId, L409-417), 0x0001 可过 — 测试期可用, 发布前必须向 PI 申请(https://www.profibus.com/products/vendor-id)。
⑦ StationName / DNS_CompatibleName 规则
仅 a-z 0-9 - .; 总长 1-240; 段长 1-63; 段不能以 - 开头/结尾; 首字符不能是数字; 禁止 port-xyz 与 IP 形态(S6)。默认值 darra-slave-01 合规。缺口: ValidationService 仅禁非 ASCII + 控制字符, 大写/下划线/首数字/连续点等未校验 — 导入不拒, 但 TIA 站名分配与 DCP 运行时识别会失败(R5)。
⑧ 其它 TIA 导入硬门槛
| 门槛 | 裁决 | 当前状态 |
|---|
| XML well-formed + UTF-8 | 必须 | 符合(XDocument.Load 可过, 无 BOM) |
| 文件名命名规则 (S2/S3) | GSDML-Vx.y-<厂商>-<设备族>-<yyyymmdd>[hhmmss].xml, 日期后不得有多余段 | 不符合 — GSDML-V2.4-Darra-Darra-PNET-IO-Device-1-0.xml 日期位置是 "1-0"(R1) |
| schema 版本 ≤ TIA 支持上限 | GSDML V2.4 需 TIA V17+(S3) | 风险 — 当前声明 V2.4(R3) |
| 与已装 GSDML 的 VendorID+DeviceID 不冲突 | 安装时查重 | 风险 — 0x0001 属 Acromag(R4) |
RequiredSchemaVersion 存在且 ≥ V2.31 | TIA 新版惯例(西门子 V2.34 文件 = V2.32; Lenze V2.35 文件 = V2.2; KUKA V2.33 文件缺省) | 符合("V2.32") |
MultipleWriteSupported / LLDP_NoD_Supported | V2.31+ 惯例属性 | 符合(true/true, 对齐西门子 L25) |
| ExternalTextList: PrimaryLanguage 不带 xml:lang; Language 必须带 | XSD 强制 | 符合(PrimaryLanguage 无 lang + Language xml:lang="zh") |
| 每模块在 UseableModules 有 ModuleItemRef | TIA 组态目录依赖 | 符合(但 AllowedInSlots 单值 → 模块槽位锁死, 见 R9) |
4. 实测导出物逐项核对表(当前 writer 2026-08-13 22:07 版)
实测方法: GsdmlWriter.cs 独立编译 + 默认工程 (VendorId=0x0001, DeviceId=0x0001, SendClock=1ms, 槽 1: DI8/DO8 双子模块) 真跑 Generate()。
| # | 核对项 | 当前输出证据行 | 西门子样例证据行 | 裁决 |
|---|
| 1 | 根节点/命名空间/schemaLocation | xmlns="http://www.profibus.com/GSDML/2003/11/DeviceProfile" + xsi:schemaLocation="... GSDML-DeviceProfile-V2.4.xsd" | L2 ..\XSD\GSDML-DeviceProfile-V2.34.xsd | 符合 |
| 2 | ProfileHeader 七件套 | ProfileIdentification/Revision/Name/Source/ClassID + ISO15745Reference(4/1/GSDML) | L3-14 逐字一致 | 符合 |
| 3 | VendorID/DeviceID hex | VendorID="0x0001" DeviceID="0x0001" | L16 0x002A/0x0119 | 格式符合; 取值见 R4 |
| 4 | DeviceFunction Family | MainFamily="I/O" ProductFamily="PROFINET IO Device" | L21 MainFamily="PLCs" | 符合 |
| 5 | DAP 必带属性 | PNIO_Version="V2.4" PhysicalSlots="0..1" ModuleIdentNumber="0x00000001" MinDeviceInterval="32" DNS_CompatibleName="darra-slave-01" FixedInSlots="0" ObjectUUID_LocalIndex="1" RequiredSchemaVersion="V2.32" MultipleWriteSupported="true" LLDP_NoD_Supported="true" | L25 同组属性全齐 (十进制/区间写法一致) | 符合 (PNIO_Version 见 R3) |
| 6 | DAP ModuleInfo (Name/InfoText/VendorName/OrderNumber/HW/SW) | 六件全出 | L26-31 同构 (西门子无 VendorName/HW 亦合法) | 符合 |
| 7 | SubslotList | SubslotNumber="0x8000" + "0x8001" (hex) | L34-35 "32768"/"32769" (十进制) | 双格式合法, 口径见 R2 |
| 8 | IOConfigData | MaxInputLength="8" MaxOutputLength="8" | L37 + MaxDataLength (可选) | 符合 |
| 9 | UseableModules | ModuleItemRef ModuleItemTarget="IDM_DARRA_1" AllowedInSlots="1" | KUKA 同构 (UsedInSlots/AllowedInSlots 单值) | 符合 (语义见 R9) |
| 10 | DAP 虚拟子模块 | SubmoduleIdentNumber="0x00000001" MayIssueProcessAlarm="false" + 空 IOData + ModuleInfo | L39 同构 + FixedInSubslots="1" (可选) + Writeable_IM_Records (可选) | 符合 |
| 11 | InterfaceSubmoduleItem | SubmoduleIdentNumber="0x00008000" SubslotNumber="0x8000" TextId="IDT_NAME_INTERFACE" SupportedRT_Classes="RT_CLASS_1" + ApplicationRelations StartupMode="Advanced;Legacy" NumberOfAR="1" + TimingProperties SendClock="32" ReductionRatio="1" | L70-73 同构 (hex SubslotNumber→十进制写法; SendClock="32" 一致; ReductionRatio 西门子为列表) | 符合 |
| 12 | PortSubmoduleItem | SubmoduleIdentNumber="0x00008001" SubslotNumber="0x8001" MAUTypes="16" CheckMAUTypeSupported="true" LinkStateDiagnosisCapability="Up+Down" + MAUTypeItem Value="16" AdjustSupported="true" | L75-79 逐字对齐 (hex SubslotNumber 除外) | 符合 |
| 13 | 模块/子模块列表 | ModuleItem ID="IDM_DARRA_1" ModuleIdentNumber="0x00000001" + VirtualSubmoduleItem ... FixedInSubslots="0x1" MayIssueProcessAlarm="true" | L39/46/57 同构 | 符合 (FixedInSubslots 双格式) |
| 14 | IOData/DataItem | Input/Output Consistency="All items consistency" + DataItem DataType="OctetString" Length="8" TextId=... | L48-51 同构 | 符合 |
| 15 | ExternalTextList | PrimaryLanguage (无 lang) + Language xml:lang="zh" | L103 PrimaryLanguage 无 lang (西门子样例无 zh 块, 但 XSD 允许) | 符合 |
| 16 | 编码/换行 | UTF-8 无 BOM + 2 空格缩进 + LF | 无关紧要 | 符合 |
| 17 | 建议文件名 | GSDML-V2.4-Darra-Darra-PNET-IO-Device-1-0.xml | 仓库样例名 GSDML-V2.34-#Siemens-PLC200smart_CPU SR20-20260811-045916.xml (含日期) | 不符合 (R1) |
5. 违规/风险清单(按严重度, 交主对话派修)
R1 — P1(TIA 安装阻断风险): 建议文件名不合 TIA 命名硬规则
- 位置:
Darra_Pnet_GUI\Services\GsdmlWriter.cs BuildSuggestedFileName (L356-363)。
- 事实: 输出
GSDML-V2.4-Darra-Darra-PNET-IO-Device-1-0.xml — "1-0" 占的是日期段位置。Siemens LT500 案例 (S2): 日期后出现额外段 → 安装报 "After the vendor and device family name, only a release date in the format 'yyyymmdd' ... may follow"; HMS (S3): 文件名违反规范 → "Checker couldn't check Gsd file"。
- 建议: 文件名改为
GSDML-V2.4-{厂商}-{设备族}-{yyyyMMdd}.xml(日期取生成当日, 或工程文件时间), 段内一律 -/_ 分词, 不放版本号。
R2 — P1(错误注释, 误导后续改动): writer 四处断言"十进制会被 TIA 拒绝"
- 位置:
GsdmlWriter.cs L418-419 / L462-463 / L480-481 / L516-521 注释。
- 事实: SubslotNumber/FixedInSubslots/FixedInSlots 为 XSD 双格式属性(§3·②)。西门子官方 TIA 导出 + Lenze/ABB/Anybus/KUKA 五家真实文件全用十进制, 且均已成功导入 TIA。"十进制会被 TIA 拒绝"与事实相反。
- 另: 与仓库
docs\GSDML_十六进制属性规范.md 第 2/7 节(项目口径=十进制; V2 要求"改写错误注释")直接冲突 — 该文档要求的方向恰恰是把这类注释改成双格式口径。
- 建议: 注释改为 "SubslotNumber/FixedInSubslots 双格式 (十进制/0x) 均合法; 项目口径建议十进制对齐西门子官方导出"。输出格式本身(hex)合法, 保留或改十进制均可, 但注释必须如实。
R3 — P1(TIA 版本兼容): PNIO_Version="V2.4" 要求 TIA V17+
- 位置:
GsdmlWriter.cs L397 (PNIO_Version="V2.4") + L298/326 (schema 引用 V2.4.xsd)。
- 事实: HMS (S3): GSDML V2.4 需 TIA Portal V17+; 低版本报 "XSD file not found"。底层 P-Net 栈实现为 V2.3x 级特性(RT_CLASS_1、LLDP_NoD、无 IRT/无 Isochrone)。
- 建议:
PNIO_Version 与 schema 引用降为 "V2.32"/"V2.33"(与西门子样例 L25 V2.33 同档), RequiredSchemaVersion 保持 V2.32; 或保持 V2.4 但在导出 UI 明示"需 TIA V17+"。
R4 — P1(设备身份, 发布阻断): VendorID 0x0001 = Acromag 已注册 ID
- 位置:
GsdmlWriter.cs 模型默认值 PnetProject.VendorId = 0x0001 (L161)。
- 事实: PI 注册表 v373 (S1): 0x0001 = Acromag。导入不拒(TIA 不做注册库比对), 但: ① 身份归属错误; ② 与已装 Acromag DeviceID=0x0001 的 GSDML 冲突 → "GSD 文件已安装/相同设备标识"提示; ③ 运行时设备识别显示错误厂商。
- 建议: 测试期保留 0x0001(GUI 校验已按用户裁定禁 0x0000); 发布前向 PI 申请本司 VendorID (
https://www.profibus.com/products/vendor-id), 并在导出 UI 顶部明示 "VendorID 为测试占位, 发布前必须替换"。
R5 — P2(校验缺口): StationName/DNS_CompatibleName 未按 PROFINET 命名规则校验
- 位置:
Darra_Pnet_GUI\Services\ValidationService.cs(现仅禁非 ASCII + 控制字符)。
- 规则 (S6): 仅
a-z 0-9 - .; 总长 ≤240; 段 1-63; 段不以 - 开头/结尾; 首字符字母; 禁 port-xyz 形态; 禁 IP 形态。
- 影响: 不阻断 GSDML 安装, 但 TIA 分配站名/DCP 识别阶段失败。
- 建议: 在 ValidateStationName 补 6 条规则 (Warning/Error 分级), 导出前阻断非法站名。
R6 — P2(惯例补强): DAP 缺 CertificationInfo
- 位置:
GsdmlWriter.cs BuildDeviceAccessPointList(未输出)。
- 事实: XSD 可选; 西门子 L32
ConformanceClass="A" ApplicationClass="" NetloadClass="I"、KUKA ConformanceClass="B"。
- 建议: 输出
CertificationInfo ConformanceClass="A" ApplicationClass="" NetloadClass="I"(纯 RT_CLASS_1 从站定位), 位置在 ModuleInfo 之后。
R7 — P2(待实测): DataItem Length 无上限拆分
- 位置:
GsdmlWriter.cs BuildIoData (L574-578) — 单 DataItem 长度 = 条目 Length 直出。
- 风险: 业界惯例 OctetString 每 DataItem ≤254 字节, 大块传送区分拆多个 DataItem(KUKA MaxInputLength=512 即分拆)。本次在线未能坐实 XSD 对 Length 的硬上限(S9 无 maxInclusive 表述), 标待实测: 生成 Length≥255 的工程在 TIA 真导入一次, 拒则加自动拆分。
- 另注意: IOConfigData MaxInputLength/MaxOutputLength 超 1440 (DAP 上限) 亦未拦 — 同批实测。
R8 — P3(信息): 导出的 GSDML 未做"真实 TIA 导入"端到端验证
- 现状: 仓库内无 TIA 环境, 现有验证止于 well-formed + 节点断言(
TEST_Config)+ 双格式校验。
- 建议: 测试机/用户 TIA (V17+) 上做一次真导入冒烟: 安装 → 目录出现 → 拖入组态 → 编译 → 下载站名。此为最终裁决判据。
R9 — P3(信息): 模块槽位锁死 + DAP/模块标识号同号段
UseableModules AllowedInSlots = 模块自身槽位单值 → 组态时模块只能放死槽位(合法, 但失去模块化灵活性)。
- DAP
ModuleIdentNumber="0x00000001" 与 Module 1 标识号同为 0x00000001 — XSD 不拒, 但厂商惯例 DAP 与模块用不同号段(西门子 DAP 0x80000201); 建议 DAP 改用独立号段(如 0x80000200)避免与模块标识号混淆。
6. 修复验收判据(修后复核用)
BuildSuggestedFileName 产物形如 GSDML-V2.4-Darra-<设备族>-20260814.xml(日期段 yyyymmdd, 其后无任何附加段)。
- 全仓 grep GsdmlWriter 注释不再出现 "十进制 … 会被 TIA 拒绝" / "十进制 … 无效" 两类错误断言(
docs\GSDML_十六进制属性规范.md V2 判据)。
PNIO_Version / schema 引用与 TIA 支持矩阵一致(或 UI 明示版本要求)。
- 导出 UI 有 "VendorID 测试占位" 明示(发布前替换)。
- StationName 校验规则 6 条上线, 非法站名导出被阻断。
- (待实测项)Length≥255 与 MaxInputLength>1440 的 TIA 真导入结果落档。
7. 审计边界声明
- 本审计只读 + 新建本报告; 未改任何代码(修复由主对话按第 5 节清单另派)。
- 在线取证的 5 家厂商 GSDML 文件未落仓库(仅临时目录, 取证后即弃)。
- TIA 真实导入是最终裁决判据(R8); 本报告所有"能导入"结论均为规范层判定 + 厂商实盘互证, 不替代真机导入冒烟。
8. 逐段属性覆盖矩阵 + 预判报错序列(2026-08-14 追加, 第二轮审计)
本轮目标: 在 t1 DAP 属性修复已合入(e0e9440 v9, 见 §8·4)之后, 逐段对齐"我们 vs 西门子样例 vs V2.32 合法性", 预判 TIA 导入的下一批报错。
实测方法: 当前 HEAD(cae9e1d, working tree 对 GsdmlWriter.cs 干净)复制到 %TEMP% 独立编译(对仓库零写入), 真跑 Generate() 三个场景: A=默认工程(槽 1 双方向 IO) / B=大长度(单 DataItem 255 入 + 1500 出) / C=空模块工程 + 站名 DarRa_Slave-01。
判据基准: ① 西门子样例 其他参考\GSDML-V2.34-#Siemens-*.xml(最权威) ② 报告第 2 节五家厂商实盘 ③ 本轮 WebSearch 新增来源(S10-S13, 见 §8·0)。
8·0 本轮新增在线来源
| # | 用途 | URL |
|---|
| S10 | V2.32 ↔ TIA V15.1-V17 对应关系(Fanuc 案例); TIA 导入失败根因清单(schema 版本/改文件名/损坏/路径/编辑器未关/权限) | https://industrialmonitordirect.com/blogs/knowledgebase/resolving-fanuc-r-30ib-plus-profinet-gsdml-errors-in-tia-portal |
| S11 | 站名规则: 仅 a-z 0-9 - .; 下划线非法(TIA 键入 plc_2 会自动转 plcxb2d1ad); 段 1-63; 首字符非数字; 禁 -/. 开头结尾; 禁 IP 形态; 禁 port-xyz 前缀; DCP Set 服务拒非法名 | https://industrialmonitordirect.com/zh-hans/blogs/knowledgebase/profinet-name-of-station-port-000-spec-conflict-resolution |
| S12 | 1440 字节/方向硬顶(IOCR 净载); 每子槽约 8 字节 IO 对象描述开销; 超限必须拆多 DataItem/子模块; 单设备 1434 保守值 | https://industrialmonitordirect.com/zh-hans/blogs/knowledgebase/profinet-io-device-maximum-process-data-frame-size-limits |
| S13 | p-net Issue #34: MaxSupportedRecordSize 声明值过小/与栈 RPC 分片配置不符 → TIA 拒导 GSDML(实测 V16 + S7-1212C) | https://github.com/rtlabs-com/p-net/issues/34 |
8·1 逐段属性覆盖矩阵
图例: ✅=有且合法 / ⬜=西门子有而我们缺 / —=西门子样例也无 / 必需度: 必需=XSD required(缺即拒导)· 警告=缺了 TIA 警告或功能降级 · 可缺=XSD optional 且无副作用。
8·1·1 DeviceAccessPointItem(属性层)
| 属性 | 我们 | 西门子样例 | V2.32 合法性 | 必需度 | 预判 |
|---|
| ID / PNIO_Version / PhysicalSlots / ModuleIdentNumber / MinDeviceInterval / DNS_CompatibleName / ObjectUUID_LocalIndex | ✅ 全出(V2.32 / 0..1 / 32 / 1) | 同组全齐(V2.33 / 128 / 100) | 全合法(hex8 标识号 + 十进制时基) | 必需 | t1 前已达标, 无预判错误 |
| RequiredSchemaVersion="V2.32" | ✅ | ✅ V2.32 | 合法(V2.31+ 惯例属性; TIA V14+ 认识, 更老版本"未知属性"拒导 — 目标 V15.1+ 无碍, S10) | 警告 | 若客户用 TIA V14 会报"XSD file not found"(S10: V2.32 ↔ V15.1-V17) |
| MultipleWriteSupported / LLDP_NoD_Supported="true" | ✅ | ✅ true | 合法(V2.31+ 惯例; 栈真实现 LLDP NoD + 多次写, 声明属实) | 警告 | 无 |
| FixedInSlots | ✅ "0" | "1" | 合法(双格式; 0 = DAP 不固定槽, 模块化设备惯例) | 可缺 | 无 |
| MaxSupportedRecordSize | ⬜ 缺 | "4068" | optional | 警告 | 栈分片 RPC 缓冲 = 1440(pnet_options.h:173 PNET_MAX_SESSION_BUFFER_SIZE 1440)。我们无 RecordDataList(无参数记录), 缺它 TIA 可导; 若补必须填 1440 且与栈一致 — 乱填小值会被 TIA 拒(S13 p-net #34 实测) |
| AddressAssignment | ⬜ 缺 | "LOCAL" | optional(default DCP) | 可缺 | 我们只走 DCP → 缺省 DCP 语义正确, 不补 |
| DeviceAccessSupported / NumberOfDeviceAccessAR | ⬜ 缺 | "true"/"1" | optional(仅 S2/I-Device 智能设备需要) | 可缺 | 普通 IO 从站不补 |
| NameOfStationNotTransferable / SharedDeviceSupported / CheckDeviceID_Allowed / ResetToFactoryModes | ⬜ 缺 | true/false/true/2 | optional(default false/false/false/0) | 可缺 | 不补 |
8·1·2 DeviceAccessPointItem(子元素层)
| 子元素 | 我们 | 西门子 | 合法性 | 必需度 | 预判 |
|---|
| ModuleInfo(6 件: Name/InfoText/VendorName/OrderNumber/HW/SW) | ✅ 全出 | 4 件(无 VendorName/HW) | 合法(西门子样例缺件亦合法, 说明这组是 minOccurs 混合) | 部分必需 | 无 |
| CertificationInfo(A//I) | ✅ 逐字对齐 | ✅ | 合法 | 可缺 | t1/v9 已补, 无 |
| SubslotList(0x8000/0x8001 + TextId) | ✅ | ✅ 十进制 | 合法(双格式, R2 口径) | 警告 | hex 保留现状合法; 口径争议已 R2 落档 |
| IOConfigData MaxInputLength/MaxOutputLength | ✅(=各模块和) | ✅ + MaxDataLength | 合法; MaxDataLength 可选 | 警告 | 值域风险见 §8·3·3: 实测 B 场景生成 MaxOutputLength="1500" > 1440 硬顶未拦 |
| UseableModules / ModuleItemRef | ✅ 单值 AllowedInSlots | —(西门子样例无 ModuleList) | 合法(五家厂商同构) | 必需(每个模块一条) | 结构风险见 §8·3·2: 空模块工程输出 <UseableModules /> 无 ModuleItemRef |
| VirtualSubmoduleList(DAP VSM) | ✅(见 8·1·3) | ✅ | 合法 | 必需 | 属性缺口见下 |
| SystemDefinedSubmoduleList | ✅(见 8·1·4) | ✅ | 合法 | 必需 | 见 8·1·4 |
8·1·3 VirtualSubmoduleItem(DAP VSM 与模块 VSM 合并看)
| 属性 | 我们 | 西门子 | 合法性 | 必需度 | 预判 |
|---|
| ID / SubmoduleIdentNumber | ✅ 0x00000001(hex8) | ✅(DAP VSM 亦 0x00000001; 功能 VSM 用 0x1000000A 等独立号段) | 合法 | 必需 | 标识混淆(R9 延伸): 我们 DAP VSM、模块 1、模块 1 子模块 1 三处同号 0x00000001 — XSD 不拒, 但 TIA 组态编译后 expected/real 模块对比诊断会把三者混为一谈, 建议号段分离(如功能模块 0x00010000 起) |
| FixedInSubslots | 模块 VSM ✅ 0x1; DAP VSM ⬜ 缺 | 全有(DAP VSM "1"; 功能 VSM "1000") | 合法(双格式) | 可缺→建议补 | DAP VSM 惯例固定子槽 1, 建议补 FixedInSubslots="1" 显式化 |
| MayIssueProcessAlarm | ✅ false(DAP)/ true(模块) | ✅ false | 合法; 栈有过程报警发送(pnet_wrapper_alarm_send_process)→ true 属实 | 警告 | 无 |
| Writeable_IM_Records | ⬜ 缺 | "1 2 3" | optional | 警告 | 栈 I&M1-4 控制器可写(pnet_api.h im1-4 read-write)→ 可如实补 "1 2 3 4", 让 TIA 支持写入 I&M 数据; 缺它 TIA 不提供 I&M 写入入口, 不阻导入 |
8·1·4 SystemDefinedSubmoduleList(接口 + 端口)
| 属性 | 我们 | 西门子 | 合法性 | 必需度 | 预判 |
|---|
| InterfaceSubmoduleItem: SubslotNumber/SubmoduleIdentNumber/TextId/SupportedRT_Classes | ✅(0x8000 / 0x00008000 / RT_CLASS_1) | ✅(32768 / 0xf00 / RT_CLASS_1) | 合法 | 必需 | 无 |
| ApplicationRelations: StartupMode / NumberOfAR | ✅ "Advanced;Legacy" / "1" | ✅ 逐字一致 | 合法 | 必需(AR 段) | t1 已补, 无 |
| TimingProperties: SendClock / ReductionRatio | ✅ 32 / "1" | ✅ 32 / "1 2 4 ... 512" | 合法(单值 = 一元素列表) | 警告 | 我们栈只支持 1:1(ReductionRatio=1)→ 单值如实; 西门子列表是因为其栈支持多缩减比, 不模仿 |
| ParameterizationDisallowed | ⬜ 缺 | "false" | optional(default false) | 可缺→建议补 | 显式 "false" 声明可参数化, 防部分 TIA 版本 default 歧义(低成本补) |
| SupportedProtocols | ⬜ 缺 | "LLDP" | optional(缺省=全默认协议 LLDP DCP RTA RTC) | 可缺 | LLDP_NoD 设备缺省语义正确, 不补 |
| PTP_BoundarySupported / DCP_BoundarySupported | ⬜ 缺 | true/true | optional(default false) | 可缺 | 非 LLDP 边界设备, 不补 |
| PortSubmoduleItem: MAUTypes/CheckMAUTypeSupported/LinkStateDiagnosisCapability | ✅ 16/true/Up+Down | ✅ 逐字一致 | 合法 | 必需(V2.31+ 惯例, t1 已补) | 无 |
| CheckMAUTypeDifferenceSupported / PortDeactivationSupported / ParameterizationDisallowed | ⬜ 缺 | true/false/false | optional | 可缺→建议补 | 西门子为完整导出; 我们单口 100BASE-TX 全双工, 缺省合法 |
| MAUTypeList / MAUTypeItem(16 + AdjustSupported) | ✅ | ✅ | 合法 | 警告 | 无 |
8·1·5 ModuleList / ModuleItem + IOData + 各可选段
| 段 | 我们 vs 西门子 | V2.32 合法性 | 必需度 | 预判 |
|---|
| ModuleItem: ID + ModuleIdentNumber + ModuleInfo + VirtualSubmoduleList | ✅(西门子样例无 ModuleList — 固定配置设备; 对照 Lenze/KUKA 实盘同构, 报告 §4·13 已核) | 合法 | 必需(每个模块) | 结构风险 §8·3·2: 模块 0 子模块时输出 <VirtualSubmoduleList /> 空元素 |
IOData: Input/Output Consistency="All items consistency" + DataItem OctetString/Length/TextId | ✅ 与西门子 VSM_2_1000/1001 逐字同构 | 合法 | 必需(有 IO 的子模块) | 值域风险 §8·3·3: 无 1440 上限拦截 + 无自动拆分 |
| DataItem UseAsBits | ⬜ 缺(西门子样例亦缺) | optional | 可缺 | 缺 → TIA 按整字节组态; 未来若要位级组态需补 |
| ExternalCommunicationList | 双方均无 | V2.32 核心 XSD 序列无此段(检索未见于任何 V2.3x 实盘文件) | 不适用 | 无需补; 属 shared-device/扩展场景 |
| ApplicationProcess 其余可选段: ValueList / ChannelDiagList / UnitDiagTypeList / GraphicsList | 全缺(西门子有 ValueList+UnitDiagTypeList+GraphicsList) | 全 optional | 可缺 | TIA 用标准诊断 + 默认图标; 若未来"状态码+文本"要进 TIA 诊断视图, 需补 UnitDiagTypeList(P3 建议, 西门子样例 L86-98 即模板) |
| ExternalTextList: PrimaryLanguage + Language zh | ✅ 与西门子同构(我们 zh 块与 PrimaryLanguage 值相同) | 合法 | 必需 | Text Value 长度上限(~255 字符)无守门 — 用户超长名称/描述会 XSD 拒(P3 低概率) |
8·2 t1 修复的对应关系(本轮审计前已合入状态)
- t1 DAP 属性波(
e0e9440 v9 "fix(GSDML P1 合规)")已消掉的是 XSD required 层最后缺口: RequiredSchemaVersion、MultipleWriteSupported、LLDP_NoD_Supported、ApplicationRelations@StartupMode/NumberOfAR、PortSubmoduleItem@MAUTypes/CheckMAUTypeSupported/LinkStateDiagnosisCapability + CertificationInfo — 即西门子样例有而我们曾缺的"V2.31+ 声明必需属性"。§8·3 预判的下一批错误全部位于 t1 未覆盖的三层(可选段补全 / 值域守门 / 结构守门), 与 t1 修复无重叠、无回退。
- 已确认 t1 修复项在当前实测导出物中全部逐字在位(§8·1·1 / 8·1·4 实测证据行)。
8·3 预判 TIA 报错序列(下一批, 按优先级)
P1-1 值域类 — 站名下划线等非法字符穿透(预计报错: 站名分配失败 / DCP 拒绝)
- 证据: 本轮实测场景 C 输入
DarRa_Slave-01 → 输出 DNS_CompatibleName="darra_slave-01"(含 _)。守门(ValidateAndNormalizeStationName)只拦非 ASCII + 控制字符 + 长度, 下划线 / 首数字 / 段首尾 - / 连续点全部穿透。
- 规范: S11 — 站名仅
a-z 0-9 - ., 下划线非法; TIA 键入 plc_2 会自动转 plcxb2d1ad, 但 GSDML 声明的 DNS_CompatibleName 不会被自动转 → TIA 用该名做 DCP Set 时设备/规范侧拒绝 → "设备名无法分配"或运行名字与工程不匹配。
- 修复: R5 六条规则落地到生成侧守门(与 ValidationService 同规则, 不重复造); 非法即阻断导出并指明字符位置。
P1-2 结构类 — 空 UseableModules / 空 VirtualSubmoduleList(预计报错: schema-invalid → "GSD 文件无法读取/无效" 拒装)
- 证据: 实测场景 C(0 模块)输出
<UseableModules /> + PhysicalSlots="0..0"; BuildModuleList 对 0 子模块模块恒输出 <VirtualSubmoduleList /> 空元素。
- 规范:
ModuleItemRef / VirtualSubmoduleItem 在 XSD 中 minOccurs≥1 — 空容器 = schema-invalid, TIA GSD 安装器直接拒装(S10: "GSD file could not be read" 类)。
- 修复: 生成侧守门 — 0 模块工程拒导(或跳过 UseableModules 段——不推荐, 模块化设备必须带); 0 子模块模块拒导。
P2-3 值域类 — 大长度工程超 1440 帧顶(预计报错: 组态编译期 "过程数据超过最大帧长度")
- 证据: 实测场景 B 单 DataItem
Length="1500" 直出, IOConfigData MaxOutputLength="1500" 无拦截(R7 待实测项本轮生成侧坐实)。Length="255" 本身合法(XSD unsigned, TIA 接受)。
- 规范: S12 — IOCR 每方向硬顶 1440(保守 1434); 每个含 IO 的子槽约 8 字节 IO 对象描述开销; 超限必须拆多 DataItem 或分子模块, 不能单 DataItem 直出。
- 修复: 生成侧加 1440 上限校验(Error 级阻断)+ 大条目自动拆分策略(或多子模块提示); 同时
MaxInputLength/MaxOutputLength 超 1440 一并拦截。
P3-4 属性缺失类(GSD checker 警告级, 不阻导入 — 建议同批顺手补, 全部有栈侧证据支撑)
MaxSupportedRecordSize="1440" — 必须与栈 PNET_MAX_SESSION_BUFFER_SIZE=1440 一致; 乱填会被 TIA 拒(S13 p-net #34)。
Writeable_IM_Records="1 2 3 4"(DAP VSM)— 栈 I&M1-4 控制器可写, 补后 TIA 可写 I&M。
- DAP VSM
FixedInSubslots="1" 显式化。
- 接口/端口
ParameterizationDisallowed="false" + PortDeactivationSupported="false" + CheckMAUTypeDifferenceSupported="true"(对齐西门子完整导出, 显式化 default 防 TIA 版本歧义)。
P3-5 标识类 — 三处 IdentNumber 同号 0x00000001(R9 延伸)
- DAP VSM / 模块 1 / 模块 1 子模块 1 三者同号 → TIA expected/real 模块对比诊断混淆。建议号段分离(如功能模块 0x00010000 起、功能子模块 0x01000001 起, DAP VSM 保留 0x00000001)。
P3-6 环境类(文件外, 预判真实报错会先撞这条)
- S10 五类环境失败: 非 ASCII 安装路径 / 路径 >260 / 硬件网络编辑器未关闭(目录数据库被锁)/ 无管理员写权限(
%ProgramData%\Siemens\Automation\GlobalData\GSD)/ 同 VendorID+DeviceID 旧版已装(0x0001 = Acromag, R4 冲突面)。装新 GSDML 前先卸旧版、关编辑器、ASCII 短路径。
不预判为错误的项(已核对干净)
PhysicalSlots="0..0"(随 P1-2 修复消失); ReductionRatio="1" 单值; ApplicationClass=""; MAUTypes="16"; PNIO_Version="V2.32"(V15.1+ 目标内); hex SubslotNumber/FixedInSubslots(双格式, R2 口径保留)。
8·4 修复优先级汇总(交主对话派修)
| 优先级 | 项 | 修复域 | 判据 |
|---|
| P1 | 站名 6 规则生成侧守门(§8·3 P1-1) | GsdmlWriter.cs 守门扩展 | 含 _/首数字站名导出被阻断 |
| P1 | 空 UseableModules / 空 VirtualSubmoduleList 守门(§8·3 P1-2) | GsdmlWriter.cs 生成侧 | 0 模块/0 子模块工程拒导 |
| P2 | 1440 上限 + 大条目拆分(§8·3 P2-3, R7 收口) | GsdmlWriter.cs + ValidationService | Length 和 >1440 被 Error 阻断 |
| P3 | MaxSupportedRecordSize=1440 + Writeable_IM_Records + FixedInSubslots=1 + ParameterizationDisallowed 显式化(§8·3 P3-4) | GsdmlWriter.cs 常量/属性 | 实测导出物 grep 命中 |
| P3 | IdentNumber 号段分离(§8·3 P3-5, R9 延伸) | PnetProject.NormalizeIdentNumbers | DAP/模块/子模块三号段互异 |
| P3 | UnitDiagTypeList 状态进 TIA 诊断(§8·1·5) | 新段生成(后置, 需产品确认诊断语义) | TIA 诊断视图出现自定义状态文本 |
9. 第二轮审计边界声明
- 本轮只读 + 仅追加本报告(§8/§9 章节); 未改任何仓库代码; 临时独立编译产物在
%TEMP%\gsdml_audit\(仓库零写入)。
- 生成器实测为 HEAD
cae9e1d 版本(含 v9 P1 修复, working tree 干净); §8 所有"我们"列证据行 = 本轮三场景实测导出物。
- 预判错误序列基于规范层 + 厂商实盘 + 在线案例互证(S10-S13), 真机 TIA 导入仍为最终裁决(R8)。