User defined scripts
  • 10 Jul 2023
  • 7 Minutes to read
  • PDF

User defined scripts

  • PDF

Article summary

User defined scripts can be used in the following cases:

  • To create a path using JavaScript functions (such as Date) and/or parameters from tags.
  • To create a custom header dynamically based on JavaScript functions and/or parameters.
  • To create the body of the request, when needed (POST, PATCH and PUT methods).
  • To parse the response obtained from the server into tag data objects, ready to write or update the tags.

These scripts use the JavaScript language and have access to the standard JavaScript functions and objects (such as parseInt or the Date object), as well as the following additional libraries and functions added by the N3uron platform.

Moment

Moment is a JavaScript library that simplifies date parsing and formatting, as well as manipulating dates (such as adding a specific duration to a date). The REST API Client version also includes Moment Timezone, which is used to parse dates in specific time zones and to manipulate the time zone of a moment object.

Moment can be accessed by directly invoking the moment() constructor, while Moment Timezone is accessed using moment.tz()

Documentation about Moment can be found in Moment.js and Moment Timezone.

Buffer

Buffer is a Node.js class that is used to create and manipulate binary arrays. This class can be used when generating or parsing a binary body. Documentation about the Buffer class can be found at Node.js Buffer API.

sprintf

Sprintf is a function used to format any string given a format pattern containing placeholders and several variables that will substitute the placeholders. The format is similar to that of the C's  sprintf function, since placeholders are declared using the special character %, followed by a letter denoting the type of the variable that will substitute the placeholder. The following examples are valid place-holders for different data types:

  • Integer: %d or %i
  • String: %s
  • Binary: %b
  • JSON: %j
  • ASCII character in decimal: %c
  • Scientific notation: %e
  • Floating point: %f
  • Fixed point: %g
  • Octal: %o
  • Unsigned integer: %u
  • Hexadecimal lowercase: %x
  • Hexadecimal uppercase: %X
  • Node buffer: %r

If the integer and the unsigned integer format type receive a decimal number, they will truncate the decimal part.

 All formats that admit decimal numbers, such as floating point or scientific notation, can be configured to specify the required number of decimals to display by using the format %.xY, where x is the number of decimals, and Y is the format used (f, for floating point; e, for exponential, etc). For example, to show a floating-point number with 2 decimals, the following format must be used: %.2f. See below for examples of the different format options in the following script:

$.sprintf("Numbers are: %d and %i", 10, 15.7)
//Numbers are: 10 and 15

$.sprintf("String is: %s”, “Hello world!");
//String is: Hello world!

$.sprintf("The binary representation of 5 is: %b", 5);
// The binary representation of 5 is: 101

$.sprintf("The ASCII character with decimal value 48 is %c", 48);
// The ASCII character with decimal value 48 is 0

$.sprintf("1000 in scientific notation is: %e", 1000);
//1000 in scientific notation is: 1e3

$.sprintf("1234 in scientific notation and 2 decimals is: %.2e", 1234);
//1234 in scientific notation and 2 decimals is: 1.23e3

$.sprintf("12.34 in floating point notation is: %f", 12.34)
//12.34 in floating point notation is: 12.34

$.sprintf("12.3456 in fixed point notation is: %.3g", 12.3456);
//12.3456 in fixed point notation is: 12.3

$.sprintf("12 in octal is: %o", 12);
//12 in octal is: 14

$.sprintf("-10 in unsigned integer format is: %u", -10)
//-10 in unsigned integer format is: 4294967286

$.sprintf("30 in hexadecimal is: %x", 30);
//10 in hexadecimal is: 1e

$.sprintf("30 in uppercase hexadecimal is: %X", 30);
//30 in uppercase hexadecimal is: 1E

const buf = Buffer.from("Hello world!");
$.sprintf("The buffer is: %r", buf);
//The buffer is: <48 65 6c 6c 6f 20 77 6f 72 6c 64 21>;


$.logger

The $.logger object is used to log messages to the module log, which can be used for both debugging and informative purposes. The log file can be found at N3uron/log/RestApiClientInstaceName/. It is shared by both the module’s internal execution and any messages written by the users. The logger has five different logging levels:

  • $.logger.error()
  • $.logger.warn()
  • $.logger.info()
  • $.logger.debug()
  • $.logger.trace()

Each of the logging functions have two arguments:

    • (String) message: Format string using sprintf formatting.
    • (Any) arguments: Arguments that will replace the placeholders in the format string.

$.parameter

Parameters in requests can be used by accessing the $.parameter object. All of these parameters are tag events and as such, have a value, a quality, and a timestamp. Parameters use the following configuration:


As an example, the parameters value is used by accessing $.parameter.Start.value.

  • The parameters value corresponds to the tag value. The type depends on the tag type, which can be a number, a string, a Boolean, or null.
  • The parameters quality is a number in the range of 0-255.
  • The parameters timestamp is a number that represents the number of milliseconds elapsed since January 1970 (Unix Epoch).

Additionally, since $.parameter is a JavaScript object, it can be iterated to programmatically obtain all parameters using the for…in syntax. An iteration example can be seen in the following snippet:

for (const [param, value] of Object.entries($.parameter)){
   $.logger.info("Parameter %s is %j", param, value);
}


$.local

$.local is an empty object that can be used to store any user variables that persist between request executions, as well as any variables that are shared between different scripts belonging to the same request. For example, when creating a local variable named "count", the following syntax is used:

//Only define the variable if it's undefined
if($.local.count === undefined) $.local.count = 0;


$.input

This variable contains the input given to the custom script, if applicable. The input type depends on the function of the custom script, and may be null if the script has no input. The current scripts with access to $.input are:

  • Response parser: The input is an object containing three keys:
    • Status code: Contains the status code that the server responded with. The most common status code is 200 – OK.
    • Headers: Contains the headers sent with the response by the server. The keys for these objects are the header name and the values are the header value.
    • Body: Contains the body of the request. The body type varies depending on the serializer used. If the serialization is binary, the type will be a Buffer. If the serialization is text, it will be plain text and finally, if the serialization is JSON or XML the result will be a JavaScript object obtained by deserializing each respective format. More information about the resulting objects can be found in the appendix.

$.output

This variable is used to set the script output. The output type depends on the function of the custom script. If an incorrect type is used, an exception will be logged and the request will be aborted. The following are valid output types for each use:

  • Custom path: When creating a path using a script, the output must be a valid string.
  • Custom header: When a script is used to create a custom header, the output must be a valid string.
  • Custom body serializer: When a custom body is created, the output depends on the type of serializer used to serialize the body. If the serializer is JSON or XML, the output must be an object (which is then converted automatically to a JSON or XML string). When the serialization is text, the output must be a string, and if the serialization is binary, the output must be a Buffer.
  • Custom response parser: When a custom response parser is used to parse the data received from the server, the output must be an array of tag data objects that contain, at the very minimum, a tag property and a value property, and optionally, a quality and a timestamp (using the UNIX Epoch with milliseconds format).

Tag data objects

Whenever data is received from a request to N3uron, the data must be parsed into a format that is compatible with N3uron tags, which is an array of tag data objects. The format of a tag data object differs slightly when the data is saved to a source tag, as opposed to when it is written to a tag. The tag data formats are as follows:

  • TAG_ADDRESS: This value is used to associate the given tag event with a tag in the N3uron tag model. Values can either be a tag path or an alias (providing that an alias is defined in the tag configuration).
  • TAG_VALUE: This is the value that will be saved to the specified tag. It can be a number, a string, or a Boolean value. If the destination tag has a different type, the value will be casted to the correct type (if possible).
  • TAG_QUALITY: This property is optional when the tag is a REST API Client source tag and will be ignored if the tag has a different source (since this will make it a tag write). If defined, this field specifies the quality of this tag event. The property type is a number between 0 and 255. Qualities with values in the 0-64 interval are considered bad, 64-127 are uncertain and values between 192 and 255 are good. If this value is omitted when acting as the source, it will automatically be set to 192 (GOOD_NON_SPECIFIC).
  • TAG_TIMESTAMP: This property is optional when the tag is a REST API Client source tag and ignored if the tag has a different source (since this will make it a tag write). If defined, this field sets the timestamp of this tag event. The property type is a number and the value must be the number of milliseconds elapsed since 1970 (UNIX Epoch with milliseconds). For easy date parsing, Date and/or moment is recommended. If this value is omitted when acting as a source, the timestamp will automatically be set to the current time (using the Date.now() function).

{
  tag: TAG_ADDRESS,
  value: TAG_VALUE,
  quality: TAG_QUALITY,
  ts: TAG_TIMESTAMP
}



Was this article helpful?

What's Next