AI 驱动文档
您想了解什么?
相机脚本
相机脚本是整个相机使用的一个脚本。它对每次完成的检测和传入的消息做出响应,可以:
- 发布到任何 MQTT 主题,使用您自己的格式
- 设置变量,供程序脚本读取
- 触发告警,显示在诊断日志中
- 运行定时器和保持状态,例如计数器和最后看到的值
它绝不会更改判定:决定通过或失败是程序脚本的职责。它在程序切换期间持续运行。
打开 Integration > Camera Script。在您开启脚本之前不会运行任何内容,因此您可以先编写和测试它。

运行方式
脚本导出多个钩子。每个钩子都是可选的:一个脚本可以只导出 onResult,或只导出 subscriptions 和 onMessage。
| 钩子 | 运行时机 |
|---|---|
onStart() | 脚本加载时:保存后、开启时以及相机启动时。在此启动定时器并初始化状态 |
onResult(result) | 每次生产检测之后。导出 options = { setup_results: true } 也可以获取设置模式的结果 |
onMessage(msg) | 当 subscriptions 中的主题收到消息,或 PLC 的用户数据发生变化时 |
onTimer(name) | 当定时器触发时 |
onStop() | 新版本接管之前、关闭脚本时以及关机时(断电时不会触发) |
export const subscriptions = ["plant/line3/cmd"]; // MQTT topics this script listens on
export function onStart() {
state.results = 0;
timers.set("heartbeat", 30 * 1000, { repeat: true });
}
export function onResult(result) {
state.results = Number(state.results ?? 0) + 1;
}
export async function onTimer(name) {
if (name !== "heartbeat" || mqtt.status() !== "connected") return;
await mqtt.publish("plant/line3/alive", { alive: true, results: state.results }, { qos: 0 });
}
**一次一个。**钩子一次运行一个,因此状态不会在钩子运行期间改变。新事件在队列中等待,最多可容纳 64 个结果和 256 条消息;当队列已满时,最旧的事件会被丢弃并计数。
**等待。**当某个钩子在 await mqtt.publish 或 vars.set 时,下一个事件的钩子可以运行。请在 await 之后再次读取 state,而不是在它之前读取。
**时间。**钩子在第一次 await 之前有 1 秒时间,之后每段有 50 毫秒。运行超时的钩子会被停止。
失败。当钩子抛出异常或被停止时,错误会出现在脚本的日志中并作为告警出现,它启动的调用会被取消,下一个事件照常运行。
可用内容
| 全局对象 | 作用 |
|---|---|
mqtt.publish(topic, payload, opts?) | 发布文本、字节或对象(以 JSON 发送)。选项:qos(0、1 或 2)、retain,以及 MQTT v5 属性 content_type、response_topic、correlation_data、user_properties、message_expiry_s |
mqtt.status() | "disabled"、"connecting"、"connected" 或 "disconnected" |
subscriptions | 要监听的主题列表,使用字符串字面量。允许使用 + 和 # 通配符 |
vars.get(name) / vars.set(name, value) | 读取任何变量;设置来源为相机脚本的变量 |
timers.set(name, ms, { repeat }) / timers.clear(name) | 命名定时器,至少 100 毫秒 |
alert.raise(title, detail?) | 触发告警。相同标题每分钟最多触发一次 |
state | 在事件之间保留的临时内存,直到脚本重新加载 |
csv(rows)、xml.build()、xml.parse() | 构建 CSV 文本,构建或解析 XML |
pack、unpack、crc、log | 与程序脚本相同的辅助函数 |
onResult 中的 result 与结果消息的结构相同:包括程序、触发、最终 judgment 和 reason、每个工具的结果、vars、metadata、tags、image.url 等。详见 MQTT。
相机脚本不能做什么
- 更改判定结果或写入 PLC 用户结果。只有程序脚本可以执行此操作
- 访问相机文件,或通过 MQTT 之外的方式访问网络
- 在重新加载或重启后保留状态:
state和定时器会重新开始 - 触发检测或切换程序。这些仍由 PLC 和 HTTP API 完成
其限制:包括 state 在内共 16 MiB 内存,最多 16 个进行中的调用、32 个定时器、每条接收的 MQTT 消息 256 KiB、每秒 50 行日志,以及每分钟 10 个告警标题。
如果脚本内存耗尽,它将被重置:state 和定时器会被清除,并且 onStart 会重新运行。请保持 state 尽可能小,例如使用计数而不是存储每个结果的列表。
模板
| 分组 | 模板 |
|---|---|
| 发布结果 | 将每个结果发布到 MQTT 主题 · 定时发布心跳 |
| 从产线接收数据 | 通过 MQTT 响应 JSON-RPC 请求 · 将供应商 JSON 消息中的字段复制到变量 |
| 监控生产 | 按班次统计通过和失败数并发布 CSV · 连续拒绝后触发告警 |

// Raise an alert after consecutive rejects
export function onResult(result) {
state.streak = result.judgment === "fail" ? Number(state.streak ?? 0) + 1 : 0;
if (state.streak === 3) {
alert.raise("Reject streak", {
streak: state.streak,
recipe: result.recipe.name,
reason: result.reason,
});
}
}
试运行
测试会以试运行方式运行您的草稿:它会通过 onStart、onResult 和 onStop 重放最近的结果,并记录每一次发布、变量写入、定时器、告警和日志行,但不会实际发送任何内容。最近的结果保存在内存中,因此重启后该列表为空。
按照模板的做法,使用 mqtt.status() === "connected" 保护发布操作,并对其使用 await 或添加 .catch()。发布失败且没有任何等待处理时,会被记录为错误。