# Script Structure

To understand how to structure your custom script, observe the structure of the default script. The default script has four main parts:

- constructor

- onResult

- onIncomingMessage

- onHeartbeat

## Constructor

The constructor method in the script sets up the topic In MQTT, a topic is a channel name where devices can publish messages, or can subscribe to for receiving messages. subscriptions for various events, such as receiving commands from external systems, receiving results from the vision system, or initiating a heartbeat message loop.

- The following lines in the default script set up the result subscriptions:

  Copy

      device.streams.results.setHandler(async (result) => {
                  await this.onResult(result);
              });

  These lines cause the onResult method to execute whenever the vision system produces a new result.

- The following lines in the default script set up the subscriptions to incoming messages:

  Copy

      connection.subscriptions.setHandler(async (payload, topic, props) => {
                  await this.onIncomingMessage(payload, topic, props);
              }, "json");

  These lines cause the onIncomingMessage method to execute whenever the vision system receives a message.

  The connection.subscriptions.setHandler has an additional parameter to interpret the incoming object type. The possible object types are the following:

  - json (default)

  - string

  - arraybuffer (to handle binary data)

- Start a heartbeat message loop using the setTimeout or setInterval JavaScript functions.

## onResult(result)

The onResult method in the script constructs the result payload based on the result metrics from the vision system.

To customize the result format, use the following onResult code snippet A snippet is one or more pre-configured cell that allows you to automate frequently performed spreadsheet tasks. You can create your own snippets, or use snippets provided by Cognex. as a template, where result is the Cognex formatted result payload:

Note: To access individual metrics, you need to know ahead of time what metric A metric is a data value with additional context such as type or properties that explain what the value means and how it is used or shown, helping systems understand and work with the data correctly. types they are going to be. The possible metric types are measurement, text, identification, counter, and classification.

- onResult method:
- Sample payload:

Copy

        async onResult(result) {
                        // Build the new object
                        let converted = {
                        id: result.sequenceNumber,
                        timestamp: result.cycleStart,
                        data: result.resultStatus === "Ok",

                        // Map metrics to new names
                        myTextMetric: result.metrics["Text Metric"]?.text || "",
                        myMeasurementMetric: result.metrics["Measurement Metric"]?.measurement || 0,
                        myClassificationMetric: result.metrics["Classification Metric"]?.class || "",
                        myIdentifierMetric: result.metrics["Identifier Metric"]?.identifier || "",
                        myCounterMetric: result.metrics["Counter Metric"]?.count || 0,
                        };

                        // Publish the result to our results topic
                    connection.publish(converted, this.resultsTopic, {});

Copy

    {
                        "cycleDurationMs": 18.475,
                        "cycleStart": "2025-09-19T04:12:26.747820046+00:00",
                        "id": "0199602c-6710-75e3-be1e-f07d8af5af86",
                        "metrics": {
                        "Brightness_1.Brightness": { "measurement": 72.55250549316406 },
                        "Brightness_1.ErrorString": { "text": "" },
                        "Classify_Brightness.PredictedClass": { "class": "Light" },
                        "Classify_Brightness.PredictedClassScore": {
                        "measurement": 55.482017993927
                        },
                        "Job.TotalCount": { "count": 701 },
                        "ReadID_1.Result00.String": { "identifier": "MEMCRU079611" }
                        },
                        "processingDurationMs": 18.476,
                        "resultStatus": "Ng",
                        "sequenceNumber": 5086
                    }

## onIncomingMessage(payload, topic, props)

The onIncomingMessage method in the script processes incoming messages, and sends commands to the vision system.

onIncomingMessage has the following parameters:

- payload - the payload in the format sent by the external system

- topic - the topic where the message arrived

- props - an object containing MQTT Message Queue Telemetry Transport (MQTT) is a lightweight messaging protocol used to send and receive data between devices. publish message properties from the external system

To customize the response to incoming messages, use the following code snippet as a template:

Copy

    async onIncomingMessage(payload, topic, props) {
            // Expected input format:
            // __job:[job file]
            // [type (S,I,F,R)]:[cell]:[value] // Type is required to use the correct cell format. String, Integer, Float, Region
            // I:Brightness_1.Min:100
            // etc.

            const lines = payload.split("\n").map((line) => line.trim());
            let jobFile = null;
            const propertiesToSet = [];
            for (let i = 0; i < lines.length; i++) {
                // Ignore empty lines
                if (lines[i].trim().length === 0) {
                    continue;
                }

                if (lines[i].toLowerCase().startsWith("__job:")) {
                    jobFile = lines[i].substring(6).trim();
                    continue;
                }

                const parts = lines[i].split(":");
                if (parts.length !== 3) {
                    console.warn(`Ignoring malformed line: ${lines[i]}`);
                    continue;
                }

                const [type, key, rest] = parts;
                propertiesToSet.push({ key: key.trim(), value: rest.trim(), type: type.trim().toUpperCase() });
            }

## onHeartbeat

The scheduleHeartbeat method sends periodic heartbeat messages from the vision system to a designated MQTT topic, allowing external systems to monitor vision system connectivity and status.

The method uses either the setTimeout JavaScript command to schedule the next heartbeat after sending each message, which allows for flexible or randomized intervals, or the setInterval command to schedule regular messages.

A heartbeat message usually includes a timestamp and message type. The script publishes the heartbeat message to a topic such as cognex/${device.id}/heartbeat.

To customize heartbeat messages, use the following code snippet as a template, and call the scheduleHeartbeat method from the constructor:

Copy

    scheduleHeartbeat() {
        const period = 40000 + Math.random() * 10000; // 40 to 50 seconds
        setTimeout(() => {
          const heartbeatMessage = {
            Header: {
              MessageTimeStamp: new Date().toISOString(),
              MessageType: "Heartbeat",
            },
          };
          connection.publish(JSON.stringify(heartbeatMessage), this.heartbeatTopic, { qos: 1 });

          // Once the message is sent, schedule the next heartbeat
          this.scheduleHeartbeat();
        }, period);
      }