DOCUMENTACIÓN CON IA
¿Qué desea saber?
Recipe Script
Un recipe script es una pieza corta de JavaScript que se ejecuta después de los Bloques en cada Inspección de una Receta. Puede:
- decidir aprobado o rechazado con su propia lógica, e indicar el motivo
- escribir sus propios bytes para los User Results del PLC
- guardar metadatos y etiquetas con la captura, para que pueda encontrarla en la Biblioteca
Cada Receta tiene como máximo un script, y se exporta junto con la Receta.
Abrir el editor
En el paso Veredicto de la Receta, desplácese hasta Recipe script y haga clic en Open script editor.

En la parte superior del paso Veredicto usted elige qué decide el Veredicto: las reglas o el recipe script. Las reglas siempre se ejecutan, y el script ve su Veredicto. Si deja la configuración en las reglas, el script no puede cambiar aprobado o rechazado, pero su motivo, metadatos, etiquetas y bytes para el PLC se siguen aplicando. Esa es una forma segura de empezar: agregue un script para el motivo y los bytes, y mantenga las reglas a cargo.

Cómo se ejecuta
Trigger → Capture and tools → Pass/fail rules → inspect(input) → Verdict, PLC User Results, Library, MQTT
El script exporta una función, inspect(input). La cámara la llama en cada Inspección de la Receta, después de los Bloques y las reglas. La línea la espera, por lo que debe ser síncrona y rápida: tiene 25 ms por defecto, hasta 200 ms en las Configuraciones del script, y su tiempo se suma al tiempo de ciclo.
input contiene todo lo que ha ocurrido hasta ahora. Es de solo lectura:
| Campo | Qué es |
|---|---|
tools | El resultado de cada Bloque, en el orden en que se ejecutaron |
tools_by_name | Los mismos resultados por nombre de Bloque |
rules | El Veredicto de las reglas: judgment, pass, not_inspected |
vars | Sus variables por nombre. Una variable sin valor es null |
vars_info | Para cada variable: received_at, age_ms y source |
recipe | id, uuid y name |
trigger | id, source (por ejemplo plc, gpio, http, manual) y metadata |
El resultado de cada Bloque tiene name, type, judgment, pass, score, plc_slot, execute_ms, error, skipped_by, y un objeto detail cuya forma depende del Bloque. Verifique type antes de leer detail, por ejemplo ai_fast_classifier (con detail.regions), ai_ocr (con detail.fields), ai_counting (con detail.count) o classical.barcode (con detail.data).
Qué devuelve
Cada campo es opcional. Un campo que omita mantiene el comportamiento normal de la cámara, por lo que un script puede establecer únicamente el motivo y dejar el Veredicto a las reglas. Devuelva nada para no cambiar nada.
| Campo | Significado | Límite |
|---|---|---|
judgment | "pass", "fail" o "not_inspected" (true, false y null significan lo mismo). Se usa solo cuando el paso Veredicto está configurado en el recipe script | |
reason | Texto que se muestra en la Biblioteca y se envía en los mensajes de resultado (MQTT, HTTP API, camera script) | 64 caracteres |
plc_user_results | Bytes para los User Results del PLC, generalmente construidos con pack() | El tamaño configurado de los User Results |
metadata | Pares clave-valor guardados con la captura y mostrados en sus detalles de la Biblioteca. Las claves son letras, dígitos y guiones bajos, comenzando con una letra; los valores son texto, números o true/false | 32 claves, valores de texto hasta 256 caracteres |
tags | Etiquetas mostradas como chips en la Biblioteca, por las que puede filtrar | 16 etiquetas, 32 caracteres cada una |
export function inspect({ tools_by_name, vars }) {
const ocr = tools_by_name["Serial"];
if (ocr?.type !== "ai_ocr" || !ocr.detail) {
return { judgment: false, reason: "no OCR result" };
}
const expected = vars["serial"];
if (typeof expected !== "string") {
return { judgment: null, reason: "serial not received" };
}
const read = ocr.detail.fields.map((f) => f.text_judged).join("");
const match = read === expected;
return { judgment: match, reason: match ? "serial matches" : "serial differs" };
}
Pruébelo
Área de pruebas del script de receta
Cambia la pieza, edita el script, presiona Ejecutar. El script recibe la misma entrada que la cámara pasa a inspect() y se ejecuta bajo las mismas reglas.
Una herramienta de Clasificación AI con 10 regiones, una por pin. Haz clic en un pin para invertirlo.
Mostrar el objeto de entrada
{
"recipe": {
"id": 3,
"uuid": "01a15a44-9a3c-72bb-ab4f-5481cce20093",
"name": "Sample recipe"
},
"trigger": {
"id": 4182,
"source": "plc",
"metadata": {}
},
"rules": {
"judgment": "fail",
"pass": false,
"not_inspected": false
},
"vars": {},
"vars_info": {},
"tools": [
{
"type": "ai_fast_classifier",
"id": "01a1-pins",
"name": "Pins",
"plc_slot": 1,
"judgment": "fail",
"pass": false,
"score": 0.9,
"execute_ms": 6,
"error": "none",
"skipped_by": "",
"detail": {
"regions": [
{
"label": "Pin 1",
"class_label": "seated",
"confidence": 0.97,
"verdict": "pass",
"threshold": 0.5,
"pass": true
},
{
"label": "Pin 2",
"class_label": "seated",
"confidence": 0.93,
"verdict": "pass",
"threshold": 0.5,
"pass": true
},
{
"label": "Pin 3",
"class_label": "seated",
"confidence": 0.95,
"verdict": "pass",
"threshold": 0.5,
"pass": true
},
{
"label": "Pin 4",
"class_label": "bent",
"confidence": 0.81,
"verdict": "fail",
"threshold": 0.5,
"pass": false
},
{
"label": "Pin 5",
"class_label": "seated",
"confidence": 0.91,
"verdict": "pass",
"threshold": 0.5,
"pass": true
},
{
"label": "Pin 6",
"class_label": "seated",
"confidence": 0.96,
"verdict": "pass",
"threshold": 0.5,
"pass": true
},
{
"label": "Pin 7",
"class_label": "seated",
"confidence": 0.94,
"verdict": "pass",
"threshold": 0.5,
"pass": true
},
{
"label": "Pin 8",
"class_label": "seated",
"confidence": 0.89,
"verdict": "pass",
"threshold": 0.5,
"pass": true
},
{
"label": "Pin 9",
"class_label": "seated",
"confidence": 0.98,
"verdict": "pass",
"threshold": 0.5,
"pass": true
},
{
"label": "Pin 10",
"class_label": "seated",
"confidence": 0.92,
"verdict": "pass",
"threshold": 0.5,
"pass": true
}
],
"overall": "fail"
}
}
],
"tools_by_name": {
"Pins": {
"type": "ai_fast_classifier",
"id": "01a1-pins",
"name": "Pins",
"plc_slot": 1,
"judgment": "fail",
"pass": false,
"score": 0.9,
"execute_ms": 6,
"error": "none",
"skipped_by": "",
"detail": {
"regions": [
{
"label": "Pin 1",
"class_label": "seated",
"confidence": 0.97,
"verdict": "pass",
"threshold": 0.5,
"pass": true
},
{
"label": "Pin 2",
"class_label": "seated",
"confidence": 0.93,
"verdict": "pass",
"threshold": 0.5,
"pass": true
},
{
"label": "Pin 3",
"class_label": "seated",
"confidence": 0.95,
"verdict": "pass",
"threshold": 0.5,
"pass": true
},
{
"label": "Pin 4",
"class_label": "bent",
"confidence": 0.81,
"verdict": "fail",
"threshold": 0.5,
"pass": false
},
{
"label": "Pin 5",
"class_label": "seated",
"confidence": 0.91,
"verdict": "pass",
"threshold": 0.5,
"pass": true
},
{
"label": "Pin 6",
"class_label": "seated",
"confidence": 0.96,
"verdict": "pass",
"threshold": 0.5,
"pass": true
},
{
"label": "Pin 7",
"class_label": "seated",
"confidence": 0.94,
"verdict": "pass",
"threshold": 0.5,
"pass": true
},
{
"label": "Pin 8",
"class_label": "seated",
"confidence": 0.89,
"verdict": "pass",
"threshold": 0.5,
"pass": true
},
{
"label": "Pin 9",
"class_label": "seated",
"confidence": 0.98,
"verdict": "pass",
"threshold": 0.5,
"pass": true
},
{
"label": "Pin 10",
"class_label": "seated",
"confidence": 0.92,
"verdict": "pass",
"threshold": 0.5,
"pass": true
}
],
"overall": "fail"
}
}
}
}Presiona Ejecutar para ver con qué terminaría esta inspección.
Una simulación en tu navegador. En la cámara, usa Probar en el editor de scripts para ejecutar el borrador sobre capturas reales antes de guardar.
Escribir bytes para el PLC
Devuelva plc_user_results, construido con pack(layout, values). El PLC lo lee con el resultado, antes del flanco Inspection Completed.
Describa los bytes una sola vez como un layout: una lista ordenada de campos { name, type }.
| Tipo | Bytes |
|---|---|
u8, i8, bool | 1 |
u16le, u16be, i16le, i16be | 2 |
u32le, u32be, i32le, i32be, f32le, f32be | 4 |
u64le, u64be, i64le, i64be, f64le, f64be | 8 |
bits con count | Un bit por valor, el primer valor en el bit más bajo |
ascii o utf8 con length | Texto, rellenado o (con truncate: true) cortado a la longitud |
bytes con length | Bytes sin procesar |
pad con length | Bytes en cero, para omitir un espacio |
const OUT = [
{ name: "regionOk", type: "bits", count: 80 },
{ name: "count", type: "u16le" },
];
export function inspect({ tools_by_name }) {
const classifier = tools_by_name["Classifier"];
if (classifier?.type !== "ai_fast_classifier" || !classifier.detail) return;
const regionOk = classifier.detail.regions.map((r) => r.pass).slice(0, 80);
return { plc_user_results: pack(OUT, { regionOk, count: regionOk.length }) };
}
Cada tipo multi-byte nombra su propio orden de bytes, y la cámara nunca intercambia bytes por usted. Use los tipos le en EtherNet/IP y los tipos be en PROFINET. La verificación del script advierte cuando un tipo no coincide con el bus de campo de la cámara.
- El byte 0 cae en el byte 288 del input assembly en EtherNet/IP, y en el byte 0 del módulo User Results en PROFINET. El resto de la región se pone a cero
packlanza unRangeErrorcuando un valor no cabe en su campo. Pruebe con una pieza que falle antes de guardarunpack(layout, bytes)lee los bytes de vuelta, ycrc(bytes, "crc16-modbus" | "crc32")calcula una suma de comprobación
Cuando algo sale mal
Si inspect lanza una excepción, se queda sin tiempo, se queda sin memoria (8 MiB), o devuelve algo que la cámara no puede aceptar (como un motivo de más de 64 caracteres o judgment: "PASS"):
- la pieza queda como No inspeccionada
- los User Results del PLC se ponen a cero
- nada de lo que devolvió (motivo, metadatos, etiquetas) se utiliza
- el error se guarda con la captura, para que pueda verlo en la Biblioteca
Los valores guardados a nivel de módulo duran solo hasta que la Receta se recarga, por ejemplo después de guardar. No cuente piezas ni mantenga historial en un recipe script. Use el camera script, que mantiene el estado entre eventos.
Lo que un recipe script no puede hacer
- Sin red, sin temporizadores y sin espera: no hay
fetch,setTimeout,importnieval, yinspectno puede serasync - No puede ver la imagen en sí, solo los resultados de los Bloques
- Lee el mundo exterior solo a través de
inputy las variables
Plantillas
La galería de Templates tiene 14 scripts funcionales, agrupados por tarea. Elija uno, complete el Bloque o la variable que usa, y Insert template.

| Grupo | Plantillas |
|---|---|
| Decidir aprobado o rechazado | Aprobar cuando suficientes regiones pasen · El número de serie coincide con el texto del OCR · El código es igual a una variable · Conteo dentro de una tolerancia de una variable |
| Elegir cuándo inspeccionar | Omitir otros tipos de pieza · Omitir cuando una variable falta o está desactualizada |
| Enviar datos al PLC | Enviar el conteo como un número de 16 bits · Empaquetar banderas aprobado/rechazado de regiones · Enviar un código de resultado por cada Bloque |
| Explicar el resultado | Nombrar el Bloque que falló · Poner el conteo en el motivo |
| Etiquetar capturas | Agregar metadatos y una etiqueta de revisión · Etiquetar casi-fallas para revisión · Guardar una variable con cada captura |
Pruebas e Historial
- Test ejecuta el borrador con un Disparo en vivo, o en capturas almacenadas: la más reciente, las últimas N (hasta 500), un filtro de la Biblioteca, o números de captura. Muestra dónde el Veredicto del borrador difiere del Veredicto que cada captura registró, para que vea lo que habría decidido antes de que entre en producción
- History conserva sus últimas 20 versiones guardadas
Escriba el script con el paso Veredicto aún en las reglas, y use Test en capturas almacenadas para comparar su Veredicto con lo que se registró. Cambie a el recipe script solo cuando no coincidan donde usted quiere que coincidan.
A dónde ir después
- Camera script, para cualquier cosa que necesite la red o memoria entre piezas
- Variables
- Paso 5: Veredicto
- PLC Handshakes, para cuando el PLC lee los User Results