Introduction¶
For conventions used for the documentation of the JavaScript functions see Conventions.
Server scripts can be written with the Server script editor and can be used in different ways, e.g. as script elements on nodes.
The JavaScript interpreter of atvise implements the following additional features:
- Control and diagnostic functions
Flow control and diagnostic
- globals object
Shared storage for scripts
- script object
Metadata of scripts
- server object
Server information and live backup
- opcua object
General operations for the OPC UA address space
- Ua functions
Manipulation of OPC UA nodes and references
- Alarming functions
Manipulation of alarms
- ChildProcess functions
Starting and controlling child processes
- CSVReader functions
Reading of CSV data (into table)
- FileSystem functions
Manipulation of the file system
- InputFileStream functions
Reading files
- OutputFileStream functions
Writing files
- XMLDoc functions
Parsing of XML documents
- HTTPClient functions
Sending HTTP(S) requests
- SMTPClient functions
Sending emails via SMTPClient
- TCPClient functions
Handling TCP Connections
- ODBCClient functions
Handling ODBC Connections
- History functions
Writes data values into the history archive
- Archive locking functions
Archive information and locking
- XML export and import functions
XML export/import for nodes
- Access control functions
Handling access rights
- Data source functions
Browse, read and write for data sources
- Security functions
Handling user passwords
- Translation functions
Handling translations
Please note, especially when using atvise script extensions like TCP or ODBC: Only execute() is asynchronous. All other calls of methods of extension are synchronous.
Definition
In atvise, scripts are stored in nodes, as is all other information. Nodes containing script must be of type "VariableTypes.ATVISE.ScriptCode" so that they are recognized by atvise as a script. Creating scripts using the menu item "Add Script …" will automatically use this type.
Location
Scripts can be stored below an arbitrary node in the address space. However, some special scripts must be stored at predefined locations.
- webMI callable scripts
These scripts must be located at the Node SYSTEM.LIBRARY.PROJECT.WEBMIMETHODS. In atvise builder, these scripts are below "webMI Method scripts".
- Scripts callable via HTTP
These scripts work like any other atvise resource (static content delivered by the integrated web server) and are therefore below System.Resources. They can be managed directly in the Resources tree.
- Script libraries
Script libraries are scripts that contain common code that can be called by any other scripts. Frequently used code can be implemented in a standalone script and stored at a predefined location.
The default location for script libraries is SYSTEM.LIBRARY.PROJECT.SERVERSCRIPTS (in the tree below the "Script Library"). Scripts that are in this folder can be called by their names as well. By means of folders, the library can be structured thematically, for example.
In addition to the default location of script libraries, script libraries can be located at arbitrary nodes. In this case, the script can be called by its full nodeID.
- Scripts triggered by timer
Scripts that are triggered by timers can be anywhere in the address space. It is recommended, however, that scheduled scripts are stored in a common folder.
- Scripts with relative addressing
Scripts that have relatively addressed parameters can only be accessed by node parameters that are hierarchically below the base node. A script may be triggered by several relatively-addressed nodes. All of these triggering node parameters must have one common ancestor, that is the base node. In most cases, this will be the direct object type or a folder in an object type.
Script Name
The name of scripts can be freely chosen. For scripts that are invoked via a webMI call, the name must begin with a capital letter, however.
Script Editor
The editor for the script code will be opened by double-clicking on the node that contains the script.
A script consists of two parts: the definition of the parameters that are passed on to the script when you call them and the actual JavaScript code.
Script Editor: Parameters
All scripts have an implicit parameter called "base" that can be accessed in the script. For scripts triggered by the atvise server, "base" is an object with following properties:
nodeid (String) – The nodeID of the base node of the script (e.g. the instance where the script is currently running)
trigger (Object) – An object specifying the parameter that triggered the script:
name (String) – The name of the parameter
type (String) – Type of the parameter
However, if a script calls another script via call(), only the content of "base.nodeid" will be passed as "base" to the called script. In any case, "base" can be used to create a valid Ua object with Ua.findNode(base) (see Ua functions).
All other parameters are defined in the upper part of the editor. The definition of a parameter consists of the name and the type of the parameter.
Following types are available:
- alarm
The alarm parameter is an alarm condition object. This parameter will be set, if the alarm status of a matching alarm condition changes.
Hint
The script will be triggered for every single change of the alarm status. Besides becoming active or inactive, such a change can also be e.g. shelving, commenting or deleting the alarm condition.
For a list of properties of the alarm object see Alarm object properties.
- boolean
boolean
- numeric
numeric value
- string
string
- node
The node parameter is a Node object with the properties: value, status, sourcetime, servertime and trigger (true, if the node triggered the script, otherwise false). The properties can be accessed via dot notation. If the specified node doesn't exist or is not a variable, the parameter is null.
- node.value
OPC UA value of the node. If the specified node doesn't exist or is not a variable, the parameter is null.
- node.status
OPC UA status of the node. If the specified node doesn't exist or is not a variable, the parameter is null.
- node.sourcetime
OPC UA source timestamp of the node. If the specified node doesn't exist or is not a variable, the parameter is null.
- node.servertime
OPC UA server timestamp of the node. If the specified node doesn't exist or is not a variable, the parameter is null.
- timer
The script runs daily on one or more specified times. A start or end date can be set optionally. The repetition time refers to one day and will be considered if the calculated time is in the range 00:00:00 to 23:59:59. The start time and end time are given in local time. The end time is exclusive, so the script is not triggered on this day if the triggering time is greater than or equal to the end time. Triggering times calculated from start time and repetitions are in local time as well. So if daylight saving time changes on a day then the day has either duplicated or non-existent times. The calculated triggering timestamps are in local time as well, so daylight saving time changes influence the triggering times: If a timestamp is duplicated on a day the calculated triggering timestamps will trigger on both timestamps. If a timestamp does not exist on a day then the script will be not triggered at that time stamp. See Scheduling rules.
Hint
Scripts which are triggered by a timer are released once the entire system is up!
Hint
Days on daylight saving time changes do not have 24 hours. They have either 23 or 25 hours.
- interval
The script runs daily on one or more specified times. A start or end date can be set optionally. The first daily triggering time is specified by offset. The number of triggering times is limited by count - or the end of the day - and the timespan between triggering times is given by interval. The offset is specified in standard time. Standard time does not take into account daylight saving time changes. So the triggering times will be shifted by one hour if daylight saving time is on. See Scheduling rules.
Hint
In standard time all days - including those with daylight saving time changes - have 24 hours.
- once
The script runs once at the specified timestamp in local time.
- startup
The script will start when the atvise server starts.
Hint
Scripts of this trigger type are triggered during the startup process before the WebAccess module and thus before the entire system is up!
- shutdown
The script will start when the atvise server is shut down. The atvise server will not be stopped until the script has finished.
- http
The http parameter is an object with the properties request, response, ip and session. See below for a description of the properties. It is only available when the script was called from an HTTP client.
- http.request
The request object. It has the following properties:
query (String) – The full query string of the URL from which the script is called
content (String) – The complete content (body) of the HTTP request
getvalues (Object) – A JavaScript object with all the parameters of a GET request as properties of the object
postvalues (Object) – A JavaScript object with all the parameters of a POST request as properties of the object
headers (Object) – A JavaScript object with all HTTP header fields as key-value pairs (e.g.: "headers":"Accept":"/", "Accept-Encoding":"gzip, deflate, br", "Accept-Language":"en-US;q=0.7",…})
- http.response
The response object. Allows to set HTTP header lines via setHeader(name, value) and writing the content via write(data).
- http.ip
IP address of the HTTP client.
- http.session
The session object. It has the following properties:
authentication (String) – Authentication type ("basic", "digest", "negotiate", "ntlm");
status (String) – Authentication state ("NotAuthenticated", "Authenticated", "InvalidUserOrPassword", "AuthenticationServiceError", "AuthenticationSecurityError")
realm (String) – Authentication realm
user (String) – Authenticated user or "null"
uri.path (String) – Request URL
uri.query (String) – Request query
client.ip (String) – IP address of the HTTP client
client.port (Number) – Port of the HTTP client
host.name (String) – Name of the HTTP server
host.ip (String) – IP address of the HTTP server
host.port (Number) – Port of the HTTP server
id (Number) – Session ID
clientToken (String) – Session client token (no empty string if /webMI/?createsession was called before)
Example for a script parameter with name h of type http:
console.log(h.request.ip);
h.response.write("Hello, world!");
Example for a script parameter with name req of type http.request:
console.log(req.getvalues["name"]); // passed as ?name=MyName
- session
The session parameter is an object with the property user. It is only available for scripts that are invoked via a webMI call.
- session.user
The login name of the user who is logged in to the browser.
Trigger: Is only relevant for parameters of the types node (including node.value, …), alarm, timer, interval, once, startup and shutdown. For node and alarm it indicates whether the script is triggered if the node or the alarm status changes. For timer, interval, once, startup and shutdown it is used to enable or disable the triggering of the script. Several parameters may be defined with triggering. Triggering a script by another parameter will set the parameters of type alarm, timer and interval to null.
Relative (
): Is only relevant for parameters of the type node (including node.value, …) and alarm and indicates whether the given address is relative to the base or an absolute NodeID.
Value: The content depends on the type of the parameter:
- alarm
Value is an OPC UA NodeID of the alarm condition in the so-called "XML" format (e.g.: "ns=1;s=AGENT.OBJECTS.TestNode.Alarm.Condition"). If you drag and drop nodes, the NodeID is entered correctly. For absolute NodeIDs (see description of Relative above) a GLOB pattern (supports the wildcards '*' and '?') can also be used.
- boolean, number, string
Value is a value of the appropriate type (true / false, integer / floating-point number or an arbitrary string). Value is passed on directly to the script. Such parameters are useful in scripts that are called by other scripts, because the value is used as default value if the calling script is not passing the parameter.
- node, node.*
Value is an OPC UA NodeID in the so-called "XML" format (e.g.: "ns=1;s=AGENT.OBJECTS.my_node"). If you drag and drop nodes, the NodeID is entered correctly.
- timer, once, startup, shutdown, session, session.*, http, http.*
Value is not used.
Hint
The types array, filecontent, stream, textfilecontent and uainput are meant for menu scripts only.
Script Code
JavaScript code can be written in the lower part of the script editor. All parameters defined by "parameter name" in the upper part and "base" can be used as a variable name in the code.
Return values (only for webMI call)
The return value of a call initiated by webMI scripts is always a JavaScript object. The type of the returned value determines the exact contents of this object:
- No return value
Empty JavaScript object (no properties)
- simple value or array
JavaScript Object with the property "result", which contains the value returned by the script
- JavaScript Object
The object is passed to the caller 1:1
Examples:
return "a value"; // {result: "a value"}
return [1, 2, 3]; // {result: [1, 2, 3]}
return {name: "hugo", age: 33}; // {name: "hugo", age: 33}
The access via client-side JavaScript to the above examples is:
webMI.data.call("ScriptName", {}, function(ret) {
ret.result; // "a value"
ret.result[1]; // 2
ret.name; // "hugo"
});
Error handling (only for webMI call)
If the script fails, an exception is thrown. If this is not captured in the script itself, then the following JavaScript object is returned to the caller:
{error: -1, errorstring: "error message"}
You can use the same error object for errors you want to return to the caller.
Attention
Negative error codes are reserved for internal use. Using negative error codes may lead to unexpected behavior of the visualization.
Calling a script from an HTTP client
Scripts that were created in Resources can be accessed directly through web browser input from a corresponding URL. A script named "myreport", for example, located in the folder "scripts", can be accessed via http://localhost/scripts/myreport. Parameters with ?par1=value1&par2=value2 are passed on to the script. A complete call could look like http://localhost/scripts/myreport?format=csv&type=summary.
Example 1: Return a simple report with historical data:
Create a script with the parameters request of type http.request and response of type http.response JavaScript code like:
// This script can be called with the corresponding parameters:
// node, max
// through a URL in a browser, e.g.:
// http://localhost/simplereport?node=instance.values.temperature&max=10
var par = request.getvalues;
var n = Ua.findNode("AGENT.OBJECTS." + par["node"]);
var numvalues = parseInt(par["max"]);
var data = n.result.dataHistory({
endTime: new Date(),
numValues: numvalues
});
// return web page
response.write("<html><head><title>Simple Report</title></head><body>");
// write report body...
response.write("</body></html>");
Example 2: Send a PDF file from the disk to the web client via "binary" mode of the "response.write" function:
var ifs = new InputFileStream("C:/temp/test.pdf", "binary");
ifs.open();
response.setHeader("Content-Type", "application/pdf");
response.write(ifs.read(0), "binary");
ifs.close();
webMI call
This method can be used in displays to call scripts and use the return value from scripts in the display itself.
Example for scripts to create an instance of an object type including a MirrorBase:
Client side script:
webMI.data.call("CreateInst", {
typedef: "Engine",
instname: "Engine1",
mirrorbase: "ds/ns=1;s=engines"
}, function(ret) {
console.log(ret);
});
Server side script "CreateInst" (with parameter request of type http.request):
// This script can be called with the parameters:
// typedef, instname, mirrorbase
// through webMI call.
var typedef = request.postvalues["typedef"];
var instname = request.postvalues["instname"];
var mirrorbase = request.postvalues["mirrorbase"];
var full_type = "ObjectTypes.PROJECT.MyTypes." + typedef;
var instance_base = "AGENT.OBJECTS.MYOBJECTS";
var full_name = instance_base + "." + instname;
var node = Ua.findNode(full_name);
node.createNode({
nodeClass: Ua.NodeClass.OBJECT,
parent: instance_base,
typeDefinition: full_type
});
var mirror = Ua.findNode(full_name + ".RelMirrorBase");
mirror.createNode({
nodeClass: Ua.NodeClass.VARIABLE,
parent: full_name,
typeDefinition: "VariableTypes.ATVISE.Mirror.Relative.Base",
dataType: Ua.DataType.STRING,
value: mirrorbase
});