QG 流程程序
QG 用来表达有顺序的自动化行为:调用 Object、判断条件、等待、记录状态,并处理故障和恢复。当前唯一源码格式是 .qg;编辑器的 Source 和 Flow 只是同一份程序的两种视图。
如果你第一次使用 QG,先完成QG 流程、对象调用与调试,再回来查本页。
什么时候使用 QG
适合放进 QG 的内容:
- 设备或业务动作的先后顺序;
- 条件、分支、有界等待和超时;
- 多个 Object 之间的协调;
- App 启动、周期更新和停止时需要执行的流程;
- 需要通过 Debug 断点观察的控制逻辑。
不适合放进 QG 的内容:
- Page 布局和按钮外观;
- 设备协议、寄存器解析或驱动实现;
- 急停、安全回路或认证安全功能;
- 项目未管理的第三方代码、动态脚本或无限后台任务。
创建并打开 QG
- 在 Resources 右键 Scripts。
- 选择新建 QG 程序,使用清楚、稳定的文件名,例如
packaging-station.qg。 - 编辑器会在
graphs/下创建源码,并为它建立对应的 Object 实例;在 Resources → Objects 中确认 Object ID 和名称。 - 在 Source 编写或审阅源码;需要结构化浏览时切到 Flow。
- 保存后先处理当前文档的实时诊断;需要完整结果时执行 Build。
每个 QG 文件开头应有一段简短 JSDoc,说明它对 App 提供的能力。描述应面向工程用途,例如“编排包装周期并处理超时恢复”,不要写实现历史或易变参数。
Source 与 Flow
- Source 是唯一源码,可以由人工或 AI 直接编辑。
- Flow 从当前 Source 生成,并把函数、条件、循环和 Object 调用投影成结构化流程。
- 在 Flow 中接受的修改会更新同一份 Source;不存在另一份连线文件、坐标文件或待同步草稿。
- Source 与 Flow 使用同一组断点。源码位置变化后应重新 Build Debug,再开始新的调试会话。
如果 Flow 无法显示,先看 Source 和 Problems。上游 QG 或 Object 错误没有解决前,不要通过删除类型或猜测方法名来强行生成空流程。
程序结构
一个 QG 通常包含三类内容:
| 内容 | 用途 |
|---|---|
| 顶层状态 | 当前运行实例内共享的短期状态;重新加载实例后会重置 |
| 普通函数 | 拆分计算和流程步骤,只在当前 QG 内使用 |
export function | 该 QG Object 对 Page、其他 QG 或在线工具公开的方法 |
可选生命周期函数只有:
Init(): void:App 开始时执行一次;Update(): void:运行期间由 Runtime 周期调用;Dispose(): void:停止或故障清理时执行。
不要在 QG 中创建自己的周期定时器或永久循环。把一次 Update 控制在可预测时长内,并为所有外部等待设置明确的超时和恢复路径。
使用 Object 能力
QG 通过 objects.<引用名>.<方法>(...) 调用当前 App 已绑定的 Object。正确流程是:
- 在 Flow 使用添加 Object 引用,或在 Object 属性中选择目标实例。
- 从编辑器提供的当前方法列表选择能力。
- 按显示的参数顺序、类型和单位传值。
- 保存并处理 Object 或 QG 诊断。
- Build 后在模拟器或受控设备状态下验证真实结果。
Object 方法必须来自当前 App 已安装的能力。不要根据旧项目、截图或类似设备猜测方法名、单位、极性和允许条件。AI 也应先检查当前 Object catalog,再只展开实际要使用的 Provider 接口。
常用语言规则
QG 使用便于 TypeScript 工具理解的语法,但不是通用 JavaScript 运行环境。
| 需要表达的内容 | 当前写法 |
|---|---|
| 布尔值 | bool |
| 有符号整数 | i8、i16、i32、i64 |
| 无符号整数 | u8、u16、u32、u64 |
| 浮点数 | f32、f64 |
| 文本和无返回值 | string、void |
| 固定记录 | 顶层 TypeScript interface,字段使用精确标量类型 |
| 一维列表 | T[],支持长度、索引、赋值、push 和 for...of |
关键限制:
- 不使用
number、boolean、any、unknown或null; - 数值转换要显式,例如
u32(value); - 不使用
async、await、Promise、异常、class、import 或动态模块; - Object 调用按源码顺序完成,即使底层操作需要等待,源码也不添加异步标记;
- 循环必须有清楚的退出条件;QG 不会自动给无限循环增加迭代上限。
以编辑器诊断为准。不要用类型断言、忽略注释或生成代码绕过错误。
时间、日志和持久状态
QG 提供少量内建能力:
QG.clock.monotonicMilliseconds():读取单调时间;QG.clock.delay(milliseconds):执行可取消等待;QG.log.debug/info/warn/error(...):写入运行日志;QG.math、QG.bits、QG.array:精确数值、位运算和数组辅助;QG.saved.get/set:保存需要跨运行实例保留的标量或固定记录。
持久状态属于当前运行目标,不会写回 App 工程,也不会随着 Git 自动迁移。一次成功的 QG.saved.set 不会因为后续故障自动回滚;修改状态结构时,应规划显式迁移或使用新的名称。
示例:
export function IncrementTotal(): u64 {
let total: u64 = QG.saved.get("totalCycles", u64(0));
total = total + u64(1);
QG.saved.set("totalCycles", total);
return total;
}
Page 需要持久值时,应调用 QG Object 的公开方法,不直接拥有另一份存储逻辑。
调试 QG
- 保存 QG 和相关 Object 修改。
- 在 Source 或 Flow 的目标语句上设置断点。
- 确认 App 已 Stopped,选择 Build Debug。
- 点击 Debug。缺少适用 Build 时,编辑器会询问是否 Build and continue;只有确认后才继续。
- 从 Page、另一个 QG 或允许的在线入口触发目标方法。
- 命中断点后检查当前语句、参数、状态、Console 和设备反馈,再点击 Continue。
- 使用 Stop 结束调试,并确认清理后的设备状态。
当前提供断点和 Continue,不提供源码单步或条件断点。Debug 不会模拟设备、跳过真实输出或自动保证流程安全。
保存、Build 与运行边界
- 保存只更新编辑态;Flow 和实时诊断也只反映源码。
- Build 使用磁盘上已保存的文件,并把结果部署到当前运行目标。
- Preview 不会 Build 或 Deploy。它只使用专用 Previewing 状态,其中的 Object 调用可能产生真实副作用。
- Start 和 Debug 运行已部署版本;当编辑器提示 Build 时,由用户明确确认后才会先 Build 再继续。
- 运行中不会热替换 QG 或 Object。修改后使用 Stop → 保存 → Build → Start/Debug。
常见问题
Flow 为空或方法缺失
先修复 Source 和 Object 的上游错误。确认引用已经绑定到正确实例,再重新打开 Flow;不要手写一份接口或使用旧方法名填空。
Page 找不到 QG 方法
确认 QG 方法使用 export function、文件已保存、对应 Object 已绑定,并重新执行 Build。Page 只会获得当前已解析 Object model 中的公开方法。
断点不命中
确认使用了当前源码对应的 Build Debug,断点位于实际执行的方法内,并且 Debug 的目标与当前编辑器绑定目标一致。
修改后设备仍是旧行为
保存不会替换运行实例。先 Stop,再 Build 并重新 Start/Debug;同时核对顶栏运行目标。
故障后 App 回到 Stopped
这是统一清理行为。记录故障阶段、消息、触发动作和 Console,再修复根因。不要通过反复 Start 掩盖未查明的故障。
工程与安全检查
在连接真实设备前,逐项确认:
- Object 身份、地址、单位、极性和量程;
- 启动允许条件和停止后的安全状态;
- 每个等待的超时、取消和恢复路径;
Init、Dispose和故障清理是否符合设备要求;- 重试是否可能重复产生不可逆副作用;
- 急停、安全门和硬限位是否由独立、合适的安全系统保证。
QG 负责流程编排,不替代设备驱动、后端授权或认证安全控制。