TiaLink
把 TIA Portal 接到你的智能体:导入、编译、读回核对、PLCSIM 仿真。本地运行,工程数据不出厂。
打开 TiaLink给整个 TIA 工程建一张知识图谱,用调用/读写/实例化关系和未解析引用回答「谁用谁、改它波及谁、哪里缺东西」,每条结论都带文件与行号。
学完你能:能对一个陌生工程做一次图谱问答,产出「对象 + 关系 + 风险」三张表,并知道哪些结论可以直接当证据、哪些必须回 TIA 复核。
上一课《改一个 IO 地址,会影响谁?》是一处一处地查;这一课换一种问法:先让 agent 给整套工程建一张图,然后直接问这张图。
一句话区别:搜索给你候选,图谱给你带行号的证据。
图里有三样东西,必须一起看:
| 组成 | 含义 | 用来回答 |
|---|---|---|
| 节点 | 工程里的对象:块、网络、接口成员、标签、触点/线圈/盒子、SCL 语句 | "工程里有什么" |
| 边 | 对象之间的关系 + 出处:调用、实例化、类型、读、写、连线 | "谁调用谁、谁写这个标签" |
| 未解析引用 | 建立了引用、但工程里找不到对应对象的名字(不建边,避免污染结论) | "哪里缺东西"——接手/迁移前最值钱的一张清单 |
本课用同一套开源工程 PLC_SCADA_HMI(MIT)实测,全程只读:你只需要说清要问什么,建图和查询都是 agent 自己完成的。
本课按一步一问组织:每步给出可复制的「你说」和对应的「它回」,先看输出再问下一步;一次要全套报告的提示词放在最后,作为熟练后的选项。
| 指标 | 本课实测(2026-10-27,TIA Portal V19 + TiaLink 1.4.0.0) |
|---|---|
| 设备 | S7-1500/ET200MP station_1,CPU 1513F-1 PN(6ES7 513-1FL02-0AB0,V2.9) |
| 建图 | 一句话,1–3 秒(本机从零开始实测 1.2 s) |
| 图 | 227 个对象节点 / 517 条关系 / 8 条未解析引用 |
| 工程规模 | OB1(4 网络)、2 个 FB、2 个实例 DB、2 张点表、51 个标签 |
核心观点三句话:
IEC_Timer_0_DB* 全是找不到对应对象的引用——这类问题编译不一定报,靠搜也很难发现。/ 谁写了这个标签",并让每条结论带上出处和行号;http://localhost:8080/mcp;PLC/PLC_SCADA_HMI.zap19),也可以用示例库里的多块示例 SCL 训练:存储功能块 练手;dirty 不影响建图,但要记下基线。本课按一步一问组织:每步只问一件事,先看输出再问下一步。后面的分析步骤都有「你说」和对应的「它回」,输入和输出对得上;熟练后想一次拿全套报告,再看文末的「熟练后:一次要全套报告」。
在博途那台机器上启动 TiaLink、打开工程。页首状态条会自动检测;然后在客户端里加一个 Streamable HTTP MCP 服务:
{
"mcpServers": {
"tialink": {
"type": "http",
"url": "http://localhost:8080/mcp",
"headers": { "Authorization": "Bearer <你的 TiaLink API Token>" }
}
}
}看到什么:客户端连上了 TiaLink,你可以直接用中文让它读工程。用不着记工具名,也不用背命令——下面每一步都只是"你说话,它去做"。
你说(一句话就行):
只读。先给当前打开的工程建一张工程图,然后告诉我图的基本情况:工程名、CPU 型号、图里有多少对象和关系、有多少条未解析引用、一共花了多久。
它回(本机实测):
| 它会告诉你 | 实测值 |
|---|---|
| 工程 | PLC_SCADA_HMI |
| 设备 / CPU | S7-1500/ET200MP station_1 / CPU 1513F-1 PN |
| 图里有多少东西 | 对象节点 227、关系 517 |
| 缺口 | 未解析引用 8 条 |
| 建图用时 | 约 1 秒(这一次从零开始 1.2 s) |
这里要盯的不是数字大小,而是三条确认,它们决定后面的结论能不能信:
PLC_SCADA_HMI);这三条任何一条说不清,先重建一次,再往下问。
不用一次写一大段。后面每一步只问一件事:盘家底、找对象、看一个块、问关系、问影响、抓缺口。每次问完先看两件事:
分开问的好处很直接:输入小、输出短,哪一步不对当场就能发现;一次问六件事,某一段被截断你很难察觉。下面的每一步都给出可以直接复制的「你说」和本次实测的「它回」。
想一次拿到整套报告?那是熟练后的用法,见文末「熟练后:一次要全套报告」。
你说:
只读。列出这个工程里有什么:块(类型、编号、语言、网络数)、实例 DB、点表、UDT、CPU 型号与订货号;同名对象单独列,没有的对象写 0。
它回:一次问清,比逐块读快,也不容易漏。本次清单:
| 项 | 实测 |
|---|---|
| CPU / 订货号 / 固件 | CPU 1513F-1 PN / 6ES7 513-1FL02-0AB0 / V2.9 |
| 块 | OB1::Main(OB 1,LAD,4 网络)、FB::Auto_mode(FB 2,LAD,1 网络)、FB::Manu_mode(FB 3,LAD,1 网络) |
| 实例 DB | InstanceDB::Block_1_DB(12)、InstanceDB::Manu_mode_DB(13) |
| 点表 / UDT | Main_variables、additional_variables / 0 个 |
| 同名对象 | 0 |
FB 2 [LAD]),可以直接和 TIA 项目树对照;你说:
只读。找
Auto_mode(换成CV-101或Conveyor也可以):按精确名 → 前缀 → 注释里的词 → 包含逐级放宽,告诉我命中的是哪一档,以及结果有没有被截断。
它回:它会按"精确名 → 前缀 → 注释里的词 → 包含"逐级放宽,并告诉你命中的是哪一档:
| 你问 | 命中 | 靠什么命中 |
|---|---|---|
Auto_mode |
4 条:FB::Auto_mode、调用点 Main::N1::I1、它的文件、它的网络 |
精确名 + 前缀 |
CV-101 |
1 条:Main_variables.CV-101(Bool %Q4.0,注释 "Conveyor") |
精确名 |
Conveyor |
3 条 | 注释里的词(不是名字) |
看到什么,两句要盯:
Auto_mode 时就是"还有更多",如果你不问一句"看全了吗",就会把前 4 条当全部。你说(主程序):
只读。把
OB1::Main一次拆开:接口、每个网络、它调用了谁、读写清单、块内缺失引用;哪一部分被截断就说明。
你说(另一个 FB):
只读。再看
FB::Auto_mode:接口、网络、读写清单、块内缺失引用。
它回:一个块一次拿全:接口、每个网络、聚合后的调用目标与读写清单、块内缺失的引用。
OB1::Main(本工程主程序)本次结果:
| 项 | 实测 |
|---|---|
| 块 | OB 1 [LAD],4 个网络(N1/N2 各有内容,N3/N4 是空网络) |
| 调用了谁 | FB::Auto_mode、FB::Manu_mode |
| 读 / 写 | 10 处读 / 0 处写 |
| 块内缺失引用 | 0 |
FB::Auto_mode(1 个网络)则是另一种画像:接口是空的(输入/输出/静态等分节都没成员),网络里却有 22 处读、17 处写、5 条找不到对象的引用——这是本工程真实的样子(不是解析出错),它直接解释了第九步的 8 条幽灵引用(另一个 FB Manu_mode 是 21 读 / 16 写 / 3 条)。
看到什么:如果结果里写着"只给了一部分",说明这个块比给你看的多(网络数或读写条数被截断);要么让它继续要,要么缩小问题范围,别拿一页当全部。
这是这套图存在的理由。问法只有两种:"谁用它"和"它用了谁"。
你说(标签读写):
只读。
additional_variables.tag3被谁读、被谁写?读写分开,每条给出块名 + 网络号 + 行号 + 出处。
你说(调用点):
只读。
Main::N1::I1属于谁、谁连到它、它调了谁?每条给出出处。
它回:先看关系形状(示例子图),再看两张关系表。
读和写分开看:同一个 tag3 有 2 条蓝色读边、2 条橙色写边,说明改动会碰到 4 个 LAD 位置;灰虚线是结构包含,紫虚线是点表包含。
问"这个标签被谁读、被谁写"(additional_variables.tag3),本次结果一条不漏:
| 关系 | 来自 | 行 | 出处 |
|---|---|---|---|
| 属于点表 | additional_variables |
— | 点表包含 |
| 读 | Auto_mode::N1::L13(触点) |
152 | 按操作数解析 |
| 写 | Auto_mode::N1::L26(线圈) |
217 | 按操作数解析 |
| 读 | Auto_mode::N1::L27(触点) |
222 | 按操作数解析 |
| 写 | Auto_mode::N1::L35(线圈) |
262 | 按操作数解析 |
同一个调用点,问"它属于谁、谁连到它、它调了谁":
| 关系 | 从 | 到 | 出处 |
|---|---|---|---|
| 属于 | Main::N1(网络) |
Main::N1::I1(调用点) |
结构包含 |
| 连线 | Main::N1::L11(LAD 零件) |
Main::N1::I1 |
LAD 导线 |
| 调用 | Main::N1::I1 |
FB::Auto_mode |
按调用解析 |
"改它会波及谁"和"谁用它"不是一回事:前者会沿关系反着走多层,每一条命中都告诉你走了几层、经过什么关系。
你说(默认关系):
只读。如果改或删
FB::Auto_mode,波及哪些对象?按层数列,标明经过什么关系。
你说(加上「包含」):
只读。再把「包含」也算上,多走几层,看它属于哪个块。
它回:下面先看关系形状,再看默认关系和加「包含」两组结果。
图里把两层画在一起:调用 / 实例化是默认问法能答的部分;①–④ 是额外把「包含」算上才出现的层级链。箭头按正常的「包含」方向画(外层的源文件 → 块 → 网络 → 内层文件);影响面是反着走这些箭头,所以离 FB::Auto_mode 最近的是第 1 层。
它回(默认关系):
| 层数 | 经过 | 命中 |
|---|---|---|
| 1 | 调用 | 调用点 Main::N1::I1 |
| 1 | 实例化 | 实例 DB InstanceDB::Block_1_DB |
可以直接写成一句人话:"Auto_mode 被主程序第 1 个网络调用,实例 DB 是 Block_1_DB;改它的接口要同时看这两处。"
但默认的关系集合里没有"包含",所以"它属于哪个块"不会出现。把"包含"也算上,并多走几层,才会沿层级往上走:
它回(加上「包含」):
| 层数 | 经过 | 命中 |
|---|---|---|
| 1 | 包含 | 它的源文件 |
| 2 | 包含 | 它所在的网络 Main::N1 |
| 3 | 包含 | OB1::Main(包含它的块) |
| 4 | 包含 | 主程序的源文件 |
这条差异值得记住:默认问的是"谁会受影响"(调用/读写/实例化),加了"包含"才回答"它长在谁身上"。
你说:
只读。列出所有未解析引用,每条给文件与行号,标「待定 / 外部」,并判定「真缺失 / 外部库 / 待补」;不能确认的不要猜。
它回:引用了、但工程里找不到对象的名字,不会被硬凑成关系,而是进这张清单——接手/迁移前最该看的东西。本工程 8 条:
| 状态 | 引用(被写入) | 文件 | 行 |
|---|---|---|---|
| 待定 | IEC_Timer_0_DB_3 |
blocks/Auto_mode.xml |
332 |
| 待定 | IEC_Timer_0_DB_4 |
blocks/Auto_mode.xml |
337 |
| 待定 | IEC_Timer_0_DB_1 |
blocks/Auto_mode.xml |
483 |
| 待定 | IEC_Timer_0_DB_2 |
blocks/Auto_mode.xml |
488 |
| 待定 | IEC_Timer_0_DB_3 |
blocks/Manu_mode.xml |
232 |
| 待定 | IEC_Timer_0_DB_4 |
blocks/Manu_mode.xml |
237 |
| 待定 | IEC_Timer_0_DB_2 |
blocks/Manu_mode.xml |
323 |
| 外部 | IEC_Timer_0_DB |
blocks/Auto_mode.xml |
493 |
怎么读这张表(本课最值得带走的方法):
交叉验证(可选但建议):让 agent 顺手编译一遍,本次结果是一句 No block was compiled. All blocks are up-to-date.("没有块被编译")。注意:这句话意味着这次"成功"不能当成"逻辑没问题"的证据,只能当成"当前没有待编译改动"。幽灵引用到底会不会炸,仍然要按上面三步人工判定。
你说:
只读。把前面的结果整理成三张表:对象表、关系表、风险表;每条结论带出处或行号,不能确认的标注「无法确认」。
它回:
dirty 与开始时一致。完整产物如下(本次运行生成;展示时只做了排版,内容未改):
只读生成 · 2026-10-27 · TiaLink 1.4.0.0 + TIA Portal V19
| 字段 | 值 |
|---|---|
| 来源 | 当前打开的工程(不是旧图) |
| 设备 / CPU | S7-1500/ET200MP station_1 / CPU 1513F-1 PN(6ES7 513-1FL02-0AB0,V2.9) |
| 图规模 | 227 个对象节点 / 517 条关系(包含 220 / 调用 2 / 实例化 2 / 读 87 / 写 52 / 连线 154) |
| 未解析 | 8(待定 7 / 外部 1) |
| 同名对象 | 0 |
| 建图时间 | 2026-10-27T17:42:33Z |
| 对象 | 类型 | 签名 | 说明 |
|---|---|---|---|
OB1::Main |
OB | OB 1 [LAD] |
4 网络;N1/N2 有内容,N3/N4 为空网络 |
FB::Auto_mode |
FB | FB 2 [LAD] |
1 网络 / 79 个网络元素;22 读 17 写;接口无成员;未解析 5 |
FB::Manu_mode |
FB | FB 3 [LAD] |
1 网络;21 读 16 写;未解析 3 |
InstanceDB::Block_1_DB |
实例 DB | InstanceDB 12 [DB] |
Auto_mode 的实例 |
InstanceDB::Manu_mode_DB |
实例 DB | InstanceDB 13 [DB] |
Manu_mode 的实例 |
Main_variables |
点表 | — | 含 CV-101(Bool %Q4.0,注释 Conveyor)等 |
additional_variables |
点表 | — | 含 HMI/MATLAB 握手与 tag3 |
| UDT | — | — | 本工程 0 个 |
| 关系 | 源 | 目标 | 出处 |
|---|---|---|---|
| 调用 | Main::N1::I1 |
FB::Auto_mode |
按调用解析 |
| 实例化 | InstanceDB::Block_1_DB |
FB::Auto_mode |
按实例解析 |
| 写 | Auto_mode::N1::L26(线圈,行 217) |
additional_variables.tag3 |
按操作数解析 |
| 写 | Auto_mode::N1::L35(线圈,行 262) |
additional_variables.tag3 |
按操作数解析 |
| 连线 | Main::N1::L11 |
Main::N1::I1 |
LAD 导线 |
| # | 风险 | 证据 | 定性 | 复核动作 |
|---|---|---|---|---|
| 1 | 8 条 IEC_Timer_0_DB* 引用无对应对象 |
未解析清单,行号见上表 | 待人工定性(疑真缺失) | 在 TIA 里查这 4 个定时器实例是否存在;不存在则补或改块 |
| 2 | 两个 FB 接口无成员,但网络里读写大量标签 | 接口分节为空;Auto_mode 22 读/17 写,Manu_mode 21 读/16 写 |
结构性风险(可编译、可运行,但不可参数化复用) | 与工程主人确认为什么不用接口变量 |
| 3 | 空网络 N3/N4 | 网络里没有元素 | 信息 | 确认是有意留白还是漏写 |
| 4 | 编译状态不可当验收 | 编译报告:No block was compiled |
盲区 | 改完必须真正改一个块再编译,才能验证 |
本报告生成过程未修改工程:只建图与查询,未导入、未改块、未保存;工程 dirty 与开始时一致。
分步问适合第一次做图谱分析:每步都能核对,出错容易定位。熟悉之后,可以把下面这段一次发出去,让它按顺序做完并给出三张表。代价是输出很长,必须逐段检查有没有「还有更多」。
只读,不要修改任何对象,也不要保存工程。请给这个工程建一张图,然后回答:
- 工程里有什么:块(类型、编号、语言、网络数)、实例 DB、点表、UDT、CPU 型号与订货号;同名对象单独列;
- 调用结构:主程序调了谁、每个调用点在哪个网络;
- 读写关系:关键 DB/标签被哪些块、哪些网络读、哪些网络写,读写分开;
- 影响面:如果我改或删掉某个 FB/DB,波及哪些对象、经过什么关系;
- 缺口:有没有引用了工程里不存在对象的名字(幽灵引用),每条给出文件与行号,并判定是「真缺失 / 外部库 / 待补」;
- 每条结论给出依据(块名 + 网络号 / 文件 + 行号 / 关系的出处),只能推断的标注「推断」,无法确认的标注「无法确认」。
最后给三张表:对象表、关系表、风险表。不要猜。
第一次做,建议还是按上面的步骤分开问;这套一次性提示词适合你已经知道该看哪些结果、只需要它跑完整套的时候。
No block was compiled);dirty 与开始时一致,未保存。把 TIA Portal 接到你的智能体:导入、编译、读回核对、PLCSIM 仿真。本地运行,工程数据不出厂。
打开 TiaLink