Virtual Point Program Examples
About Virtual Points
Virtual points enable building of complex logic on top of existing points in the system without the creation of additional points or complex control code on devices. A simple JavaScript function is executed on each update of the source point(s) and can produce one or more outputs for the virtual point. Virtual points are ideal for unit conversion, computing periodic averages or sums, or for running more advanced application-specific logic.
function run(device, point, latest, state, emit, toolkit){ /* device */ } |
Term from JavaScript program | Description |
---|---|
function run ( ) |
Takes in arguments (for example: point, device, etc.) and executes them each time the point is updated. |
point |
A JSON object that has properties, such as point.tags, which reflect Project Haystack. Examples:
Note: Examine the point object's available properties using Using Data Explorer. |
device |
Every point is associated with a device. The device scope is a JSON object that contains relevant tag values. Note: For the data structure, please search for the device in Using Data Explorer. |
latest |
A JSON object with the following keys:
|
emit |
Allows you to add to the trend value. You can pass the following:
|
state |
An empty JSON object that can be used to save information. |
toolkit |
A set of JavaScript libraries, including: |
Examples
Estimating Power
function run(device,point, latest, state, emit, toolkit){ emit({ t: latest.t, v: latest.v*115 }) } |
The first line contains variables coming into the function. For instance, latest is a variable containing the current time and value of the source point.
The second line emits variables out of the function.
latest.v is the value read from the real point.
v is the value you want the virtual point to be. This example is creating a rough estimate of power. The real point is measuring current. The virtual point will be 115 times the current reading.
The time is t.
The emit argument is a JSON object, which is a way of expressing name:value pairs. You can separate each pair onto its own line. Each name:value pair is separated by a comma.
The colon (:) is similar to an equal sign, so the name t is being set to latest.t. The value will typically be a calculation.
Binary Virtual Point to Indicate an Analog Point is Too High
function run(device,point, latest, state, emit, toolkit){ emit({ t:latest.t, v: latest.v > 80 }) } |
Continuous Sum (Sigma)
The sigma function sums all the values over time. Here we use state to persist sum and add whenever a point is updated.
function run(device, point, latest, state, emit, toolkit){ // Compute the continuity of all current values (Sigma Function) var sigma = 0;
if(state.sigma){ sigma = state.sigma; }
sigma+= latest.v;
emit({ v: sigma, t: toolkit.moment().valueOf() });
} |
Fahrenheit to Celsius
Here is a run function that applies the Fahrenheit to Celsius formula to the latest value:
function run(device, point, latest, state, emit, toolkit){ // Get the latest.v point in Fahrenheit and convert to Celsius; var c = (latest.v - 32) * (5/9); emit({ v: c, t: toolkit.moment().valueOf() }); } |
Celsius to Fahrenheit
Here is a run function that applies the Celsius to Fahrenheit formula to the latest value:
function run(device, point, latest, state, emit, toolkit){ // Get the latest point in Celsius and convert to Fahrenheit; var f = (latest.v *(9/5)) + 32; emit({ v: f, t: toolkit.moment().valueOf() }); } |
Weekly Average
Here is a run function that computes the average of the values updated for a week (Sunday-Saturday):
function run(device,point, latest, state, emit, toolkit){ // average if(state.sum == null) state.sum = 0; if(state.num == null) state.num = 0; if(state.t == null) state.t = toolkit.moment(new Date()).startOf('week'); state.num++; state.sum += latest.v; // only emit once we've passed the end of a day if(toolkit.moment(latest.t).startOf('week')!=toolkit.moment(state.t).startOf('week')){ emit({t: toolkit.moment(state.t).endOf('day'), v: state.sum/state.num}); state.t = null; state.num = null; state.sum = null; } } |