thethings.iO Developer Center

Here you'll find everything you need to get started or go deep on developing IoT Products, Applications and Services with the thethings.iO IoT Platform.

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 'to@receiver.com'.

function trigger(params, callback){
  console.log('trigger triggered!!')
  //ignore non write events
  if(params.action !== 'write') return callback()

  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 API USER',
            api_key: 'YOUR API KEY'
          }
        },
        {
          from: 'your@email.com',
          to: 'to@receiver.com',
          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!!')
  //igrnore non wirte events
  if(params.action !== 'write') return callback()
  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 API USER',
        api_key: 'YOUR API KEY'
      }
    },
    {
      from : 'thingswarner@thethings.io', //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'
  })
}

Cloud Code Triggers