VNode Manual Scripting v1.6
VNode Manual Scripting v1.6
Reference Manual
vNode Scripting
v1.6
www.vnodeautomation.com
2
Index
Introduction .................................................................................................................................................... 3
Configuration ................................................................................................................................................. 4
Tasks .............................................................................................................................................................. 4
Actions .......................................................................................................................................................... 4
Scripts ...........................................................................................................................................................11
Libraries ......................................................................................................................................................17
Source ..........................................................................................................................................................19
API ..................................................................................................................................................................... 20
Examples ........................................................................................................................................................ 73
www.vnodeautomation.com
I
3
Introduction
vNode’s Scripting module allows the execution of custom logic within the current vNode
node in response to various triggers, such as timers, tag changes, tag conditions, and
more. This logic is implemented using a native JavaScript interpreter (Node.js) capable of
executing user-provided code and granting access to both Node.js native libraries (e.g., fs,
net, or HTTP) and the extensive Node.js ecosystem of libraries (e.g., through NPM).
Furthermore, Scripting has complete access to the vNode API, enabling direct interaction
with tags (including real-time and historical data), alarms, retrieval of the
current vNode node's status, module status, and many other features.
• Access to both the native Node.js libraries as well as its entire ecosystem of
packages.
www.vnodeautomation.com
I
4
Configuration
Tasks
A task is a collection of different actions, each with its own trigger, which can execute one
or several scripts. While the scripts in each task are independent, they can share data
within the same task by using $.taskLocal and between tasks by using $.global:
Each task can be individually enabled or disabled by configuring the “Enabled” option. If
the task is disabled, none of the actions in the task will be triggered and the scripts will
not be executed. Each task can have an unlimited number of actions.
Actions
An action is an object that can have several scripts, as well as a trigger, which will start the
execution of these scripts. There are 6 different types of actions, each with their own
configuration settings:
www.vnodeautomation.com
I
5
• External: Never executes by itself. Will execute when called by external modules.
Start-up, shutdown, and external do not require any specialized configuration, whilst the
others will require different configuration settings to be applied.
Periodic
• Period: Specifies the time period for this action, displayed in ms. The default value is
10 seconds.
• Period type: Selects how the period will be calculated. Valid values are:
o Fixed delay: The scripts trigger after the specified period in ms has elapsed since
the scripts have completely finished executing. For example, if the scripts take
250 ms to complete execution, the period is set to 10,000 ms, and the current time
is 00:00:00.000, the first execution will be at 00:00:10.000, the second execution
at 00:00:20:250, and the third at 00:00:30.500 and so forth.
o Fixed rate: The scripts trigger after the specified period in ms has elapsed since
the last trigger, independently of when the script finished its execution. For
example, if the scripts take 250 ms to complete execution, the period is set to
www.vnodeautomation.com
I
6
10,000 ms, and the current time is 00:00:02.463, the first execution will be at
00:00:12.463, the second execution at 00:00:22:463, and the third at 00:00:32.463
and so forth. If the scripts don't finish before the next period triggers, the script
will start as soon as the previous execution finishes.
o Fixed interval: The action starts at fixed intervals depending on the period,
independently of when the script finished execution. If the specified period
elapses before the script finishes, all missed intervals will be skipped. For example,
if the period is 10,000 ms, the script will always execute at 00:10:00.000,
00:20:00.000, etc., independently of when the script ends. If execution of the
script takes longer than the specified period, enough intervals are skipped to
allow the script to execute at the next interval.
o Cron: The action starts periodically based on a cron expression. If the script doesn't
finish before the next scheduled time, this execution will be skipped.
Change
• Trigger type: Selects between the different trigger types for the tag change action.
o Single tag: This trigger type will execute the script whenever the specified tag
generates a tag event.
www.vnodeautomation.com
I
7
o Tag group: This trigger type will execute the script whenever any of the tags
within the group generate a tag event.
o Multiple tags (Filter): This trigger will execute the script whenever any of the
tags that meet the filter conditions generate a tag event.
www.vnodeautomation.com
I
8
• Trigger options:
o Property: Selects which of the tag’s properties should be monitored for changes.
The valid values are Any, Value, Quality, or Timestamp.
o Initial change: If enabled, the initial event after a tag subscription can trigger the
scripts. Otherwise, the initial event is discarded.
o Maximum event buffer size: Specifies the maximum number of events that will be
buffered in case the events are received faster than the script can execute. After
the buffer fills up, the oldest events will be discarded. Otherwise, the script will be
triggered once for each event in the buffer. The minimum value is 1, which means
that the script will always execute using the last event received.
Condition
www.vnodeautomation.com
I
9
• Tag: Selects which tag will be monitored by this action. Each condition action can
only monitor one tag.
• Property: Selects which tag property will be used to check the condition. The valid
values are Value, Quality, and Timestamp.
• Initial change: If enabled, the initial event after a tag subscription can trigger the
condition check. Otherwise, the initial event is discarded.
• Condition: Selects the condition that must be met for the scripts to trigger. The valid
values are:
o Equal to: Triggers if the tag property is equal to the specified value.
o Not equal to: Triggers if the tag property is not equal to the specified value.
o Greater than: Triggers if the tag property is greater than (but not equal to) the
specified value.
o Greater than or equal: Triggers if the tag property is greater than or equal to the
specified value.
o Less than: Triggers if the tag property is less than (but not equal to) the specified
value.
o Less than or equal: Triggers if the tag property is less than or equal to the specified
value.
• Value: Specifies the value that will be used along with the condition to see if the
script needs to trigger.
• Condition type: Selects how the condition applies. The valid values are:
o If true: The scripts will trigger when the condition becomes true.
o If false: The scripts will trigger when the condition becomes false.
o While true: The scripts will trigger once when the condition becomes true and
then trigger again periodically while the condition remains true.
o While false: The scripts will trigger once when the condition becomes false and
then trigger again periodically while the condition remains false.
If the condition type is either If true or If false, the following two additional configuration
options are shown:
• Trigger on update: If enabled, scripts will trigger every time a new tag event is
received while the condition remains true. Otherwise, the scripts will not trigger again
until after the condition is cleared.
• Maximum event buffer size: Specifies the maximum number of events that will be
buffered in case the events are received faster than the script can execute. When the
www.vnodeautomation.com
I
10
buffer becomes full, the oldest events will be discarded. Otherwise, the script will be
triggered once for each event in the buffer. The minimum value is 1, which means that
the script will always execute using the last event received.
If the condition type is While true or While false, the following two additional
configuration options are shown:
• Period: Specifies the period between script executions, displayed in ms. The default
value is 10 seconds.
• Period type: Selects how the period will be calculated. The valid values are:
o Fixed delay: The scripts trigger after the specified period in ms has passed since
the scripts have completely finished executing. For example, if the scripts take
250 ms to complete execution, the period is set to 10,000 ms, and the current time
is 00:00:00.000, the first execution will be at 00:00:10.000, the second execution
at 00:00:20:250, and the third at 00:00:30.500 and so on.
o Fixed rate: The scripts trigger after the specified period in ms has passed since the
last trigger, independently of the time when the script finished its execution. For
example, if the scripts take 250 ms to complete execution, the period is set to
10,000 ms and the current time is 00:00:02.463, the first execution will be at
00:00:12.463, the second execution at 00:00:22:463, and the third at 00:00:32.463
and so on. If the scripts don't finish before the next period triggers, the script will
start as soon as the previous execution finishes.
o Fixed interval: The action starts at fixed intervals depending on the period,
independently of when the script finished its execution. If this period elapses
before the script finishes, all missed intervals will be skipped. For example, if the
period is 10,000 ms, the script will always execute at 00:10:00.000, 00:20:00.000,
etc., independently of when the script ends. If execution of the script takes longer
than the specified period, enough intervals are skipped to allow the script to
execute at the next interval.
o Cron: The action starts periodically based on a cron expression. If the script doesn't
finish before the next scheduled time, that execution will be skipped.
External
External actions are different from normal actions, they never invoke the script, instead
they wait to be called from another vNode module, such as via OpcUaServer methods.
These methods receive the arguments passed from the module that calls them and return
a value back to the module that called them.
www.vnodeautomation.com
I
11
When calling an external action, it takes a single object argument containing key-value
pairs, where each key is the argument name and the value is the argument value:
The return value can be any anything and depends on what the calling module is
expecting. For example, OpcUaServer expects the return value to be an object where each
key is the output argument name and each value is the value of that output argument.
More detail about the specific return values can be found in the documentation for all
modules that allow calling external scripts.
Scripts
A script is user defined JavaScript code that will execute every time an action triggers.
Each action can have one or more scripts.
Each script has access to several objects and functions that are used to interface with
vNode and to share data between different scripts in the same task or between different
tasks. All of these objects are detailed in the API section of this manual.
Scripts also have access to all Node.js native libraries (such as fs or net), as well as user
defined libraries.
www.vnodeautomation.com
I
12
• Script: Contains the script that will be executed. By clicking the code button, a code
editor will be displayed where the user code can be entered.
• Parameters: These parameters are passed to the script in the $.parameters object.
They are usually used to define a configuration that is then used for the script. For
example, a parameter can be used to set a basepath that will be used in the script, or
the host + port combination used to open a socket in the script. These parameters are
read-only. If they are written, they will throw up an exception. Parameters can be one
of the following types:
www.vnodeautomation.com
I
13
www.vnodeautomation.com
I
14
www.vnodeautomation.com
I
15
o TagPath: Users can select a tag previously created in the Tags section by clicking
on the blue button on the right-hand side of the Value field.
www.vnodeautomation.com
I
16
www.vnodeautomation.com
I
17
Libraries
This section allows users to declare shared libraries that can then be used by all the tasks
in this Scripting instance. There are three types of libraries, as seen in the following
screenshot:
• Internal libraries: These libraries are bundled with vNode and as such, can be loaded
directly without installing anything more. The internal libraries available to Scripting
are:
o Cron: This library is used to validate a given cron expression, as well as retrieving
the next time the expression has to be executed. More information can be found
at cron.
o JsPDF: This library is used to generate PDF documents using JavaScript. The
included version is X. More information can be found at JsPDF.
o JSZip: This library is used to read and write .zip files. The included version is 3.1.4.
More information can be found at JSZip.
o LZ4: This library is used to compress data using the LZ4 algorithm. The included
version is 0.5.3. More information can be found at LZ4.
o Moment.js: This library is used to parse and format dates & times. This library
version includes both moment (version 2.23.0) and moment-timezone (version
0.5.23). More information can be found at Moment and Moment Timezone.
o MongoDB: This library is used to connect and execute queries to a MongoDB
database. The included version is 2.2.36. More information can be found at
MongodB.
o MQTT.js: This library is used to communicate with a MQTT broker using the MQTT
protocol. The included version is 2.2.1. More information can be found at MQTT.js.
www.vnodeautomation.com
I
18
o MySQL: This library is used to connect to a MySQL database and execute queries.
The included version is 2.17.1. More information can be found at MySQL.
o PostgreSQL: This library is used to connect to a PostgreSQL database and execute
queries. The included version is 6.4.2. More information can be found at
PostgreSQL.
o Protobuf.js: This library is used to serialize and parse messages using Google’s
Protocol Buffers format. The included version is 6.8.0. More information can be
found at Protobuf.js.
o SQL Server: This library is used to connect to a SQL Server database and execute
queries. The included version is 3.3.0. More information can be found at SQL
Server.
o WebSockets: This library is used to create a WebSocket client and server. The
included version is 1.1.0. More information can be found at WebSockets.
o XLSX Writer: This library is used to write data to XLSX files.
o Xml2Js: This library is used to serialize and parse XML. The included version is
0.4.16. More information can be found at Xml2Js.
• External libraries: These libraries are external to vNode and must be installed by the
user. They can be installed manually, but the recommended method is through the
Node Package Manager (npm). More information about install libraries can be found
here. When using external libraries, this is either the path of the library entry point
(index.js and main.js being the typical entry points) or the path to the folder containing
the package.json file (typically, node_modules/LIBRARY_NAME).
• Static libraries: These libraries contain user defined code directly in vNode. A use case
for these libraries is creating one or multiple classes that are shared across different
scripts. These libraries have full access to the same API as the rest of Scripting and
they are also saved to vNode backups (unlike external libraries, which are not saved).
In order to export data from a static library, the module.exports syntax is used.
www.vnodeautomation.com
I
19
Source
Scripting can also act as a data provider for tags. To do this, all new tags will need to be
configured with Scripting as their source, as seen in the following screenshot:
Scripting source tags accept a single optional parameter in the form of an alias that will
be used to reference the tag when providing data for that tag. If provided, the tag can be
updated using said alias. Otherwise, the full path will need to be used. The full path can be
used regardless of whether a tag has an alias or not. In order to update a tag, the
$.api.tag.update or $.api.tag.updateAlias functions must be called.
www.vnodeautomation.com
I
20
API
Each script has access to the following features that are not part of the Javascript
standard. Instead, these are added by vNode. Most of them are accesed via a special
$ object. However, some (like the sprintf function) can be used directly:
Sprintf is a function that can be used to create a new string from a format string that can
contain placeholders (for example %s and %d) and a list of values that will replace the
placeholders in the format string in order to generate the new string. The following are
valid placeholders for different data types:
• Integer: %d or %i
• String: %s
• Binary: %b
• Boolean: %t
• JSON: %j
• ASCII character from numeric value: %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 unsigned integer format types receive a decimal number, the decimal part
will be truncated.
Most of these placeholders can also accept modifiers that will affect how the string will be
formatted. For example, %02f will force a floating point number to always use 2 decimals.
More information about the sprintf function can be found at NPM sprintf-js.
An example of various format strings with different placeholders can be seen in the next
code snippet:
www.vnodeautomation.com
I
21
$.global
The $.global object is a key-value store that can be used to share data between all the
scripts, even if they are in different tasks. It has two functions:
• get(property: string) => any: This function is used to retrieve a value from the global
store.
• set(property: string, value: any) => void: This function is used to store a value with a given
key in the global store. Only values that can be serialized using the structured clone
algorithm can be stored in the global store. This includes number, strings, booleans,
objects (without any associated functions), maps and sets. If a value can't be serialized,
an error is thrown. Some common variables that can not be serialized are class
instances and functions.
www.vnodeautomation.com
I
22
$.taskLocal
The $.taskLocal object is a key-key store shared between all the scripts within the same
task, but not between scripts in different tasks. It has two functions:
• get(property: string) => any: This function is used to retrieve a value from the global
store.
• set(property: string, value: any) => void: This function is used to store a value with a
given key in the global store. Only values that can be serialized using the structured
clone algorithm can be stored in the global store. This includes number, strings,
booleans, objects (without any associated functions), maps and sets. If a value can't
be serialized, an error is thrown. Some common variables that can not be serialized
are class instances and functions.
$.local
The $.local is a persistent object within a specific script. This can be used to store state
between script executions. Unlike $.global and $.taskLocal, since this is an object, it can
store any value that can be stored in an object (including functions or class instances).
These values do not persist between module restarts.
$.lib
$.lib is a function used to import libraries declared in the Libraries configuration in a Script.
This is done by invoking the $.lib(name: string) => any function with the same name that
was given when declaring the library in the configuration section.
$.paths
The $.paths object contains different paths for vNode, irrespective of where vNode is
installed or the operating system. The $.paths object has two nested objects, one labelled
global and one labelled local. The first one contains paths relevant to the vNode
installation, while the latter contains paths related to the current Scripting instance.
For example, if vNode is installed in the default windows installation folder and the current
Scripting instance named as “Scripting”, the $.paths object has the following contents:
www.vnodeautomation.com
I
23
{
base: C:\Program Files\vNode,
global: {
bin: C:\Program Files\vNode\bin,
config: C:\Program Files\vNode\config,
log: C:\Program Files\vNode\log,
data: C:\Program Files\vNode\data,
licenses: C:\Program Files\vNode\licenses
},
local: {
bin: C:\Program Files\vNode\bin\modules\Scripting,
config: C:\Program Files\vNode\config\Scripting,
log: C:\Program Files\vNode\log\Scripting,
data: C:\Program Files\vNode\data\Scripting
}
}
The $.exit() function is used to indicate that the current script execution has finished. This
function must be called when the script has executed completely (that includes both
synchronous and asynchronous executions), and after it is called, no further code should
be executed. As such, it is recommended to follow a call to $.exit() with the return;
statement to stop the script from executing any more code.
This function takes two optional parameters. If the function is called without parameters,
it is assumed that it finished without errors and without a return value:
• error: If set, the error will be automatically logged to the log. If there are no errors and
the script has a return value, the error argument must be set to null.
• returnValue: When set, this will be the return value of the script. This is mostly used
by external actions in order to return values to other modules. The return value can
have any type, although other modules may impose a specific format for the return
value in order to function properly.
$.event
The $.event object contains information about the trigger that launched the current script.
This object will vary depending on which type of action launched the script, as seen in the
following list:
• Start-up
o $.event.startTime: Contains the time when the module was started, in UNIX epoch
with milliseconds.
• Shutdown
o $.event.stopTime: Contains the time when the module was stopped, in UNIX
epoch with milliseconds.
www.vnodeautomation.com
I
24
• Periodic
o $.event.time: Contains the time when the periodic action was triggered, in UNIX
epoch with milliseconds.
o $.event.initial: Boolean flag that indicates if the current execution is the initial one
(when Run on startup is true) or a normal periodic execution.
o $.event.blockTs: Contains the start time of the current execution rounded to the
nearest interval (only applies to interval and cron period types). For example, if the
interval is 60 seconds, or the cron job runs every minute, the blockTs will be
rounded to XX:01:00, XX:02:00, even if the script executes slightly later due to timer
delays.
• Tag change
o $.event.tag: Contains the full path of the tag that changed, as a string.
o $.event.oldValue: Contains the old event of the tag before the change. It's an
object with value (whose type depends on the tag type), quality (as a number) and
ts (as a number in UNIX Epoch milliseconds).
o $.event.newValue: Contains the new event of the tag which triggered the script.
It's an object with value (whose type depends on the tag type), quality (as a
number) and ts (as a number in UNIX Epoch milliseconds).
o $.event.changes: Contains an object indicating which properties have changed
in the new tag event compared to the old tag event. It has three boolean
properties, a value, quality, and timestamp. which are set to true if the property
has changed, or false if it hasn't changed.
• Condition
o $.event.tag: Contains the full path of the tag that triggered the condition, as a
string.
o $.event.value: Contains the event that triggered the condition, or the current
value if the condition type is whileTrue or whileFalse. It's an object with value
(whose type depends on the tag type), quality (as a number) and ts (as a number
in UNIX Epoch milliseconds).
o $.event.time: Contains the time when the periodic tag condition action was
triggered, in UNIX epoch with milliseconds. Only applies if the condition type
is whileTrue or whileFalse.
o $.event.initial: Boolean flag that indicates if the current execution is the initial one
(when the condition first triggers), or a normal periodic execution. Only applies if
the condition type is whileTrue or whileFalse.
o $.event.blockTs: Contains the start time of the current execution rounded to the
nearest interval (only applies to interval and cron period types). For example, if the
interval is 60 seconds, or the cron job runs every minute, the blockTs will be
rounded to XX:01:00, XX:02:00, even if the script executes slightly later due to timer
delays. Only applies if the condition type is whileTrue or whileFalse.
www.vnodeautomation.com
I
25
• External action
o External actions contain their arguments as keys to the $.event object. For
example, if an external action receives value1=23 and value2=60as arguments, the
event object will contain $.event.value1 and $.event.value2.
The following code block contains examples of all the different $.event objects:
$.config
The $.config object contains static information about the action that triggered the script.
This object contains the following keys:
• $.config.type: An enumeration that identifies the action that triggered this script. The
values for this enumeration are the following:
o Start-up: 0
o Shutdown: 1
o Periodic: 2
o Tag Condition: 3
o Tag change: 4
o External: 5
www.vnodeautomation.com
I
26
$.parameters
The $.parameters object is used to retrieve configuration parameters for the current script.
The structure of this object is the same as the one in the configuration. For example, if
there is a parameter named "Basepath", it's value can be retrieved by using
$.parameters.Basepath. These parameters are read-only and will throw an error when
attempting to modify them (this includes functions that modified them as a side effect,
such as the .push() method of an array).
$.logger
The $.logger object is used to log messages to disk and can be used for both debugging
and informative purposes. The log file can be found in vNode/log/ScriptingInstance/. It is
shared by both the internal module code and any messages written by users, which can
be easily distinguished by the “User” string appended to them. The logger has five
different logging levels:
• $.logger.error(msg: string, ...params: any[])
• $.logger.warn(msg: string, ...params: any[])
• $.logger.info(msg: string, ...params: any[])
• $.logger.debug(msg: string, ...params: any[])
• $.logger.trace(msg: string, ...params: any[])
Each logging function takes at least one argument, containing the string that is going to
be logged. This string can also be a format string with placeholder, in which case the rest
of the arguments will be used to resolve these placeholders. This is the same behaviour as
sprintf.
$.api
The $.api object is used to interface with vNode, and provides access to several of vNode
functionalities, such as tags, links, vNode node stats, etc. Each of these functions is hosted
in a different namespace, depending on which part of vNode they affect. For example,
functions that affect tags are hosted in the tag namespace, functions that provide the
status of a host machine are present in the system namespace, and so on:
Most of the functions in $.api execute asynchronously and return a promise that is fulfilled
when the asynchronous request finishes. This can also be used with the await keyword
function straight to the top level, without needing to wrap it into an async function. These
functions can also reject promises in case of an error, in which case, the rejection reason
is a string with information about the error.
www.vnodeautomation.com
I
27
$.api.authentication
$.api.authentication.getRoles
Function prototype: $.api.authentication.getRoles(options: {}): Promise<string[]>
This function retrieves the user roles available on the target node.
Example:
const roles = await $.api.authentication.getRoles({});
$.api.authentication.get
Function prototype: get(user: string, password: string): Promise<{id: string, name: string,
roles: string[]}>
This function performs authentication for a specific user and returns its internal ID and the
roles the user belongs to.
Example:
const { id, name, roles } = await $.api.authentication.get("admin", "vNode");
$.logger.info("ID: %s, Name: %s, Roles => %s", id, name, JSON.stringify(roles));
www.vnodeautomation.com
I
28
$.api.system
$.api.system.status
This function queries the status of the host system, and returns an object with information
about the current hardware, the host name, uptime, etc.
Example:
$.logger.info(JSON.stringify(statusResult));
$.api.system.errorCount
This function queries the number of errors in the current node. If there are no errors, 0 is
returned, otherwise, it returns the number of errors (this can be caused by invalid tag
configuration, invalid link configuration, etc...).
Example:
www.vnodeautomation.com
I
29
$.api.system.getStandby
This function queries the standby status of the current node. If the node does not use
redundancy, or if it's the standby node, the function returns false, otherwise, it returns true.
Example:
$.api.system.getNetworkAdapters
Function prototype:
$.api.system.getNetworkAdapters(options: {}) Promise<NetworkInterface[]>
This function retrieves the network interfaces available in the host system.
Example:
$.logger.info(JSON.stringify(adapters));
$.api.system.restartService
Example:
www.vnodeautomation.com
I
30
$.api.system.restartService({});
$.api.license
$.api.license.getUid
Function prototype: $.api.license.getUid(): Promise<UidObject>
Example:
type UidObject = {
host: string,
uid: string
}
$.api.license.get
Function prototype: $.api.license.get(): Promise<ReadonlyArray<LicenseFile>>
This function retrieves the list of licenses installed in the target node.
Example:
www.vnodeautomation.com
I
31
type LicenseFile = {
name: string,
error: string,
id: string,
host: string,
uid: string
nonce: number,
unlicensed: boolean,
licenses: ReadonlyArray<License>,
}
type License = {
version: string,
error: string,
host: string,
uid: string,
expires: string,
type: "production",
modules: ReadonlyArray<ModuleLicense>,
supportExpires: number,
nonce: number,
id: string
}
type ModuleLicense = {
type: string,
tagAccess: "remote"|"local",
count: number,
used: number
}
$.api.license.read
Example:
$.logger.info(license);
$.api.license.add
www.vnodeautomation.com
I
32
Example:
$.api.license.remove
Example:
try {
await $.api.license.remove(license, {});
$.logger.info("License '%s' removed", license);
} catch (error) {
$.logger.error("Failed to remove license: %v", error);
}
$.api.license.unlicense
Example:
try {
const unlic = await $.api.license.unlicense(
"node001-20240213.105718.n3l",
{}
);
$.logger.info("Unlicense file ==> %s", unlic);
} catch (error) {
$.logger.error("Failed to unlicense: %v", error);
}
www.vnodeautomation.com
I
33
$.api.link
$.api.link.get
Example:
$.logger.info(JSON.stringify(linkStatus));
The return value is a promise that resolves an object with the following structure:
type LinkStatus = {
nodeInfo: {
name: string
},
links: {
[linkName:string]: {
local: {
subscription: null | string,
tagCount: number,
view: {
name: string,
ro: boolean,
ae: boolean,
ack: boolean
},
sf: {
enabled: boolean,
paused: boolean
}
},
name: string,
online: boolean,
remote: null | {
endpoint: string,
subscription: null | string,
tagCount: number,
view: {
name: string,
ro: boolean,
ae: boolean,
ack: boolean
},
sf: {
enabled: boolean,
paused: boolean
}
},
type: "in"|"out"
}
}
}
www.vnodeautomation.com
I
34
$.api.link.sfPause
This function pauses the Store&Forward mechanisms for a specific link. When paused, no
more events from S&F will be sent over that link until it is unpaused. This can be used if
the receiver gets saturated with events from a link. By pausing the link, it can process the
events it received before unpausing it to receive more events. It takes two arguments:
o paused: When true, it pauses the link. When false, it unpauses the link.
Example:
$.api.link.sfPause("central01", true);
$.api.certificate
$.api.certificate.get
This function is used to retrieve certificates with a specific type from a module. It takes a
single argument:
▪ type: Selects which type of certificate will be retrieved. For bootstrap, it can
be "outbound" or "inbound", while other modules can define their own
types. The types of certificate for other modules can be found in their
documentation.
Example:
www.vnodeautomation.com
I
35
The return value is a promise which resolves to an array of the following object:
type Certificate = {
c: string,
dn: string,
from: number,
id: string,
o: string,
sn: string,
to: number,
type: string,
status: string
}
$.api.certificate.set
This function is used to execute an action against a certificate. It takes a single argument:
o options: Options used to select the target certificate and action that will be applied.
▪ type: Select the type of certificate that will be affected by the action. For
bootstrap, it can be "outbound" or "inbound", while other modules can
define their own types. The types of certificates for other modules can be
found in their documentation.
▪ id: Select which certificate will be affected by the action. The id can be
retrieved by a call to $.api.certificate.get.
▪ action: Select which action will be executed. The available actions depend
on the module and the state of the target certificate (for example, a
certificate that is already trusted can't be trusted again). The actions
available to bootstrap link certificates are "clear", "reject", and "trust".
Example:
await $.api.certificate.set({
moduleName: "bootstrap",
type: "outbound",
id: "pending/CENTRAL01__LinkManager[F07A91C73030507C4ABCB3689C46257A6E9406A5]",
action: "trust",
});
www.vnodeautomation.com
I
36
$.api.certificate.export
o options: Options used to select the target certificate that will be exported.
▪ type: Selects the type of certificate that will be exported. For bootstrap, it
can be "outbound" or "inbound", while other modules can define their own
types. The types of certificate for other modules can be found in their
documentation.
▪ id: Selects which certificate will be exported. The id can be retrieved by a call
to $.api.certificate.get.
Example:
$.logger.debug(cert);
The return value is a promise that resolves to a base64 string of the certificate's contents.
$.api.certificate.remove
o options: Options used to select the target certificate that will be removed.
▪ type: Select the type of certificate that will be removed. For bootstrap, it can
be "outbound" or "inbound", while other modules can define their own
types. The type of certificate for other modules can be found in their
documentation.
www.vnodeautomation.com
I
37
▪ id: Select which certificate will be removed. The id can be retrieved by a call
to $.api.certificate.get.
Example:
await $.api.certificate.remove({
moduleName: "bootstrap",
type: "outbound",
id: "pending/CENTRAL__LinkManager[F07A91C73030507C4ABCB3689C46257A6E9406A5]",
action: "remove",
});
$.api.module
$.api.module.details
This function is used to retrieve details about the current node (such as uptime, RAM
usage, etc.) as well as details of the created modules (such as running status, license status,
etc.). It returns a promise that resolves to the following object:
Example:
$.logger.info(JSON.stringify(details));
www.vnodeautomation.com
I
38
type ModuleDetails = {
memoryUsage: {
arrayBuffer: string,
external: string,
heapTotal: string,
heapUsed: string,
rss: string
},
modules: {
moduleName: string]: {
api: null | {
online: boolean,
info: {
category: Array<"source"|"publisher">,
fileversion: string,
name: string,
releaseType: string,
requisites: {
exeVersion: undefined | {min: string, max: string},
bootstrapVersion: undefined | {min: string, max: string}
}
type: string,
version: string
},
stats: {
tx: {ok: number, error: number},
rx: {ok: number, error: number}
}
}
config: {
required: boolean,
type: string,
start: {
enabled: boolean,
delay: number
},
monitor: {
enabled: boolean,
delay: number
}
},
lastStart: null | string,
lastStop: null | string,
license: {
acquired: boolean,
mode: "production"|"demo",
period: number,
tagAccess: "local"|"remote"
},
mode: null,
pid: null | number,
running: boolean
}
},
pid: number,
running: boolean,
ts: string,
uptime: string
}
www.vnodeautomation.com
I
39
$.api.module.getConfig
Function prototype:
$.api.module.getConfig<T>(moduleName: string): Promise<TagSourceConfiguration<T>>
This function is used to retrieve the configuration of the source tags belonging to a specific
module. It returns a promise that resolves to an object containing the configuration of the
source tags for the given module. It takes the following arguments:
Example:
$.logger.info(JSON.stringify(tagConfig));
The following snippet is an example of the source tag configuration for a ModbusClient
module:
type TagSourceConfiguration<ModbusClient> = {
[tagPath: string]: {
type: "number"|"boolean"|"string",
link: null | string,
data: {
value: number|string|boolean|null,
quality: number,
ts: number
},
source: {
device: string,
address: string,
type: string,
rate: number
}
}
}
$.api.module.getConfigData
This function is used to retrieve a specific configuration from a module. It returns a promise
that resolves to the configuration of that module. The configuration is the raw
unprocessed configuration, it is the same as if reading the respective configuration file. It
takes two arguments:
www.vnodeautomation.com
I
40
• configName: Name of the configuration that will be retrieved. This can be found by
using $.api.module.getConfigList.
Example:
$.logger.debug(JSON.stringify(configData));
$.api.module.getConfigList
This function is used to retrieve the different configurations available to a module (such as
the default configuration, the logger configuration, etc...). It takes one argument:
Example:
$.logger.debug(JSON.stringify(configData));
The return value is a promise that resolves to the list of configurations available to the
specified module type. The structure of this object can be seen in the next type definition:
type ConfigList = {
[configName: string]: {
text: string,
icon: string
}
}
www.vnodeautomation.com
I
41
$.api.module.getConfigPresent
This function is used to retrieve which configuration files are present (such as the default
configuration, the logger configuration, etc...). It takes one argument:
Example:
const configPresent = await $.api.module.getConfigPresent("OpcUaClient");
$.logger.info(JSON.stringify(configPresent));
The return value is a promise that resolves to an object containing information about
which configurations are present. The structure of this object can be seen in the next type
definition:
type ConfigPresent = {
[configName: string]: boolean
}
$.api.module.getInstalled
This function is used to retrieve a list of the modules installed in the current node. It takes
no arguments and returns a promise that resolves to an array of strings containing the
name of the installed modules.
Example:
www.vnodeautomation.com
I
42
$.api.module.setConfigData
This function is used to update the configuration of a module. It takes four arguments:
o configData: New configuration that will be saved to disk for the specified module.
The configuration must be in a valid format, that is, it needs to follow the same
format as $.api.module.getConfig (in general, the easiest way to ensure the format
is correct is to retrieve the configuration and modify it).
o options:
Example:
const config =
'{"version":{"main":1,"editor":2},"result":["Object",{"bufferLimit":["Number",500000],"m
axDays":["Number",60],"db":["Object",{"run":["Boolean",false],"protocol":["String","mong
odb"],"host":["String","db-
mongo.internal"],"port":["Number",27017],"database":["String","history"],"parameters":["
String",""],"auth":["Object",{"enabled":["Boolean",false],"username":["String",""],"pass
word":["SecuredString",""]}],"tls":["Object",{"enabled":["Boolean",false],"ca":["String"
,""],"rejectUnauthorized":["Boolean",true]}]}]}],"editor":{"extends":{"module":null},"mo
dified":1711467825068,"comment":"","UID":0}}';
try {
await $.api.module.setConfigData("Historian", "default", config, {
restart: true,
});
} catch (error) {
$.logger.error(error);
}
www.vnodeautomation.com
I
43
$.api.backup
$.api.backup.create
This function creates a new backup of the current node configuration. The newly created
backup will be saved to vNode/data/bootstrap/backup. It takes two arguments:
o metadata.user: User that created the backup. This can be any string and doesn't
have to be an existing user.
Example:
await $.api.backup.create("20240623-backup", {
user: "scripting",
description: "Automatic backup created with Scripting.",
});
$.api.backup.delete
This function deletes a backup from the current node. It takes one argument:
Example:
try {
await $.api.backup.delete(backupName);
$.logger.info("Backup deleted => %s", backupName);
} catch (error) {
$.logger.error("Failed to delete backup %s: %v", backupName, error);
}
www.vnodeautomation.com
I
44
$.api.backup.export
This function exports a backup from the current node. The return value is a promise that
resolves to a base64 string of the backup files's binary content (in .zip format). It takes one
argument:
Example:
const fs = require("fs");
try {
fs.writeFileSync(
"/var/vNode/backups/" + backupName + ".zip",
decodedContent
);
$.logger.info("Backup exported => %s", backupName);
} catch (error) {
$.logger.error("Failed to export backup to disk: %v", error);
}
$.api.backup.get
This function retrieves the list of backups present in the current node. The return value is
a promise that resolves to the following object:
type Backups = {
[name: string]: {
description: string,
user: string,
node: string,
ts: string,
version: {
modName: string]: string
}
}
}
www.vnodeautomation.com
I
45
Example:
$.api.backup.import
This function imports a backup to the current node. It takes two arguments:
Example:
const fs = require("fs");
const path = "/var/vNode/backups/20240404.1651.zip";
try {
const backupFile = fs.readFileSync(path);
const encodedData = Buffer.from(backupFile).toString("base64");
$.api.backup.import("test", encodedData);
$.api.backup.load
This function applies the configuration of a backup to the current node. It takes two
arguments:
o options.rollback: When true, if the backup loading fails, the configuration will be
rolled back to the previous configuration. Otherwise, the backup loading process
proceeds, ignoring any errors that might result in invalid configuration for some
modules.
www.vnodeautomation.com
I
46
Example:
try {
await $.api.backup.load("20240404.1651", { rollback: true });
} catch (error) {
$.logger.error(error);
}
$.api.backup.rename
Example:
await $.api.backup.rename("20240404.1651", "monthly-04");
$.api.redundancy
$.api.redundancy.status
Example:
const status = await $.api.redundancy.status({});
$.logger.info(JSON.stringify(status));
$.api.redundancy.sync
This function is used to synchronize files between the primary and backup nodes when
using redundancy. As such, it doesn't do anything if redundancy is not enabled. It takes
two arguments:
o paths: An array of paths that will be synchronized between the redundant nodes.
www.vnodeautomation.com
I
47
o absolute: This flag selects how the paths will be synchronized between the nodes.
If it's false, the paths will be relative to the vNode base folder (for example, when
synchronizing files in vNode/data between two vNode instances installed in
different paths). If it's true, the absolute path will be used so that files will be in the
same location in both nodes.
Example:
try {
await $.api.redundancy.sync(["data/ExampleModule"], false);
} catch (error) {
$.logger.error(error);
}
$.api.redundancy.unsync
This function is used to stop the synchronization of files between the primary and backup
nodes when using redundancy. As such, it doesn't do anything if redundancy is not
enabled. When executing $.api.redundancy.unsync, it will carry out one last
synchronization of the paths to synchronize their current state before stopping any further
synchronization. It takes two arguments:
o paths: An array of paths that will be synchronized between the redundant nodes.
o absolute: This flag selects how the paths will be synchronized between nodes. If it's
false, the paths will be relative to the vNode base folder (for example, when
synchronizing files in vNode/data between two vNode instances installed in
different paths). If it's true, the absolute path will be used, so the files will be in the
same location in both nodes.
Example
try {
await $.api.redundancy.unsync(["data/ExampleModule"], false);
} catch (error) {
$.logger.error(error);
}
www.vnodeautomation.com
I
48
$.api.tag
$.api.tag.browse
This function lists the tags and groups present in a given path, and optionally, in all of the
sublevels of that path. It takes two arguments:
o path: Select which tag group to browse. To browse the root path, this argument
should be ‘/’. The path must end with a trailing ‘/’.
o options.recurrent: If true, the result will also include tags and groups in the sub-
levels of the given path.
o options.flat: If true, returns an array with the full paths of all the tags at the given
paths (and in sub-levels if recurrent is set). This option only returns tags. It does not
return groups and as such, it cannot be used to list the groups in a given path.
Example:
$.logger.info(JSON.stringify(result));
The return value of this function is a promise that can resolve to either an array of strings
(if options.flat is set) or the following object:
type BrowseResultObject = {
tags: Array<string>,
groups: {
[name: string]: BrowseResultObject
}
}
www.vnodeautomation.com
I
49
$.api.tag.read
Example:
$.logger.info(JSON.stringify(tag));
The return value of this function is a promise that resolves to one of the following
objects, depending on the arguments:
type TagData = {
data: {
value: null|number|string|boolean,
quality: number,
ts: number
},
status: {
value: 0|1,
ts: number
}
}
type GroupReadResult = {
groups: {
[name: string]: GroupReadResult
},
tags: {
[name: string]: TagData
}
}
www.vnodeautomation.com
I
50
$.api.tag.details
Function prototype: $.api.tag.details<T>(path: string, {recurrent: boolean, filter: string}):
Promise<TagDetails<T>|GroupDetailsResult<T>>
This function retrieves details about a tag or tags present in a tag group. It takes two
arguments:
o path: Selects the tag or group that will be queried for details. If the path is a group,
it must end in ‘*’.
o options.recurrent: If true, the details of the tags in the sub-levels of the given group
will also be retrieved. This only applies when the path is a group.
o options.filter: When present, only tags that match the filter will be queried. This is
a string that will be converted to a regular expression with the "ignore case" flag
set.
Example:
const details = await $.api.tag.details("/*", {
recurrent: true,
filter: "Turbine",
});
$.logger.info(JSON.stringify(details));
The return value of this function is a promise that resolves to one of the following objects,
depending on the arguments:
o If the path refers to a group, it resolves to GroupDetailsResult<T>.
o If the path refers to a tag, it resolves to TagDetails<T>.
type GroupDetailsResult<T> = {
groups: {
[name: string]: GroupDetailsResult<T>
},
tags: {
[name: string]: TagDetails<T>
}
}
www.vnodeautomation.com
I
51
type TagDetails<T> = {
fullPath: string,
remote: null|string,
status: {
value: 0|1,
ts: number
},
data: {
value: null|number|string|boolean,
quality: number,
ts: number
},
config: {
clientAccess: "R"|"RW",
deadband: "string",
default: string,
description: string,
engUnits: string,
format: null|string,
persistency: 0|1|2,
security: {},
simulation: {
enabled: boolean
},
type: "number|string|boolean",
views: Array<string>,
extensions: {
ae: {
alarms: {
[name: string]: {
enabled: boolean,
description: string,
limit: number,
priority: 1|2|3|4,
mode: "ge"|"gt"|"le"|"lt"|"eq"|"ne"
}
}
},
history: {
enabled: boolean,
module: string,
config: {
deadband: string,
defaultMethod: "first"|"last"|"min"|"max"|"avg",
interpolation: "linear"|"step",
mode: "change",
rangeY: [min: number, max: number],
rate: [min: number, max: number]
}
},
scaling: {
enabled: boolean,
raw: [min: number, max: number],
eu: [min: number, max: number],
clamp: [min: boolean, max: boolean]
},
source: {
enabled: boolean,
module: string,
type: string,
config: TagConfiguration<T>
}
}
}
}
www.vnodeautomation.com
I
52
$.api.tag.history
Function prototype: $.api.tag.history(tag: string, start: number, end: number, options:
{mode: "raw"|"aggregated"|"filter"|"delta", method?: null|"first"|"last"|"min"|"max"|"avg",
interval?: number, deadband?: number}): TagHistory
This function is used to query historical data from a tag. It takes four arguments:
o tag: Selects the tag that will be queried for historical data.
o start: Selects the start date of the query. This is a date in UNIX Epoch format with
milliseconds.
o end: Selects the end date of the query. This is a date in UNIX Epoch format with
milliseconds.
o options.mode: Selects how the data is retrieved. More information about the
different ways of retrieving data can be found in vNode Historian’s User Manual.
o options.method: Selects the aggregation method that is used when retrieving the
data (only applies when the mode is "aggregated"). If set to null, it uses the method
defined in the tag configuration. More information about the different aggregation
methods can be found in vNode Historian’s User Manual.
o options.interval: Selects the aggregation interval, displayed in milliseconds (only
applies when the mode is "aggregated").
o options.deadband: Selects the deadband used when retrieving the data (only
applies when the mode is "delta" or "filter").
o options.invalidAsNull: Converts non-good quality values to null when using raw
mode (optional parameter, by default it is enabled).
o options.limit: Maximum number of samples to return when using raw mode
(optional parameter)
Example:
$.logger.info(JSON.stringify(history));
The return value of the function is a promise that resolves to the following object:
www.vnodeautomation.com
I
53
type TagHistory = {
request: {
tag: string,
start: number,
end: number,
options: {
remoteNode?: true|string|string[],
mode: "aggregated"|"raw"|"filter"|"delta",
method?: "first"|"last"|"min"|"max"|"avg",
interval?: number,
deadband?: number
},
data: Array<[ts: number, value: null|number|string|boolean]>
}
}
TagHistory.request is a copy of the arguments that were passed when executing the
historical request.
$.api.tag.write
o value: Selects the value that will be written to the tag. The type must match the tag
type, otherwise, the write may fail or the written value might not be correct.
Example:
$.api.tag.getViews
This function retrieves the views available in the current node. It takes one argument:
The return value of this function is a promise that resolves to an array of strings containing
the views available in the current node.
www.vnodeautomation.com
I
54
Example:
$.api.tag.update
This function is used to generate an update event on a Scripting source tag using its tag
path (it cannot be used to update tags whose source is not Scripting). It takes five
arguments:
o tag: Sets the path of the tag that will be updated. If the path is invalid or the tag is
not a Scripting source tag, a warning will be logged and the tag will not be updated.
o value: Sets the value of the tag update event. The type depends on the type of the
tag and if the types do not match, it is implicitly converted, if possible. This is not
recommended, since implicit conversion is not always valid ("hello world" can't be
converted to a number) and can result in invalid values.
o quality: Sets the quality of the tag update event. This value is optional and if not
provided, the tag will be automatically updated with good quality (192). vNode uses
an enum for the different qualities that can be found at $.qualityCodes. However,
any number in the 0-255 range is valid.
o ts: Sets the timestamp of the tag update event. The format is a number in UNIX
Epoch with milliseconds. This value is optional and if not provided, the event
timestamp will be set to the current time.
o force: If set, the function will always generate a new tag event, even if the value or
quality does not change. Otherwise, a tag event will only be generated if the value
or quality changes.
Example:
www.vnodeautomation.com
I
55
$.api.tag.updateAlias
This function is used to generate an update event on one or various Scripting source tags
using its tag alias (since multiple tags can have the same alias, it can be used to update
multiple tags at once with the same value). It takes five arguments:
o alias: Selects the alias that will be used to generate tag events. All of the tags with
matching alias will be updated. If the alias is non-existent, a warning will be logged
and the tag will not be updated.
o value: Sets the value of the tag update event. The type depends on the tag type
and if the types do not match, it is implicitly converted, if possible. This is not
recommended, since implicit conversion is not always valid ("hello world" can't be
converted to a number) and can result in invalid values.
o quality: Sets the quality of the tag update event. This value is optional and if not
provided, the tag will be automatically updated with good quality (192). vNode uses
an enum for the different qualities that can be found at $.qualityCodes. However,
any number in the 0-255 range is valid.
o ts: Sets the timestamp of the tag update event. The format is a number in UNIX
Epoch with milliseconds. This value is optional and if not provided, the event
timestamp will be set to the current time.
o force: If set, the function will always generate a new tag event, even if the value or
quality does not change. Otherwise, a tag event willonly be generated if the value
or quality changes.
Example:
$.api.tag.browseSource
This function returns all the Scripting source tags present in the given path. It takes two
arguments:
o path: Selects the path that will be browsed. This path must start and end with a “/”.
Otherwise, the browse will fail.
o options.recurrent: When set, it will return tags from the given group, as well as any
sub-levels that are present. Otherwise, only tags present in the given group will be
returned.
www.vnodeautomation.com
I
56
This function returns a promise that resolves to an array of tag paths for all the tags that
were browsed.
Example:
$.api.tag.browseAlias
This function is used to retrieve all of the tag aliases and the tags that they refer to that are
present in the tag models' Scripting source tags. It takes no arguments and returns a
promise that resolves to the following object:
type TagAliasList = {
[alias: string]: Array<string>
}
Example:
$.logger.info(JSON.stringify(aliases));
$.api.tag.subscribe
This function is used to subscribe to tag events from a list of tags. It takes three arguments:
o tags: Selects tags that are part of the subscription. If only one tag is needed, an
array of one element must be used.
o Handler: Sets the callback that will be called whenever the given tags emit an
update event. The callback will be called with the following arguments:
www.vnodeautomation.com
I
57
▪ initial: If true, it indicates that the event was received in response to a new
subscription (such as when the tag model changes). Otherwise, it's a normal
event.
This function returns a symbol, which can then be used to cancel the subscription by
calling $.api.tag.unsubscribe using the returned symbol.
Example:
$.api.tag.unsubscribe
Example:
$.api.tag.unsubscribe(sub);
$.api.alarm
$.api.alarm.get
This function is used to retrieve the tag alarms present in a given path. It takes two
arguments:
www.vnodeautomation.com
I
58
o path: Sets the path that will be browsed for alarms. This must refer to a tag group.
o options.recurrent: When set, alarms for the given group, as well as any sub-groups,
will be retrieved. Otherwise, only alarms present in the given sub-group will be
returned.
o options.filter.path: Sets a regular expression that will be used to filter alarms based
on their full path. If the regular expression matches, the alarm will be shown in the
result.
o options.filter.status: Select which alarms will be shown in the result based on their
status. This can be set to null to retrieve all alarms independently of status, or it can
be an array of numbers selecting which alarms to retrieve based on the following
criteria: This is an array containing one or more of the following status codes:
o options.filter.priority: Selects the minimum alarm priority that will be shown in the
result. A value of null or 0 will retrieve all alarms. Otherwise, one of the following
priority codes can be used:
• 0: Low priority
• 1: Medium priority
• 2: High priority
• 3: Critical priority
Example:
$.logger.info(JSON.stringify(alarms));
www.vnodeautomation.com
I
59
The return value of this function is a promise that resolves to an array of the following
object:
type TagAlarmInfo = {
path: string,
description: string,
priority: number,
remote: Nullable<string>,
online: 0|1,
status: 0|1,
ts: number,
value: tag.TagEvent,
format: Nullable<string>,
ackInfo: null | {
msg: string,
user: string,
options: {},
node: string,
module: string
}
}
$.api.alarm.count
This function is used to retrieve the number of alarms present at a given path that match
a filter (such as number of active and unacked alarms). It takes two arguments:
o path: Sets the path that will be browsed for alarms. This must refer to a tag group.
o options.recurrent: When set, alarms for the given group, as well as any sub-groups,
will be retrieved. Otherwise, only alarms present in the given sub-group will be
returned.
o options.filter.path: Sets a regular expression that will be used to filter alarms based
on their full path. If the regular expression matches, the alarm will be shown in the
result.
o options.filter.status: Selects which alarms will be shown in the result based on their
status. This can be set to null to retrieve all alarms independently of status, or it can
be an array of numbers selecting which alarms to retrieve based on the following
criteria: This is an array containing one or more of the following status codes:
www.vnodeautomation.com
I
60
o options.filter.priority: Selects the minimum alarm priority that will be shown in the
result. A value of null or 0 will retrieve all alarms. Otherwise, one of the following
priority codes can be used:
• 0: Low priority
• 1: Medium priority
• 2: High priority
• 3: Critical priority
The return value of this function is a promise that resolves to the number of alarms that
match the filter.
const count = await $.api.alarm.count("/", {
recurrent: true,
filter: {},
priority: 0,
});
$.api.alarm.history
This function is used to query historical alarm data. It takes four arguments:
o path: Sets the path that will be browsed for alarms. This must refer to a tag group.
o start: Selects the start date of the query. This is a date in UNIX Epoch format with
milliseconds.
o end: Selects the end date of the query. This is a date in UNIX Epoch format with
milliseconds.
o options.recurrent: When set, alarms for the given group, as well as any sub-groups,
will be retrieved. Otherwise, only alarms present in the given sub-group will be
returned.
o options.filter.path: Sets a regular expression that will be used to filter alarms based
on their full path. If the regular expression matches, the alarm will be shown in the
result.
o options.filter.status: Selects which alarms will be shown in the result based on their
status. This can be set to null to retrieve all alarms independently of status, or it can
be an array of numbers selecting which alarms to retrieve based on the following
criteria: This is an array containing one or more of the following status codes:
www.vnodeautomation.com
I
61
o options.filter.priority: Selects the minimum alarm priority that will be shown in the
result. A value of null or 0 will retrieve all alarms. Otherwise, one of the following
priority codes can be used:
• 0: Low priority
• 1: Medium priority
• 2: High priority
• 3: Critical priority
Example:
$.logger.info(JSON.stringify(history));
The return value of this function is a promise that resolves to the following object (where
request is a copy of the historical request):
www.vnodeautomation.com
I
62
type TagAlarmData = {
path: string,
description: string,
priority: number,
remote: Nullable<string>,
online: 0|1,
status: 0|1,
ts: number,
value: tag.TagEvent,
format: Nullable<string>,
ackInfo: null | {
msg: string,
user: string,
options: {},
node: string,
module: string
}
};
type TagAlarmHistory = {
request: {
path: string,
start: number,
end: number,
options: {
recurrent?: boolean,
filter: {
path?: string,
status?: Nullable<Array<number>>,
priority?: Nullable<number>
}
}
},
data: Array<TagAlarmData>
};
$.api.alarm.ack
This function is used to acknowledge one or multiple alarms with a message and the user
that executed the acknowledgement. It takes three arguments:
o paths: Selects which alarm will be acknowledged. It can be either a single alarm, or
a list of alarms. The path must be a path to the specific alarm that will be
acknowledged, not a path for the tag that declares the alarm (alarm paths are
formed of TAG_PATH.ALARM_NAME). For example, if the tag
/C01/TemperatureAlarm has a “HiHi" alarm, the path of the alarm would be
/C01/TemperaturaAlarm.HiHi
o (Function) callback (err): This callback will be called once the acknowledgement
request finishes. It has the following arguments:
www.vnodeautomation.com
I
63
Example:
$.qualityCodes
This enumeration provides different OPC quality codes that can be used to compare
against the quality value of a tag. The different qualities, along with their values are:
$.qualityCodes = {
www.vnodeautomation.com
I
64
cron library
cron is an internal vNode library used for both validation of cron syntax, as well as parsing
and retrieving the next (or several future) time(s) when the expression must execute.
When retrieving this library, an object will be returned with two keys; one which acts as
cron expression validation and the other as a scheduler.
The validate function is used to validate a cron expression. This function is a simplified
version of cron-validate, where it only takes a single string argument (no options required).
The return type is the same as cron-validate since it returns a Result-type. An example of
the validate function can be seen in the below code snippet:
Schedule
The schedule key contains the default export for the cron-schedule library. As such, any
code that is valid with that library is equivalent to using cron.schedule. The next code
snippet shows an example of how to get the next value assigned a cron expression:
www.vnodeautomation.com
I
65
xlsxwriter library
xlsxwriter is an internal vNode library that can be used for basic data ingestion to Microsoft
Excel XLSX files. The library exports the following functions and classes:
Workbook
The workbook class represents an XLSX workbook, which is composed of one or several
sheets. This class can't be directly constructed. Instead, a new Workbook is created using
the static asynchronous Open method. Workbooks have the following methods:
This static method is used to open a new XLSX workbook at a given path.
This method is used to retrieve a worksheet from the current workbook. In order to select
which worksheet will be retrieved, a worksheet id must be provided. This can be either a
number, in which case it's the index of the worksheet, or a string corresponding to the
name of the worksheet.
setCalculateFlag(): Promise<void>
This method sets the "calculate on open" flag on the workbook. When set, the next time
the workbook is opened in Microsoft Excel, all of the cells of the workbook are recalculated.
If not set, the cells will keep their current cached values. If a cell is affected by a
modification using this library (whether it's directly affected or one of its dependencies is
affected), this flag must be set, otherwise the modification won't be propagated.
Worksheet
The worksheet class represents a worksheet in the current workbook. This class can't be
directly constructed. Instead, an instance of it is created by the getSheet method of the
workbook. It has the following methods:
This method writes new data to the worksheet, overwriting any existing data. It takes the
following arguments:
• data: Data that will be written to the worksheet as an array of rows, where each row
is also an array.
• startRow: Selects which column will be written as the first row of the data. The data
will write rows, starting from startRow up to the length of each row in data.
• startColumn: Selects which column will be written as the first column of the data.
The data will write columns starting from startColumn until it has written all the
columns in data.
www.vnodeautomation.com
I
66
This method appends new data to the worksheet, keeping any existing data if the cells
already contain data. It takes the same arguments as writeData.
Scripting supports the use of any third-party libraries with the following limitations:
• Native libraries can or cannot work depending on how they interact with the Node.js
runtime. In general, N-API libraries and NAN libraries that are declared as “context
aware” should work, but it depends on the implementation of each library.
Node.js version 12.22.12 must first be installed first on the host machine in order to install a
new third-party library and all of its dependencies from the NPM using just one single
command. The following sections show how to install Node.js 12.22.12, as well as how to
install NPM libraries.
• Download the installer from https://nodejs.org/dist/v12.22.12/. There are two versions for
Windows, one for 32-bit (node-v12.22.12-x86.msi), and one for 64-bit OS, located in the x64
folder(node- v12.22.12-x64.msi). The recommended one is the 64-bit version.
www.vnodeautomation.com
I
67
Click next until the Custom Setup window is opened. Include NPM package manager in
the features to install. It is also advisable to add Node.js to PATH:
Keep clicking next until Node.js finishes installation. It will then be possible to test if that
node has been successfully installed by opening a command prompt, and running the
following command to get the Node.js version installed: node --version.
www.vnodeautomation.com
I
68
In this example, the got library will be installed in the vNode node.
1. The first step is to search for the NPM got library, which in this case is located at
https://www.npmjs.com/package/got. Since the library must be compatible with Node
12.22.12, the package.json file of the library must be checked to see if it lists the minimum
compatible version of Node.js. This file can be found by navigating to the repository of the
library:
2. In the repository, the package.json file can be checked to see if it lists the minimum
supported Node.js version. This property is not mandatory, so some libraries might not have
it, but since it's good practice to include it, most will have it.
www.vnodeautomation.com
I
69
3. Within this package.json file, the keyword “engines” can be found using the search function.
This keyword is used to indicate the minimum node version supported by the library,
although, as mentioned earlier, this field is not required. If this keyword search returns no
results, the only way to test whether the library is compatible with Node.js 12.22.12 is by trial
and error, i.e. by installing the library and trying to use it. The following screenshot shows that
the current version of the library requires a Node.js version higher than v.14.16, and therefore,
this library is not compatible with vNode.
www.vnodeautomation.com
I
70
4. Even though the current version is not compatible, an older version might be. Older versions
can be checked by checking the tags in the repository, until one of the older version is
compatible with vNode.
5. Checking the package.json of the 11.8.3 version shows that this version is compatible with
vNode:
www.vnodeautomation.com
I
71
6. In order to install the library, a command prompt in the destination folder (usually
vNode/data/Scripting) must be opened. Once it's open, the following command installs
the specific library and version:
www.vnodeautomation.com
I
72
After executing this command, the got library will be install to the node_modules folder
(which is created if it doesn't exist) in the Scripting data folder. In order to load the library,
a new external library must be created, and it's path has to point to node_modules/got.
www.vnodeautomation.com
I
73
Examples
Inserting tag values to a MySQL database
Scripting can be used to connect to MySQL by using the mysql internal library. More
information about internal libraries can be found at Libraries.
The following example shows how to insert each new value of a tag into one of the tables
in the database.
This assumes a database and a table are already created with the following schema:
In order to insert the events, two scripts will be created, one serving as wrapper over the
raw MySQL connection (as a static library), and one startup script that will subscribe to
events and export them to the database.
www.vnodeautomation.com
I
74
//This function must be called when the client is no longer being used
//in order to terminate the connection
dispose(){
return new Promise((resolve, reject) => {
if(this._client){
//If the client is online, end the client
this._client.end((err) => {
if(err){
reject(err);
} else {
resolve();
}
this._client = null;
})
} else {
reject(new Error("Connection already terminated"));
}
});
}
www.vnodeautomation.com
I
75
}
//Static method used to asynchronously create a new client, which is necessary
since creating a connection
//is an asynchronous operation
static Connect(connOpts){
return new Promise((resolve, reject) => {
//Create the client with the provided options
const client = mysql.createConnection(connOpts);
//Connect the client to the DB
client.connect(err => {
if(err){
reject(err);
} else {
//If the connection is OK, create a MySqlConnection instance using the
client
//and resolve the promise with that instance
const connection = new MySqlConnection(client);
resolve(connection);
}
});
});
}
}
www.vnodeautomation.com
I
76
The startup script that relies on the library and is responsible for sending the event uses
the following code:
//Handler that gets called whenever the tags have a new event
function onTagEvent(tag, data){
//Save the event to the buffer
events.push({tag, value: data.value, quality: data.quality, ts: data.ts});
}
//Async function called every PERIOD milliseconds to insert data into the DB
async function pushEvents(){
//If the client is null or offline, connect the client
if(!client || (client && !client.online())){
try{
await connect();
} catch (ex){
//If the connection fails, schedule a new timer
$.logger.warn("Error connecting: %s", ex.message);
return setTimeout(pushEvents, PERIOD);
}
}
www.vnodeautomation.com
I
77
//If the client is connected, remove the events from the buffer
//and transform them into a format that can be used by MySQL
const ev = events.splice(0).map(el => {
//Set number_ev, string_ev and bool_ev either to the event
//or to null if the type does not match
const number_ev = (typeof el.value === "number")?el.value:null;
const string_ev = (typeof el.value === "string")?el.value:null;
const bool_ev = (typeof el.value === "boolean")?el.value:null;
//Return a 6 element tuple representing the values that will be inserted into
the DB
return [el.tag, number_ev, string_ev, bool_ev, el.quality, new Date(el.ts)];
});
try{
$.logger.debug("Inserting %d events", ev.length);
//Execute an INSERT query using ? as placeholder for the values
await client.query(`INSERT into tag_events (tag, number_value, string_value,
bool_value, quality, ts) VALUES ?`, ev);
$.logger.debug("Inserted OK", ev.length);
} catch (ex){
$.logger.warn("Error during query: %s", ex.message);
//If the query fails and the client is offline, null the client
if(!client.online()){
client = null;
}
} finally{
//After finishing the query (whether it was successful or not)
//schedule a new timer
setTimeout(pushEvents, PERIOD);
}
}
www.vnodeautomation.com
I
78
This example reads data from a Microsoft SQL Server database and saves it to Scripting
source tags. This is done using the mssql NPM library, which is integrated in vNode (and
thus can be used as an internal library).
This example assumes the target table has the following schema, and that it's data it's being
updated from an external source:
This data will be saved to Scripting source tags using an alias, this allows the tags in vNode
to have a different structure to those in Microsoft SQL Server. A configuration of a source tag
can be seen in the next screenshot:
www.vnodeautomation.com
I
79
This example will use two scripts (a periodic script and a static library) as well as an internal
library. The following two libraries are used:
www.vnodeautomation.com
I
80
//This function must be called when the client is no longer being used
//in order to terminate the connection
dispose(){
if(this._client){
this._client.close();
this._client = null;
} else {
throw new Error("Connection is already closed");
}
}
//Checks whether the client is online or not
online(){
return this._client !== null;
}
}
//Static method used to asynchronously create a new client, which is necessary
since creating a connection is an asynchronous operation
static async Connect(connOpts){
//Create the client with the provided options and connect with DB
const client = await mssql.connect(connOpts);
//If the connection is OK, create a SqlServerConnection instance
//using the client and return it
return new SqlServerConnection(client);
}
}
www.vnodeautomation.com
I
81
The periodic script has a 10 second trigger, and it's used to retrieve data from the database
and save it to the source tags. It has the following code:
//Retrieve the data, and exit the script after the async call is finish
await getData();
$.exit();
www.vnodeautomation.com
I
82
This example reads data from Historian, using the history API call, and stores it to a
template XLSX file that can be used for further data processing. This example will use the
following XLSX file:
The Processed Data worksheet contains an average function over all the rows (skipping
the first row, which are going to be used as the headers) of column B of _Data, while the
_Data worksheet is empty, and it will be automatically filled by vNode based on data from
Historian.
www.vnodeautomation.com
I
83
In order to have access to the XLSX writer library, an internal library instance must be
created:
Finally, the following script is used to retrieve events from Historian, and insert them as
well as the headers:
// Write the data, setting the startRow to 1 in order to not overwrite the headers
sheet.writeData(cellData, 1, 0);
www.vnodeautomation.com