Scripting Data Source
The Scripting data source executes a single JavaScript (ECMAScript) script on a cron schedule and allows that script to set values on multiple data points in a single execution. It is similar to the Meta data source but differs in two important ways: the script runs at the data source level (not per-point), and it can set values on any of its points using the set() function rather than returning a single value. This makes it ideal for complex calculations that produce multiple outputs, simulation models, and coordinated multi-point updates.
The scripting engine uses the Rhino JavaScript implementation, providing a full ECMAScript environment without browser DOM objects. Script context (variables and their states) is maintained across executions for the lifetime of the data source runtime, enabling stateful computations.
Overview
| Property | Value |
|---|---|
| Module | mangoAutomation-ScriptingDS |
| Protocol | N/A (scripted) |
| Direction | Scripted |
| Typical Use | Advanced multi-point scripting with autonomous execution |
Prerequisites
- Knowledge of JavaScript for writing the data source script.
- Optionally, existing data points from other data sources to serve as external context inputs.
- Understanding of cron expressions for scheduling script execution.
Configuration
Data Source Settings
| Setting | Description |
|---|---|
| Name | A descriptive name for the data source. |
| XID | A unique identifier across all data sources. |
| Cron pattern | A cron expression that determines when the script executes. A cron pattern generator wizard is available by clicking the icon next to the field. |
| Execution delay (seconds) | Number of seconds to delay script execution after the cron pattern fires. This allows external context points to update in case of network or processing latency. The script still executes with the timestamp of when the cron pattern originally fired, not including the delay. |
| Sets Historical | When checked, the script can execute set directives even when the point being set already has a more recent value. Required for backfilling historical data. |
| Log level | Controls the level of log messages written to the script log file. Options include None (no logging), Trace, Debug, Info, Warn, Error, and Fatal. If set to None, no messages are written (although a log file may still be created). |
External Context
The External context allows points from other data sources to be included in the script's execution context.
| Setting | Description |
|---|---|
| Point | The external data point to include. |
| Variable name | The name by which the point can be referenced in the script. Must be unique across all context variables (both external and data source points). |
Script
The main script is an arbitrary JavaScript program. The execution context includes:
- All data source points (referenced by their configured variable names)
- All external context points (referenced by their configured variable names)
- POINTS -- a list of all point names included in the context (both data source and external), enabling dynamic lookup at runtime
- LOG -- a logging object with methods:
trace(),debug(),info(),warn(),error(), andfatal(), corresponding to Log4J log levels - Functions and variables from global scripts (automatically included)
The print() and println() functions are available for debugging during testing but are discarded during normal data source runtime.
Use the Validate button to test-execute the script without actually setting any point values. The values that would have been set are displayed in the results area below the script editor.
If global scripts are modified, the Scripting data source must be restarted to reload them.
Data Point Configuration
| Setting | Description |
|---|---|
| Variable name | The name by which the point object can be referenced in the script. |
| Data type | The Mango data type (Binary, Multistate, Numeric, or Alphanumeric). Values provided by set() are automatically coerced to this type where possible. |
| Settable | Whether the point can be set from outside the data source's script (e.g., from the UI or REST API). |
| Updates context | Whether setting this point's value triggers execution of the data source's script. Do not set values to points that update the context from within the script itself, as this will cause recursive execution. |
Setting Point Values from Scripts
The primary mechanism for updating point values is the set(value, timestamp) function on each point object:
// Set a numeric point to a value at the current execution time
myPoint.set(42.5);
// Set a point with a specific timestamp (epoch milliseconds)
myPoint.set(42.5, 1708099200000);
Key behaviors of the set() function:
- Local points (belonging to this data source) are updated directly.
- External points are set and annotated. External points can only be set if they are configured as settable.
- The value is coerced to the point's data type. If coercion fails, a data type error event is raised.
- The optional timestamp parameter is an epoch value in milliseconds. If omitted, the execution time (the cron fire time, not including the execution delay) is used.
Differences from the Meta Data Source
| Aspect | Meta Data Source | Scripting Data Source |
|---|---|---|
| Script scope | Per-point (one script per data point) | Per-data-source (one script for all points) |
| Output mechanism | Script return value | set() function calls |
| Multiple outputs | No (one value per script) | Yes (any number of set() calls) |
| Context persistence | Reset each execution | Maintained across executions |
| Disabled points | Raise "missing point" events | Do not raise events (but may cause script errors if not handled) |
Example: Lorenz Attractor Simulation
The following script implements the Lorenz equations. Three numeric points must be defined with variable names x, y, and z. A cron pattern of 0/2 * * * * ? runs the script every 2 seconds.
if (x.value == 0 && y.value == 0 && z.value == 0) {
// Initial point values
y.set(1);
}
if (typeof(rho) == "undefined") {
rho = 28;
sigma = 10;
beta = 8/3;
dt = 0.01;
}
dx = sigma * (y.value - x.value);
dy = x.value * (rho - z.value) - y.value;
dz = x.value * y.value - beta * z.value;
x.set(x.value + dx * dt);
y.set(y.value + dy * dt);
z.set(z.value + dz * dt);
Note the use of typeof() to check whether constants need to be initialized. Because the script context persists across executions, this pattern effectively initializes variables only on the first run after data source startup.
Common Patterns
Coordinated Multi-Point Calculations
When a single computation produces multiple related outputs (e.g., calculating both real power and reactive power from voltage and current readings), the Scripting data source is more efficient and maintainable than creating multiple Meta points with duplicate logic.
Simulation and Modeling
Use the persistent script context to maintain state variables for physical simulations, PID models, or finite state machines. The Lorenz attractor example above demonstrates how differential equations can be solved iteratively with state carried forward between executions.
Scheduled Data Processing
The cron-based scheduling allows scripts to run at specific times (e.g., midnight for daily calculations, the top of each hour for hourly aggregations). Combined with the execution delay, this ensures that upstream data sources have had time to complete their polls before the script runs.
Logging and Diagnostics
Use the LOG object to write diagnostic information to the log file during normal operation:
LOG.info("Processing started, x=" + x.value + ", y=" + y.value);
Set the Log level to the appropriate threshold to control verbosity.
Troubleshooting
Script Execution Errors
- Undefined variable -- ensure all referenced point variable names match exactly (case-sensitive) and that the points are enabled.
- Type coercion error -- the value passed to
set()must be convertible to the point's configured data type. - Recursive execution -- if a point with Updates context checked is set from within the script, the script will re-execute. This can cause infinite loops or unexpected behavior.
External Context Points
- The script executes even if external context points are disabled. If the script does not handle this condition (e.g., checking for null values), it may throw exceptions.
- Disabled local points (on this data source) do not raise "missing point" events as they do in the Meta data source, but accessing their values in the script may fail.
Stale Context After Global Script Changes
If you modify a global script, the Scripting data source must be restarted to load the updated global script definitions. Until restarted, the data source continues using the previous version.
Execution Delay Not Working as Expected
The execution delay postpones script execution but does not change the timestamp used for set() calls. The timestamp corresponds to the moment the cron pattern fired. If you need the timestamp to reflect the actual execution time, compute it explicitly within the script.
Related Pages
- Data Sources Overview — General data source and data point concepts
- Meta Data Source — Simpler derived points using script expressions on existing data
- Virtual Data Source — Generate simulated data for testing scripting logic
- SQL Data Source — Access external databases directly as an alternative to scripted database queries