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:

  • point.tags.curVal (the current value)

  • point.tags.his (a boolean indicating whether or not the point is trended).

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:

  • v: (the current value of the point, otherwise referred to as curVal)

  • t: (timestamp)

emit

Allows you to add to the trend value. You can pass the following:

  • v: (the current value of the point, otherwise referred to as curVal)

  • t: (timestamp)

state

An empty JSON object that can be used to save information.

toolkit

A set of JavaScript libraries, including:

  • Moment (a data and time utility library)

  • Lodash (a modern JavaScript utility library delivering modularity, performance, and extras)

 

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;

}

}