> ## Content Index
> Fetch the complete content index at: https://www.hubwiz.com/blog/llms.txt
> Use this file to discover other available public pages before exploring further.

# 智能体驱动的 PLC 编程
- URL: https://www.hubwiz.com/blog/agentic-plc-programming/
- Published: 2026-07-31T12:14:49.000Z
- Updated: 2026-10-13T14:50:14.000Z
- Description: 我们如何在Machine Expert的IronPython脚本引擎中构建CODESYS远程API，让基于Linux的AI代理直接通过HTTP读取、修改、编译和下载PLC程序。
- Author: admin
- Tags: AGENT, MACHINE EXPERT, #Import 2026-10-14 14:41

在[之前的文章](https://fulminis.ro/blog/llm-plc-programming-schneider-xef.html?ref=hubwiz.com)中，我们描述了如何教LLM读写施耐德电气的Control Expert XEF文件——M340 PLC背后的XML格式。这种方法之所以有效，是因为XEF文件是文本。导出、编辑、导入。

但对于我们运行在施耐德M241（TM241CE40R）上的混凝土工厂项目，我们转向了EcoStruxure Machine Expert——一个完全不同的工具，基于CODESYS 3.5。而Machine Expert的项目文件是二进制的。默认情况下没有文本导出。没有XSD模式。没有明显的入口。

问题是：我们能否给LLM与Control Expert相同的Machine Expert访问级别？不只是读取代码，而是修改它、构建它，最终下载到实时PLC——全部从Linux终端，通过SSH，通过AI代理？

答案是肯定的，但通往那里的道路比预期的更有趣。

## 1、三种方法，并行测试

我们首先研究了所有可能的远程控制Machine Expert的方法。三个并行研究方向：

**方法1：脚本化运行中的GUI。** Machine Expert有一个"Scripting Immediate"面板——一个IronPython 2.7 REPL，完全访问CODESYS脚本API。我们能从外部向它馈送命令吗？

我们发现Machine Expert（LogicBuilder.exe）不暴露COM对象、命名管道或命令行转发。`--runscript`标志启动一个*新*实例，而不是发送到正在运行的实例。在运行中的IDE中执行脚本的唯一方法是通过GUI的`>>>`提示。

使用Windows UI Automation（具有`Interactive`登录类型的计划任务 + `AutomationElement`来查找`>>>`输入字段），我们设法以编程方式粘贴和执行`execfile()`命令。脆弱，但它确实工作了。

**方法2：无头运行。** Machine Expert附带`LogicBuilderShell.exe`——一个为CI/CD设计的无头变体。它接受`--noUI --runscript`，应该非常适合自动化。

它拒绝启动。虚拟机没有激活施耐德电气许可证（以演示模式运行），而演示模式对话框需要GUI会话。Shell变体崩溃并显示：

```
System.InvalidOperationException: Showing a modal dialog box or form when the
application is not running in UserInteractive mode is not a valid operation.

```

没有付费许可证就是死胡同。

**方法3：在Machine Expert内部运行HTTP服务器。** 如果我们*在*IDE的IronPython环境中启动一个Web服务器呢？脚本引擎可以访问Python 2.7的`BaseHTTPServer`，而CODESYS明确支持通过`system.execute_on_primary_thread()`使用后台线程。

这是获胜者。

## 2、架构

解决方案是一个在Machine Expert的IronPython引擎中运行的单个Python 2.7脚本。当通过Scripting Immediate面板执行时，它在后台线程上启动一个HTTP服务器：

```
[Linux / Claude Code]  --HTTP-->  [Windows VM: Machine Expert + Bridge on port 8090]
                                         |
                                         v  (IronPython scripting API)
                                    [CODESYS engine]
                                         |
                                         v  (Modbus TCP via port proxy)
                                    [PLC TM241CE40R]

```

桥接器暴露一个REST API：

```
GET  /api/status          - 项目路径、脏标志、应用程序名称
GET  /api/tree            - 列出所有对象（POU、GVL、类型）
GET  /api/st/read?name=X  - 读取任何POU的声明 + 实现
POST /api/st/write        - 修改任何POU的ST代码
POST /api/build           - 编译应用程序
POST /api/xml/import      - 导入PLCopen XML
POST /api/xml/export      - 将对象导出为PLCopen XML
POST /api/project/save    - 保存项目
POST /api/shutdown        - 停止桥接器

```

每个触及项目的操作都通过`system.execute_on_primary_thread()`编组到主线程，而HTTP服务器在守护线程上运行。这是CODESYS明确支持的，但在其文档中标记为"仅限专家"。

## 3、编码陷阱

第一个版本立即对简单操作有效——`/api/ping`、`/api/status`、`/api/build`都返回了干净的JSON。但当我们试图从POU读取ST代码时，响应为空。

Machine Expert控制台中的错误说明了问题：

```
UnicodeDecodeError: 'unknown' codec can't decode byte 0xB3 at position 8673

```

CODESYS返回的.NET `System.String`对象包含来自Windows代码页的字符（在这种情况下，来自代码注释中`kg/m³`单位的`³`）。Python 2.7的`json`模块试图将它们解码为UTF-8并失败了。

修复是一个递归清理器，强制每个字符串通过`unicode()`并使用`xmlcharrefreplace`回退：

```python
def _sanitize(obj):
    if isinstance(obj, dict):
        return {_sanitize(k): _sanitize(v) for k, v in obj.items()}
    if isinstance(obj, (list, tuple)):
        return [_sanitize(item) for item in obj]
    if isinstance(obj, bool) or isinstance(obj, (int, float)) or obj is None:
        return obj
    try:
        s = unicode(obj)
        return s.encode("ascii", "xmlcharrefreplace").decode("ascii")
    except:
        return u"<encoding error>"

```

此后，每个POU——包括那些带有罗马尼亚语变音符号和工程单位符号的——都干净地序列化为JSON。

## 4、我们能用它做什么

随着桥接器的运行，Linux上的AI代理对Machine Expert项目拥有完整的编程访问权限。以下是典型工作流的样子：

**读取所有PLC代码：**

```bash
$ curl -s http://<vm-ip>:8090/api/tree?recursive=true | python3 -m json.tool
{
  "objects": [
    {"name": "Continuous_Dosing_Control", "has_declaration": true, "has_implementation": true},
    {"name": "FB_BeltScale", "has_declaration": true, "has_implementation": true},
    {"name": "GVL_Dosing", "has_declaration": true},
    ...
  ],
  "count": 55
}

$ curl -s "http://<vm-ip>:8090/api/st/read?name=Continuous_Dosing_Control"
{
  "name": "Continuous_Dosing_Control",
  "declaration": "PROGRAM Continuous_Dosing_Control\nVAR\n    max_component: REAL; ...",
  "implementation": "(* Recipe calculations *)\nrecipe_density := aggregate1_target + ..."
}

```

**修改代码并构建：**

```bash
$ curl -X POST -d '{"name":"MAIN","implementation":"PRG_ModbusComm();\nPRG_Control();"}' \
    http://<vm-ip>:8090/api/st/write
{"name": "MAIN", "updated": ["implementation"]}

$ curl -X POST http://<vm-ip>:8090/api/build
{"result": "build_complete", "message_count": 0, "messages": []}

```

**导出PLCopen XML用于版本控制：**

```bash
$ curl -X POST -d '{"name":"Application","path":"C:\\export.xml","recursive":true}' \
    http://<vm-ip>:8090/api/xml/export
{"result": "exported", "path": "C:\\export.xml"}

```

## 5、实际使用：分析和修改配料算法

桥接器立即证明了它的价值。我们需要理解和修改混凝土工厂的连续配料算法——一个PLC程序，它根据配方目标计算皮带速度，带有VFD校正因子和自动数量跟踪。

使用桥接器，AI代理：

**读取所有12个POU和6个GVL**来自实时项目，理解从配方输入到速度计算再到VFD输出的完整数据流。

**识别了一个设计问题**：速度计算没有考虑不同的皮带容量。一条在100%时输送72,000 kg/h的皮带和一根在100%时输送19,000 kg/h的水泥螺旋，如果给定相同的百分比设定点，会产生错误的比例。

**提出并验证了修复**：在计算速度比率之前，将配方目标按校准值归一化。七行结构化文本，独立于工厂操作员准备的电子表格计算进行了验证。

**在操作员在Machine Expert中应用更改后读回代码**，在下载到PLC之前确认修改是正确的。

所有这些都是通过SSH进行的，AI代理在通过WireGuard VPN连接到工厂网络的Linux笔记本电脑上运行。PLC通过SCADA计算机上的端口代理访问，Machine Expert在KVM虚拟机中运行。

## 6、引导：唯一的手动步骤

桥接器需要一个手动操作：打开Machine Expert的Scripting Immediate面板并输入：

```python
execfile(r"C:\Users\Adi\me_bridge_server.py")

```

之后，一切都是远程的。只要Machine Expert打开，桥接器就会保持。如果Machine Expert重新启动，需要重新输入命令——或通过UI Automation使用计划任务自动化。

我们研究了通过Windows UI Automation自动化此步骤（通过其`AutomationId`查找`>>>`输入字段，设置焦点，通过剪贴板粘贴，发送Enter）。它有效，但很脆弱且需要交互式桌面会话。目前，手动引导是可以接受的——这是每个Machine Expert会话的一次性操作。

## 7、CODESYS脚本API

桥接器之所以有效，是因为CODESYS附带了全面的IronPython脚本API。注入脚本命名空间的关键对象：

- `**projects**` — 打开、保存、关闭项目。`projects.primary`返回活动项目。
- `**system**` — 消息存储、线程、UI控制。`system.execute_on_primary_thread()`是线程安全操作的关键方法。
- `**online**` — PLC连接、登录、下载、启动/停止。`online.create_online_application()`提供对实时变量读写的访问。

API通过安装目录中的`.pyi`存根文件记录：

```
LogicBuilder/ScriptLib/Stubs/scriptengine/
├── ScriptProject.pyi      # 项目操作、XML导入/导出
├── ScriptApplication.pyi  # 构建、重建、清理、引导应用程序
├── ScriptOnline.pyi       # PLC连接、下载、变量访问
├── ScriptTextualObject.pyi # 读取/写入ST代码
├── ScriptTreeObject.pyi   # 导航项目树
└── ScriptSystem.pyi       # 线程、消息、UI

```

这些存根是Machine Expert等同于Control Expert的XSD模式——使编程访问成为可能的未记录关键。

## 8、下一步

桥接器开启了我们仍在探索的可能性：

- **自动化回归测试**：修改POU、构建、检查错误、恢复——全部在脚本中。
- **实时变量监控**：`ScriptOnlineApplication.read_value()`方法可以实时读取PLC变量，实现AI辅助调试。
- **持续部署**：修改代码、构建、下载到PLC、验证——工业自动化的CI/CD管道。
- **多项目管理**：相同的桥接器模式应该适用于任何基于CODESYS 3.5的IDE（ABB Automation Builder、WAGO e!COCKPIT等）——未经测试，但脚本API是共享的。

根本见解与我们Control Expert工作的见解相同：工业自动化工具比其供应商宣传的具有更多的编程访问权限。你只需要查看安装目录。

---

原文链接:[ Building an HTTP Bridge Inside Machine Expert for LLM-Driven PLC Programming](https://fulminis.ro/en/blog/llm-machine-expert-bridge.html?ref=hubwiz.com)

汇智网翻译整理，转载请标明出处

> **这是「AI × 工业 / PLC」专题的一部分。**完整地图见：[AI × 工业 / PLC 完全指南](https://www.hubwiz.com/blog/ai-industrial-stack/)