ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

TIA Portal Openness实战:用C#批量生成PLC数据块完整指南

TIA Portal Openness实战:用C#批量生成PLC数据块完整指南 简介西门子Openness自动生成小示例是一套面向自动化集成工程师与PLC程序员的TIA Portal二次开发参考项目演示如何在Visual Studio中通过Openness开放接口控制TIA Portal自动完成PLC项目创建、程序生成与参数配置等重复性工作适合希望将手工组态转化为脚本化、批量化操作的开发者学习。压缩包共421个文件容量1.28MB内部以312张PNG截图、72个C#源文件为主搭配XAML窗体、config、settings及解决方案文件其中图片可辅助查看界面效果和操作流程CS与XAML共同构成WPF客户端程序便于读者对照源码理解封装逻辑。整个示例从启动检查、版本匹配、日志记录到状态切换均有完整实现并展示了如何在项目中组织Openness API调用、连接MES/ERP等外围系统以及处理项目备份和异常恢复等实际工程细节。通过这份源码自动化工程师能快速掌握TIA Portal开放接口的使用方法将日常重复开发任务交给程序自动完成为后续搭建自己的自动化工具链提供可直接参考的蓝本。目前已有598人学习浏览是一份面向智能工厂和工业4.0场景的轻量实用学习资料。 做自动化项目最烦的是什么不是接线不是调试而是面对几十上百个结构相似的数据块一个一个在博途里手动创建。我经历过一次需要生成 40 多个 DB、每个 DB 里十几个变量的项目手动建到第三个就开始怀疑人生。后来接触了西门子 TIA Portal Openness才明白这些重复劳动完全可以交给脚本。这篇文章就从最小示例讲起把 Openness 怎么用、怎么批量生成 DB、以及我踩过的那些坑一次性说清楚适合正在搞 S7-1200/1500 程序自动化的工程师也适合刚开始接触 Openness 的程序员。1. Openness 到底给自动化工程师带来了什么1.1 它是 TIA Portal 对外开放的 API 接口简单说Openness 是博途对外开放的一组程序集和接口外部程序可以通过 C# 或 VB.NET 去操纵 TIA Portal 的项目对象。你可以把它理解成博途的“遥控器”正常人在界面上点击鼠标完成的操作Openness 都能通过代码触发而且更稳定、更可重复。我经常用一句话给同事解释你平时在博途里做的事——新建项目、添加设备、创建 DB、添加变量、编译、下载——Openness 基本都能做只不过把鼠标和键盘换成了 C# 代码。这并不意味着它会取代工程师的调试工作而是把高重复、强规则的机械操作剥离出来让人的精力集中在真正的控制逻辑上。1.2 最适合自动化生成的三类任务实际项目里Openness 最常见的用法有三个方向第一批量创建数据块。这是本文重点。项目里经常有一批结构相同但数据不同的 DB比如 10 台水泵、20 台电机的参数区完全可以用 CSV 或 Excel 驱动脚本自动生成。第二批量导入导出符号表、变量和注释。尤其是从上位机系统或第三方 CAE 工具拿到的点位表需要快速变成 PLC 变量表时Openness 的导入导出能力能省掉大量复制粘贴。第三自动编译和构建。CI/CD 思路在 PLC 领域一样适用。晚上跑一次自动编译早上来直接看合格报告比在多人协作时手工编译靠谱得多。你不需要一上来就把三样全学会先跑通一个最小示例理解 API 的工作方式后面自然能扩展到更多场景。2. 动手前的三个准备工作不然代码写得再对也跑不起来2.1 版本必须严格匹配这是头号坑TIA Portal Openness 的版本必须和博途主程序完全一致。你装了 V17 的博途代码里就必须引用 V17 自带的 Openness 程序集如果你用 V15 的程序集去连 V17启动时大概率直接报错或者行为诡异。我见过最典型的报错是无法将类型为“System.__ComObject”的 COM 对象强制转换为接口类型“Siemens.Engineering.SW.Blocks.IBlock”。这基本就是版本不匹配导致的。所以下载安装博途时一定要记住版本号并且从安装目录下引用对应的程序集路径通常是C:\Program Files\Siemens\Automation\Portal V17\PublicAPI\V17\Siemens.Engineering.dll顺带说一句不同版本之间的 API 名称有小幅变化。比如早期版本获取 PLC 软件对象用GetAttribute(PLCSW)新版本里又出现GetService(PlcSoftware)。因此建议你安装好后在 Visual Studio 的对象浏览器里翻一遍Siemens.Engineering.SW.Blocks和Siemens.Engineering.HW命名空间心里有数再动手。2.2 安全选项和运行权限TIA Portal 默认是不允许外部程序随意调用的你需要在博途的项目属性里打开 Openness 相关的许可选项。具体位置在项目属性 - 保护 - Openness勾选“允许从外部应用程序访问此项目属性”如果你的项目文件是别人提供的他没勾选这个选项你的脚本怎么调都会被拒绝。这个坑我在接手第三方项目时踩过一次排查了半天才发现是项目文件自带保护。另外运行你的 Openness 程序时Windows 用户账户控制不能拦。建议开发阶段直接用管理员身份运行 Visual Studio或者把生成的 exe 属性里的“以管理员身份运行”勾上。否则 Openness 实例启动博途时可能中途失败甚至没有任何提示。2.3 引用方式选对程序集并知道帮助文档在哪里在你的 C# 工程中添加对Siemens.Engineering.dll的引用。注意不要直接引用 COM 组件使用托管的 .NET 程序集会让代码编写舒服很多。引用完成后为代码文件加上这些命名空间using Siemens.Engineering; using Siemens.Engineering.HW; using Siemens.Engineering.SW; using Siemens.Engineering.SW.Blocks; using Siemens.Engineering.SW.Types;然后就是 Openness 自带的帮助文档。它不像网上那些教程那么花哨但真要看 API 的准确签名这是最权威的。安装博途时勾选 Openness 文档组件之后在开始菜单里能找到TIA Portal Openness帮助文档我基本每次写代码都要翻它。3. 最小示例让博途帮我们创建一个数据块3.1 自动化流程的逻辑骨架任何 Openness 程序的基本流程都差不多记好这条链路启动 TIA Portal 实例 - 连接或创建项目 - 找到 PLC 软件对象 - 在块组中创建/修改块 - 保存项目 - 退出实例理解这条链路比背几个 API 签名重要得多。因为不管你是建 OB、FC、FB 还是 DB不管是读写变量还是编译项目骨架全是这一套。我在实际编写时会把TiaPortal对象放进using块中确保程序退出时能正确释放。TiaPortalMode.WithoutUserInterface表示以无界面模式启动博途也就是隐藏窗口脚本在后台跑。这个模式对批量自动化几乎是必须的否则每次弹一个博途界面脚本容易受到人为干扰。3.2 创建/打开项目的核心代码下面这段代码演示如何启动 Openness、打开一个已有项目、并定位到 PLC 软件对象using System; using Siemens.Engineering; using Siemens.Engineering.SW; class Program { static void Main(string[] args) { // 以无界面模式启动 TIA Portal using (TiaPortal portal new TiaPortal(TiaPortalMode.WithoutUserInterface)) { portal.Start(); // 打开已有项目注意路径需要使用项目文件.ap17 之类 Project project portal.Projects.Open(D:\MyProject\Demo.ap17); // 按名称查找设备这里假设 PLC 名称为 PLC_1 Device device project.Devices.Find(PLC_1); if (device null) { Console.WriteLine(未找到 PLC_1退出。); return; } // 获取 CPU 对应的 DeviceItem名称一般是 CPU 模块名 DeviceItem cpuItem device.DeviceItems[CPU_1]; // 获取 PLC 软件对象新版本用 GetService(PlcSoftware) PlcSoftware plcSoftware cpuItem.GetService(PlcSoftware) as PlcSoftware; if (plcSoftware null) { Console.WriteLine(获取 PLC 软件对象失败); return; } // 后续创建 DB 的代码都在这里 CreateDataBlock(plcSoftware); // 保存项目 project.Save(); Console.WriteLine(项目保存完成。); } } }注意Devices.Find(PLC_1)里的名称是博途项目树里显示的名称不是硬件订货号。cpuItem的获取要使用 CPU 的模块名这个名称同样可以在项目树中看到。如果运行时抛异常用(device.DeviceItems as IEngineeringObject).Name打印一下所有DeviceItem的名称就能对上。3.3 通过 API 在 PLC 软件中创建 DB 并添加变量拿到PlcSoftware后就可以在它的块组里创建数据块了。下面是核心方法static void CreateDataBlock(PlcSoftware plcSoftware) { // 获取 PLC 的默认块组也可以自己创建分组 PlcBlockGroup group plcSoftware.BlockGroup; // 创建 DB DataBlock db (DataBlock)group.Blocks.CreateBlock( DB_Motor1, // 块名称 BlockType.DB, // 块类型 -1, // 块编号-1 表示自动分配 ProgrammingLanguage.DB // DB 使用 DB 编程语言 ); // 向 DB 中添加变量 StructType dbStruct (StructType)db.Type; dbStruct.Members.CreateMember(iRatedCurrent, Real); dbStruct.Members.CreateMember(bEnable, Bool); dbStruct.Members.CreateMember(sMotorName, String); dbStruct.Members.CreateMember(iDelay, Int); Console.WriteLine(DB_Motor1 创建完成成员数量 dbStruct.Members.Count); }这段代码在多数 V15 以上版本中可以直接运行。值得说明的是Blocks.CreateBlock的返回类型是PlcBlock需要用DataBlock强转。BlockType.DB表示创建数据块ProgrammingLanguage.DB是数据块的编程语言枚举不要把它和 LAD/FBD 混在一起。创建完后DB 里就会多出四个成员额定电流、使能布尔、电机名称和延时整数。你会在博途的数据块编辑器中立刻看到它们和手工操作的效果一模一样。4. 从“一个 DB”到“50 个 DB”批量生成的工程化思路4.1 用数据表驱动脚本而不是写 50 遍 CreateBlock演示示例中直接写死变量名没什么问题但真实项目一定是动态的。我的做法是先用 CSV 或 DataTable 定义好清单再遍历创建public class DbDefinition { public string DbName { get; set; } public List(string MemberName, string DataType) Members { get; set; } } static void CreateAllDataBlocks(PlcSoftware plcSoftware, ListDbDefinition dbList) { foreach (var def in dbList) { DataBlock db (DataBlock)plcSoftware.BlockGroup.Blocks.CreateBlock( def.DbName, BlockType.DB, -1, ProgrammingLanguage.DB); StructType dbStruct (StructType)db.Type; foreach (var member in def.Members) { dbStruct.Members.CreateMember(member.MemberName, member.DataType); } Console.WriteLine($已创建 {def.DbName}); } }DB 清单可以放在 Excel 里通过 NPOI 或 ClosedXML 读取也可以放在 CSV 里直接用CsvHelper解析。核心思路是一致的数据与代码分离以后项目增加一台设备只需要在表格里加一行完全不需要改程序。我习惯把每个 DB 的结构定义放在一个独立的DbDefinition对象中而不是用三层嵌套的集合因为后续如果需要生成符号表、变量导出文件直接复用这个对象非常方便。4.2 批量生成时的项目保存与异常处理批量生成时建议每创建完一批就保存一次不要等全部完成再保存。在大项目里几十个 DB 加上每个 DB 内部的变量Openness 在后台生成时内存占用很高中间一旦遇到异常之前的工作可能全部丢失。我一般的写法是分阶段保存int count 0; foreach (var def in dbList) { CreateOneDataBlock(plcSoftware, def); count; if (count % 10 0) { project.Save(); Console.WriteLine($已处理 {count} 个 DB项目已保存。); } } project.Save();同时要捕获EngineeringException或COMException把出错 DB 的名称和堆栈写进日志文件。典型原因是变量数据类型的字符串拼写错误比如将Real写成REAL或者Int写成Integer这在 Openness 中会直接抛异常不像博途界面里还能给个友好提示。4.3 提速技巧始终复用同一个 TIA Portal 实例启动一次博途无界面实例大约需要 10 到 20 秒频繁启停会浪费大量时间。批量任务应该在一开始启动一个 portal 实例执行完所有 DB 创建后再退出而不是每建一个 DB 就启动和关闭一次。另一个提速点是减少项目打开次数。如果你只生成 DB那么只打开一个项目和对应的 PLC 软件对象即可。不要为了读一些配置反复打开、关闭项目这种折腾在 Openness 中代价很高。还有一点不要试图在同一个PlcSoftware对象上并发调用创建接口。Openness 的 API 不是线程安全的我在尝试多线程并行创建 DB 时出现过程度不一的崩溃和“非法调用”错误。老老实实用单线程遍历数据量在几百个 DB 以内单线程耗时完全可以接受。5. 我在真实项目里踩过的坑希望你能绕开5.1 “对象被占用”和“操作未执行”的真相刚开始写 Openness 程序时我经常碰到Operation not executed或者Object is currently in use这类错误一度以为是 API 用法问题后来排查发现原因五花八门但最常见的是两个第一个是博途界面上正开着同一个项目。如果你是以界面模式启动 TIA Portal并且手动打开着项目再用代码去操作同一个项目文件十有八九会报占用。解决办法就是WithoutUserInterface模式启动并且保证项目没有被其他进程打开。第二个是上一个 Openness 实例没有正常释放。程序崩溃后用任务管理器查看会发现Siemens.Automation.Portal.exe还在后台运行进程不退出项目文件就一直被锁着。这时要么手动结束进程要么在代码里用try-catch-finally确保TiaPortal.Dispose()一定会执行。5.2 DB 命名与变量命名规则Openness 比你想象的更严格PLC 变量名有一套自己的限制不能以数字开头不能包含空格和特殊符号长度有限制。Openness 的CreateMember方法虽然接收字符串参数但它不会帮你做友好过滤任何非法字符都会导致异常。我之前用了一个变量名1stMotor直接在创建成员时报错。后来我养成了一个习惯创建前用正则表达式过滤一遍static bool IsValidPlcName(string name) { if (string.IsNullOrEmpty(name)) return false; if (char.IsDigit(name[0])) return false; return System.Text.RegularExpressions.Regex.IsMatch(name, ^[A-Za-z0-9_]$); }另外注意DB 名称在同一个 PLC 的块组中必须唯一。如果你想生成DB_Motor1和DB_Motor2不要用Motor1和Motor1这种容易重复的名字重复时CreateBlock会直接抛异常。代码里最好提前做一次集合判重。5.3 编译报错时如何从日志和错误码里快速定位Openness 创建的 DB 如果存在类型或结构问题编译时会报错。此时你可以在代码里调用编译接口并读取编译结果CompilationResult result plcSoftware.Compile(); if (result.State CompilationState.Error) { foreach (var entry in result.Messages) { Console.WriteLine(${entry.State}: {entry.Description}); } }但实际项目里很多时候你不一定需要实时编译。你可以等所有 DB 生成完后用 Openness 或直接在博途界面中编译查看错误。报错信息里通常包含 DB 的名称和成员路径对照着修数据驱动表格里的定义就行。还有一个容易被忽略的问题生成的 DB 没有设置属性时优化访问和标准访问的行为不同。对于 S7-1200/1500默认创建的 DB 可能是优化访问模式某些老项目需要标准访问。这个属性 Openness 也可以设置但如果你只是生成新的 DB保持默认即可不要去手工修改一堆属性否则容易引入莫名的编译一致性错误。5.4 别忘了处理许可证和杀毒软件拦截Openness 启动博途实例时相当于又启动了一个博途进程这个进程需要占用一个可用的 TIA Portal 许可证。如果你机器上只有一个许可证而正常博途界面正开着占用了许可证那么后台 Openness 实例可能因为拿不到许可证而自动退出。建议运行批量脚本时关掉手动打开的博途把许可证留给后台实例。杀毒软件偶尔也会拦截 Openness 的进程间通信。我遇到过 Windows Defender 把Siemens.Automation.Portal.exe当作可疑程序隔离的情况导致 Openness 启动后瞬间消失。遇到这种诡异现象先去安全中心查看隔离记录。给博途程序目录加白名单可以有效避免。最后分享一点我的实际体会Openness 这套东西入门门槛其实不高难的是第一次把环境和最小示例跑通。只要跑通一次你会发现后续扩展特别快今天能创建一个 DB明天就能从 Excel 导入 200 个 DB今天能编译明天就能把自动编译挂到每天下班后的任务计划里。我现在已经把批量生成 DB、符号表和注释的工具沉淀成了内部小工具输入一张 Excel 表半小时能完成以前一天的手工活。关键是这种做法还降低了人工录入的出错率生成的 DB 在博途中编译一次通过比手工建块放心得多。如果你也被重复性 PLC 工程量困扰建议花一个周末试一下 Openness用最小的示例项目开个头你会回来感谢自己。本文还有配套的精品资源点击获取
返回列表