IoTIFY Helper APIs

There are several helper function and libraries provided by IoTIFY which help you simulate your solution faster.

We have written several helper functions which will help you simulate complex behavior easily.

Getting Current Simulation Job Information

When a template is running, it is called a simulation job. When you write a template, you don't have any information on how it will be run. You could use some template helper functions which will provide the currently running simulation job details to create more dynamic functionality. Here are few job information helper functions:

jobClients()

Returns number of clients being launched in the current simulation job.

jobId()

Returns the assigned name of simulation job. This could be used to store the results in an database.

jobInterval()

Returns the time interval in seconds between each iteration

jobRepeat()

Returns the total number of iteration specified in the job.

Let's look at example

{
if (client() == 0 && index() == 0){
console.log(
`Current Job name ${jobId()} \
with ${jobClients()} clients repeating \
${jobRepeat()} times with a gap
${jobInterval()} seconds`)
}
}

Above code snipped will print e.g. the following when the template will run. The actual values will depend upon your specified parameters.

Current Job name test123-demo-users with 10 clients repeating 5 times with a gap 5 seconds

index()

While simulating, you will specify the number of iterations for template. The current iteration can be determined within the template by using keyword index(). Here is an example

{
return "This is the "+index()+" iteration";
}

Above template will send a message containing the current iteration index, starting from 0.

client()

While simulating, you will need to implement a client specific behavior. The current client ID can be determined within the template by using keyword client(). Here is an example

{
return "This is the client "+client() + " on "+index()+" iteration";
}

Above template will send a message containing the current client with iteration index, starting from 0.

Simulate moving vehicles with drive()

To simulate a vehicle driving from one location to another is simply a matter of specifying the starting and end address. Use the following function in your template:

{
state['location'] = drive({start:'Munich,DE',end:'Berlin,DE',accuracy:5});
return JSON.stringify(state, null, 2);
}

Above template will generate drive coordinates starting from Munich to Berlin on real time traffic conditions. Upon each iteration, the function will automatically spit out updated GPS coordinates.

You should never call this function within a loop.

Following are the input parameters:-

  • start, end : A starting and ending real world address where you would like to drive. It could be a city name, a street address or even a point of Interest such as:

{
drive({start:'Disneyland, CA',end:'Universal Studios, CA'})
}
  • accuracy: Since real world GPS devices are not perfect, we will need to simulate the defects as well. Accuracy specifies how much maximum accuracy we should provide when simulating coordinates. In simple words, an accuracy of 5 meters specifies that the resulting coordinate could be anywhere within the 5-meter radius of actual coordinate.

  • key: provide your own Google maps direction key, if required.

Output format of drive function

The output of the drive() function is a JSON object, that’s why it is important to save this into a string with JSON.stringify(). Here is what the output looks like:

{
latitude: 34.123456, // decimal
longitude: 23.123455, // decimal
speed : 6, // meter per second
accuracy: 2 // meter radius
finished: // undefined, set to true for the last step
}

Note: once the drive has been finished, the output will contain an additional field finished set to true to indicate that the current drive has been finished. Use the field to calculate the next set of drive or return.

Get GPS location()

Location function converts an address to its GPS coordinates, again with given accuracy parameter.

state['location'] = location({address:'Delhi,IN',accuracy:5})

This will generate a GPS coordinate near New delhi with an accuracy of 5 meters. Similar to drive function, you could also pass the actual address in the parameter and it will convert that to a set of GPS coordinates. The accuracy of this could be still controlled by the accuracy parameter. The output of location function is following:

{
latitude: 34.123456, // decimal
longitude: 23.123455 // decimal
}

Get the real world weather

weather.temperature() and weather.humidity() function will query weather API to get the current weather of a city. Example:

{
var temperature = weather.temperature({location: 'London, UK', unit: 'f'});
var humidity = weather.humidity({location: 'London, UK');
}

This will return the current temperature of London in degree fahrenheit and relative humidity in percentage. If the weather can not be found or if the location is incorrect, an error message will be returned.

By default, if no unit is specified, the output is in centigrade.

To change the temperature to Fahrenheit, provide unit : 'f' as an argument.

Mocking CPU and memory

cpu() and memory() functions will return mock CPU and memory usage of a running system in percentage points.

{
state['cpu'] = cpu();
state['memory'] = memory();
}

Simulating continuous variables

A volatile variable is useful while modelling a complex value such as stock price or temperature. The value of volatile variable is dependent upon its last value and can move upto max +/- delta steps from the last value at random.

{
state['temperature'] = volatile({min : -10, max: 100, delta: 4, key:"myvar"});
}

A volatile variable takes 3 parameters, min range, max range and delta value as an input.

The value of volatile will start from the middle of min and max, i.e. min+max/2 Upon each iteration, volatile will change by a minimum of 0 to a maximum of delta in either positive or negative direction from its last value. e.g.

var chart = volatile({min : 10, max: 20, delta: 3, key:"myvar"})

chart will be initialized to 15 at iteration 0. (10+20)/2

At iteration 1, chart can be anywhere +/-3 of 15, i.e. min 12 and max 18. Let’s say it reaches 14

At iteration 2, chart can be anywhere +/-3 of 14, i.e. min 11 and max 17 and so on.

Volatile is useful for modelling dependent values such as stock prices and temperature graphs, where next value depends upon the last value.

Always provide a unique key for each volatile variable within an object, so that they do not collide in value.

HTTP REST APIs (rest.[get|post|put|patch|delete])

Within your device template, you could call a REST API and get data from an external source, or push data to an external service. Following helper APIs are available in the template.

rest.get({url:'https://httpbin.org/get'})
rest.post({url:'https://httpbin.org/post', json: { hello: 'world'}})
rest.put({url:'https://httpbin.org/put', json: { hello: 'world'}})
rest.patch({url:'https://httpbin.org/patch', json: { hello: 'world'}})
rest.delete({url:'https://httpbin.org/delete'})

All API returns the response as a string. In the following example, we will get the current public IP address of our node and send this address to our backend application to whitelist our client.

{
//Getting the current IP address of the server executing the template
state['myip'] = rest.get({url: 'https://ifconfig.co/ip'});
// posting the IP to my application to whitelist the source
let response = rest.post({url: 'https://httpbin.org/post', json: { ip: state.myip }});
//return a string value which will be sent as the message payload
return JSON.stringify(state, null, 2);
}

The rest APIs accept a lot of option parameters. For a full documentation, please refer to the option parameters for NPM package request

Setting Iteration result via assert()

Usually an iteration for a client will be marked as failed, when client is unable to publish a message to the server within the given timeout period. However, there may be cases where you would like to declare a test as failed, when certain criteria is not met. When using IOTIFY for testing, you could force a test iteration to be failed even if message sending is successful using test assertion with assert() function.

assert(condition, message) function takes two parameters

condition: A boolean condition which should be tested for truth (true) message: A string describing the cause of assertion failure which can be stored in test results.

E.g. following statement checks for an assertion failure in your template and marks the test result as failed, if retval doesnt equal 123.

assert(retval == 123, "Return value doesnt equal"+123);

The assertion will overwrite the usual results, i.e. Even if the message has been successfully sent to the server endpoint, the failure of assertion will mark the test result as failed.

glob APIs (glob.[get/set/delete])

IoTIFY provides a simple, fast and persistent key-value storage which is private to your account and accessible to all your running jobs. They key value storage could be used for multiple purposes, e.g. to sync between multiple jobs, control the simulation behavior dynamically or revert back from the last state of device. The API take a string value as a key and a string/integer/object as a value. Here is an example

{
glob.set('mykey', 55);
let val = glob.get('mykey'); // val will be 55
glob.delete('mykey');
glob.set('client_'+client(), 21124); // specfic to the client
}

Any existing glob key values could be seen and modified in the UI under the DBStore tab. These glob values will also be accessible via APIs

metric.add() Time series Metrics API

When the simulation is running, you may want to store some performance parameters for later stage analysis. Normally, you would need to create a separate backend application which could store such metrics, however with a very large scale dataset, this could become difficult. IoTIFY provides the simple and easy to use time series database for this purpose via metrics api.

{
metric.add('latency', 55);
}

Metrics could be visualized and aggregated in the Metrics tab. Metrics will also be available via API in the future.