Hopefully, you've already written a few basic rules to capture useful information for your app, but sometimes you need to do more than just collect certain event types.
This tutorial will help you create rules to meet some common needs of connected car apps:
Correlate Device ID and VIN
Extract Vehicle Odometer Support
Other Advanced Examples
To create these rules, you'll need to log in to the Dashboard app and go to the rule wizard page.
Correlate Device ID and VIN
Suppose you want to maintain a lookup table of device ID and VIN.
1 ) Since VIN is reported in every trip start, we'll write a rule to capture this information from that event.
2) Instead of using the suggested rule name, we'll indicate what we're using this rule to do: map device ID to VIN.
3) Next, we'll pick out the fields we want from the event: device ID, VIN, and timestamp, so we know how recent the information is.
4) Before creating the rule, we must choose a destination for the output of this rule.
Extract Vehicle Odometer Support
An odometer reading is provided in every UDP event, but whether or not that odometer reading comes from the vehicle or from the device is not provided in every event. So let's create a lookup table for vehicle odometer support.
1) Since vehicle odometer support is provided in a UDP GPS message, we'll collect it from this event.
2) Instead of using the suggested rule name, we'll indicate what we're using this rule to do: record vehicle odometer support.
3) Next, we'll pick out the fields we want from the event: device ID, vehicle odometer support, and timestamp, so we know how recent the information is.
4) Choose a destination for this data.
5) Since most devices are configured to send many GPS events in a trip, and we only want to get this message once per trip, we'll have to customize this rule further.
The UDP GPS message has trigger reasons (see explanation below from our event catalog), so we'll filter by trip start. This will reduce the number of times we get the odometer support event to once per trip.
6) On the customization page, we'll refine the type of event to capture.
The customized where
clause is also written below for you to copy and paste.
where and(eq(body.message.type, 'GPSMessage'), eq(body.message.messageTriggerReason, 'TripStart'))
Other Advanced Examples
The sample rules below use advanced concepts of our rule syntax and cannot be created with the basic rule creator. If you're interested in using these rules wholesale or as templates, you can copy the text and paste it into the text box on the advanced rule page of the Dashboard.
Fuel Level Decrease Events Excluding Certain Tags
This rule looks for fuel level decrease events from devices that are not tagged with a staging or testing tag and modifies the JSON output.
create rule ProdFuelDecrease
using myMap = {
eventId = header.eventId,
deviceId = header.deviceId,
timestamp = body.header.timestamp,
tripNumber = body.header.tripNumber,
gps = {
latitude = body.header.latitude,
longitude = body.header.longitude
},
eventType = body.message.fuelEventType,
previousFuelLevelInPct = body.message.previousFuelLevel,
currentFuelLevelInPct = body.message.currentFuelLevel,
fuelConsumedSinceTripStartInGal = body.message.cumulativeFuelConsumed
}
where and(eq(body.message.fuelEventType, 'FuelLevelDecrease'), and(not(contains(header.tags, 'staging')), not(contains(header.tags, 'testing'))))
with amqp(body = json(bindings.myMap))
JSON Output of Rule
The example below shows how an event that matched the rule above would appear when it was delivered to your app.
{
"eventId": "bf1de4b4-c08a-4b20-a89f-9247e7270f2a",
"deviceId": "6020981918",
"timestamp": "2018-03-31T20:12:18-05:00",
"tripNumber": 3,
"gps": {
"latitude": 42.279937744140625,
"longitude": -83.74799346923828
},
"eventType": "FuelLevelDecrease",
"previousFuelLevelInPct": 54,
"currentFuelLevelInPct": 14,
"fuelConsumedSinceTripStartInGal": 5.394000053405762,
}
Speeding Events Longer Than 60 Seconds
This rule looks for speeding end events where the duration was greater than or equal to 60 seconds and modifies the JSON output.
create rule LongSpeedingEvent
using myMap = {
eventId = header.eventId,
deviceId = header.deviceId,
timestamp = body.header.timestamp,
tripNumber = body.header.tripNumber,
gps = {
latitude = body.header.latitude,
longitude = body.header.longitude
},
eventType = 'LongSpeedingEvent',
speedingStartLatitude = body.message.initialLatitude,
speedingStartLatitude = body.message.initialLongitude,
speedingStartOdometer = body.message.startODO,
speedingDurationInSec = body.message.duration,
speedingDistance = body.message.distance,
peakSpeed = body.message.peakSpeed,
avgSpeed = body.message.averageSpeed
}
where and(eq(body.message.type, 'OverSpeedingMessageEnd'), gte(body.message.duration, 60))
with amqp(body = json(bindings.myMap))
JSON Output of Rule
The example below shows how an event that matched the rule above would appear when it was delivered to your app.
{
"eventId": "89c5bace-3965-481b-bdcc-79cdb8d4b18c",
"deviceId": "6020981918",
"timestamp": "2018-05-23T02:22:58-04:00",
"tripNumber": 124,
"gps": {
"latitude": 42.06966781616211,
"longitude": -86.4334945678711
},
"eventType": "LongSpeedingEvents",
"speedingStartLongitude": -86.49169921875,
"speedingStartLatitude": 42.04869079589844,
"speedingStartOdometer": 6163,
"speedingDurationInSec": 158,
"speedingDistance": 5.300000190734863,
"peakSpeed": 124,
"avgSpeed": 122
}
Current or Pending DTC Events
Note: If the event is a pending DTC, there is no milStatus field, so the milOn value would be null instead of a boolean (compare the two JSON outputs below).
Note: The key that provides the numDtcRecords
has different names in the two events. In order to select the array regardless of which event came in, I specified a back-up field using the pipe character.
create rule CurrentOrPendingDTCs
using myMap = {
eventId = header.eventId,
deviceId = header.deviceId,
timestamp = body.header.timestamp,
tripNumber = body.header.tripNumber,
gps = {
latitude = body.header.latitude,
longitude = body.header.longitude
},
eventType = body.message.type,
milOn = body.message.milStatus,
numDtcRecords = length(body.message.dtcSpnOrPidRecords | body.message.dtcRecords),
dtcRecords = body.message.dtcSpnOrPidRecords | body.message.dtcRecords
}
where or(eq(body.message.type, 'VehicleCurrentDTCInfo'), eq(body.message.type, 'VehiclePendingDTCInfo'))
with amqp(body = json(bindings.myMap))
JSON Output of Rule (Current DTC Event)
The example below shows how a current DTC event that matched the rule above would appear when it was delivered to your app.
{
"eventId": "fde9ffa9-2a0d-4ba6-960a-98ec9417e6af",
"deviceId": "6020981918",
"timestamp": "2018-01-16T17:31:28-05:00",
"tripNumber": 87
"eventType": "VehicleCurrentDTCInfo",
"gps": {
"latitude": 42.54637908935547,
"longitude": -83.79325103759766
},
"milOn": true,
"numDtcRecords": 4,
"dtcRecords": [
"P3412",
"C2745",
"B0888",
"P2222"
]
}
JSON Output of Rule (Pending DTC Event)
The example below shows how a pending DTC event that matched the rule above would appear when it was delivered to your app.
{
"eventId": "42f8ef4b-b64c-4e2a-8523-5d9f09d0a78f
"deviceId": "6020981918"
"eventType": "VehiclePendingDTCInfo",
"timestamp": "2018-04-10T12:11:15-05:00",
"tripNumber": 9
"gps": {
"latitude": 42.54637908935547,
"longitude": -83.79325103759766
},
"milOn": null,
"numDtcRecords": 1,
"dtcRecords": [
"P3412"
]
}