Saltar al contenido principal

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.

Paso Veredicto: aprobado/rechazado se decide por 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 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.

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 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:

CampoQué es
toolsEl resultado de cada Bloque, en el orden en que se ejecutaron
tools_by_nameLos mismos resultados por nombre de Bloque
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

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.

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 que se muestra en la Biblioteca y se envía en los mensajes de resultado (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 los User Results
metadataPares 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/false32 claves, valores de texto hasta 256 caracteres
tagsEtiquetas mostradas como chips en la Biblioteca, por las que puede filtrar16 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 sola 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) cortado 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 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
  • pack lanza un RangeError cuando un valor no cabe en su campo. Pruebe con una pieza que falle antes de guardar
  • unpack(layout, bytes) lee los bytes de vuelta, y crc(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
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​

  • Sin red, sin temporizadores y sin espera: no hay fetch, setTimeout, import ni eval, y inspect no puede ser async
  • No puede ver la imagen en sí, solo los resultados de los Bloques
  • Lee el mundo exterior solo a través de input y 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.

Galería de Templates del recipe script

GrupoPlantillas
Decidir aprobado o rechazadoAprobar 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 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 aprobado/rechazado de regiones · Enviar un código de resultado por cada Bloque
Explicar el resultadoNombrar el Bloque que falló · Poner el conteo en el motivo
Etiquetar capturasAgregar 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
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 que se registró. Cambie a el recipe script solo cuando no coincidan donde usted quiere que coincidan.

A dónde ir después​