Cloud Code Triggers

Triggers are snippets of code executed after an event happens like a thingWrite. You can use a trigger to send an alarm or generate an event to be aggregated later. In addition, you can call external web services.

Each trigger must contain a function trigger(params, callback)

Where:

  • params is an object with the keys:
    • action: one of 'write' | 'read'
    • thingToken: the thing that triggered the trigger
    • values: only if action == 'write' is an array of values where each value is an object with:
      • key: the key
      • value: the data sent
      • datetime: (can be null)
  • callback is a function to be called when the trigger ends. It can contain a parameter string error if the trigger needs to report an error.

The execution of a trigger is limited to 2 seconds. If the execution takes longer, the server will end the sandbox.

Setup Alarm

This code sends an email when the temperature is higher than 50 degrees to '[email protected]'.

function trigger(params, callback){
  console.log('trigger triggered!!')

  var values = params.values
  var thingToken = params.thingToken

  //iterate over the values of the write
  for(var i=0; i<values.length; ++i){
    if(values[i].key === 'temperature' && values[i].value >= 50){
      console.log('omg too hot')
      email(
        {
          service : 'SendGrid',
          auth: {
            api_user: 'YOUR ACCOUNT USER',
            api_key: 'YOUR ACCOUNT PASSWORD'
          }
        },
        {
          from: '[email protected]',
          to: '[email protected]',
          subject : 'The temperature is too high',
          text : 'Master, it’s too hot here! \n\n Always yours,\n '+ thingToken
        }
      )
    }
  }
  //end the trigger
  callback()
}

Generate Events

You can generate events from inside the code. The following code generates a simple event which stores the value to an event called 'temperature'. To be later retrieved from a job:

function trigger(params, callback){
  console.log('trigger triggered!!')
  var values = params.values
  //iterate over the values of the write
  for(var i=0; i<values.length; ++i){
    analytics.events.create({name:'temperature', value:values[i].value})
  }
  //end the trigger
  callback()
}

Playing with Geolocation

This example shows how you can combine geolib and the geolocation of your things to send an email when your thing is not inside a predefined circle.

In the example the description key/resource is used to store the predefined coordinates and the user's email.

var MAX_DISTANCE = 5000;

function trigger(params, callback){
  //ignore non write events
  if(params.action !== 'write'){
   return callback()
  }
  var position = null
  for(var i=0; i<params.values.length; ++i){
   if(params.values[i].key === 'location'){
    if(params.values[i].geo){
     position = params.values[i].geo
    }
   }
  }
  //also we ignore the keys that are not location and don't have geolocation
  if(!position){
   return callback()
  }
  //get the thing description resource
  httpRequest({
    host: 'api.thethings.io',
    path: '/v2/things/'+params.thingToken+'/resources/description'
  },response(callback, position))
}

function response(callback, position){
 return function(error, headers, data){
    if(error){
      console.error(error)
      return callback()
    }else{
     data = JSON.parse(data)
     //ensure that the description is defined with coordinates
     if(data.length < 1 || !data[0].value.coordinates){
         console.error('description not defined with coordinates')
        return callback()
     }
     var coordinates = data[0].value.coordinates
     //check if the position is inside the circle
     var inside = geolib.isPointInCircle(
        {latitude: position.lat, longitude: position.long},
        {latitude: coordinates.lat, longitude: coordinates.long},
        MAX_DISTANCE
    );
     console.log('inside', inside, data[0].value.email)
     //generate an analytics event to get data insigts later
     analytics.events.create({name:'inside', value:inside})
     if(!inside && data[0].value.email){
       //if the email is defined send a warning email
      sendWarningEmail(data[0].value.email,position)
     }
     callback()
    }
  }
}

//this function geneartes and sends a cool warning email
function sendWarningEmail(receiver, coords){
  var coordsStr = '<a href="https://www.google.com/maps/dir//'+coords.lat+','+coords.long+'/@'+coords.lat+','+coords.long+',15z">https://www.google.com/maps/dir//'+coords.lat+','+coords.long+'/@'+coords.lat+','+coords.long+',15z</a>'
  console.log('sending email to', receiver)
  email(
    {
      service: 'SendGrid',
      auth: {
            api_user: 'YOUR ACCOUNT USER',
            api_key: 'YOUR ACCOUNT PASSWORD'
      }
    },
    {
      from : '[email protected]', //this email is completly random
      to: receiver,
      subject: 'Your thing has escaped!',
      text: 'Your thing has escaped from the safe zone!\n \n Last seen in: '+coordsStr+' \n\n Att,\n Overlord'
  })
}