Skip to main content
Documentation - Limelight XE™ - Tutorial
Tutorial
Monitoring Property Changes with Scripts

Quite often there are applications where object properties need to be reflected or processed only when they change value. This is very simple to do with Limelight XE™ via several language extensions.  However, first we need to discuss how the embedded scripting engine executes JavaScript code.

The ChakraCore engine is single threading and isolated from all other threads and processes... it runs in its own memory, but has access to the entire system object library.

Warning - Scripts run with administrator privileges and therefore have complete control of the system... they can alter any writeable property on any accessible object including those on other Limelight XE servers. This includes all connected hardware such as PLCs, access control components, video sources, etc.

There are several language extensions that are useful for monitoring properties for changes.

 

Looping and Checking Methods

We will discuss each method and show example code to clarify the use case.  The most easy to understand is the getProperty() and the getProperties() functions.  Both of these functions simply attempt to retrieve the value of the given property as a string.

Note - both functions return values as a string regardless of the value type. it is up to the implementer to convert the resulting string to the correct value type based on the use case.

Example using getProperty() to monitor a single property value

// example for monitoring a property with ace.getProperty()
// uses a single global variable named Test
(()=>{  // main script begins...
 // create GUID constant to global variables
 const globVarGUID = '{759161EB-1005-0010-0000-000000000000}';
 // clear console
 console.clear();
 // initialize the property value
 var test = ace.getProperty(ace.this.serverGUID, globVarGUID, 'Test');
 var test_current = test;
 // report the current value
 console.log('Test = ' + test);
 // wait for it to change
 while (test == test_current) {
  // wait 5 seconds
  ace.wait(5000);
  // get the current value
  test_current = ace.getProperty(ace.this.serverGUID, globVarGUID, 'Test');
 }
 // value has changed
  console.log('Test = ' + test_current);
}
)(); // end of main script...

Example using getProperties() to monitor multiple property values 

// example for monitoring multiple properties with ace.getProperties()
// uses two global variables named Test and Test2
(()=>{  // main script begins...
 // create GUID constant to global variables
 const globVarGUID = '{759161EB-1005-0010-0000-000000000000}';
 // clear console
 console.clear();
 // initialize the properties
 var obj = ace.getProperties(ace.this.serverGUID, globVarGUID);
 // make sure it is a valid object
 if (typeof obj != 'undefined') {
  // initialize
  var test = obj.Test;
  var test2 = obj.Test2;
  var test_current = test;
  var test_current2 = test2;
  // report the current value
  console.log('Test = ' + test);
  console.log('Test2 = ' + test2);
  // wait for it to change
  while ((test == test_current) && (test2 == test_current2)) {
   // wait 5 seconds
   ace.wait(5000);
   // get the current values
   obj = ace.getProperties(ace.this.serverGUID, globVarGUID);
   test_current = obj.Test;
   test_current2 = obj.Test2;
  }
  // a value has changed
  console.log('Test = ' + test_current);
  console.log('Test = ' + test_current2);
 }
 else {
  console.log('invalid object');
 }
}
)(); // end of main script...

System Monitoring Methods

Looping to monitor each property is inefficient and will waste CPU cycles, however there may be reasons to use this method.  A better approach is to let the system monitor the property for you.  This is done either by initiating a "wait until the property changes" method or to start a background task that calls the code back when something changes.

Here is a simple example to wait for a single variable value to change

// example for monitoring a property with ace.waitForProperty()
(()=>{  // main script begins...
 // create GUID constant to global variables
 const globVarGUID = '{759161EB-1005-0010-0000-000000000000}';
 // clear console
 console.clear();
 // get the current value
 var test = ace.getProperty(ace.this.serverGUID, globVarGUID, 'Test');
 // report it
 console.log('Test = ' + test);
 // now wait for it to change with a timeout of 10 seconds (if value changes sooner, it immediately returns)
 test = ace.waitForProperty(ace.this.serverGUID, globVarGUID, 'Test', 10000);
 // report current value
 console.log('Test = ' + test);
}
)(); // end of main script...

This works great and can be set to wait forever by omitting the timeout value (e.g. providing only the server GUID, object GUID and property name in the call). Note that waiting is a blocking method - that is, the script will stop execution until either a timeout or the property changes. A more sophisticated method is to use call-backs.  This makes it very simple to monitor multiple properties simultaneously.

Note - scripts run in a single thread so you must yield execution of the script for background tasks to function. This can be accomplished by calling ace.wait() with or without a timeout or simply exiting the main script.

Here is an example of using ace.notifyPropertyChange() and ace.clearNotify() functions

// example for monitoring a property with ace.notifyPropertyChange()
// create GUID constant to global variables
const globVarGUID = '{759161EB-1005-0010-0000-000000000000}';
// create a callback pass counter
var passes = 0;
// monitor two global variables named Test and Test2 - call back when either of them change value
var taskId1 = ace.notifyPropertyChange(NotifyCallback, ace.this.serverGUID, globVarGUID, 'Test');
var taskId2 = ace.notifyPropertyChange(NotifyCallback, ace.this.serverGUID, globVarGUID, 'Test2');
// return control to system to monitor for changes. Note: you can also use a timeout and loop to keep the
// script running if it needs to do other tasks.  use a while(true) {} loop with a ace.wait(timeout) call to accomplish
// this function.  Here, we just exit the main script which returns control to any pending tasks.

// callback function from ace.notifyPropertyChange().  Called when a property change notification is triggered. 
function NotifyCallback(task_id, serverGUID, objGUID, PropName, Value) {
 // report which property changed
 console.log('Task ID = ' + task_id);
 console.log('Server GUID = ' + serverGUID);
 console.log('Object GUID = ' + objGUID);
 console.log('Property Name = ' + PropName);
 console.log('New Value = ' + Value);

 // after 10 changes, prevent further object property changes from triggering this callback again
 // (note: remove the following lines to allow indefinite notifications on object property value changes) 
 passes++;
 if (passes >= 10) {
  ace.clearNotify(task_id1);
  ace.clearNotify(task_id2);
 }
}

 


About

Strasis Systems, LLC is a provider of software for command and control centers, data visualization, security and systems integration.