Claude Code 接博途:从空工程到跑通仿真的全链路
一句话需求 → 它自己写 FB → 编译 0 错 0 警 → 下载进仿真器 → 三个场景全部对上。
让 Claude Code 这类编码智能体改博途程序,链路上没有神秘环节——加 CPU、导 SCL、编译、下载、跑仿真,每一步要么给你确定的成功,要么给你确定的报错。我们从一台空设备跑到终点:编译 0 错 0 警、下载进仿真器、三个场景跑出稳定数值。全程 34 个工具、9 个步骤,提示词、产出的 SCL 和实测数字都贴在下面。
披露:本文的实测数据来自 2026-10-27 在一台 Windows 机器上的真实运行(博途 V19 / Openness 19.0 / S7-PLCSIM Advanced 6.0 / 网关 TiaLink 1.3.2.0)。
一、它能做什么
把博途里那些日常动作,变成智能体能直接执行的操作:看、改、组、验、存,一条链走完。
| 能力 | 具体动作 |
|---|---|
| 看 | 读工程树、块内容、变量表、UDT、交叉引用、HMI 画面、硬件组态 |
| 改 | 生成或改写 SCL、建块建表、写回工程,单块编译或整 PLC 编译 |
| 组 | 加 CPU、插模块、建子网、连 IO 系统、配 PN 设备名 |
| 验 | 下载到 S7-PLCSIM Advanced、读写变量、跑场景看结果 |
| 存 | 导出 SimaticML,做离线比对与版本归档 |
本版共 34 个工具,上面五类各有一组(另有 LAD 规范与目录一组,给"写梯形图"用)。
装在不同客户端里,用法都一样:说一句话,它自己选工具、自己排步骤。
二、接上:一份端点,五个客户端
网关是 HTTP 型 MCP,接哪个客户端都只改配置,不用改程序。
| 客户端 | 加法 | 备注 |
|---|---|---|
| Claude Code | claude mcp add --transport http tialink http://192.168.1.110:8080/mcp |
Claude Code 2.1.311 实测,--transport http 是必须的 |
| pi | 项目内 .pi/mcp.json 写 mcpServers.tialink.url |
同一份配置换了个客户端 |
| Cursor | .cursor/mcp.json 的 mcpServers |
工具数量多时注意客户端的工具上限 |
| Claude Desktop | claude_desktop_config.json |
改完要完全重启 |
| WorkBuddy / CodeBuddy | 界面「连接器 → 自定义连接器 → 添加 MCP」 | 加完必须显式【启用】,否则工具不出现 |
Claude Code 配置方法如下:
claude mcp add --transport http tialink http://192.168.1.110:8080/mcp
claude mcp list # 确认连上、看工具数
pi 的配置只要几行:
{
"mcpServers": {
"tialink": {
"url": "http://192.168.1.110:8080/mcp",
"timeout": 180
}
}
}
顺带一个实践提醒:timeout 别用默认值。加 CPU 我们实测 34 s(旧固件那台)、导入 SCL 11.8 s、下载 9.6 s,客户端的 60 s 默认超时会在这些"正常慢"的地方先炸,让人误以为是失败。
三、一个需求,从提示词到能跑的程序
看完整链路前,先看最要紧的三样东西:需求、提示词、产出。
需求(工程师原话,两台电机的顺序启动):
- 一台启动按钮启动 1 号电机;1 号运行 3 秒后自动启动 2 号
- 停止按钮(常闭)或任一电机故障 → 两台立即全停
- 两台各有运行输出,定时用 IEC 定时器
- 逻辑写成一个可复用的 FB,OB1 调用
- 输入输出走 M 区:
M0.0启动、M0.1停止(常闭)、M0.2故障、M0.31 号、M0.42 号
提示词(实际下发的那段,原文照抄):
【需求】两台电机的顺序启动控制
- 一台启动按钮启动 1 号电机;1 号电机运行 3 秒后自动启动 2 号电机
- 停止按钮(常闭)或任一电机故障时,1 号、2 号电机立即全部停止
- 两台电机各有运行输出,定时用 IEC 定时器
- 逻辑写成一个可复用的 FB,OB1 里调用它
- 输入输出用 M 区:M0.0 = 启动按钮,M0.1 = 停止(常闭,1 表示允许),M0.2 = 故障,
M0.3 = 1 号电机,M0.4 = 2 号电机
【要求】
1. 自己决定步骤和工具,把它们下发到 PLC_3 并编译通过(0 错误)
2. 编译通过后下载到 S7-PLCSIM Advanced,创建全新的实例名,运行后用场景验证
3. 不要保存工程
4. 最后贴出完整的 SCL 源码和实测数值
没有指定"先读工程、再建块"这类步骤,也没给 SCL 模板——步骤和工具是它自己选的。
产出(它写出来的 FB,接口 + 实现):
FUNCTION_BLOCK "FB_MotorSeq"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_INPUT
Start : Bool; // 启动按钮(M0.0)
StopPermit : Bool; // 停止按钮 常闭,1=允许运行(M0.1)
Fault : Bool; // 故障(M0.2)
RunDelay : Time := T#3S; // 2 号电机延时
END_VAR
VAR_OUTPUT
Motor1 : Bool; // 1 号电机运行(M0.3)
Motor2 : Bool; // 2 号电机运行(M0.4)
END_VAR
VAR
statRun : Bool; // 运行自锁
statPermit : Bool; // 允许运行
rtStart : R_TRIG; // 启动按钮上升沿
tonRun2 : TON_TIME; // IEC 延时定时器
END_VAR
BEGIN
// 允许运行:停止按钮常闭点闭合(1)且无故障
#statPermit := #StopPermit AND NOT #Fault;
// 启动上升沿置位自锁;停止/故障立即复位
#rtStart(CLK := #Start);
#statRun := (#rtStart.Q OR #statRun) AND #statPermit;
// 1 号电机立即运行,2 号电机在 1 号运行 RunDelay 之后启动
#Motor1 := #statRun;
#tonRun2(IN := #Motor1,
PT := #RunDelay);
#Motor2 := #statRun AND #tonRun2.Q;
END_FUNCTION_BLOCK
OB1 里调用它,把它接到 M 区:
ORGANIZATION_BLOCK "Main"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
BEGIN
"DB_MotorSeq"(Start := %M0.0,
StopPermit := %M0.1,
Fault := %M0.2,
RunDelay := T#3s,
Motor1 => %M0.3,
Motor2 => %M0.4);
END_ORGANIZATION_BLOCK
编译:state=Success, errorCount=0, warningCount=0,Main (OB1) 与 FB_MotorSeq (FB1) 都通过。
这段代码有两个地方值得看:启动用了上升沿 R_TRIG(否则按住按钮会一直置位),以及停止/故障走的是 #statPermit 这一条独立通路,不经过定时器。后者正是下面第三个场景要验的东西。
四、全链路实测:从空工程到跑起来的 9 步
同一台机器上的一次完整下发,从空设备到一个能跑的程序,每一步的实际耗时如下。
| # | 动作 | 实测耗时 |
|---|---|---|
| 1 | 探活:确认网关连上了博途、当前工程名、设备数、前置检查 | < 1 s |
| 2 | 从硬件目录里查 CPU 型号 6ES7 516-3AN02-0AB0 / V2.9 |
~1 s |
| 3 | 建 CPU(PLC_2,CPU 1516-3 PN/DP V2.9) |
2.2 s |
| 4 | 导入 FB(SCL 源码,导入后自动生成块) | 11.8 s |
| 5 | 导入单实例 DB + 调用它的 OB1 | 各 0.6 s |
| 6 | 编译 | 1.4 s |
| 7 | 建虚拟 PLC 并上电 | ~6 s |
| 8 | 下载到 S7-PLCSIM Advanced | 9.6 s |
| 9 | 运行、写变量、读变量 | < 100 ms/次 |
第 4 步之后有个细节值得知道:导入不等于编译,块的"已编译"标记还是空的,这时候连导出都会被拒(Block is inconsistent (not compiled))。所以"导入 → 编译 → 再读"这个顺序不是建议,是硬约束。
第 8 步的返回很能说明这套东西的可信度——它把 TIA 的结果树完整摊开:
target device: PLC_2 6ES7 516-3AN02-0AB0 FW V2.9
removed PLC protection for the simulated PLC: master secret (WithoutPassword), access level (was NoAccess)
Success: PLC_2
Success: Hardware configuration
Success: Certificate configuration was loaded successfully.
Success: Hardware configuration was loaded successfully.
Success: Connection configuration was downloaded successfully.
Success: Routing configuration was loaded successfully.
Success: PLC_2 started.
Success: 'DB_MotorCtrl' / 'FB_MotorCtrl' / 'Main' were loaded successfully.
如果只回一句 Success: PLC_2,你分不清它是真下去了,还是只是回了个成功。
五、三个场景:数值对不对得上
先看时序,再看数值:
编译通过只说明它能进 PLC。下面三个场景是在仿真器里跑出来的,同一套 M 区读写。
| 场景 | 操作 | 观测 | 结论 |
|---|---|---|---|
| 启动 | M0.1=1(允许),M0.0 打一个脉冲 |
1 号电机立即 =1;3.12 s 后 2 号电机 =1;松开启动按钮后两台保持 |
延时设定 T#3s,误差来自 150 ms 轮询粒度 |
| 停止 | 两台运行中,M0.1 → 0 |
同一个采样点两台同时 =0;恢复 M0.1=1 后不自动重启 |
停止走的是立即断开通路,且不会自己恢复 |
| 故障 | 两台运行中,M0.2 → 1 |
13 ms 内(一次扫描)两台全停;故障复位后仍不自动重启 | 故障优先级高于一切,需人工重新启动 |
三个场景对应三件事:
- 3.12 s 证明定时器接的是"1 号电机运行"这个条件,而不是"按下启动按钮"——差这一层,实际设备上就是"按钮一松 2 号就不来了"。
- 同一个采样点全停证明停止通路没被定时器拖住。这类错误编译期查不出来,现场也未必复现,只有跑场景才看得见。
- 13 ms + 不自动重启证明故障是独立的锁断条件,且不会自愈——这条在真实设备上决定"要不要人按复位"。
另一台设备上我们还跑过一次"启动延时 2 s"的类似逻辑:定时器设定 2 s、实测 2.16 s,断开 0.06 s 内归零。两次的偏差都在一个采集周期量级,说明延时和断开两条路径的行为是稳定的。
六、读完再信:Success 之外还核对了什么
下载成功后我们没有直接收工,而是把块导出成 SimaticML 做离线核对——因为"下载成功"只说明数据下去了,不说明下去的是你写的那份。
| 对象 | 导出体积 | 核对点 |
|---|---|---|
Main(OB1) |
7,766 B | 确实调用了 DB_MotorCtrl,实参是 %M0.0/0.1/0.2,输出 => %M0.3 |
FB_MotorCtrl(FB1) |
15,978 B | 定时器用的是 IEC TON,没有夹带别的 FB 实例 |
DB_MotorCtrl(DB1) |
6,903 B | 单实例、consistent: true |
为什么用导出而不是"再读一遍块内容":导出是可归档、可 diff 的文本,改前改后一对比就知道谁动了什么,这也正好是验收清单里"改前归档"那条的落地方式。块的元数据里还有两个便宜信号:编程语言说明它到底是 SCL 还是 LAD,编译状态说明它编译过没有。
还有一个概念必须说清楚,网关自己的说明里写得很直白:Nothing is persisted until POST /save。导入、硬件写、删除、编译全部只在内存里,只有显式保存才落盘。这既是可回滚性(写坏了不 save 就等于没写),也是坑——如果你没 save 就以为改完了,关掉博途那一刻什么都没了。我们的做法是先不 save 跑完验证,通过了再一次 save。
七、上线前的验收清单
八条,按顺序过,一条不过就别往下走:
- 先只读。让它读项目树、块、交叉引用,确认它"看懂"了你的工程,再谈写。
- 写只开预览。网关支持预览模式,跑一周,把它预览出来的 diff 和人写的比。
- 必须带回读校验。写完导出 SimaticML 或读回
contentHash,不一致就当没写。 - 单项目、单会话、串行写。Openness 侧本来就是串行的,多个 Agent 并发写只会造出半成品。
- 编译当门禁。编译过不等于逻辑对,但编译不过一定不能提交——这条是唯一可以完全自动化的门禁。
- 改前先归档。VCI 或 Git 把块导成可比对的文本,出问题能一眼看出改了什么。
- 审计留痕。谁、什么时候、用什么模式、改了哪个对象。
- 别把下载/上线交给无人值守的 Agent。要下装到真机,人在回路、单步确认、有回滚预案。
再加一条红线:AI 生成的 SCL 必须人工复核,尤其急停、互锁、F 程序。工具能保证"写进去了",保证不了"写得对"。
八、版本与边界:先对号再动手
| 项目 | 实测结论 |
|---|---|
| 博途版本 | V19 / V20(本次实测 V19 + Openness 19.0) |
| Openness | 随博途安装,版本严格匹配;本机实测 Openness 19.0(2 个程序集) |
| 仿真器 | S7-PLCSIM Advanced 6.0,Softbus 模式;CPU 固件要够新(本文实测 V1.1 失败、V2.9 通过) |
| 部署形态 | 网关必须与博途同机;智能体可在另一台机器,只要能访问网关的 HTTP 端口 |
| 工具规模 | 本版 34 个工具(读写块、硬件、网络、编译、导出、仿真、LAD 规范各一组) |
关于"只能在同机"这条常见误解要澄清一下:MCP 网关必须和博途同机,但调用它的智能体不必。本文所有调用都是从另一台机器发 HTTP 请求过去的——本文所有调用都是从另一台机器发 HTTP 请求过去的。
再补一条容易被问到的日志行:成功下载的返回里有一句 removed PLC protection for the simulated PLC: master secret (WithoutPassword), access level (was NoAccess)。意思是网关在下载前会把仿真 PLC 的保护临时抹掉(否则块根本写不进去),而这句出现在日志里,总比它默默做掉、让你事后猜要强。
九、想自己跑一遍
要的东西只有两样:一台装了博途 V19 / V20 的 Windows 机器,和装在同一台机器上的 TiaLink。 装完它会在 http://localhost:8080/ 给出网关地址,客户端那边加上第二章那一条配置就通了。
安装方式与版本支持看产品页; 想让模型先读懂工程再动手,配套的 TIA-Context 负责把块、变量表、调用关系喂给它。
跑通之后最容易犯的错,是让它一次写太多。从一个小块、一个有测试用例的改动开始,比丢给它"帮我重构这个项目"稳得多——同一套工程的 WorkBuddy 版本里也是这个结论(AI 驱动的 PLC 程序开发)。
相关阅读:AI 改博途程序:TIA Openness MCP 的写保护与边界 | OPC UA MCP 上手实测:读数据、浏览节点、写设定值 | AI × 工业 / PLC 完全指南 | AI 编程 / Vibe Coding 完全指南
来源与版本:TiaLink 1.3.2.0(工具清单、前置检查项、下载结果树均由网关返回);S7-PLCSIM Advanced 6.0;Claude Code 2.1.311 的 claude mcp add --help 帮助文本;博途 V19。文中耗时与报错原话来自 2026-10-27 的运行记录。
本文由汇智网原创整理,转载请注明出处。AI 生成的 PLC 程序必须经人工复核后才能用于生产。