Zum Hauptinhalt springen

KI-GESTÜTZTE DOKUMENTATION

Was möchten Sie wissen?

Recipe-Skript

Ein Recipe-Skript ist ein kurzes JavaScript-Stück, das bei jeder Prüfung eines Rezepts nach den Tools ausgeführt wird. Es kann:

  • über Pass oder Fail entscheiden mit Ihrer eigenen Logik und eine Begründung liefern
  • eigene Bytes schreiben für die User Results der SPS
  • Metadaten und Tags speichern mit der Aufnahme, sodass Sie sie in der Library finden

Jedes Rezept hat höchstens ein Skript, und es wird mit dem Rezept exportiert.

Editor öffnen​

Scrollen Sie im Beurteilung-Schritt des Rezepts zu Recipe-Skript und klicken Sie auf Skripteditor öffnen.

Beurteilungsschritt: Pass/Fail wird durch die Regeln oder das Recipe-Skript entschieden, mit einem Diagramm dessen, was bei jeder Prüfung ausgeführt wird

Oben im Beurteilungsschritt wählen Sie aus, was die Beurteilung entscheidet: die Regeln oder das Recipe-Skript. Die Regeln laufen immer, und das Skript sieht deren Beurteilung. Wenn Sie die Einstellung auf die Regeln belassen, kann das Skript Pass oder Fail nicht ändern, aber seine Begründung, Metadaten, Tags und SPS-Bytes werden trotzdem angewendet. Das ist ein sicherer Einstieg: Fügen Sie ein Skript für die Begründung und die Bytes hinzu und lassen Sie die Regeln die Entscheidung treffen.

Recipe-Skripteditor

Wie es ausgeführt wird​

Trigger → Capture and tools → Pass/fail rules → inspect(input) → Verdict, PLC User Results, Library, MQTT

Das Skript exportiert eine Funktion, inspect(input). Die Kamera ruft sie bei jeder Prüfung des Rezepts auf, nach den Tools und den Regeln. Die Linie wartet darauf, daher muss sie synchron und schnell sein: Sie hat standardmäßig 25 ms, bis zu 200 ms in den Einstellungen des Skripts, und ihre Zeit kommt zur Zykluszeit hinzu.

input enthält alles bisher. Es ist schreibgeschützt:

FeldWas es ist
toolsDas Ergebnis jedes Tools, in der Reihenfolge der Ausführung
tools_by_nameDieselben Ergebnisse nach Toolnamen
rulesDie Beurteilung der Regeln: judgment, pass, not_inspected
varsIhre Variablen nach Namen. Eine Variable ohne Wert ist null
vars_infoFür jede Variable: received_at, age_ms und source
recipeid, uuid und name
triggerid, source (zum Beispiel plc, gpio, http, manual) und metadata

Jedes Toolergebnis hat name, type, judgment, pass, score, plc_slot, execute_ms, error, skipped_by und ein detail-Objekt, dessen Form vom Tool abhängt. Prüfen Sie type, bevor Sie detail lesen, zum Beispiel ai_fast_classifier (mit detail.regions), ai_ocr (mit detail.fields), ai_counting (mit detail.count) oder classical.barcode (mit detail.data).

Was es zurückgibt​

Jedes Feld ist optional. Ein weggelassenes Feld behält das normale Verhalten der Kamera bei, sodass ein Skript nur die Begründung setzen und die Beurteilung den Regeln überlassen kann. Geben Sie nichts zurück, um nichts zu ändern.

FeldBedeutungGrenze
judgment"pass", "fail" oder "not_inspected" (true, false und null haben dieselbe Bedeutung). Wird nur verwendet, wenn der Beurteilungsschritt auf das Recipe-Skript eingestellt ist
reasonText, der in der Library angezeigt und in Ergebnismeldungen (MQTT, HTTP API, Kameraskript) gesendet wird64 Zeichen
plc_user_resultsBytes für die User Results der SPS, üblicherweise mit pack() erstelltDie konfigurierte Größe der User Results
metadataSchlüssel-Wert-Paare, die mit der Aufnahme gespeichert und in ihren Library-Details angezeigt werden. Schlüssel sind Buchstaben, Ziffern und Unterstriche, beginnend mit einem Buchstaben; Werte sind Text, Zahlen oder true/false32 Schlüssel, Textwerte bis zu 256 Zeichen
tagsLabels, die als Chips in der Library angezeigt werden, nach denen Sie filtern können16 Tags, je 32 Zeichen

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" };
}

Ausprobieren​

Rezept-Skript-Playground

Teil ändern, Skript bearbeiten, Ausführen drücken. Das Skript erhält dieselbe Eingabe, die die Kamera an inspect() übergibt, und läuft unter denselben Regeln.

Beispielteil
OK/NG wird entschieden durch
Feldbus

Ein AI-Klassifikations-Tool mit 10 Regionen, eine pro Pin. Klicken Sie auf einen Pin, um ihn umzuschalten.

Bisherige Prüfung
Regeln besagen: n.i.O.
Eingabeobjekt anzeigen
{
  "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"
      }
    }
  }
}
Rezept-Skript

Klicken Sie auf Ausführen, um zu sehen, wie diese Prüfung ausfallen würde.

Eine Simulation in Ihrem Browser. An der Kamera verwenden Sie Test im Skript-Editor, um den Entwurf vor dem Speichern an echten Aufnahmen auszuführen.

Bytes für die SPS schreiben​

Geben Sie plc_user_results zurück, erstellt mit pack(layout, values). Die SPS liest es mit dem Ergebnis, vor der Inspection Completed-Flanke.

Beschreiben Sie die Bytes einmal als Layout: eine geordnete Liste von { name, type }-Feldern.

TypBytes
u8, i8, bool1
u16le, u16be, i16le, i16be2
u32le, u32be, i32le, i32be, f32le, f32be4
u64le, u64be, i64le, i64be, f64le, f64be8
bits mit countEin Bit pro Wert, der erste Wert im niedrigsten Bit
ascii oder utf8 mit lengthText, aufgefüllt oder (mit truncate: true) auf Länge gekürzt
bytes mit lengthRohbytes
pad mit lengthNullbytes, um eine Lücke zu überspringen
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 }) };
}
Byte-Reihenfolge des Feldbusses beachten

Jeder Mehrbyte-Typ benennt seine eigene Byte-Reihenfolge, und die Kamera vertauscht niemals Bytes für Sie. Verwenden Sie die le-Typen bei EtherNet/IP und die be-Typen bei PROFINET. Die Skriptprüfung warnt, wenn ein Typ nicht zum Feldbus der Kamera passt.

  • Byte 0 landet bei Input-Assembly-Byte 288 auf EtherNet/IP und bei Byte 0 des User-Results-Moduls auf PROFINET. Der Rest des Bereichs wird auf null gesetzt
  • pack wirft einen RangeError, wenn ein Wert nicht in sein Feld passt. Testen Sie mit einem fehlerhaften Teil, bevor Sie speichern
  • unpack(layout, bytes) liest Bytes zurück, und crc(bytes, "crc16-modbus" | "crc32") berechnet eine Prüfsumme

Wenn etwas schiefgeht​

Wenn inspect eine Exception wirft, die Zeit überschreitet, den Speicher überschreitet (8 MiB) oder etwas zurückgibt, das die Kamera nicht akzeptieren kann (etwa eine Begründung über 64 Zeichen oder judgment: "PASS"):

  • das Teil ist Nicht geprüft
  • die SPS User Results werden auf null gesetzt
  • nichts, was es zurückgegeben hat (Begründung, Metadaten, Tags), wird verwendet
  • der Fehler wird mit der Aufnahme gespeichert, sodass Sie ihn in der Library sehen können
Status im Kameraskript halten

Werte, die auf Modulebene gehalten werden, bestehen nur bis zum erneuten Laden des Rezepts, zum Beispiel nach einem Speichern. Zählen Sie keine Teile und führen Sie keinen Verlauf in einem Recipe-Skript. Verwenden Sie das Kameraskript, das den Status zwischen Ereignissen beibehält.

Was ein Recipe-Skript nicht kann​

  • Kein Netzwerk, keine Timer und kein Warten: Es gibt kein fetch, setTimeout, import oder eval, und inspect kann nicht async sein
  • Es kann das Bild selbst nicht sehen, nur die Ergebnisse der Tools
  • Es liest die Außenwelt nur über input und Variablen

Vorlagen​

Die Vorlagen-Galerie enthält 14 funktionierende Skripte, gruppiert nach Aufgabe. Wählen Sie eines aus, füllen Sie das Tool oder die Variable aus, die es verwendet, und Vorlage einfügen.

Galerie der Recipe-Skript-Vorlagen

GruppeVorlagen
Pass oder Fail entscheidenPass wenn genügend Regionen bestehen · Seriennummer stimmt mit dem OCR-Text überein · Barcode entspricht einer Variablen · Anzahl innerhalb einer Toleranz einer Variablen
Wählen, wann geprüft wirdAndere Teiletypen überspringen · Überspringen, wenn eine Variable fehlt oder veraltet ist
Daten an die SPS sendenAnzahl als 16-Bit-Zahl senden · Region-Pass/Fail-Flags packen · Einen Ergebniscode für jedes Tool senden
Ergebnis erklärenDas Tool benennen, das fehlgeschlagen ist · Die Anzahl in die Begründung aufnehmen
Aufnahmen beschriftenMetadaten und ein Review-Tag hinzufügen · Grenzfälle zur Überprüfung taggen · Eine Variable mit jeder Aufnahme speichern

Test und Verlauf​

  • Test führt den Entwurf auf einem Live-Trigger aus oder auf gespeicherten Aufnahmen: die neueste, die letzten N (bis zu 500), ein Library-Filter oder Aufnahmenummern. Es zeigt, wo die Beurteilung des Entwurfs von der Beurteilung abweicht, die jede Aufnahme aufgezeichnet hat, sodass Sie sehen, was er entschieden hätte, bevor er live geht
  • Verlauf behält Ihre letzten 20 gespeicherten Versionen
Im Regel-Modus starten

Schreiben Sie das Skript, während der Beurteilungsschritt noch auf die Regeln steht, und verwenden Sie Test auf gespeicherten Aufnahmen, um seine Beurteilung mit dem Aufgezeichneten zu vergleichen. Wechseln Sie erst dann auf das Recipe-Skript, wenn sie dort abweichen, wo Sie es möchten.

Wie es weitergeht​