Chuyển đến nội dung chính

TÀI LIỆU ĐƯỢC HỖ TRỢ BỞI AI

Bạn muốn biết điều gì?

Recipe Script

Recipe script là một đoạn mã JavaScript ngắn chạy sau các tool trên mỗi inspection của một recipe. Nó có thể:

  • quyết định pass hoặc fail bằng logic riêng của bạn, và nêu lý do
  • ghi các byte của riêng bạn cho User Results của PLC
  • lưu metadata và tags cùng với ảnh chụp, để bạn có thể tìm thấy chúng trong Library

Mỗi recipe có nhiều nhất một script, và nó được export cùng với recipe.

Mở trình chỉnh sửa​

Tại bước Judgment của recipe, cuộn đến Recipe script và nhấp Open script editor.

Judgment step: pass/fail is decided by the rules or the recipe script, with a diagram of what runs on every inspection

Ở đầu bước Judgment, bạn chọn thứ quyết định kết quả: the rules hoặc the recipe script. Các rules luôn chạy, và script nhìn thấy kết quả của chúng. Nếu bạn để cài đặt ở the rules, script không thể thay đổi pass hay fail, nhưng reason, metadata, tags và các byte PLC của nó vẫn được áp dụng. Đó là cách bắt đầu an toàn: thêm một script cho reason và các byte, và để các rules nắm quyền quyết định.

Recipe script editor

Cách nó chạy​

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

Script export một hàm duy nhất, inspect(input). Camera gọi nó trên mỗi inspection của recipe, sau các tool và các rules. Dây chuyền chờ nó, vì vậy nó phải đồng bộ và nhanh: nó có 25 ms mặc định, lên đến 200 ms trong Settings của script, và thời gian của nó cộng vào cycle time.

input chứa mọi thứ có cho đến lúc này. Nó chỉ đọc:

TrườngÝ nghĩa
toolsKết quả của mỗi tool, theo thứ tự các tool đã chạy
tools_by_nameCùng các kết quả đó theo tên tool
rulesKết quả của các rules: judgment, pass, not_inspected
varsVariables của bạn theo tên. Một variable không có giá trị là null
vars_infoVới mỗi variable: received_at, age_ms và source
recipeid, uuid và name
triggerid, source (ví dụ plc, gpio, http, manual) và metadata

Mỗi kết quả tool có name, type, judgment, pass, score, plc_slot, execute_ms, error, skipped_by, và một đối tượng detail có cấu trúc phụ thuộc vào tool. Kiểm tra type trước khi bạn đọc detail, ví dụ ai_fast_classifier (với detail.regions), ai_ocr (với detail.fields), ai_counting (với detail.count) hoặc classical.barcode (với detail.data).

Nó trả về gì​

Mọi trường đều là tùy chọn. Trường bạn bỏ qua giữ nguyên hành vi bình thường của camera, vì vậy một script có thể chỉ đặt reason và để rules quyết định verdict. Trả về không có gì để không thay đổi gì.

TrườngÝ nghĩaGiới hạn
judgment"pass", "fail" hoặc "not_inspected" (true, false và null có cùng ý nghĩa). Chỉ được dùng khi bước Judgment được đặt là recipe script
reasonVăn bản hiển thị trong Library và gửi trong các result message (MQTT, HTTP API, camera script)64 ký tự
plc_user_resultsCác byte cho User Results của PLC, thường được tạo bằng pack()Kích thước User Results đã cấu hình
metadataCác cặp khóa-giá trị được lưu cùng với ảnh chụp và hiển thị trong chi tiết Library của nó. Khóa là chữ cái, chữ số và dấu gạch dưới, bắt đầu bằng một chữ cái; giá trị là văn bản, số hoặc true/false32 khóa, giá trị văn bản tối đa 256 ký tự
tagsNhãn hiển thị dưới dạng chip trong Library, nơi bạn có thể lọc theo chúng16 tag, mỗi tag 32 ký tự

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

Thử nó​

Khu thử nghiệm script của recipe

Thay đổi chi tiết, chỉnh sửa script, nhấn Run. Script nhận cùng đầu vào mà camera truyền cho inspect() và chạy theo cùng các quy tắc.

Chi tiết mẫu
OK/NG được quyết định bởi
Fieldbus

Một công cụ AI Classification với 10 vùng, mỗi vùng cho một chân. Nhấp vào một chân để đảo trạng thái.

Kết quả kiểm tra đến thời điểm này
Các quy tắc cho biết: Không đạt
Hiển thị đối tượng đầu vào
{
  "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 của recipe

Nhấn Run để xem kết quả mà lần inspection này sẽ cho ra.

Mô phỏng trong trình duyệt của bạn. Trên camera, hãy dùng Test trong trình soạn thảo script để chạy bản nháp trên các ảnh chụp thực tế trước khi lưu.

Ghi các byte cho PLC​

Trả về plc_user_results, được tạo bằng pack(layout, values). PLC đọc nó cùng với kết quả, trước cạnh Inspection Completed.

Mô tả các byte một lần dưới dạng layout: một danh sách có thứ tự các trường { name, type }.

TypeByte
u8, i8, bool1
u16le, u16be, i16le, i16be2
u32le, u32be, i32le, i32be, f32le, f32be4
u64le, u64be, i64le, i64be, f64le, f64be8
bits với countMột bit cho mỗi giá trị, giá trị đầu tiên ở bit thấp nhất
ascii hoặc utf8 với lengthVăn bản, được đệm hoặc (với truncate: true) cắt theo độ dài
bytes với lengthByte thô
pad với lengthCác byte zero, để bỏ qua một khoảng trống
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 }) };
}
Khớp byte order của fieldbus

Mỗi type nhiều byte đặt tên byte order riêng của nó, và camera không bao giờ hoán đổi byte thay cho bạn. Sử dụng các type le trên EtherNet/IP và các type be trên PROFINET. Phần kiểm tra script cảnh báo khi một type không khớp với fieldbus của camera.

  • Byte 0 nằm ở input assembly byte 288 trên EtherNet/IP, và ở byte 0 của module User Results trên PROFINET. Phần còn lại của vùng được đặt về zero
  • pack ném một RangeError khi một giá trị không vừa với trường của nó. Hãy kiểm tra với một bộ phận fail trước khi bạn lưu
  • unpack(layout, bytes) đọc lại các byte, và crc(bytes, "crc16-modbus" | "crc32") tính toán checksum

Khi có sự cố xảy ra​

Nếu inspect ném lỗi, hết thời gian, hết bộ nhớ (8 MiB), hoặc trả về thứ gì đó mà camera không thể chấp nhận (chẳng hạn như reason trên 64 ký tự hoặc judgment: "PASS"):

  • bộ phận là Not inspected
  • User Results của PLC được đặt về zero
  • không có gì nó trả về (reason, metadata, tags) được sử dụng
  • lỗi được lưu cùng với ảnh chụp, để bạn có thể xem trong Library
Giữ trạng thái trong camera script

Các giá trị được giữ ở cấp module chỉ tồn tại cho đến khi recipe tải lại, ví dụ sau khi lưu. Không đếm các bộ phận hoặc giữ lịch sử trong một recipe script. Sử dụng camera script, nơi giữ trạng thái giữa các sự kiện.

Những gì một recipe script không thể làm​

  • Không có mạng, không có timer và không chờ: không có fetch, setTimeout, import hoặc eval, và inspect không thể là async
  • Nó không thể nhìn thấy chính hình ảnh, chỉ thấy kết quả của các tool
  • Nó đọc thế giới bên ngoài chỉ thông qua input và variables

Templates​

Thư viện Templates có 14 script hoạt động được, nhóm theo công việc. Chọn một, điền vào tool hoặc variable mà nó sử dụng, và Insert template.

Recipe script Templates gallery

NhómTemplates
Quyết định pass hoặc failPass khi đủ số region pass · Serial number khớp với văn bản OCR · Barcode bằng một variable · Count nằm trong dung sai của một variable
Chọn khi nào inspectBỏ qua các loại bộ phận khác · Bỏ qua khi một variable bị thiếu hoặc lỗi thời
Gửi dữ liệu đến PLCGửi count dưới dạng số 16-bit · Đóng gói các cờ pass/fail của region · Gửi mã kết quả cho mỗi tool
Giải thích kết quảĐặt tên tool đã fail · Đưa count vào reason
Gán nhãn ảnh chụpThêm metadata và tag review · Gán tag các trường hợp sát nút để review · Lưu một variable với mỗi ảnh chụp

Test và History​

  • Test chạy bản nháp trên một Trigger trực tiếp, hoặc trên các ảnh chụp đã lưu: ảnh mới nhất, N ảnh cuối cùng (lên đến 500), một bộ lọc Library, hoặc các số ảnh chụp. Nó hiển thị nơi kết quả của bản nháp khác với kết quả mà mỗi ảnh chụp đã ghi lại, để bạn thấy nó sẽ quyết định điều gì trước khi nó được đưa vào hoạt động
  • History giữ 20 phiên bản đã lưu gần nhất của bạn
Bắt đầu ở chế độ Rules

Viết script khi bước Judgment vẫn ở the rules, và sử dụng Test trên các ảnh chụp đã lưu để so sánh kết quả của nó với những gì đã được ghi lại. Chỉ chuyển sang the recipe script khi chúng không đồng ý ở nơi bạn muốn.

Tiếp theo đi đâu​