# Script Function JavaScript Source Code and API Reference

The following guidelines must be observed when creating JavaScript source code for the Script function. The implementation of JavaScript follows version 5 of the open standard approved by the European Computer Manufacturer’s Association, also known as ECMAScript 5 (ECMA5).

## Constructor

The JavaScript source code must set a "module.exports" equal to a function that represents the constructor of the tool. This function is invoked, with no arguments, after the script is compiled, which initializes an instance of the Tool object.

Note:

- The Tool function name in the following examples is arbitrary (and has no effect on the operation of the Script function itself), and is used in all the In-Sight examples and sample scripts. Any other name can be given to the Tool function name, but the name must be used consistently throughout the source code in a Script function. Also, within the examples below, the "this" keyword refers to the Tool object created and initialized using the constructor function.
- Based on the implementation of JavaScript by In-Sight, Script methods (for example, constructor, run, save, load and/or draw) can be called more than once while editing the Script function or closing the Edit Script Dialog. For example, after a script has been created in the Edit Script dialog, when the script is saved by pressing the Save button, the run method can be run additional times to ensure it compiles correctly, and to return results, so multiple messages can appear in the console.log.

For example:

    function Tool() {
      // Initialize the tool state
      this._partTotal = 0;
    }
    module.exports = Tool;

## Run Method

The Tool object must define a "run" method, which is called whenever the Script function is executed. Otherwise, the Script function returns #ERR. The Script function arguments are passed to the run method of the script in the order they are specified.

The following example shows the recommended syntax for defining the run method:

    Tool.prototype.run = function(a, b) {
      return "The average is" + (a+b)/2;
    };

Note:

- All JavaScript functions are variadic, so the run method in the script does not need to declare the same number of arguments that are passed to the Script function. The Script function can also access a variable number of arguments, using the "arguments" array.
- Based on the implementation of JavaScript by In-Sight, Script methods (for example, constructor, run, save, load and/or draw) can be called more than once while editing the Script function or closing the Edit Script Dialog. For example, after a script has been created in the Edit Script dialog, when the script is saved by pressing the Save button, the run method can be run additional times to ensure it compiles correctly, and to return results, so multiple messages can appear in the console.log.

## Run Method Return Values

The run method can return any of the following types of values:

- A number
- True (1) or false (0)
- A string
- A Binary data structure
- A Blob, Edge, Histogram, or Patterns Vision Data Access functions data structure
- A shape object
- An object
- An Image
- Null, undefined or no return statement (which is treated the same as an empty object)

Note:

- When a number or string is returned, the Script function displays a number or string as the output result.
- When an object is returned, the Script function displays an Object data structure.
- When an array is returned, the Script function displays an Array data structure.

## Draw Method

The Script function supports a "draw" method, which allows the function to generate graphics similar to the Image functions. The draw method is given a single argument, which is a graphics context object.

Note:

- The draw method is optional, and can be omitted if there are no graphics being drawn.
- If an exception is thrown in the draw, save or load methods, the exception is logged to the console and the method exits at that point. However, the Script function does not necessarily return #ERR in that event; it returns the result of the run method, or #ERR if the run method throws an exception or the code cannot be compiled.
- Based on the implementation of JavaScript by In-Sight, Script methods (for example, constructor, run, save, load and/or draw) can be called more than once while editing the Script function or closing the Edit Script Dialog. For example, after a script has been created in the Edit Script dialog, when the script is saved by pressing the Save button, the run method can be run additional times to ensure it compiles correctly, and to return results, so multiple messages can appear in the console.log.

Use the following methods to generate graphics:

- plotArc(centerX, centerY, startX, startY, endX, endY, name, color [,show])
- plotCircle(X, Y, radius, name, color [,show])
- plotCross(X, Y, angle, width, height, name, color [,show])
- plotLine(X0, Y0, X1, Y1, name, color [,show] [,startAdornment] [,endAdornment])
- plotPoint(X, Y, name, color [,show])
- plotRegion(X, Y, width, height, angle, curve, name, color [,show])

Note:

- The bracketed parameters are optional.

- The plotRegion method recognizes additional flags that can be ORed with the show parameter values:

  - 0x100: Plot only the region perimeter, with no X/Y axis labels.
  - 0x200: Plot a filled (solid color) region, with no X/Y axis labels.

  For example, passing a show parameter value of 0x101 will plot a region with no axis labels, and it is always plotted (that is regardless of whether or not the cell is the current cell). Similarly, passing a value of 0x201 plots a solid-color region.

- The JavaScript parameters have the same meaning as the Image Functions parameters, except that they do not take an image as the first parameter. Graphics produced by a Script function are displayed on the image of the first AcquireImage cell reference found in the list of input arguments to the Script function. If a Script function is not given an image as an input argument, then its graphics will be displayed on the image of the first AcquireImage cell found in the sheet.
- The "color" parameter is specified as a 24-bit RGB color value.
  Given red, green, and blue values in the range 0-255, an RGB color value can be calculated using the formula (red * 65536) + (green * 256) + blue. Expressed in hexadecimal, this is in the 0xRRGGBB format. For example, the hexadecimal constant 0xFF8020 translates to: red=255, green=128, blue=32.

## Drawing Shapes

In addition to the above graphics, there is a draw method for creating "shapes," which is the equivalent of the PlotPolygon and PlotCompositeRegion functions, where the "shape" can be any of the supported Shape Objects.

- plotShape(shape, name, color [,show])

Note: The polygon is not graphically displayed if its length exceeds approximately 4950 points.

The following example illustrates the correct syntax for defining the draw method:

    Tool.prototype.draw = function(gr) {
      gr.plotPoint(this._foundx, this._foundy, "Found Feature", 0xFF00FF);
    };

## Save and Load Methods

The Script function supports "save" and "load" methods, which allow the function to archive its internal state when the job is saved, and to restore the state of the function when the job is loaded. The save method requires no arguments, and returns an Object that contains the state to be saved. The object is stored in the job file, and when the job is loaded, the object is provided as the lone argument for the load method of the function.

Note:

- The save and load methods are optional, and may be omitted if the tool does not save a state in the job.

- If an exception is thrown in the draw, save or load methods, the exception is logged to the console and the method exits at that point. However, the Script function does not necessarily return #ERR in that event; it returns the result of the run method, or #ERR if the run method throws an exception or the code cannot be compiled.

- Based on the implementation of JavaScript by In-Sight, Script methods (for example, constructor, run, save, load and/or draw) can be called more than once while editing the Script function or closing the Edit Script Dialog. For example, after a script has been created in the Edit Script dialog, when the script is saved by pressing the Save button, the run method can be run additional times to ensure it compiles correctly, and to return results, so multiple messages can appear in the console.log.

The following example illustrates the recommended syntax for defining the save and load methods:

    Tool.prototype.save = function() {
      return {total: this._total, avg: this._average};
    };
    Tool.prototype.load = function(saved) {
      this._total = saved.total;
      this._average = saved.avg;
    };

## Timeout

Each of the JavaScript methods that is called by the Script function (i.e. the constructor, run, draw, save and load methods) is subject to a timeout. By default, the default timeout is ten seconds, with a one second default granularity (the timeout is specified in milliseconds, with a minimum value of 1 and a maximum of 60000; the granularity is also specified in milliseconds, with a minimum of 1 and a maximum of 10000). If any of the methods take longer than ten seconds, the method is aborted, exhibiting the same effect as though an exception had been thrown, with a message indicating that a timeout has occurred.

Note: The purpose of the timeout is to avoid locking up the In-Sight vision system in the event that an infinite loop is inadvertently created in the script, versus providing a function-specific timeout to limit the length of time a job is allowed to run, like the Timeout parameter of a FindPatMaxRedLine function. For that type of functionality, use the hrtime([time]) method in the script to periodically check the elapsed time to determine whether the function needs to continue.

It is also possible to change the duration of the timeout for all Script cells manually, as the following script shows.

                function Script() {
    }

    module.exports = Script;
    Script.prototype.run = function (arg0) {

                // Find the script configuration object.
    var scriptConfig = process.binding("InSight.Camera").config.script;

                // Change the (shared) Script timeout.
    scriptConfig.toolTimeout = 3000 /*ms*/;
    return true;
    }

## File Paths

For the JavaScript functions described in this topic that require a file name or directory path, they can either be a simple name (when referencing files on the local file system) or a URL (using the FTP scheme when referring to files and directories on an FTP server).

When a URL is used, it must follow the FTP URL format, as specified in RFC 1738: ftp://<user>:<password>@<host>:<port>/<url-path>

Note: Some or all of the parts "<user>:<password>@", ":<password>", "<port>" and "/<url-path>" can be excluded.

## Script Modules

All In-Sight JavaScript code is loaded as modules that are offered privacy of their top scope, facility for importing singleton objects from other modules, and exporting their own API. This format is used for loading the JavaScript code contained within a Script function, as well as when loading external script modules from files.

Note: While the module system is based on those of CommonJS and NodeJS, Cognex does not guarantee any compatibility with modules designed for those systems.

The following example illustrates how to import source code:

                /*
    This script returns the roots of a quadratic equation, given the coefficients a,b,c from a standard form equation.
    */
    function Script() {

    }
    /*
    This is a required statement, and enables the Spreadsheet to call the Script function, which initializes this cell.
    */
    module.exports = Script;
      var quad = require('quadratic'); 	// Imports the module
    /*
    This is where the quadratic module can be put to use.
    */
    Script.prototype.run = function() {
        var a = 1, b = 4, c = 2;
        return quad.roots(a,b,c); //Put the module to use
    }

Note: If the specified .js file is not readable when the require() function is called, the require () function returns the value "undefined," and does not throw an exception.

## Global Scope

The global scope module is unique to that module, meaning that any free variables defined by the module are only visible to that module.

## "require" Function

In a module, "require" is a free variable that acts as a function. The "require" function accepts a Module Identifier, and returns the exported API of the imported module. If the requested module cannot be returned, the "require" function returns the value "undefined."

## "module" Variable

In a module, there is a free variable, "module," which is an Object. The "module" object has an "exports" property that represents the exported API of the module, and it is initially set as an empty object.

A module can simply add properties to the default-created "module.exports" object in order to export its API. Alternatively, a module may assign a new object to the "module.exports" property in order to export a different object as its API, rather than using the default-created empty exports object.

## "exports" Variable

In a module, there is a free variable called "exports," which initializes the value of "module.exports."

Note: This variable is provided as a convenience, allowing scripts to simply add properties to the "exports" object, rather than having to specify "module.exports."

## Module Identifier

A module identifier is either the name of file on the local file system of an In-Sight vision system, or the name of a file on an FTP server, as specified under the File Paths section.

Note: If the name is specified without a file extension, the .js extension is automatically appended to the file when attempting to load it.

## Data Structure Inputs/Outputs

The Blob, Edge, Histogram, or Patterns Vision Data Access functions data structure are supported both as inputs and outputs from a Script function. These data structures are read-only, and cannot be created or modified by JavaScript source code. Each of the data structures exposes methods that correspond to the corresponding Vision Data Access functions 2D Vision Data Access functions supported by the particular data structure.

For example, a Blobs data structure supports the following methods:

- blobs.getNFound() – Returns the number of blobs found.
- blobs.getAngle(index) – Returns the angle of an indexed blob's center of mass.
- blobs.getArea(index) – Returns the area (in pixels) of an indexed blob.

## Binary Structures Inputs/Outputs

The Binary data structure returned by a BStringf or ReadDevice function, and the UserData data structure returned by the GetBufferData function are supported as inputs to a Script function. When these structures are passed into JavaScript, the binary data is copied into a JavaScript DataView object, which can be used to read/write individual bytes, or to create a different typed array view, such as an Int32Array or a Uint8Array. Because the Script function is given a copy of the data, the function can save or modify the contents of the DataView object without affecting the original source data.

When a JavaScript DataView, ArrayBuffer or other typed array object is returned by a JavaScript function, the data is copied into a Binary data structure, which can be used by other In-Sight functions (such as a WriteDevice function) that accept a Binary data structure as an input argument.

Note: The Int32Array and Uint8Array are standard JavaScript classes. For more information, see the links above.

The following example takes a Binary data structure as an input argument, views the data structure as an array of 32-bit floating point values, and then returns a new Binary data structure, which contains 64-bit floating point values, in the opposite order.

    Tool.exports.run = function(data) {
      var input = new Float32Array(data.buffer);
      var output = new Float64Array(input.length);
      for (var i=0; i<output.length; ++i)
        output[output.length - i] = input[i];
      return output;
    }

The next example illustrates a function that formats and returns a hypothetical 14-byte binary message to be sent to a PLC. The function does not need to write padding fields because they are automatically initialized to zero. The returned value is a 14-byte Binary data structure in the spreadsheet.

    // Message Format:
    // Byte padding[2]; /* Fill with zeroes */
    // uint32 count;	/* 32-bit unsigned integer, big-endian order */
    // double delay;	/* 64-byte double, little-endian order */
    //
    Tool.exports.run = function(count, delay) {
      var data = new DataView(new ArrayBuffer(14));
      data.setUint32(2, count);		// big-endian by default
      data.setFloat64(6, delay, true);	// little-endianreturn data;
    }

## Shape Objects

A shape object can be input to a Script function as an argument (for example, using a reference to an EditRegion function), and can be output as a return value. Shape objects are created by using constructor functions that are provided as members of the 'cognex' module.

The following illustrates how shape objects can be created:

                function Example()
    {
    }
    var cognex = require('cognex');
    module.exports = Example;

    Example.prototype.run = function(x, y)
    {
      var annulus = new cognex.Annulus(150, 250, 25, 45);
      var circle = new cognex.Circle(50, 250, 30);
      var fixture = new cognex.Fixture(230, 300, 45);
      var line = new cognex.Line(270, 530, 290, 50);
      var point = new cognex.Point(330, 500);
      var polygon = new cognex.Polygon();
      polygon.add(340,230);
      polygon.add(390,210);
      polygon.add(370,230);
      polygon.add(390,250);
      var region = new cognex.Region(440, 300, 40, 50, 30, 45);
      this.shapes = [annulus,circle,fixture,line,point,polygon,region];
      return this.shapes;
    }

    Example.prototype.draw = function(gr)
    {
      this.shapes.forEach(function(shape) {gr.plotShape(shape, JSON.stringify(shape), 0xc0ffee*Math.random());});
    }

## Annulus

The Annulus constructor function requires the following arguments, and the object provides read/write properties with the same names:

- X: The X-offset.
- Y: The Y-offset.
- innerRadius: Defines the inner radius.
- outerRadius: Defines the outer radius.

## Circle

The Circle constructor function requires the following arguments, and the object provides read/write properties with the same names:

- X: The X-offset.
- Y: The Y-offset.
- radius: Defines the radius.

## Fixture

The Fixture constructor function requires the following arguments, and the object provides read/write properties with the same names:

- X: The X-offset.
- Y: The Y-offset.
- theta: The angular orientation.

## Line

The Line constructor function requires the following arguments, and the object provides read/write properties with the same names:

- x0: The X-offset of the first endpoint.
- y0: The Y-offset of the first endpoint.
- x1: The X-offset of the last endpoint.
- y1: The Y-offset of the last endpoint.

## Point

The Point constructor function requires the following arguments, and the object provides read/write properties with the same names:

- X: The X-offset.
- Y: The Y-offset.

## Polygon

The Polygon constructor function requires no arguments, and returns an empty polygon. The polygon object provides the following properties and methods:

- length: Returns the number of points in the polygon. For example, a triangular polygon has three points.
- add(x,y): Appends a new point to the polygon.
- clear(): Removes all points from the polygon.
- remove(n): Removes the specified point (n) from the polygon. It does nothing if the index is a number outside the valid range of indices.
- set(n,x,y): Sets the coordinates of a point (n) of the polygon.
- x(n): Returns the x-coordinate of point (n) of the polygon.
- y(n): Returns the y-coordinate of point (n) of the polygon.
- clone(): Returns a copy of the polygon.

- points: Gets or sets an array of numbers containing the polygon point coordinates:

  [x0, y0, x1, y1, x2, y2, ...]

  Reading this property returns a new array containing a copy of the polygon points, so modifying the array does not have any effect unless it is assigned back to the points property.

  Tip: When iterating over the polygon points, it is far more efficient to read this property only once at the start of a loop rather than reading it on every iteration.

  When setting this property to an array of values, each element is converted to a single precision floating point value. An exception is thrown if this property is set to a value that is not an array with an even number of elements. The behavior is undefined if any value in the array cannot be converted to a number within the range of single precision floating point.

- reserve(count): Reserves space to store count points, but does not change the length property. This can make it faster to create large polygons. An exception is thrown if the requested space cannot be allocated.

- translate(tx, ty): Adds the specified values to every point in the polygon. Each point is transformed as follows:

  new_x = x + tx

  new_y = y + ty

- scale(xScale, yScale): Multiplies every point in the polygon by the specified values. Each point is transformed as follows:

  new_x = x * xScale

  new_y = y * yScale

- transform(m00, m01, m10, m11, tx, ty): Applies a transformation matrix to the polygon points. Each point is transformed as follows:

  new_x = x * m00 + y * m01 + tx

  new_y = x * m10 + y * m11 + ty

In case an index (n) is specified, the first point has an index of zero. In case the index (n) does not exist, getters return zero, while setters return an Index out of bounds error, unless specified otherwise.

## Region

The Region constructor function requires the following arguments, and the object provides read/write properties with the same names:

- X: The X-offset of the origin.
- Y: The Y-offset of the origin.
- w: The X-axis dimension of the region.
- h: The Y-axis dimension of the region.
- angle: The angular orientation, in degrees.
- curve: The angular deviation between the X-axis of the region and the opposing boundary line.

## Process Object

Within any module, a free variable, "process," provides an object with the following methods.

## uptime()

This method returns the number of seconds, as a floating-point value, with sub-microsecond precision, since the system powered up.

Note: The accuracy depends on the accuracy of the system clock crystal and additional factors, so no specific accuracy is guaranteed.

The following illustrates how the method can be used:

                var start = process.uptime();
    someTimeConsumingFunction();
    var elapsedSeconds = process.uptime() - start;

## hrtime([time])

This method returns the current time in a high-resolution tuple Array (seconds, nanoseconds), where the first element is an integer number representing seconds, and the second element is an integer number representing nanoseconds since the start of the current second. The primary use of this method is for measuring time between intervals.

Note: The accuracy depends on the accuracy of the system clock crystal and additional factors, so no specific accuracy is guaranteed.

If this method is called without an argument, the returned time is relative to when the In-Sight vision system powered up. If the method is called with the result of a previous call to hrtime(), the returned time is the time difference, relative to the previous time.

The following illustrates how the method can be used:

                var start = process.hrtime();
    someTimeConsumingFunction();
    var diff = process.hrtime(start);
    var elapsedSeconds = diff[0] + diff[1] / 1e+9

## sleep(ms)

This method specifies that the Script function needs to sleep for the specified number of milliseconds.

Note: The sleep period is aborted if a Timeout elapses before the sleep period has finished.

## memoryUsage()

This method returns an object with two properties:

- heapTotal: Indicates the total size of heap memory.
- heapUsed: Indicates the amount of heap memory currently in use.

## Console Object

Within any module, a free variable, "console," provides an object with the following methods.

## console.log(message)

This method prints a message, as normal text, to the Output pane.

## console.warn(message)

This method prints a message, with black text on a yellow background, to the Output pane .

## console.error(message)

This method prints a message, with black text on a red background, to the Output pane.

## File System Module

The "fs" module provides access to files on the local file system of an In-Sight vision system, as well as those on remote FTP servers.

Note: All of the methods in the file system module end in "Sync" to denote that they are "synchronous," which means that the execution of the script within the Script function blocks until the file operation is completed.

This module is obtained using the require function:

     var fs = require("fs");

The file system object provides the following methods.

Note:

- The same file type visibility support exists between the source code written in a Script function and the file types supported on the vision system (for example, .txt, .htm, .xml, .js, .css, .rtf and .json). However, if accessing a third party FTP server, authorized users can read/write other file types.
- Due to the multitude of possible FTP server configurations, Cognex recommends that before using the File System Module methods (especially appendFileSync, as it relies upon existsSync, readFileSync and writeFileSync), the intended FTP server and file paths are tested to verify their compatibility and suitability before implementation. For example, in some "blind drop" FTP server configurations, the existsFileSync method may return false for an existing file, or the readFileSync method can fail, leading to data loss.

## appendFileSync(file name, data)

This method appends the given data to a file, if it exists, or writes the data to a new file if the file does not already exist. If the data parameter is a JavaScript typed array, such as a Uint8Array or a DataView, it is written to the file as binary data. Otherwise, it is converted to a string, and written to the file as a UTF-8 string.

## existsSync(file name)

This method returns true if the specified file exists.

## readFileSync(file name [,"binary"])

This method reads and returns the entire contents of the file. The contents of the file are read as UTF-8 text, and returned as a string. If the optional "binary" argument is used, the contents of the file is returned as binary data in a DataView. For example:

    var binaryData = fs.readFileSync('ftp://server/xyz.dat', "binary");

Note: This method throws an exception if an attempt is made to read a system file.

## readdirSync(path)

This method reads the contents of a directory, and returns an array of file names. To read only the contents of an In-Sight vision system directory, specify an empty string or "."; to read the contents of a directory of an FTP server, specify the FTP URL, only.

## statSync(path)

This method receives the status of a file or directory, and returns an object with the following property:

- size: The size, in bytes, of the file.

Note: If the file does not exist, this function returns an object with size=0, instead of throwing an exception.

## unlinkSync(file name)

This method is used to delete the file. However, if the file does not exist, the method does nothing.

## writeFileSync(file name, data)

This method writes the entire contents of the file, and will overwrite an existing file (if the file does not exist, the file is created). If the data parameter is a JavaScript typed array, such as a Uint8Array or a DataView, it is written to the file as binary data. Otherwise it is converted to a string (if it is not already a string), and written to the file as a UTF-8 string.

Note: This method throws an exception if an attempt is made to write to a system file.