Saltar al contenido principal

DOCUMENTACIÓN CON IA

¿Qué desea saber?

Recipe Script

Un recipe script es un fragmento corto de JavaScript que se ejecuta después de las herramientas 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 metadata 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.

Paso Veredicto: aprobado/rechazado lo deciden las reglas o el recipe script, con un diagrama de lo que se ejecuta en cada Inspección

En la parte superior del paso Veredicto 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 el aprobado o rechazado, pero su motivo, metadata, etiquetas y bytes para el PLC aún se aplican. Esa es una forma segura de empezar: añada un script para el motivo y los bytes, y mantenga las reglas al mando.

Editor de recipe script

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 las herramientas 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 recopilado hasta el momento. Es de solo lectura:

CampoQué es
toolsEl resultado de cada herramienta, en el orden en que se ejecutaron
tools_by_nameLos mismos resultados, pero por nombre de herramienta
rulesEl veredicto de las reglas: judgment, pass, not_inspected
varsSus variables por nombre. Una variable sin valor es null
vars_infoPara cada variable: received_at, age_ms y source
recipeid, uuid y name
triggerid, source (por ejemplo plc, gpio, http, manual) y metadata

Cada resultado de herramienta tiene name, type, judgment, pass, score, plc_slot, execute_ms, error, skipped_by, y un objeto detail cuya forma depende de la herramienta. 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).

Lo que devuelve​

Cada campo es opcional. Un campo que omita mantiene el comportamiento normal de la cámara, por lo que un script puede establecer solo el motivo y dejar el veredicto a las reglas. No devuelva nada para no cambiar nada.

CampoSignificadoLí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
reasonTexto mostrado en la Biblioteca y enviado en los mensajes de resultados (MQTT, HTTP API, camera script)64 caracteres
plc_user_resultsBytes para los User Results del PLC, generalmente construidos con pack()El tamaño configurado de User Results
metadataPares clave-valor guardados con la captura y mostrados en los 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/false32 claves, valores de texto de hasta 256 caracteres
tagsEtiquetas mostradas como chips en la Biblioteca, donde puede filtrar por ellas16 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.

Pieza de muestra
El aprobado/rechazado lo decide
Fieldbus

Una herramienta de Clasificación AI con 10 regiones, una por pin. Haz clic en un pin para invertirlo.

Inspección hasta ahora
Las reglas dicen: Fallar
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"
      }
    }
  }
}
Script de receta

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 vez como un layout: una lista ordenada de campos { name, type }.

TipoBytes
u8, i8, bool1
u16le, u16be, i16le, i16be2
u32le, u32be, i32le, i32be, f32le, f32be4
u64le, u64be, i64le, i64be, f64le, f64be8
bits con countUn bit por valor, el primer valor en el bit más bajo
ascii o utf8 con lengthTexto, rellenado o (con truncate: true) recortado a la longitud
bytes con lengthBytes sin procesar
pad con lengthBytes 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 }) };
}
Haga coincidir el orden de bytes del bus de campo

Cada tipo de varios bytes 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 en cero
  • pack lanza un RangeError cuando un valor no cabe en su campo. Pruebe con una pieza rechazada antes de guardar
  • unpack(layout, bytes) vuelve a leer los bytes, y crc(bytes, "crc16-modbus" | "crc32") calcula una suma de verificació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 en cero
  • no se usa nada de lo que devolvió (motivo, metadata, etiquetas)
  • el error se guarda con la captura, para que pueda verlo en la Biblioteca
Mantenga el estado en el camera script

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​

  • No tiene red, ni temporizadores, ni esperas: no hay fetch, setTimeout, import ni eval, y inspect no puede ser async
  • No puede ver la Imagen en sí, solo los resultados de las herramientas
  • Lee el mundo exterior solo a través de input y las variables

Plantillas​

La galería de Plantillas tiene 14 scripts funcionales, agrupados por tarea. Elija uno, complete la herramienta o variable que utiliza, y Insert template.

Galería de plantillas de recipe script

GrupoPlantillas
Decidir aprobado o rechazadoAprobar cuando suficientes regiones aprueban · El número de serie coincide con el texto OCR · El código es igual a una variable · Conteo dentro de una tolerancia respecto a una variable
Elegir cuándo inspeccionarOmitir otros tipos de pieza · Omitir cuando una variable falta o está desactualizada
Enviar datos al PLCEnviar el conteo como un número de 16 bits · Empaquetar banderas de aprobado/rechazado de regiones · Enviar un código de resultado por cada herramienta
Explicar el resultadoNombrar la herramienta que falló · Poner el conteo en el motivo
Etiquetar capturasAñadir metadata y una etiqueta de revisión · Etiquetar casos límite para revisión · Guardar una variable con cada captura

Prueba e Historial​

  • Test ejecuta el borrador en 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 qué habría decidido antes de ponerlo en producción
  • History conserva sus últimas 20 versiones guardadas
Comience en modo Reglas

Escriba el script con el paso Veredicto aún en las reglas, y use Test en capturas almacenadas para comparar su veredicto con lo registrado. Cambie a el recipe script solo cuando no coincidan donde usted desee.

A dónde ir después​