Scripted Trip and Idle report

Trip and idle data can now be combined with tools available in Event Rules for use in Event Rule reports. In this example, we will create a report that shows total duration of trip time and total of duration idle time within periods spent outside a Geofence.


Prerequisites

Being familiar with creating reports and using Script Expressions in Event Rules.

Trip/Idle in Script Expressions

Trip and idle data is a part of reporting data available only if you set the Event Rule that you want to use it in to Disabled. This way, rule is not evaluated in live mode, but you can still generate reports for it.

Rule Disabled

In the Expressions section, add a Script Expression and edit it. New report object can be used to access trip and idle information.

report object

Click on elements of the “report” object in the “Exposed objects and test values” panel to see additional information (same goes for other items in the panel).

This new data could be used to regenerate a Trip/Idle-like report through events. This script would include:

  • creating events using
     
    context.startEvent(report.tripIdle.state);
  • reporting the current duration by

     
    context.setVariable(report.tripIdle.previousState, report.tripIdle.duration);
  • ending the events on trip/idle state change by

     
    if (report.tripIdle.hasChanged) context.endEvent(report.tripIdle.previousState);

However, the key power of the newly available data is in combining it with the rest of the tools available in Script Expressions.

Example: Trip/idle While Outside Geofences

Let us say that we want to collect the total duration of trip time and total of duration idle time within periods spent outside a Geofence, and also track the time that has passed from the previous event.
This can be done using the script below. See the comments in the script to see what it does and why.

 
 
// skip possible invalid track points at the start and the end of the track
if (report.tripIdle.state == 'sleep') return false;
 
// shorthand aliases for current track point data
var lo = trackPoint.position.longitude;
var la = trackPoint.position.latitude;
var moving = trackPoint.velocity.speed > 0;
var utc = trackPoint.utcTimestamp.getTime(); // timestamp as a number in miliseconds
 
// acquire the state from previous message or initialize it for the first eligible message
var st = context.state || { prevActive: false, prevUtc: utc, duration: {run: 0, idle: 0, sleep: 0, off: 0} }
 
// time difference in seconds between this and previous track point
var diff = (utc - st.prevUtc)/1000;
 
// inside will be true if within the coordinates of a geofence in tag “tag1”
// for best performance, it is recommended to create a single tag for this purpose
// that will contain all eligible geofences
var inside = geofence.find(lo, la, "tag1").length > 0;
 
// should the event be active now?
// yes if not within a geofence
// or if the vehicle is back in the geofence but is still moving.
// i.e. only end the event when it stops there.
var active = !inside || (st.prevActive && moving);
 
// the calculation of period duration actually depends on the activity in the previous message.
// this is so that when a period ends with a current message,
// we can pick up the final time difference between the previous and that message,
// and add it to total duration of the finished period.
if (st.prevActive == false) {
  // previously inactive?
  // add the time difference between this and previous message
  // to the "off" duration counter only.
  st.duration.off += diff;
  // keep run and idle values at 0 as they are not calculated inside geofence.
  st.duration.run = 0;
  st.duration.idle = 0;
   
  // update the value of the "OFF" variable to be used in a report argument.
  // format() will put the number of seconds into time format (hh:mm:ss)
  context.setVariable('OFF', format(st.duration.off, 'SHORT_TIME_SPAN', false));
}
else {
  // previously active?
  // add the time difference between this and previous message
  // to the appropriate duration counter. the value used as index below,
  // "report.tripIdle.previousState", will be either 'run' or 'idle', depending
  // on whether the previous message belongs to a trip or idle segment.
  st.duration[report.tripIdle.previousState] += diff;
  // keep the "off" duration at 0, as it is only counted when the event is inactive.
  st.duration.off = 0;
   
  // update the values of "IDLE" and "RUN" variables to be used in report arguments.
  context.setVariable('IDLE', format(st.duration.idle, 'SHORT_TIME_SPAN', false));
  context.setVariable('RUN', format(st.duration.run, 'SHORT_TIME_SPAN', false));
}
 
// save the rest of the relevant current data to state
// to have it available for the next message
st.prevActive = active;
st.prevUtc = utc;
// save the state
context.setState(st);
 
// turn the event on/off depending on value of active
return active;

 

You may wish to remove the comments before saving the rule so as not to exceed the maximum allowed length of the script.

In the Notifiers section, add Report Argument notifiers corresponding to event variables set from the script, like in the picture below.

notifiers

Using $FINAL(), we can correctly pick up the value of the variables set from the script even if they were set during an evaluation in which the event was switched off.

Now save the rule, and run the default “Event Rule” report for this rule.
The result should look something like this.

result

Additional Notes

  • You can use report.tripIdle.useParkedVariable(strVarName) at the beginning of a script to specify a mapped field that will be interpreted as an “Ignition” or “Engine” variable and further split the “idle” state into “idle” (idle with engine running) and “parked” (idle with engine off) states.
  • When testing the script from the editor using the Test Script button, enter the exact UTC time of an existing track point for the user selected in the vehicle list into the trackPoint.utcTimestamp field in the editor. For the test run, values in the report object should represent the expected values at that track point.