Overview
The Meta data source creates derived data points: points whose values are computed by a script from other points already in Mango by Radix IoT. A meta point reads no device. It reads its context points, runs your script, and stores the result like any other point value. Use it for unit conversions, for combining several inputs (a delta T, a weighted average), for conditional logic, or for totals.
Meta point scripts are JavaScript, and they run on the Mango server, not in the browser.
Prerequisites
- The Meta Data Source module installed (it is listed under Administration > Modules)
- At least one data source already collecting values
- Permission to create data sources (the Data source management system permission)
- Basic JavaScript
Step 1: Create the Meta Data Source
- Go to Data integration > Data sources and click New
- Set Data source type to Meta Data Source
- Enter a descriptive name (e.g., “Building A Calculations”) and save it
Info
A single Meta data source can hold many derived points. Group related calculations together for easier management. A new Meta data source and its points start disabled; enable them once the points are configured.
Step 2: Add a Meta Data Point
- On the data source’s Data points tab, click Add. Mango opens Create data point
- Name the point, then on the Meta data point section set Data type to what your script returns: Numeric, Binary, Multistate or Alphanumeric
- Leave Variable name as
myunless you have a reason to change it. It is the name this point uses for itself inside its own script
Step 3: Add Context Points
Context points are the existing points your script reads.
- Open the External context points drop-down and select one or more points. They can come from any data source, not only this one
- On each new row, type a Key: the variable name your script uses for that point (e.g.,
supplyTemp,returnTemp). Keys must be valid ECMAScript identifiers: start with a letter or underscore, and no spaces - Tick Updates context on each row whose new values should make the script run
Warning
Updates context starts unticked on every new row, and the Timer update event starts at None. With both left at their defaults, nothing ever triggers the script and the meta point never gets a value.
Note
Key and Variable name are different fields. The Key on each context row names a source point. Variable name names the meta point itself. Confusing them silently reads the wrong point.
Step 4: Choose When the Script Runs
Two settings trigger the script, and they work together:
| Setting | Options | What it does |
|---|---|---|
| Context event type | Update (default), Change, Logged | For rows with Updates context ticked: run on every new value, only when the value changes, or only when the value is logged |
| Timer update event | None (default), Start of minute, Start of hour, Start of day, Start of week, Start of month, Start of year, Cron pattern | Run on a schedule. Cron pattern adds a second field for the pattern |
A timer does not switch off context triggering. For a purely scheduled calculation, set the timer and untick Updates context on every row.
Execution delay(seconds) is a whole number of seconds and defaults to 0:
- At 0 the script runs immediately, on the thread that delivered the context value, so a slow script also slows the data source that fed it.
- Above 0, every context update restarts the countdown, and the script runs once no update has arrived for that many seconds. One or two seconds suits several context points from different data sources updating at nearly the same moment. If updates keep arriving faster than the delay, the script waits until they pause.
Step 5: Write the Script
Mango wraps the script body in a function, so it must return the new value. Each Key is an object with the point’s value and history:
var now = supplyTemp.value; // present value
var ts = supplyTemp.time; // its timestamp, epoch milliseconds
var prev = supplyTemp.lastValue(1); // previous logged value/time object, or null
var hourAgo = supplyTemp.ago(HOUR); // the value one hour ago
var avg15 = supplyTemp.past(MINUTE, 15).average; // numeric points: 15-minute average
Tip
ago() takes a time period, not a count of samples: p.ago(HOUR, 3) is the value three hours ago. p.ago(1) still runs, but it means one second ago and returns a bare value. For the previous sample use p.lastValue(1), and check it for null before reading .value or .time. On binary, multistate and alphanumeric points, past() and prev() return state counts and runtimes, not an average.
Unit Conversion (Fahrenheit to Celsius)
return (supplyTemp.value - 32) * 5 / 9;
Combining Multiple Points (Delta T)
return Math.abs(supplyTemp.value - returnTemp.value);
Conditional Logic (Operating Mode)
// Multistate result: 0=Off, 1=Heating, 2=Cooling
if (!fanStatus.value) return 0;
if (supplyTemp.value > returnTemp.value) return 1;
return 2;
Weighted Average
var totalFlow = flow1.value + flow2.value;
if (!totalFlow) return UNCHANGED; // no flow: keep the last value
return (temp1.value * flow1.value + temp2.value * flow2.value) / totalFlow;
Returning UNCHANGED leaves the point’s value as it is for that run. Returning null does not skip the run: Mango converts it to 0 (false for a binary point, an empty string for an alphanumeric one) and stores it as a real reading.
Step 6: Setting Custom Timestamps
By default the value is stored with the time of whatever triggered the run: the context value’s timestamp for a context update (even after an execution delay), or the scheduled time for a timer. To store it at a different time, assign epoch milliseconds to TIMESTAMP:
// Store the value at the start of the minute of the triggering update
TIMESTAMP = supplyTemp.time - (supplyTemp.time % 60000);
return (supplyTemp.value - 32) * 5 / 9;
Warning
TIMESTAMP must be milliseconds since the epoch. A value that is not a number is ignored, and a value in seconds stores the reading in January 1970.
Step 7: Data Type Conversion
Mango converts the returned value to the point’s Data type. Return a matching JavaScript type:
| Point Data Type | Script Return | Example |
|---|---|---|
| Numeric | Number | return 72.5; |
| Binary | Boolean | return temp.value > 80; |
| Multistate | Integer | return 2; |
| Alphanumeric | String | return "Zone A: " + temp.value; |
A result that cannot be converted raises a “Script result type error” event.
Step 8: Generate History (Backfill)
The Meta data source’s Generate history tab recomputes past values from the context points’ stored history, which is useful when you add a new meta point.
- Save the meta point, then open the data source’s Generate history tab
- Set From date and From time, To date and To time, and a Timeout (m)
- Tick Delete existing data in range if the range already holds values
- Click Generate history for data source, or select points on the Data points tab first and click Generate history for selected data points
Mango replays the context points’ stored values between the two dates (they default to the last month) through the script, and fires any Timer update event on schedule across the range. A context-triggered point gets no values where its context points have no stored history. On SQL point value stores, a range that already has values can end up with duplicates, which is what Delete existing data in range is for. set() calls during generation store values without sending anything to devices.
Warning
Generating history over a large range is resource-intensive. Keep the range to what you need and run it off-peak.
Script Logging and Debugging
LOG writes to the meta point’s own script log, not to ma.log. Set Log Level under the script editor first: it defaults to None, which logs nothing.
LOG.info("Supply: " + supplyTemp.value + " Return: " + returnTemp.value);
var delta = supplyTemp.value - returnTemp.value;
if (delta < 0) {
LOG.warn("Negative delta T detected: " + delta);
}
return delta;
The file is metaPoint-<id>.log in Mango’s logs directory, where <id> is the point’s internal numeric id, not its XID. With a log level set, the editor shows the file and adds Log file size (MB) and Log files to keep.
Verification
- Save and enable the point, then click Validate under the script. It runs the script once and reports the result, and it needs the point saved and enabled first
- Enable the data source and confirm the meta point’s value changes when a context point updates, or when the timer fires
- Check Events for any meta data source events
Troubleshooting
The meta point never updates
- Confirm at least one row has Updates context ticked, or a Timer update event is set. At their defaults, nothing triggers the script
- Confirm the Meta data source and the point are both enabled. Both start disabled
A “Context point disabled” event
- A context point is disabled, deleted, or on a disabled data source. Mango raises this event (Urgent by default) and removes that Key from the script until the point is back, so a script that uses the Key also raises a script error. Re-enable the point, or remove its row
Script error: “variable is not defined”
- The name in the script must match the row’s Key exactly (case-sensitive)
- Check for a “Context point disabled” event: a disabled context point’s Key is removed from the script
Generate history produces no results
- The context points must have stored history in the selected range
- Points whose logging type is Do not log have none
Performance issues with many meta points
- A slow script with Execution delay(seconds) at 0 delays the data source that delivered the value. Give it a delay, or run it on a timer
ago(),past(),prev()andlastValue()read stored history each time the script runs. Use them sparingly in scripts that run often- For expensive calculations, use a Timer update event instead of running on every context update