Script Expressions

Script Expressions enable to you write your own custom scripts. They can be used in much more complex evaluation scenarios compared to regular event rules. JavaScript should be used as the scripting language.

Features

Some of the problems that you can solve with script expression: 

  • Combining complex AND/OR evaluations, since it is possible to use multiple variables in a single expression.
  • Preserve data between evaluations, and base the result of the current evaluation on a combination of current and historical data.

Setup

To use script expressions, follow these steps:

1. Go to Application Management, and enable _EditScriptExpression.

mceclip0.png

2. Save the application properties.

Setting up your Script Expression

1. Log in to your application.

2. Go to Admin > Event Rules.

3. Select + Event Rule to create a new event rule.

4. When you reach 4. Expressions, select Script Expression.

Screenshot 2024-08-14 at 13.29.03.png

5. Click on Edit to open the script editor.

Screenshot 2024-08-14 at 13.29.43.png

6. To develop your scripts, we recommend following these guidelines.

Screenshot 2024-08-14 at 13.54.37.png

7. When you're done with your script, click on Test Script.

8. Save your script.

9. Save your Event Rule.

Important

  • It is only possible to add one script expression per event rule
  • Script expressions are not available in end expressions. A single script allows you to control conditions for triggering and ending the event in fine detail, so this doesn't create a limitation.
  • Script expressions should return the result convertible to boolean type (true or false), denoting whether this condition for triggering the event is fulfilled. Note: returning values 0, empty string, null or undefined, or script throwing an error is equivalent to returning false, while returning non-zero values or defined objects is equivalent to true.
  • You can use fields.get(...) function to get values of variables mapped in step “3. Mapping” of the Device Mapper. The first parameter is the variable name, the second parameter is a default value that can be used if the variable does not exist (eg. if the device has never sent it). You should always handle this “missing variable” case to avoid evaluation errors. Note that used variables should be mapped for devices to which the Event Rule will be applied. Scripted variables mapped in step “4. Scripts” of the Device Mapper are accessible from Script Expression scripts.
  • You can use context.setState(...) to set the context.state object accessible from the script, which is preserved between separate evaluations. The parameter of setState can be any value or object defined in the script. State will be saved in JSON format. Note: JSON distinguishes only between Number, String, Boolean, Array, Object or null types; for types such as Date, the type information will be lost, while functions cannot be saved to state.
  • You can access track point data through the trackPoint object, e.g.
    var foo = trackPoint.position.longitude;
  • Try to write efficient code and avoid unnecessary instructions in the scripts.
  • There is an execution step limit for each script to prevent bad scripts from crashing the server.

Examples

Example 1: Create a notification when the speed of a vehicle changes

You could use this to know when the vehicle stops idling.

var velocity = trackPoint.velocity.groundSpeed;
var oldvelocity = context.state;
log('velocity: '+velocity);
log('oldvelocity: '+oldvelocity);

if (velocity !== oldvelocity)
{
context.setState(velocity);
return true;
} else return false;

Screenshot 2024-08-14 at 13.55.16.png

Example 2: Know when a vehicle is speeding only

-but only when speeding is happening continuously, over several received messages

We will use the trackPoint object to access speed data (trackPoint.velocity.groundSpeed) and context.state object to preserve information between evaluations. We will set a threshold of three received messages.

To check the speed, and if it crosses the threshold for the first time, we save the information that it happened once, but don’t trigger the event. If it happens again, we have the information that it already happened once in the state object, and we update the state to denote the critical level, but still don’t trigger the event. If it happens the third time, we will see that the state is on critical, and now we will trigger the event.

Finally, if, at any point, the speed goes under the limit, we need to reset the state. We can use a script that looks like this:

---

var speedLimit = 23; // speed in meters/second

if(trackPoint.velocity.groundSpeed > speedLimit){
// speed is over the limit

if(context.state == 'once') {
context.setState('critical');
return false;
}
else if (context.state == 'critical') {
return true;
}
else {
context.setState('once');
return false;
}
}
else {
// speed is not over the limit
context.setState('');
return false;
}

Screenshot 2024-08-14 at 13.57.51.png

Example 3: Calculate the time difference between messages

The following script will get triggered when the difference in time between two different device position reports is surpassed.

---

var d = new Date(trackPoint.utcTimestamp);
var newTime = d.getTime();
var oldTime = context.state;
var limit = 5000; //time in milliseconds

log('newTime: ' + newTime);
log('oldTime: ' + oldTime);

if (!context.state)
{
context.setState (newTime);
log('check1');
}

if ((newTime - oldTime) > limit) // if it's more than the limit then this expression should be true
{
return true;
log('check2');
} else {
context.setState (newTime);
log('check3');
return false;
}

Screenshot 2024-08-14 at 13.58.37.png

Note: The Event Rule cannot be saved if the script contains errors.

Example 4: Query the road type (speeding expressions), and if the speed limit of that road exceeds the speed value set, trigger an alert:

---

var road_type = road.getRoad().type;
var speed = fields.get("Speed",0);
log(road_type);
if(road_type=='motorway' && speed>22,22) // 80kmh to m/s
{
  return true;

return false;

Example 5: tell the distance driven between different POI categories visited

Visit this article to see this solution.

Example 6: Calculate the daily distance and Maximum Speed of the day:

(read about this solution in the Customize the vehicle status panel with key daily statistics)

---

var local_time=new Date(trackPoint.utcTimestamp.getTime()-new Date().getTimezoneOffset()*60000);
log(local_time);
//If no state or a new day
if(!state || state == '' || (new Date(state.date) < local_time)){
var tonightMidnight = local_time;
tonightMidnight.setUTCHours(0,0,0,0);
tonightMidnight.setUTCDate( tonightMidnight.getUTCDate()+1);
var myObject = {
'date': tonightMidnight, //reset midnight tomorrow
'odometer': odometer, //Odometer value
'speed': speed //Speed
}
context.setState(myObject);
}
else
{
if(speed >= state.speed || state.speed =='')
{
state.speed=speed;
context.setState(state);
}
max_speed=state.speed * 3.6;
context.setVariable('Max_Speed', max_speed.toFixed(1));
context.setVariable('Daily_Distance', (odometer - state.odometer)/1000);
return true;
}
return false;

Example 7: detect fuel theft

The following script saves 8 consecutive fuel level measures and calculates the mean for the first 4 values and also the mean of the last 4 values.
If the difference is larger than the threshold specified, it would indicate abnormal fuel consumption.
By default, the script has a threshold of 3 (the difference between both means in liters). This value can be modified according to the fuel level signal inputs you receive from your device (liters/gallons). 

var threshold = 3; //the difference between both means in liters
var fuel = fields.get("Fuel level",0);
if(!context.state || context.state == ''){ //first time
var fuelarray = [fuel]; //add fuel values
context.setState(fuelarray);
}
else{ //not first time
var updatedArray = context.state;
if (context.state.length > 7){//calculate mean
var mean1 = 0, mean2 = 0;
for (var i = 0; i < 4; i++){
mean1 += context.state[i];
}
mean1 = mean1 / 4;
for (var i = 4; i < 8; i++){
mean2 += context.state[i];
}
mean2 = mean2 / 4;
if(mean1 - mean2 > threshold){
if(fuel != 0){
updatedArray.shift();
updatedArray.push(fuel);
}
context.setState(updatedArray);
return true;
}
if(fuel != 0){
updatedArray.shift();
updatedArray.push(fuel);
}
}
else{//add values
if(fuel != 0){
updatedArray[context.state.length] = fuel;
}
}
context.setState(updatedArray);
}

More on Testing

  • Use the log() function to produce debug information in the script editor output in test mode.
  • Use the device simulator to generate data for your tests. You can read more about this tool here.
  • You can use the terminal to view how the data is exchanged between the server and the tracker. You can read more about using the terminal here.