20,919,685Total Points24,106Total Sites23,382Cell Towers69,500Racks Monitored56,753HVAC Units Monitored31,322UPS Units Monitored24,788Generators Monitored20,919,685Total Points24,106Total Sites23,382Cell Towers69,500Racks Monitored56,753HVAC Units Monitored31,322UPS Units Monitored24,788Generators Monitored20,919,685Total Points24,106Total Sites23,382Cell Towers69,500Racks Monitored56,753HVAC Units Monitored31,322UPS Units Monitored24,788Generators Monitored

Chapter 8: Scripting & AutomationLesson 44 of 65

How to Use Global Scripts for Reusable Functions

Global scripts are a shared function library that Mango by Radix IoT evaluates into the scripts it runs — what that means for your code, why they have no schedule, and where the scheduling actually lives.

  • 10 min read
  • Intermediate
  • Mango 4.x / 5.x

Overview

A global script is a shared function library, not a scheduled job. Mango by Radix IoT evaluates every global script into the scope of the scripts it runs — meta points, Scripting data sources, the set point and email handlers' scripts, and Excel report scripts — so the functions you define in one become available in all of them, with nothing to import. The one exception is the Script event handler, which runs on a different script service and does not load global scripts. Understanding that one mechanism explains everything else about them, including what you must never put in one.

Warning

Global scripts have no schedule. There is no cron field, no enabled toggle and no permission field on a global script, and nothing runs one on a timer. If you came here to schedule work, see Running something on a schedule below — the scheduled thing is a data source or a handler that calls your function.

Prerequisites

  • The SST Global Scripts module
  • A superadmin role — the page and its API are admin-only
  • Somewhere to call the function from: a meta point, a Scripting data source or an event handler

What a Global Script Actually Is

When one of those scripts is loaded, Mango concatenates the text of all global scripts and evaluates that block into the engine scope. A meta point or Scripting data source loads it once, when it starts; a set point handler, email handler or Excel report script loads it on every run. Three consequences follow, and they are the whole lesson:

  • Your functions are already in scope. A meta point can call celsiusToFahrenheit() as soon as it has loaded the global script that defines it. There is no import, no reference, no "mark as a utility". This is also the only route by which helper functions like avg() or clamp() become available to a script — and note that Mango ships none of them: the globalScripts table is created empty, so if a helper works on your instance it is because someone defined it here
  • Top-level code runs everywhere the block is loaded. A statement outside a function does not run on a schedule — it runs every time any of those scripts loads the block: each time a meta point or Scripting data source starts, and on every run of a set point, email handler or Excel report script. Across a whole instance, that adds up fast
  • A global script that throws takes everything with it. That evaluation happens inside every script's setup, so an exception thrown at the top level of one global script fails every script that loads the block: set point and email handler scripts on their next run, and each meta point and Scripting data source the next time it starts. After a Mango restart, that is all of them at once

Saving is safe in one important respect: a global script that does not compile is rejected at save time, so a typo cannot reach production. Code that compiles and then throws when evaluated is the case to be careful about.

Creating a Global Script

  1. Go to Data integration > Global scripts
  2. Click New global script
  3. Enter a Name
  4. Enter an XID. Mango's own prefix for these is GS_, so GS_UNIT_CONVERSIONS fits the convention
  5. Write your functions in the editor
  6. Click Validate to compile and check it
  7. Click Save

That is the entire form: Name, XID, the script editor, Save and Delete. Saving or deleting clears Mango's cached copy of the shared block. Set point, email handler and Excel report scripts pick up the change on their next run. A running meta point or Scripting data source keeps the version it loaded when it started, so restart (disable and re-enable) the ones that use the function.

Writing Shared Functions

Define functions and nothing else. This is the shape that works:

// GS_UNIT_CONVERSIONS
function celsiusToFahrenheit(c) {
    return (c * 9/5) + 32;
}

function clamp(value, low, high) {
if (value < low) return low;
if (value > high) return high;
return value;
}

Any meta point can then return celsiusToFahrenheit(sensor.value); with no further setup.

Danger

A global script is compiled unwrapped, so a return outside a function is a syntax error and the script will not validate. This is the opposite of a meta point script, which Mango wraps in a function for you and where a top-level return is required. Do not copy a meta point body into a global script.

Running Something on a Schedule

Put the logic in a global script function, then have one of these call it:

You wantUseHow it is scheduled
A script on a clock, producing valuesScripting data sourcePolling on, then an Update period, or Use cron with a Cron pattern. Use cron fills in * * * * * ?, which is every second, so replace it. With Polling off, the script runs only on its Updates context points. There is also an Execution delay(seconds)
A calculation refreshed on an intervalMeta data source pointTimer update event — start of minute, hour, day, week, month, year, or a cron pattern
A recurring reportExcel report templateIts own schedule and cron expression

The scripting data source also has its own Log Level, from None through Trace, which is the easiest way to get output from scheduled work without turning up logging globally.

Calling the Mango API

The global scripts editor has no context points, so a global script cannot reference context variables — your functions receive what the calling script passes them. The utility bindings are available in the calling script's scope, so a function you write can use them:

Finding points

// One known point by XID; returns null if there is no such point
var point = DataPointQuery.byXid("DP_BLDG_A_RTU_01_TEMP");

// Several points by RQL. Tags are queryable as tags.<key>.
// The default limit is 100 – add &limit(-1) for all of them.
var points = DataPointQuery.query(“eq(tags.site,Building-A)&limit(-1)”);

// A query returns a Java List: use size() and get(i), never length or [i]
for (var i = 0; i < points.size(); i++) {
var p = points.get(i);
if (p.runtime !== null) {
LOG.info(p.name + “ = “ + p.runtime.value);
}
}

Note

A point’s runtime is null when the point exists but is not running, so point.runtime.value throws on a disabled point. Checking that the point is not null is not enough — check runtime too, which is also how you detect a stopped point.

Writing a value

var point = DataPointQuery.byXid("DP_BLDG_A_SUMMARY_STATUS");
if (point !== null && point.settable && point.runtime !== null) {
    point.runtime.set(1);              // or set(value, timestamp[, annotation])
}

The write is set() on the point's runtime, and it throws if the calling script's roles are not allowed to set that point.

Calling an external service

// get(url, headers, parameters) -- all three arguments are required
HttpBuilder.get("https://api.example.com/data", {"Authorization": "Bearer token"}, {})
    .resp(function(status, headers, content) {
        var data = JSON.parse(content);
        LOG.info("Got " + data.length + " records");
        return true;
    })
    .err(function(status, headers, content) {
        LOG.error("Bad response: " + status);
    })
    .excp(function(exception) {
        LOG.error("Request failed: " + exception.getMessage());
    })
    .execute();

The body arrives as the content argument of the resp callback. A status of 200 goes to resp, anything else to err, and a local exception to excp.

The other bindings

  • DataSourceQuery — the same query(rql) shape for data sources
  • RuntimeManager — refresh, enable and disable points and data sources, and sleep(). It does not set values and it cannot change a polling interval
  • PointValueQuery — bulk history across several points, including rollups, delivered to a callback
  • JsonEmport — configuration import and export from a script
  • DateTimeUtility and UnitConverter — formatting, timezone offsets and unit conversion. Note the binding is UnitConverter, not the class name you may see elsewhere
  • LOG — trace, debug, info, warn, error, fatal

Logging and Debugging

  • Validate compiles the script and reports errors. It is the only action on the page — there is no Run button, because there is nothing to run on its own
  • Script output does not reach the main Mango log, and it goes wherever the caller's LOG goes. A global function has no log of its own. Called from a meta point it writes that point's metaPoint-N.log, and from a Scripting data source that data source's scripting-N.log (N is the internal id, not the XID), and only once the caller's Log Level is above None. Called from a set point or email handler's script, LOG output is discarded. Searching ma.log finds nothing either way — which looks exactly like a script that never ran
  • To test a function end to end, call it from the script that will use it and validate that script, where you have context points and a result

Permissions

A global script has no permissions of its own. Editing one requires superadmin, and when a function runs it runs with the script roles of whatever called it — so the same function can succeed in one meta point and throw a permission error in another. Grant roles on the calling script, not here.

Troubleshooting

IssueCauseFix
Nothing happens on a scheduleGlobal scripts have no scheduleCall the function from a Scripting data source that polls on an update period or a cron pattern, or from a meta point with a timer update event
Set point and email handler scripts fail right after a global script edit, and meta points and Scripting data sources after their next startTop-level code in a global script threw, and that block is evaluated in every script that loads global scriptsMove all executable statements inside functions and keep the top level to declarations only, then restart the meta points and Scripting data sources
A meta point or Scripting data source still runs the old version of a changed functionIt loaded the global scripts when it started; saving a global script does not reload them in a running scriptDisable and re-enable it
The script will not validateA return or other function-only construct at the top levelWrap it in a function; global scripts are not wrapped for you
No log outputLooking in ma.log, or the calling point's Log Level is NoneRaise the calling point's Log Level and read its own metaPoint-N.log or scripting-N.log. A set point or email handler script has no log output
A loop over query results does nothingpoints.length and points[i] on a Java listUse points.size() and points.get(i)
Permission error setting a pointThe calling script's roles cannot write itAdd the role to the calling script, and check settable first

Summary

Treat a global script as a library: define functions, keep the top level free of anything that executes, and call those functions from the place that has the trigger and the context. The scheduling lives on a Scripting data source or a meta point, the permissions live on the caller, the output lands in the caller's log, Validate is how you check your work, and a running meta point or Scripting data source sees a changed function only after a restart. Get the mechanism right and global scripts become the cheapest way to stop duplicating logic across a Mango instance.

Get free access to all 65 Mango by Radix IoT training lessons

One short form unlocks every lesson and its video in this browser.

This form is hosted by Zoho. It loads only after you enable support cookies or choose to load it below.

We honored your browser’s Global Privacy Control signal — optional cookies are off and nothing is tracked.