模拟对象、Graph 与调试
现在把“页面自己改状态”升级为接近真实工程的分层方式:Object 表达工作站能力,Graph 编排包装周期,Page 只发命令和显示状态。整个例子仍是纯模拟,不连接 PLC、运动轴或 IO。
本节目标
- 理解 Object、Graph 和 Page 的责任边界
- 让 AI 先读取当前应用可用能力,再创建模拟能力
- 在 Graph 中使用有界等待和明确的 Timeout 分支
- 设置断点并用调试(Debug)观察执行
- 人工改变超时参数,验证故障路径
只需要先懂四个概念
| 概念 | 作用 |
|---|---|
| Object | 一个设备或业务模块的运行实例,对外提供有名字的状态和方法。 |
| Graph | 把对象方法、条件和等待编排成可视、可调试的流程。 |
| Wait Until | 重复检查条件,成功时继续;超过明确时限则进入 Timeout。 |
| 调试(Debug) | 带断点运行 Graph,暂停后检查节点、变量和对象状态。 |
推荐的依赖方向是:
Page → Object 方法 → Graph 编排 → 小而稳定的模拟/设备能力
页面不拥有机器流程,Graph 也不猜测物理设备语义。
开始前
- 已完成页面变量、按钮与 Page Method。
- App 已停止。
- 这是一个明确的模拟器任务:模拟封口在约 1.5 秒后完成,不访问任何物理 IO。
第 1 步:让 AI 先做架构判断再实施
在 AI Command Center 中通过 @ 选择 qxauto、qxgraph、qxscript 和 qxpage。同时引用当前首页。发送:
目标:把当前包装工作站的纯页面模拟改成“模拟 Object + Object-bound Graph + Page”的可调试实现。
已确认的模拟语义:
- 这是纯软件模拟,不连接 PLC、Pulsar、轴、IO、相机或 Safety
- 启动一个包装周期后,模拟封口在约 1500 ms 后完成
- 正常完成时包装计数加 1,状态回到 Ready
- 等待超时时进入 Fault,保留可读错误信息,并提供 ResetFault
架构要求:
- 先检查当前对象、可用方法、Graph 节点和页面控件
- 优先复用已有能力;如果当前 app 缺少模拟能力,再创建最小的 app-local ObjectBase 模拟对象
- 创建一个语义清楚的包装工作站对象,并绑定一个 graphs/ 下的 Graph
- Graph 保留 Init、Update、Dispose 生命周期,并公开 StartCycle 和 ResetFault 等页面需要的方法
- Graph 级等待使用当前应用提供的标准 Wait Until 节点
- WaitUntil 的 Timeout ms 必须是明确正值,Poll interval ms 必须明确;Success 和 Timeout 都要连接
- 增加可在属性面板编辑的 Graph 变量 cycleTimeoutMs,默认 3000
- 不写无限循环,不把等待放进 Page Method,也不吞掉超时
- 页面改为调用对象/Graph 方法,并从对象运行变量读取状态、计数和错误;删除上一课不再需要的页面模拟状态
验证要求:
- 分别校验最终 page 和 graph
- 对保存后的 Graph/C# 运行应用构建,修复到构建成功
- 最后列出新增或修改的文件、对象 ID、Graph methods、正常分支、Timeout 分支和构建结果
让 AI 根据当前应用实际可用的对象方法和 Graph 节点决定最小实现。不要在提示词里杜撰 C# 基类成员、Graph 端口顺序或运行 API。
AI 预期影响面
合理的修改可能包括:
objects.jsongraphs/packaging-station.qxgraphscripts/下一个小型模拟 Object 源文件(仅在现有能力不足时)pages/packaging-station.qxpagei18n.json
AI 还会运行页面和 Graph 诊断以及应用构建。生成的构建输出不应被当成教程中要手工维护的源码。
不应修改 pulsar.json、PLC、Vision、查询、用户或 Safety 配置。
第 2 步:在编辑器中检查分层结果
- 在 资源(Resources)→ 对象(Objects) 中找到包装工作站对象,确认 ID 和描述能表达“模拟包装工作站”,而不是
Object1之类的模糊名称。 - 在资源 → Graph中打开
packaging-station。 - 确认 method 列表包含
Init、Update、Dispose,以及页面需要调用的周期和复位方法。 - 找到 Wait Until,沿控制流确认 Success 和 Timeout 都有后续处理。
- 确认
Condition是每轮检查后重新读取的布尔状态,Timeout ms和Poll interval ms都有明确值。 - 打开首页,确认按钮调用对象/Graph 方法,状态显示读取对象变量,而不是旧的
QX.globals.lineRunning。 - 打开问题(Problems),确认没有错误;标题栏的构建状态应显示成功。
如果 AI 给出的是一个大 Page Method 或一个吞掉所有细节的巨大 C# 方法,要求它按 Object capability、Graph orchestration、Page UI 三层重新拆分。
第 3 步:先验证正常分支
- 在 Graph 中找到正常完成后的关键节点。
- 点击节点标题区右侧的断点点位。
- 点击标题栏的调试。
- 打开运行页,点击启动包装周期的按钮。
- 大约 1.5 秒后,编辑器应在正常分支断点暂停,应用状态显示 已暂停。
- 在调试面板检查对象状态和计数,再点击 继续。
预期结果:周期完成、计数增加 1、状态回到 Ready,错误信息为空。
人工微调:故意制造一次超时
cycleTimeoutMs 被设计为可在属性面板编辑,正好用来学习“参数由人确认,AI 帮你编排”。
- 先点击 停止,让 App 回到已停止状态。
- 在资源的对象树中选择包装工作站对象。
- 在右侧属性面板把
cycleTimeoutMs的对象覆盖值改为500。 - 在 Graph 的 Timeout 处理节点上设置断点。
- 再次点击调试,从运行页启动一个周期。
模拟封口约 1500 ms 才完成,而超时只有 500 ms,因此执行应进入 Timeout 分支并在断点暂停。继续后,页面应显示 Fault 和可读错误;调用 ResetFault 后回到可再次测试的状态。
对象属性变化会在下一次显式加载、开始或调试时进入新的运行实例。Theseus 不会在运行中替换正在执行的对象实例。
调试验收清单
- 默认 3000 ms 时走 Success,计数增加
- 对象覆盖为 500 ms 时走 Timeout,不会无限等待
- 暂停时编辑器自动定位当前 Graph 节点
- 继续能离开断点,停止能结束调试
- Fault 信息能在页面看到,ResetFault 能恢复模拟状态
- 问题中没有错误,应用构建成功
安全边界
这个模拟对象不能直接替换现场设备对象。接入 PLC、轴、IO 或相机前,工程人员必须定义真实对象、地址、单位、动作、允许条件和故障语义。AI 可以按这些事实生成编排,但不能发明它们。
- 页面上的停止按钮不是急停。
- Graph Timeout 是软件流程恢复路径,不是 Safety 联锁。
- 真实设备的有界等待应由稳定的对象 API 暴露,再由 Graph 编排。
- 在设备上试运行前,人工检查 Init、Dispose、异常分支和所有输出动作。
出问题时怎么恢复
| 症状 | 检查和恢复 |
|---|---|
| 构建按钮不可用 | App 仍在运行、调试、暂停或停止中;先点击继续或停止,回到已停止状态。 |
| Graph 找不到对象方法 | 先检查 C# 构建诊断和对象类型,再让 AI 重新读取当前应用可用的对象方法;不要手填猜测的方法名。 |
| Wait Until 总是超时 | 检查 Check 分支是否刷新状态,Condition 是否在每轮重新读取,模拟完成时间是否小于 timeout。 |
页面仍改 QX.globals | 要求 AI 删除旧页面模拟路径,改为只读对象变量并调用对象/Graph 方法。 |
| 调试没在断点停下 | 确认断点设在实际执行的方法内,并且是用调试而不是开始启动。 |
| 运行时异常 | 查看错误详情和 Graph Trace,先停止,再 @ 引用 Graph/脚本让 AI 做只读原因分析;确认方案后再修复和构建。 |
下一步
保留 500 ms 的故障演练结果,下一课会先把它恢复到可交付参数,再构建远端目标并用 Player 绑定运行页:构建、远程 Runtime target 与 Player。