# Home

Learn about benefits of using a scalable cloud based IoT device simulator.

As billions of IoT devices are being connected every day to the internet, IoT platforms are rapidly evolving to offer more features to ingest, analyze, and monetize data. Developing these applications on different IoT platforms is also getting more challenging due to the increasing complexity of the devices and the introduction of new concepts like digital twins.&#x20;

IoTIFY offers a scalable and flexible IoT device simulation platform that works with your favourite IoT Application Enablement Platform and enables rapid development, testing, and deployment for your IoT solution handling millions of devices at scale. Let's learn more about IoTIFY.

### Device Simulation in IoT

Getting started with an IoT idea is exciting - however, building an end to end IoT solution comes with its own challenges. One of the first and perhaps most crucial steps in developing IoT applications is to create a device simulator. Usually, this could be a simple script, a tiny program or even a third-party tool customized to mimic the behaviour of your IoT device.&#x20;

For a very basic application, these homegrown simulators are fine and will deliver fast time to market. However, as the complexity of your IoT application starts growing, you will need to put in extra effort to get the simulator to support all these features. Then, as scalability comes into the picture, you'll have to look into scaling the simulator instances, and it's orchestration. After all of that, you need to collect different results, measure different latencies, and the whole time, keep troubleshooting the simulator, which will keep getting more and more challenging.

Eventually, as more and more features are shipped, the complexity of the simulator reaches a tipping point. Where you realize that writing a complex, scalable and efficient simulator is taking up as many resources, as designing and implementing your scalable and functional IoT cloud application itself. At this point, it makes sense to ask whether solving the same problem twice has any benefits? Or could there be an alternate solution that simplifies large scale IoT simulation so that you could focus entirely on building your cloud-based applications?

### Introducing IoTIFY

![IOTIFY overview](/files/JERglE1xeHYA8eoPVHec)

If you are a manager handling cloud application development, you want all hands on deck for delivering a compelling IoT solution, not building an equally challenging test framework for it. That's where IoTIFY comes into the picture.

IoTIFY is an intelligent IoT system simulation platform on the cloud, which makes it perfect for simulating a large scale Cloud-based IoT device deployment. Our Rapid IoT application development environment helps you prototype, scale, and manage your IoT applications with ultimate flexibility and ease.&#x20;

### Our Features

At IoTIFY, we are focused on building an intelligent IoT system simulation platform on the cloud, which will enable you to simulate a large scale and realistic IoT device deployment. With IoTIFY, you can prototype, scale and manage your IoT application easily and quickly. What sets IoTIFY apart from other testing tools?

#### Purpose-built for IoT

The fundamental difference between IoTIFY and other commercial or open-source testing tools is the fact that IoTIFY was built specifically for IoT applications. While other testing tools were built for the web, and later added support for IoT protocols, IoTIFY was designed from the ground up to deliver the best experience for testing IoT applications. How does that matter?

Focusing exclusively on IoT use cases enables us to leave a lot of baggage from the past behind and build features that are needed for IoT use cases. For example, while a web client doesn't interact with another web client in its vicinity. IoT devices do communicate with each other all the time. Another example could be actuators, which do not send any data but wait to receive actions.

Being focused on IoT means we do not need to worry about web-specific features such as cookies and browser versions. However, the most crucial difference is the fundamental design, which we discuss in detail as follows.

#### Designed for scalability

One of the biggest challenges in IoT is to handle scalability. Millions of sensors and hundreds of thousands of gateway could connect to any IoT platform at any given point of time. The dynamic nature of connectivity media (3G/4G/LoRaWAN/Satellite) adds packet loss, latency, and out-of-order delivery and replication to the networking.&#x20;

To ensure that IOTIFY could truly match and even outperform the capabilities of the IoT Platform under test, we have built it on the same principles used to build scalable cloud platforms. For example, every module of IoTIFY is fully modular; we use in-memory databases, focus on read and write latencies, use messaging protocols such as NATS to speed things up, and heavily use replication and load balancing. We use a dynamic and responsive orchestration of containers to deliver the best performance with minimal resource consumption, passing cost benefits to our consumer.

#### Stateful device Modeling

Just like the real-world; each simulated IoT device has its own temporary and persistent memory. The simulated devices could save any meta-information to these memories, which could also be retrieved and edited by external APIs/UI. For example, a serial number of the device is usually a static field that remains valid throughout the lifetime of the device. This information could be saved into persistent glob storage for each device and could be used as an identifier for every test case run.

#### Device to Device and Cloud to Device Interaction

Device to Device interaction is one of the unique features of IoT. Devices could talk to each other either directly (through LAN), via gateway or via the cloud. All of these scenarios can be simulated with IoTIFY. Our mailbox APIs allow multiple different devices or gateways to talk to each other in real-time simulating local connections like those over WiFi, Bluetooth or ZigBee.&#x20;

Additionally, there are also ways in which devices could communicate with each other via out-of-band means. Consider a fire extinguisher spraying water on a device having temperature and humidity sensors. The action of spraying water is actually causing the temperature to drop and humidity to increase. Similarly a garbage pickup truck emptying a smart trash container is causing the ultrasound sensor to report empty bin. Such out of band or physical behavior could be simulated in IOTIFY using global stores - which enable devices to affect each other's internal states.&#x20;

#### IoT multi-protocol support

IoT has a wide standard of protocols, which are also evolving with time. IOTIFY supports a wide variety of these protocols and continues to keep on adding newer versions. Our current SaaS version supports MQTT, HTTP, CoAP, LWM2M as well as UDP and TCP raw protocols (binary). Adding a new protocol is also quite easy, thanks to our flexible architecture.&#x20;

#### Native integration with popular IoT cloud platform

Configuring and administrating IoT devices in the cloud platform require some scripting to be setup beforehand. At IoTIFY we have listened to the feedback of testers and observed their day to day workflow. The result is Connectors - UI Wizards which make provisioning and enrollment of virtual IoT devices extremely easy. With the wizards, configuring hundreds of thousands of IoT devices becomes a matter of just few clicks. And not only provisioning - cleaning up resources after test execution is also super easy.&#x20;

### **Feeling excited?** Let's dig deeper into understanding our approach a bit more.&#x20;

In the next sections, we will learn more about how IoTIFY helps you develop super complex scalable simulations with ease.&#x20;


# Release Notes

Stay up to date with the latest features and bug fixes for the IoTIFY platform

Coming Soon


# Getting Started

Getting Started with IoTIFY is simple. Just signup and follow the guide below to run your first test.

Welcome to IoTIFY, your one-stop solution for all your IoT testing needs. This guide will walk you through the steps for creating and running your very first test.

When you first log into IoTIFY, you will be greeted into the interface. It's divided into two parts, The left pane, and the work area.

The left pane houses the Workspace Selector, the navigational shortcuts to move from one part of the platform to another, and the profile menu. This pane can also be minimized by clicking on the arrow in the profile menu so that the full screen can be utilized for work.

![](/files/DzVjq7czueFtnMtmqIXe)

The right side of the screen is what we will call the work area. The contents of this change according to the part of the interface we are in. Since we are in the Tests interface, it shows a list of all the tests created in the workspace.&#x20;

<figure><img src="/files/hsADHmFLd6u5I7yduwfS" alt=""><figcaption></figcaption></figure>

Let's move forward and see how we can create our first test.


# Create your first Test

In the Tests interface, we can start by either importing a sample test provided by us or by creating a new test from scratch. We will be importing and working with one of our sample tests for this guide. The sample tests include all the code required for creating a device model for different devices.&#x20;

However, if you want to start building your own test from scratch, you can look at the guide below.

{% content-ref url="/pages/-Li8yZMslZ0s5TO-ev-F" %}
[Understanding Tests](/concepts/understanding-a-test)
{% endcontent-ref %}

To take a look at all the sample tests available, click on the `Create from Sample` button at the top right of the screen. This will open up a list of all the samples that are available at the moment.&#x20;

<figure><img src="/files/JDIS6bq0lxI6oDRGxpas" alt=""><figcaption></figcaption></figure>

For this guide, we will be using the `Smart Home` sample. New sample tests for different devices and purposes are always getting added, so this list will look different than the one below.&#x20;

Click on the Smart Home tile and then click on Create. This will import the Smart Home test to your workspace and you will be able to see the same in your list of tests.

<figure><img src="/files/UfjBFL6jgyRtxjLhTy1w" alt=""><figcaption></figcaption></figure>

Now click on the Smart Home test tile to open the test and start tinkering with it. The basic device model is already available and you can start simulating the Smart Home test now.

<figure><img src="/files/LVFiCJ3koEa01tMwnCk3" alt=""><figcaption></figcaption></figure>

You can go to the `Understanding Tests` guide linked at the beginning of this article to properly understand the device model. For now, let's simulate this test.

To simulate your test, click on the `Run Test` button on the top right of the screen. This will open up a sidebar where you can give this simulation job a name and choose the run settings parameters for the job. By default, a run setting would be created for you.

<figure><img src="/files/SpoptcCP77zXUy1eiUJi" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/l0RK50HXBjDSX0WOdXb0" alt=""><figcaption></figcaption></figure>

To tinker with the run settings parameters, go to the next page or you can click the `Run` button at the bottom to start the simulation job.


# Create Run Settings


# Analyze the results

Understanding the final results after the simulation

After your simulations have completed running, you will want to see how many requests went through, how many failed and other data related to the simulation.&#x20;

You can find all of the data related to the simulation run in a well-organized manner on the Results page. Here, you will see a list of all the different simulation jobs with an overview of their results. The status of currently running tests are updated in real-time.&#x20;

![](/files/McnKklds1r4mqJLZy21O)

On this page, you can also stop an ongoing simulation job, delete an old job or restart a completed job. All of these can be done by clicking on the respective icons under the Operations column.

If you want to know about more detailed results for a specific job, you can do so by clicking on the folder icon under the Operations column. Once you click that, the detailed results for the specific job will be opened. &#x20;

The results are divided into several tabs: Summary, Logs, State and Payload. Let's go through them one by one.

{% hint style="info" %}
If you are sending more messages or connecting more clients than what your server could handle, every client is eventually going to wait for its turn to connect and send, thereby stretching the overall test duration. It is important to carefully tune timeout values in your template to handle this worst case, otherwise, the iteration will be marked as failed.
{% endhint %}


# Job Summary

Job summary is an overview of specified runtime parameters and overall test results per iteration.

This tab provides an overall look at the results and a summary for all iterations. The test results per iteration are shown aggregated across all the clients. This gives an idea of how many clients succeeded per iteration.

The next graph shows the client activity over time. Here, you can see how many individual clients were active at the given points in time.

![](/files/RMJW18nAN9sWtbIVXZP4)

The final graph shows the average, minimum and maximum time it took to send a message to the back-end. This is a true measure of your server performance, as it doesn't count the time it took to generate the message. As we could see, the packet sending latency is fairly maintained consistent with time.&#x20;

{% hint style="info" %}
Packet sending latency is highly dependent upon the protocol and transport. E.g. for MQTT QoS 0, the packet sending latency will be lower, as the transmission of the packet is marked completed almost immediately. If the QoS value used is 1 or 2, the sending latency will be much higher for the same test, as higher QoS values require every sent message to be acknowledged for delivery, therefore considerably increasing the latency.&#x20;
{% endhint %}


# Logs

Logging provides a way to look into the

Logs provide a way to understand how your tests are working and also a way to see critical information for specific clients at different iterations. You can `console.log()` or `console.error()` in your tests and log critical information for the clients.

![](/files/FbgYQwMO2kunnftnX7GW)

You can easily find the logs for a particular device and see the logs at every iteration. Along with the user logs, system logs are for each iteration are also captured and displayed here.

{% hint style="info" %}
Double-tap any of the logs to pretty-print the logs for that iteration.&#x20;
{% endhint %}


# State

The state tab provides a place to easily look at the state objects for the clients.

The state tab provides a summary of the iteration results along with the contents of the state object for each iteration. You can also find the stage at which the device model was at each iteration here.

![](/files/prNo4aRnERD7Y2ea0XuE)

This can be a great place to understand the execution of the tests and how the device model is working.

{% hint style="info" %}
You can use the toggle in the top right corner to Format the JSON objects.
{% endhint %}


# Payload

The outgoing and incoming payloads for the test.

The Payload tab allows you to see the communication between the test and your backend. Here, you can see the complete payloads that the test has sent to your backend and the payloads that the receiver function has received. This information can be critical during troubleshooting any problems regarding the connection between your backend and the tests.

![](/files/YyqnsmXJbP46zDZwZV6x)

{% hint style="info" %}
You can use the toggle in the top right corner to Format the JSON objects.
{% endhint %}


# Look deeper with Metrics

We also have a robust Metrics engine that keeps a track of many important metrics throughout all test runs, with the ability to add custom metrics as well. The Metrics can then be visualized using the Metrics section on IoTIFY. Graphs can be generated with a multitude of filters to better understand how the system has been performing.

![](/files/DAcJogo6WrK7sqbhJUnL)

Here, you can select which metric you want to see from the drop-down here, then choose an aggregate function and the job you want the metrics for, and finally click on the Update Chart button to create the chart.

{% hint style="info" %}
We log certain metrics like message latency and sending latency by default for all simulation jobs. Additionally, you can also see the system metrics like the number of MQTT connects, total bytes sent via MQTT and more by the `System-wide Metrics` toggle.
{% endhint %}


# Workspaces

Collaborate with your team with workspaces

With IoTIFY, it is simple and intuitive to collaborate on your simulations with your team. Workspaces make it possible to share resources and work on simulations together.

When a user signs up on IoTIFY, a default workspace is created and the user can create tests and run simulations there. You can then start inviting other users to this workspace for collaboration.

![](/files/Uy6qK0tUMGZDaVN9ZKNi)

It can be a good idea to create a separate workspace for collaborating with different teams. To create a new Workspace, just click on the arrow beside the workspace name and a dropdown will appear with a list of workspaces you are in and an option to create a new workspace.

![](/files/DgpfAUCtxdG08J0z0O4u)

Once you click on `Create Workspace`, you need to provide a Workspace Name and click on the `Add` button. A new workspace will be created and now you can start inviting people in the same way.

![](/files/txoO2VHaZL5X1RYqQxvk)

We provide robust RBAC support for workspaces, to learn more go to the next page.


# Role Based Access Control (RBAC)

With Workspaces on IoTIFY, collaborating with your team becomes very easy. In this guide you will learn more about different roles you can assign your teammates depending on the level of access you want to give them to the workspace.

To change the role of any user in the current workspace, click on the Workspace selector, then click on the gear icon towards the right of your workspace name, and you will be taken to the Workspace management console.

![](/files/cJbvf81ughvxKk3RKRkt)

Here, you can invite a new member to the workspace, see the members, change their roles and delete already added members.

![](/files/1Jxha2rSThBXdf0ZDUPx)

The admin of the workspace can easily change the other users' roles by clicking on their current role in the Members list. A dropdown will appear with all the roles and the admin can then select from the given options.

![](/files/zf81aTFW7ISmFpqbxTyY)


# Invitation Management

First, you need to be in the Workspace management console. To add a new member to the current workspace, Just click on the Invite button, this will bring a small form where you have to provide the email ID and the role for the user, once the data has been added, click on Invite and the invitation will be sent to the user as an email.&#x20;

![](/files/QJiFIu7Q9VoV3usyr0lD)

The users can either accept the invitation from the Email or when the user opens up IoTIFY, they will get a popup with the invitation. Once the user accepts the invitation, they will be added to the current workspace. &#x20;

<figure><img src="/files/yhfbIqyjDCfS3VnJGp7y" alt=""><figcaption></figcaption></figure>

To see a list of all the invitations you have sent you can go to the Sent Invitations tab. Here, you will see all of the invitations you have sent and their current Status.

<figure><img src="/files/7BrbWQ3a8hGM85RQ3RAU" alt=""><figcaption></figcaption></figure>

To delete an already sent invitation, just click on the delete button (the garbage can button) present on the right side of any sent invitation.


# GitHub Integration

You can connect your GitHub account with IoTIFY to create backups for the tests each time you make any changes to them.

To get started, head to your Workspace management console again and head to the `Github` Tab. This is a two-step process first, you will need to install the `IoTIFY Nsim` app on GitHub, and then you need to select the repository where IoTIFY should save your tests.

![](/files/d5lK8HWRDsgVqv1sOG7B)

To get started, click on the `Install Github App` button, this will open a new window, where you will need to sign in to your GitHub account, and then you can install the `IoTIFY Nsim` app. You can choose to install it in all repositories, or only a specific one. After the installation is complete, you will be redirected back to IoTIFY.

![](/files/AUJqN6Pp3ri9WV1YAek6)

Now the button will say `App already installed` and you can move to step two, click on the dropdown menu and you will see a list of repositories that have the app installed. Select the repository where you want to save the tests and click on the `Select` button.&#x20;

![](/files/I9BUaUj8GqWrdcc010n3)

Your GitHub account is now connected and every time you save a test on IoTIFY, it will be saved in the GitHub repository automatically as well.


# Deletion of Workspaces

While it is quite convenient to create new workspaces for each project, managing multiple workspaces can quickly become a hassle and a waste of precious resources. Especially when the project at hand is complete. Hence, it can be a good idea to delete workspaces when they are not needed.

Firstly, there are two types of Workspaces, the default workspace created for a user when they join the platform and the ones that are created thereafter. The permission requirements are different for the two, but the steps are the same.

To delete a default workspace, one needs to be a `root user` for the workspace. For the other workspaces, the user would need to be an `admin user`.

Now that we know which roles have the ability to delete a workspace, let's move forward. First, go to the Workspace management console again. Here you will be able to see a Delete Workspace button on the top right of the screen. Click on this button.

<figure><img src="/files/V6CycVgQqKO0n9Nttgex" alt=""><figcaption></figcaption></figure>

A popup will appear asking you to confirm whether you want to delete the workspace, click on Ok. If you have valid permissions, the workspace and all its entities will be deleted.

<figure><img src="/files/dL1Wv9XpE2MHFk2NjwPL" alt=""><figcaption></figcaption></figure>

Once the current workspace is deleted you will be redirected to another workspace you're a part of. If you deleted your default workspace, then a new default workspace will be created and you'll be redirected to it.


# System Status

The system status sidebar is a convenient and quick way to gauge the load on the system.

To access the system status sidebar, click on the System Status button on the left navigation pane.&#x20;

<figure><img src="/files/gHx9TUj0gW3nq7D2S6F4" alt=""><figcaption></figcaption></figure>

This will open up the system status sidebar. Here you can see the maximum number of simulation agents you can run and how many of them are busy at any given point in time. You can also get the Public IPs for these simulation agents from here.&#x20;

<figure><img src="/files/avMATjrV3t7JterbTf7U" alt=""><figcaption></figcaption></figure>


# Understanding Tests

A test is a JavaScript document which describes the behaviour of your virtual device during simulation. Tests consist of Device Model, Library Management, Protocol Settings and Security Parameters.

Once we have figured out what our device lifecycle looks like and what kind of device state variables we will have, we can jump to writing a test. A test is essentially a JavaScript document which describes how a single simulation will be executed. It's important to clarify that tests describe only a single device's behaviour. When you run a test, you can create multiple devices out of the same test. Each of these multiple devices could behave differently based on their unique client IDs. Every aspect of the device behaviour which needs to be modelled therefore should be described in the test.

How are the Tests used in the simulation? When a simulation is started, the simulation engine will parse the test and create virtual devices out of it. Each virtual device will have its own memory, state, and connect to the IoT cloud platform until your simulation is running. The following diagram describes the instantiation of the tests.&#x20;

![](/files/zhOHxlqJq9ScNAFskyF8)

If you are familiar with C++ or any other object-oriented programming language, think of tests as **Classes** and virtual devices as **Objects**.  Once a test is defined, you could create as many instances of it as you want.&#x20;

> You could also create multiple tests to simulate an end to end system. Take the example of simulating a smart city environment, you would need to create separate tests to simulate street lights, trash cans, parking slots among other things. When you need a complete simulation, you will run all these tests together. These tests would also be able to talk to each other, as we will see in the later documentation.

#### Device Model

A device model encapsulates the behaviour of the physical device into different stages, each defined as a JavaScript program. There are 2 stages (**Init** & **Finished**) which are always present in a device model. There is no limit to the maximum number of stages a test can have, which allows us to simulate devices with a very high level of complexity. The virtual devices can also be programmed to move to any of the stages at any point, by using the **next()** function.

Each of these JavaScript programs is passed a JavaScript object called **state** which could be used to hold device-specific informatio&#x6E;**.** A device model is independent of the connection protocol and the security parameters so you could reuse a device model across HTTP and MQTT protocols with ease.

![](/files/NHql4a819R0b63G40V5n)

So how are these device models executed? Let's understand this with the help of the picture given below.

![](/files/-Li96MgjQPF98ZiG1ULG)

In the above picture, time is taken on the x-axis. The first stage on any device model is the **Init** stage. This stage can be used to describe some initial values, retrieve data from the persistent storage or assign random values to different components. During the Init stage a setup function runs which takes care of setting up the virtual devices. This setup function is triggered even before a connection to the backend is attempted. This function doesn't need to return any value.

After the Init stage is complete the rest of the stages can start. These stages are used to define the core functionality of the device and all of its features. There can be any number of such stages according to the complexity of the device. These stages offer a logical separation between the different states the physical device can be in. Each of these stages is also divided into a Sender and a Receiver unit. The Sender is used to send messages to the backend and the Receiver handles the responses or commands coming from the backend. These stages are invoked for the specified number of iterations according to the run settings of the test. The duration between each iteration is also configurable and can be changed in the run settings.

After the device has gone through all the different stages with the device functionality, it finally goes to the **Finished** stage. The Finished stage can be used to clean up any server-side resources or to summarize the test results.&#x20;

The other components of the tests are as follows :&#x20;

#### **Library**

We allow users to import any additional npm packages or custom scripts to enhance the device functionality. These npm packages or scripts are imported at every run of the test and can be used everywhere. Currently, we only allow up to a maximum of 5 such packages and scripts in total.

To know how you can use external libraries with IoTIFY, jump to the page linked below.

{% content-ref url="/pages/jngVqzWqMCy6s7Edz6mR" %}
[External Libraries](/additional-helpers/external-libraries)
{% endcontent-ref %}

#### Protocol

Protocol specifies the server settings and underlying option for the chosen connectivity. The details are specific to each protocol. It's important to note that many of these protocol parameters are scriptable i.e. you could change them dynamically with the help of state objects or other helper functions. This is particularly interesting for MQTT e.g. where you would like to listen to a device-specific MQTT Topic. You could simply subscribe with the following string:

`/device/{{client()}}/command`

When the test is executed, the part within the double parenthesis will be evaluated and client() function will return a unique client ID, starting from zero. For example, if you are simulating 100 clients, each one of them will have its own unique client ID. The string would thus evaluate to the following for client 66:

`/device/65/command`

Protocol is also used to specify the client-specific security settings such as username/password or preshared keys/certificates etc. The fields related to security are also scriptable.

To understand the different protocols and how to utilise them with IoTIFY, please visit the page linked below.

{% content-ref url="/pages/-M8PNnhfSM5unK58MlcS" %}
[Protocol Settings](/temp/protocol-settings)
{% endcontent-ref %}

### Summary&#x20;

A test consists of a device model, protocol and run settings details. Each test is passed a unique JavaScript object called state which could be used to maintain the device status through its run time. There are several helper functions and scripting options that make fields configurable inside the protocol tab.&#x20;

> Should we describe the entire behavior of a device into the single test? Not necessarily. We will learn in the later chapters about glob key-value stores which could save device states in persistent memory. Using this storage, we could create separate tests which retrieve the last known value of a device state, run a scenario and then save the latest state back in the memory.&#x20;

Now we have a good overview of what a test is, let's jump to the finer details of these tests.&#x20;


# Stages Management

To capture the full lifecycle of the IoT devices, the device model has multiple stages. This captures the whole behaviour of the devices as they can behave differently in different scenarios.&#x20;

In any device model two stages, the Init and the Finished are always present and cannot be deleted. They represent the first stage of the device lifecycle as it is initialised and the final stage of the device when it needs to shut down.

Apart from these two stages, an additional stage named Running is created by default. This stage is supposed to be the active stage of the device. The bulk of the device logic should go in the running stage and other stages that can be created between Init and Finished. There is no limitations to the number of such stages.

<figure><img src="/files/SfP2eTAaSfR2uYiy9ucX" alt=""><figcaption></figcaption></figure>

Having the device model broken into such stages makes it easier to work with the device and allows for a high degree of complexity to be implemented in the device model.

Let's now look at how to work with these stages. Starting with the Init Stage.


# Init Stage

Initialise the devices and add default values

The **init** stage is where the device initialisation happens. This stage is invoked with an empty state object. Use this stage to populate different parameters that the device will use in its lifetime. It is also a good place to set up device credentials or to configure some external resources. An example of an Init stage is given below.

#### init(state)

```javascript
{
    let serial = glob.get('serial_' + client());
    if (!serial)  //if serial is not found, then create one
    {
        serial = chance.guid();
        glob.set('serial_' + client(), serial);
    }
    state.serial = serial;
    next();
}
```

As a result of this code, each of your clients will be assigned a unique serial number which will remain persistent throughout all of the simulations. You could always delete the DBStore entries or modify them.

> Note that the Init stage is invoked before the connection is made to your backend server. This is an ideal place to setup any device credentials or set the server settings.

The Init stage does not need to return a value.&#x20;


# Running Stage(s)

The majority of the device logic is written in the running state(s). These stages must return a payload to be sent to the server.

The core of your device logic can be divided into different parts through its lifecycle. We can use multiple running stages to partition the device simulation into logical segments.&#x20;

For Example, if we are trying to simulate a smart lock, we could have a **booting** stage that simulates how the device behaves when being switched on, then we could have an **online** stage that defines how the device behaves under normal working conditions and finally we could have an **offline** stage which simulates how the device would behave without a network condition and so on.

Partitioning the device logic into multiple such stages makes it easier for others to understand the device logic and also help while troubleshooting any issues that may arise while running a functional test for the device. There is no limit to the number of such stages that can be created. Let's see how to work with these different stages.

![](/files/RTVBzFnQDPA7dRvHAsKQ)

To add a new stage to the Device Model, move your mouse over the line between the stages where you want to add the new stage, a plus button will appear. On clicking this plus button, a new stage will be created. A new stage can be created anywhere between the Init and the Finished stages, but not outside them.

![](/files/x2rKFHyohej1Dbq41Yzc)

To rename any of the stages, click on their names, a text field will appear and you can rename the stages.

![](/files/ywkgYQo9Vvcid2pannVl)

To delete any stage, move your mouse to the icon above the stage you want to delete, a cross icon will appear. On clicking the cross icon, the stage will be deleted.

![](/files/Qx0cRLMdlBabT4BfGm4T)

To transition to another stage from a given stage use the **next()** function. If the next() function takes the name of any stage as the parameter. If no parameter is supplied to the next() function it will transition to the next stage on the timeline.

```javascript
{
    let serial = glob.get('serial_' + client());
    if (!serial)
    {
        serial = chance.guid();
        glob.set('serial_' + client(), serial);
    }
    state.serial = serial;  
  
    next() //Transitions to the next stage on the timeline
    //Or
    next("Other_Stage") //Transitions to the given stage
}
```


# Finished State

Once all of the iterations have been run and device is about to be torn down, the finished stage is invoked. This stage could be used to delete/create any glob entry or push any metrics into the system.&#x20;


# Generating Messages

Each stage in the device model has a Sender and a receiver function. The sender function is used to send outbound messages to an external server. It is where we generate payloads depending on the device logic and send them to your backend. The sender function must return a payload which will be passed on to the server. Let's take a look at some use cases and functions you may come across while working with a sender function.

<figure><img src="/files/C52tZHo3PfYGb10UE7zw" alt=""><figcaption></figcaption></figure>

#### Getting the current iteration&#x20;

When the template is running, it might be required to do some actions based on a specific iteration, For example, for every 10th call, you would like to send a special message. Simply call the **index()** function to find out which iteration you are currently in. The iterations start from 0 and continue up to the number of iterations you have specified in the run settings tab.

```javascript
{
    if (index() == 0 ) {
        return "This is the first iteration"
    }  
    if (index() % 10 == 0 ) {
        return "Special Message at every 10th iteration"
    }
    if (index() % 2 == 0 ) {
        return "Special Message at every even iteration"
    }   
    var randomIteration = Math.floor(Math.random()*100);
    
    if (index() == random ) {
        return "This is a random message triggered one time in 100 iteration"
    }      
    
    return "Normal message";
}
```

#### Knowing the client ID

If you are simulating more than 1 client, you could find the current client ID in the template by accessing the **client()** function. This returns an integer starting from 0 and going up to the maximum number of clients specified. If you have passed a client offset while running the simulation, that offset will be added to the client.&#x20;

```javascript
{
    if (client() === 0 ) {
        return "I am the leader with ID 0"
    }
    return "I am the follower with id "+ client();
}
```

A combination of the **client()** and **index()** functions could be used to create some complex scenarios. For example:

```javascript
{
    if ( (client() % 3 == 0) and (index() %5 == 0) ) {
        return "I am a rogue client"
    }
    else { 
        return "I am a good client"
    }
}
```

In the above case, every third client on every 5th iteration will send a rogue message while others will send a good message. The behaviour could also be changed dynamically by using **glob** keys.&#x20;

#### Logging&#x20;

You can call **console.log() or console.error()** anywhere in the function. The output for this would be saved in the results and can be seen in the Logs tab under results. Note that other console functions such as **console.warn()** are not captured and will not be displayed to the user.

```javascript
{
    console.log("This is a log", state.myvariable);
    console.error("This is an error")
}
```

#### Generating Payload

The device model will eventually generate a payload to be sent to the cloud platform. This could be a string or the sender function could also return a binary payload. This is really helpful when dealing with TCP/UDP payload types. For example, let's create a raw payload and send it as a Buffer.&#x20;

```javascript
{ 
  state.content = [0x62, 0x75, 0x66, 0x66, 0x65, 0x72];
  state.content.push(0);

  return Buffer.from(state.content);
}
```

This will result in the following hex content being sent to the server

```
62 75 66 66 65 72 00
```

You can also generate a JSON payload to be sent at the end of the iteration.&#x20;

```javascript
{
    var message = {
        device: "Light_RGB",
        id: client(),
        brightness: state.brightness,
        r_value: state.r_value,
        g_value: state.g_value,
        b_value: state.b_value,
        status: "ON",
      };
    
    return JSON.stringify(message, null, 2);
}
```

This will send a payload which looks like the JSON object below:

```json
{
    device: "Light_RGB",
    id: 99,
    brightness: 45,
    r_value: 230,
    g_value: 230,
    b_value: 250,
    status: "ON",
}
```

#### Skipping message sending

It is important that at the end of processing, the function body must return a value to be sent to the cloud platform. The return value could either be a string or a Node.js binary Buffer object, depending upon what values are accepted by your cloud platform provider. If you would like to skip sending anything for that particular iteration, simply call the **skip()** helper function. This will cause the current payload to be skipped from being sent to the cloud platform.&#x20;

```javascript
{ 
  if (index() == 2){
    skip(); // This will cause payload sending to be skipped
  }
  
  return JSON.stringify(state, null, 2);
}

```

When a skip call is encountered by our back-end simulation engine, the message-sending part will be skipped for the client for that iteration, even though a payload has been successfully generated. This helps in simplifying the code structure for the end user. Note that the skip() effect will be automatically cleared for the next iteration for the client. However, the iteration result will **not** be counted as a failure if the payload is skipped. If you want to explicitly mark the current client iteration as a failure, you could use the **assert(false)** function.


# Scripting Environment


# State Object

We have discussed that a device model describes the behaviour of a device by using different stages. The state object allows us to access data and functions throughout all the different stages.

Every IoT device has several important parameters that can be reported to the cloud platform. An example could be a temperature value read through a sensor or the current CPU load. The device also has some internal parameters such as available SSD and memory usage, which are required to be tracked. While modelling the device, you will need a local store to save these values and any other intermediate variable which needs to be preserved through the life of the simulation. **State** is a JSON object which can be used to save device status. E.g. consider the following code snippet of a simple template:

```javascript
{
    // if temperature has not been defined previously
    if (state.temperature === undefined ) {
        state.temperature = 50;
    }
    state.temperature++;
    return JSON.stringify(state);
}
```

In the very first iteration when this function is invoked, the state object will be empty. The if condition checks this and initializes the temperature with a default value of 50. Since state is preserved across iterations, the temperature value will be set to 51 in the next iteration and it will keep getting incremented by 1 with each subsequent iteration. At the end of each iteration, the function simply stringifies the JSON object and return the string as a payload. Here is what the first payload sent from this function will look like:

```javascript
{
   temperature: 51
}
```

The state object is available through all of the function calls. It is important **not** to use a similarly named variable in your local function or scope to avoid confusion and namespace conflicts.&#x20;

> It is not necessary to always stringify and return state as a payload. You could choose to send any string or even a Node.js Buffer as a return value of the function.

In this example, we are only sending two properties of the state as a payload and not the entire object.&#x20;

```javascript
{
   var retVal = {
      myval: state.myval,
      myString: state.myString
   }
   
   return JSON.stringify(retVal);
}
```


# Response Handler

IoT communication is bidirectional in nature, it includes both device-to-cloud and cloud-to-device communication. So far we have seen how to generate messages and send them to your IoT platform. Let's discuss how to handle the messages or commands coming from the server side.

The responses are handled by the receiver function in the device model. To handle such responses, go to the stage you want the logic to be in and then switch to the Receiver tab.

The handling of these messages are specific to the protocol in use, however, the common functions remain the same.&#x20;

```javascript
function receiver(response)
{ 
    console.log("Received a message on the subscribed topic ", response)
    state.received++;                
    state.recv_queue.push(response);            
}

```

It is important to understand that while a simulation is running, the handler may be invoked asynchronously. This is because the command from the server side could be initiated at any time. To be on the safer side and avoid any race condition, the subscription handler should be small and defer all actions to be executed in the next iteration call. In the above example, we have simply produced a log and pushed the received message to the receive queue.&#x20;

{% hint style="info" %}
Note that the subscription handler does not need to return any value.&#x20;
{% endhint %}

{% hint style="info" %}
The subscription handler could be invoked multiple times asynchronously while your simulation is running. That's why the results of the subscription should be stored in a queue rather than being processed, as a second run could overwrite the previous run's results.&#x20;
{% endhint %}

While the basic function of the response handler is the same, the data that it contains varies with the protocol. To understand how to handle the data that is received for each protocol, follow the examples given below.

**Response Handler for MQTT**

In MQTT, a client could subscribe to any particular topic. The subscription topic can be specified in the template by enabling the subscription button in the protocol tab. When a publication is received on the chosen topic, the subscription handler is invoked with&#x20;

```javascript
function(response)
{
   //response.topic   - The MQTT topic on which subscription has been received
   //response.message - A buffer object which is sent for the subscription 
}
```

**Response Handler for HTTP**

In HTTP, the custom handler is invoked with the result of the operation performed. For example, if you did a POST operation, you could handle the response sent by the server.&#x20;

```javascript
function(response)
{
   //response.header - The header info for the operation that was performed
   //response.status- The status for the operation that was performed
   //response.body   - A buffer object which is sent by the server
}
```

**Response Handler for NONE**

In NONE, if loopback is set to on. The payload that was supposed to be sent is received back.

```javascript
function(response)
{
   //response - The payload that was sent by the sender function
}
```


# Preview Tests

Before we actually start a simulation run, it can be a good idea to validate if a connection can be established to the server. To make sure that we can connect to the server, we will preview the test.

To preview any test, go to the Test Editor and click on the Preview button on the top right of the screen.

<figure><img src="/files/dWAeaW2wlatu75SMa9cN" alt=""><figcaption></figcaption></figure>

When we hit Preview, the simulation engine tries to establish a connection to the server with the authentication and then runs the Init stage of the test.&#x20;

Once the Init stage has been run a report is generated with all the data and displayed to the user.

<figure><img src="/files/9nj8iVGk99eNfdNvGlYe" alt=""><figcaption></figcaption></figure>


# Exporting/Importing Tests

When you have finalised your tests, you may want to take a local backup of the test, or you may want to send the test that you're working on to another person. For such cases, we allow you to export the whole test as a JSON file, that is easy to understand.

### Exporting

To export any test, go to the Tests interface by clicking on Tests in the left navigation drawer. Now move your cursor to the 3 dot icon at the bottom right of the test you want to export.&#x20;

<figure><img src="/files/PpMFiLe87BTgYTZ3PBqy" alt=""><figcaption></figcaption></figure>

This will open an overflow menu where you will get the option to export your test. Click on Export and the JSON file will be downloaded to your system.

### Importing

If you have a JSON definition of a test and you want to import it back to the platform, just go back to the Tests interface and click on the Import button on the top right of the screen.&#x20;

This will open another overflow menu, here click on `Import IoTIFY Test`. This will open a file picker, navigate to the folder where you have stored the JSON file and open it.&#x20;

<figure><img src="/files/GivyYrQCQ8qCasOjMUoh" alt=""><figcaption></figcaption></figure>

The file will be uploaded and parsed and the test will be added to your workspace.


# Import OpenAPI JSON/YAML

IoTIFY allows you to create a basic test for your API endpoints with intelligent payloads and simple automations in one click. Export your API specifications as an OpenAPI 3 JSON or YAML file and IoTIFY can do the work for you.

To get started, go to the Tests interface and click on the Import button on the top right of the screen.&#x20;

This will open another overflow menu, here click on `Import from OpenAPI/Swagger YAML/JSON`. This will open a file picker, navigate to the folder where you have stored the JSON or YAML file and open it.&#x20;

<figure><img src="/files/vhNVfHreJQgbRlu8tSK4" alt=""><figcaption></figcaption></figure>

The file will now be uploaded and parsed and a new test will be automatically be created and added to your workspace.

<figure><img src="/files/bmwPCBYVBev45Q9D7Gk4" alt=""><figcaption></figcaption></figure>

Click on this test to open up the definition and you will see intelligent payloads being created for each method for each route mentioned in the API specifications.

<figure><img src="/files/vNKPrtSP9qvwqLK4rvnl" alt=""><figcaption></figcaption></figure>

Now you just need to add the base server path and you are ready to test your API endpoints.

{% hint style="info" %}
While the engine is smart enough to understand things like names, addresses, and so on and add intelligent payloads. It can sometimes fail to understand what a particular variable demands. In those cases, it is left as `"UNRECOGNIZED"`.&#x20;

It is a good practice to go through all the stages and fix these before running the simulation.
{% endhint %}


# Locking/Unlocking a test

With workspaces, it becomes really easy to collaborate with your teammates. Everyone in the workspace can access the same tests and work on them (granted they have proper permissions). However, while you are working on any test in the workspace, you would not want another person to be able to open and modify the test at the same time.&#x20;

To avoid this situation, when a workspace has multiple users, once any user starts working on a test and saves it, the test is locked for everyone else. When a test is locked, a small lock icon is shown beside its name in the test list.

<figure><img src="/files/wfhSnUdYR3SrqsgGDD7f" alt=""><figcaption></figcaption></figure>

Everyone else will still be able to open the test and view the contents and even start simulations for the test, but they can't modify the test until it is unlocked.

<figure><img src="/files/MqKgvmkJPIDL6oYXAyKM" alt=""><figcaption></figcaption></figure>

The user who has locked the test has an Unlock button, which they can use to unlock the test. The test will automatically get unlocked if the user has closed the tab or if there was no activity for over 30 minutes. Additionally, any user with an Admin role in the workspace will also have the Unlock button in the test editor.

<figure><img src="/files/LCdSAAfhx2De5VlFGGvK" alt=""><figcaption></figcaption></figure>


# Stateful Simulation


# Mapping the IoT device lifecycle

One of the first step to get started with IoT simulation is to map your device lifecycle into states and events.

### What is a device lifecycle?

Every IoT product has a defined lifecycle which takes into account the various distinct software and hardware conditions. Before starting with an IoT device simulation, it is important to research and visualize the complete device lifecycle and it's corresponding state. Let's take the example of a smart light bulb. It typically has following life stages -

![](/files/-Li8u4N283n3yWpsZeVg)

**Factory**: A light bulb is manufactured at factory and is assigned a unique serial number. An initial firmware is installed on that bulb and a power on test is performed. Device connectivity is tested and upon verification all the test data is erased and bulb is again brand new.&#x20;

**User Purchase:** Bulb is sold to an end customer who installs it and bootstraps for the first time. Bulb connects to the API backend, gets the information about user account and is registered with the user profile.&#x20;

**API Configuration:** The bulb is assigned a unique identity in the backend aka Digital Twin. User uses the bulb through a mobile App. A smart home device like Alexa also controls the bulb through remote APIs.&#x20;

**Software Management:** A software download is triggered for the bulb. The App uploads the latest firmware on it and then it reboots.&#x20;

**Replacement:** After a while the bulb is defective or it's life runs out, user initiates a replacement. The replacement arrives and the previous profile of the bulb is reassigned to the new bulb.&#x20;

**Recycling:** The old bulb is now marked defective and can no longer be used to connect with the app or the backend. Any attempt to access the backend service through the old bulb must now be marked a suspicious activity and should immediately be flagged.&#x20;

During these stages of the lifecycle, there are several persistent parameters which are associated with the bulb. Let's take a look at them&#x20;

| Property      | Sample Value | Description                                         |
| ------------- | ------------ | --------------------------------------------------- |
| SW version    | R9.123.1.1   | A string describing current version of the software |
| Serial Number | L32112112234 | An Alphanumeric unique identifier of the bulb.      |
| Power State   | 1            | Specify whether bulb is currently powered on/off    |
| Colour Value  | 0x334422     | A hex value describing current colour of the light  |
| Intensity     | 78           | Intensity of the light.                             |
| Location      | Bedroom      | A user assigned string identifying bulb's location  |
| Lifetime      | 3442         | Number of hours the light bulb has been switched on |

Even though our example of bulb was a preliminary one, we saw that managing device state could be quite challenging. Any lifecycle event on the bulb may alter one or more of its property. It's important to prepare all the lifecycle state and events in advance and then create a state diagram mapping the transition of stages. Once it is prepared, we are ready to simulate device in IoTIFY.&#x20;

{% hint style="info" %}
&#x20;It is important to classify the type of the device parameters e.g. constant and variables.&#x20;

E.g. Serial number once assigned can not be changed. Software version is a read only variable which usually comes from the software itself and can not be overwritten. Power State could be triggered by the user or the backend API as well and user preference may overwrite the API actions.&#x20;
{% endhint %}

The device lifecycles once mapped would provide you the top level logical states of the device. A device can be in any of these states at a given point of time. Let's build a state machine out of it.&#x20;

![Device States for a light bulb](/files/-M7gOB4fkJrpH9_Ja1rf)

We have mapped the device state into three major states.&#x20;

**Factory**: The device is manufactured, the serial number is assigned and a basic firmware is loaded on the device. Power On Self test is passed and device is shipped.

**In Use:** A customer purchases the devices, opens it and powers it on for the first time. Device is connected through the app and a software update is performed. Device is now mapped into user's account. In this mode, device will periodically send data to the cloud platform, receive commands from the cloud or through the local mobile app from the user. A new software update shall be installed periodically on the device.&#x20;

**Deactivate**: The device is defective or is thrown away for recycling by the customer. The serial number should be marked invalid and device shouldn't be allowed to download software or access the cloud backend.&#x20;

Now we have got some top level idea about how to map a simulated device behaviour to states and transitions, lets delve a bit more into mapping this behaviour into a test for the device.&#x20;


# Protocol Settings

IoTIFY Supports multiple protocols to connect with cloud platforms. Let's discuss each of these protocols in detail.

The protocol settings specify the connection parameters for connecting to the server.

To learn how to use MQTT with IoTIFY, refer to this page:

{% content-ref url="/pages/-M8PO4VkU-3B2r5\_87Eb" %}
[MQTT](/concepts/protocol-settings/mqtt)
{% endcontent-ref %}

To learn how to use HTTP with IoTIFY, refer to this page:

{% content-ref url="/pages/-M8PVcRU98GQb6KywZO7" %}
[HTTP](/concepts/protocol-settings/http)
{% endcontent-ref %}

You can also use any other protocol according to your needs. To learn how you can use additional protocols, refer to this page:

{% content-ref url="/pages/Sl4G8fkxXBZPGUsWthM8" %}
[Using other protocols](/concepts/protocol-settings/using-other-protocols)
{% endcontent-ref %}


# MQTT

MQTT is the most widely used and known protocol for IoT devices. Let's have a basic look at MQTT and how could we use it with IoTIFY

The MQTT protocol is based on TCP and is one of the most commonly used publish/subscribe protocols in use today. For a detailed overview of MQTT let's refer you to the Hivemq tutorial which has covered this subject pretty well.

{% embed url="<https://www.hivemq.com/blog/mqtt-essentials-part-1-introducing-mqtt/>" %}

What should you know about MQTT?

1. MQTT requires that all client connect to a broker. There are several public broker available today and you could launch your own MQTT broker as well.&#x20;
2. The clients of MQTT publish data on the topics which are hierarchical in nature. E.g. A topic could be formed for a university as follows:
   * /university/
   * /university/EECS/
   * /university/MECH/
3. MQTT protocol provides three quality of service(QoS) levels:&#x20;
   1. QoS 0: **at most once**
   2. QoS 1: **at least once**
   3. QoS 2: **exactly once**

### Overview of MQTT Template Settings

![](/files/EAUUMAXQkteimwsyoCWc)

In the protocol tab, you can modify several settings for the MQTT Protocol:

**MQTT Endpoint**: The name or IP address of the server along with the port number. It must be a public server IP address that is reachable over the internet.&#x20;

**Keep Alive**: The keepalive timer duration for the protocol. The hello message is sent every keepalive interval to make sure the server is aware of the client being connected.&#x20;

**QoS**: QoS settings ensure that the delivery of the message is guaranteed. Higher the QoS Settings more will be the latency of packet sending as the server will need to ensure that the messages are delivered with a guarantee.&#x20;

**Retain**: Whether the server should retain the messages for a future delivery.&#x20;

**Publication Topic**: The topic on which messages should be published. The topic field is scriptable, i.e. you could use template strings in **Topic** to dynamically change the content of the topic. For example,

```
/iotify/temperature/{{client()}}   // will translate to /iotify/temperature/0 
```

Any field within {{ }} will be evaluated at runtime and will be replaced with the actual contents.&#x20;

```
/iotify/temperature/{{state.topic}}    
```

Will change to whatever state.topic variable value is at the run time. For performance reasons, make sure that the fields are not too complex.&#x20;

**Subscription Topic**: (Can be enabled when required) The topic to which the client should subscribe. This field is scriptable but only at the beginning of the simulation (after the Init stage). For example, if you use {{state.topic}} within the Subscription Topic string, the subscription will be initialized to whatever value the topic had past the Init stage. However, the content will not change as the simulation runs.&#x20;

**Timeout**:  The timeout value to establish a connection with the server and wait for the messages to be sent. If the operation doesn't complete within the timeout period, it is marked as failed.&#x20;

**Security**: If the connection to the server requires authentication, the required fields can be passed here. For MQTT connection we support:

* Username and Password combination
* Pre-Shared Keys
* Certificates


# HTTP

Many of the IoT devices also use HTTP as a connectivity option. Let's see what HTTP parameters could be configured.

![](/files/WfsCfSzVRKeFIwhmpN8a)

HTTP is very common as most of the web runs on it. The following fields could be configured in the IoTIFY HTTP client:

**Protocol:** Specify whether to use HTTP Secure or unsecured HTTP. It is always recommended to use secure HTTPS even if you don't have any security settings such as a password or preshared key.&#x20;

**Method:** HTTP Rest method to use.

**Endpoint:** The Rest API path to which you are connecting. This field is also scriptable, which means you could dynamically change the path at the run time with a templated string such as <http://httpbin.org/api/v1/\\{{state.endpoint\\}}>

**Timeout:** The timeout value after which the iteration must be marked as failed if no response is received.&#x20;

**Additional Headers:** Configure any additional REST headers here. They may be useful to pass any bearer tokens or other authentication headers. The fields in this are scriptable and could be used with templated strings such as "**Bearer {{state.token}}"**&#x20;

{% hint style="info" %}
IoTIFY also enables REST APIs usage within the device model functions. Check [here ](/additional-helpers/iotify-helpers#calling-http-rest-apis-rest-get-or-post-or-put-or-patch-or-delete)for more details.&#x20;
{% endhint %}


# Using other protocols

We allow the usage of a wide variety of protocols by the help of NPM packages. If there is any protocol you want to use, you can search the [npm repository](https://www.npmjs.com/) for a library for that protocol and then import it into the test.

<figure><img src="/files/25K9c8TfZz1KtJ8VkRHr" alt=""><figcaption></figcaption></figure>

Once you have found the library, you can copy the library name, now go to the test you want to use the protocol in. In the test editor, go to the Library tab and paste the library name. You also need to set the variable name via which you will invoke the library methods.&#x20;

<figure><img src="/files/poqytM6WCJP23pXtrYE9" alt=""><figcaption></figcaption></figure>

You will find all the method descriptions on the npm page of the library.

{% hint style="info" %}
You can also use these protocols with MQTT and HTTP at the same time.
{% endhint %}


# Run Settings

Once the device model has been finalized, the run settings define the parameters regarding the simulation of the devices.

Once the device model is ready, before running the simulation, we have to define the parameters of the simulation. This tells us about the scale of the simulation, and the frequency of the messages being sent.

Go to the **Run Settings** option in the left menu bar. Here we can create and update different run settings for our tests. The run settings are accessible whenever we want to run a test including from the **Tests** screen and the **Results** page.&#x20;

![](/files/q2KDeJ8oU4l7Kzkvj3iP)

To create a new run setting, click on the `Add new` button on the top right corner of the page.

<figure><img src="/files/C2vHsATp1IWY9qSserGQ" alt=""><figcaption></figcaption></figure>

This will open up a form where you can set all the required properties and when you are done, hit Save. The new run setting will be saved and shown in the list.

<figure><img src="/files/bZvhS88jtBNRcMqUKFzO" alt=""><figcaption></figcaption></figure>

To edit any of the already available run settings, click on the blue edit button on the corresponding run setting card. This will open a similar form to the one we used to create the run setting.

<figure><img src="/files/7ZEUEETU1ncq25Fen4hf" alt=""><figcaption></figcaption></figure>

To delete a run setting, click on the red delete button on the corresponding run setting card. The selected run setting will be deleted.

Here is a quick explanation of the settings

### Basic Parameters

**Current Run Settings:** Here we can choose from a list of previously defined run settings or create a new one. These run settings are accessible throughout IoTIFY.

**Clients**: Specify how many total clients you want to launch here. This is limited by your current account settings and can be upgraded based on your license. &#x20;

**Iterations**:  The number of times this simulation will repeat itself.&#x20;

**Iteration Interval**: The gap between the end of one iteration and the start of the next iteration.

**Max Simultaneous Clients Connection**: The maximum number of clients that can connect to the server at any given time.

**Client ID Offset**: By default, the client IDs start from 0, if you need to offset the client ID, it can be done here.

**Gap Between Each Client**: The interval between each individual client. In other words, how fast the messages should be sent to the server. This will decide the total duration of the simulation.&#x20;

**Client Group Size**: The clients are batched into groups which are simulated with the Network Agents, this will tell the backend how many clients should be in one batch.

**Gap Between Each Group: T**he interval between each individual group of clients.

You can also choose what to save for the results of the test. You can choose to save the Logs, State and Payloads according to your needs. The results which you choose to keep will be visible in the test results.

{% hint style="warning" %}
Keep in mind that you can't change these settings once the test has started.
{% endhint %}

{% hint style="info" %}
In a real-world test, due to server and client latencies, the gap between two messages may be larger than what is specified. Thankfully, in the result analysis tab, you could see how exactly the mean, minimum and maximum latencies have been measured.&#x20;
{% endhint %}


# Network Simulation


# Execution Strategies


# Client Distribution


# Scenarios

### Introduction

There may be times when you need to orchestrate multiple tests all depending on each other. This can be quite tiresome since you need to keep checking the status of the currently running test and start another test when it reaches the required pass or fail status.

With Scenarios, we make it a lot easier for you to orchestrate such complex workflows so that you don't have to spend considerable time on such issues. You can use the easy-to-use editor to create these custom workflows and you can run it at any time with just one click.&#x20;

![](/files/niQaoK6OcfTFPvZfnFkE)

To start using Scenarios, click on the `Scenarios` options in the sidebar. This will take you to the Scenario selector, where all the scenarios that you have created will be listed. To create a new scenario, `Create Scenario` button on the top right corner.&#x20;

![](/files/shs0OVV1YnqgGhuhvIYY)

This will bring you to the Scenario Editor, which is an easy-to-use interface for creating these workflows. The top of this editor has the name of the scenario and control buttons for saving, running, stopping and resetting the scenarios. Below is the actual working area which is divided into 2 parts.

![](/files/2Sm8L0cHALO6WExnsAzF)

The left houses all the different types of nodes that are supported by us and the right side is where we can drag these nodes and start connecting them to create the workflows. The editor already has a start and an end node and you can connect as many nodes in between as required.

The 2 nodes that we can use are the `Test Nodes` and the `Delay Nodes`. The test nodes are the nodes which actually run the simulations, here we can select the test from a dropdown menu. You can select any test you have in your workspace, then select a `timeout` for this test run, set the Pass and Fail condition percentages and finally the `Run settings` you want with the particular test. With the delay node, you can have an additional delay after any test run.

{% hint style="info" %}
It is a good practice to have a small delay of a few seconds between 2 subsequent test runs.
{% endhint %}

Once you have laid and configured all the nodes, you can join them according to the pass and fail conditions. Each node has 2 outputs, the green being the output for the pass condition and the red being the output for the fail condition. Once all the nodes are connected, you can start running the Scenario.

![](/files/3h07jrPJGJxIOXoeibR7)

The nodes will change their colors according to their status (blue: ongoing; red: failed; green: success) and the results for the individual test runs can be found in the results page.

![](/files/3yIQK1EOwuGGGxHqyWui)


# Glob Storage

Glob is the persistent key-value store that forms an integral part of IoTIFY. The Glob storage behaves like a common storage block for all the tests. It is private to your workspace, which means only people that have been added to the workspace can access the glob storage. It can also be accessed by all the tests in the workspace.

The key-value pattern allows for a simple and fast storage solution which is easy to integrate into your tests. The glob can be used in a lot of ways, like, to sync between multiple jobs, control the simulation behaviour dynamically or revert back from the last state of the device to name a few.

There are two ways to interact with the Glob storage:

* Via the GUI
* Via Functions inside the tests

Firstly let's talk about the Glob storage option in the IoTIFY app, to get started, click on the `Glob` option in the sidebar. This will open the Glob page. Here you will be able to see all the entries that have been made to the Glob storage from all the tests in your workspace. You can Edit or Delete the individual entries, Add new entries or choose to clear the Glob by deleting all the entries.

![](/files/5nfcPxcKzogJv6peQndW)

Another option that is available here is to export all the data in the Glob to create a backup, which can be downloaded and stored locally. For Enterprise customers, a cloud backup option is also available. These backups can be used to restore the Glob to its previous state.

![](/files/KiEmq3veep2gWlNOCgzO)

The second way to interact with the Glob storage is via the functions available inside tests. This is how you can utilize the Glob storage inside your simulations.&#x20;

To understand how you can integrate Glob APIs inside your tests, please check our Glob Functions page.

{% content-ref url="/pages/ZR0a74r84H1xieJRltQv" %}
[Glob Functions](/additional-helpers/iotify-helpers/glob-functions)
{% endcontent-ref %}


# Metrics

We log certain metrics like message latency and sending latency by default for all simulation jobs. Additionally, you can also see the system metrics like the number of MQTT connects, total bytes sent via MQTT and more by the `System-wide Metrics` toggle.

![](/files/DAcJogo6WrK7sqbhJUnL)

You can also log your own custom metrics inside any test using a simple command. You can find the details on the page linked below:

{% content-ref url="/pages/J2FVWPxhfR4cfCyTENev" %}
[Metrics Functions](/additional-helpers/iotify-helpers/metrics-functions)
{% endcontent-ref %}

Once these custom metrics have been logged, they will show up in the dropdown just like the other metrics.

You can also download these charts and export the data in multiple formats by clicking on the hamburger menu in the top right corner of the chart.


# Mailbox

In IoT systems, devices can also talk to each other apart from communicating with the server. With IoTIFY you can also simulate such LAN connections between the devices using the Mailbox.

At its core, Mailbox is basically a fast array that the devices can push to and read from. All the simulations in your workspace can access the mailbox at any time.

You can see all the data that is currently in the Mailbox, by going to the Mailbox from the left navigation pane. Here, you can also Add new entries to the Mailbox, clear the whole Mailbox, or export the data.

<figure><img src="/files/FQbUX5wTj1V87aw7MMiT" alt=""><figcaption></figcaption></figure>

To get started with LAN simulation using Mailbox, you can use the Mailbox Hub and the Mailbox Thermostat sample tests and follow [the guide present here](https://blog.iotify.io/lan-simulation-using-the-iotify-mailbox-api-143c0ae6c315).

<figure><img src="/files/uef0WuvO6eA0VGYx3f1l" alt=""><figcaption></figcaption></figure>

To learn more about the methods available to interact with the mailbox in your test, you can refer to the page linked below:

{% content-ref url="/pages/IqNQX9ZKs1NlYpCwQ1Wr" %}
[Mailbox Functions](/additional-helpers/iotify-helpers/mailbox-functions)
{% endcontent-ref %}


# Licensing and Limits

While the base tier of IoTIFY is available free to use for everyone, there are some limitations to what can be used in the free tier. To fully unlock the power of IoTIFY, you can upgrade to our higher-tier packages.&#x20;

The Limitations are applicable to the features/aspects mentioned below:

* Number of virtual devices
* Number of parallel simulation jobs
* Duration of the simulation run
* Access to certain protocols
* Ability to create multiple workspaces
* Access to Scenario Editor
* NPM package support
* API access
* And more

To find more about the pricing and different tiers that are available, please refer to the pricing page at: <https://iotify.io/pricing/>


# Deployment Models

This page details the deployment options available for IoTIFY

Being a platform purpose-built for IoT, we have done a lot of custom engineering to make our systems as performant and efficient as possible. The following are the ways in which you can use IoTIFY.&#x20;

1. Public Hosted Application: IoTIFY is accessible at <https://nsim.iotify.io> for developers and small teams to use.&#x20;
2. Domain-Separated and Managed Deployment: As part of an enterprise license, you can request a managed and domain-separated deployment of IoTIFY. This will be accessible through a custom domain and ensures the data is logically separated from the Public facing application mentioned above. The infrastructure and application are managed by IoTIFY.&#x20;
3. On-prem Deployment: If you wish to deploy IoTIFY on your own VPS, Our team will help you get this set up. IoTIFY can run on any managed Kubernetes Cluster. Please [contact us](https://iotify.io/contact-us) for further details.&#x20;


# External Libraries

IoTIFY supports importing additional libraries and scripts to make your life easier

In a lot of cases, you may require some functionality in your code which can be easily solved by importing an existing library or a script. Writing custom logic for everything can be time-consuming and may not always be helpful. Hence, with IoTIFY, you can import any NPM package or a custom script you can find online to help you write your code easily.

To import any library or a custom script, go to the Library tab and here you can add up to 5 libraries and scripts in total.

![](/files/jWOURhNh00S4y13HiMiW)

**Import As**: Name of the module object that will be used as a kind of namespace when referring to the imported library.

**Type**: Select whether you are importing an NPM package or a custom script.

**NPM Package or Public node script**: The name of a valid NPM package or an URL to the custom script. When a valid package name or URL is given the icon beside the input turns into a tick mark. This means that it is a valid package and can be imported into the test.

To delete any of the packages, you can click on the cross icon at the right end of the library.

{% hint style="warning" %}
You can only import up to a total of 5 additional packages into the tests. &#x20;

Many commonly used libraries are already inbuilt into IoTIFY, which you do not need to separately import. We will look into all the inbuilt libraries shortly.
{% endhint %}


# Inbuilt Libraries

A summary of external helper libraries available in the tests

There are many additional external helper functions available in the scope of the test body. Let’s have a short look at them.

### Chance.js <a href="#chancejs" id="chancejs"></a>

[Chance.js](https://chancejs.com/) is a random content generation library which is quite useful to generate data. For example, if you wanted to generate a random street address, you can use chance.js:

```javascript
state['street'] = chance.address();
state['city'] = chance.city();
state['zip'] = chance.zip(); 

return JSON.stringify(state);
```

And voila, you have a completely random fake street address.

### Day.js <a href="#momentjs" id="momentjs"></a>

[Day.js](https://day.js.org/) is another useful library, especially to manipulate time. In the example given below, we will calculate the elapsed time since the simulation started (iteration 0)

```javascript
{
    if (state['start'] === undefined) {
        state['start'] = dayjs();
    }

    state['elapsed'] = dayjs(state['start']).fromNow();

    return JSON.stringify(state);
}
```

### Underscore.js/Lodash <a href="#underscorejs" id="underscorejs"></a>

[Underscore.js](http://underscorejs.org/) is another popular library that is a must-have for serious javascript programmers. Here is an example of filtering even values in an array:

```javascript
{

    var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) {
        return num % 2 == 0;
    });

    return JSON.stringify(evens);
}
```

### DeAsync.js <a href="#deasync-js" id="deasync-js"></a>

[DeAsync.js](https://github.com/abbr/deasync) can be used to create synchronous behaviour out of async or callback-based functions. Though async functions should be used as much as possible, in some cases, DeAsync could make life easier. For Example, in the code snippet given below, we are waiting for the callback function to finish while calling setTimeout() async function.

```javascript
{
    var ret;
    setTimeout(function() {
        ret = "hello";
    }, 3000);
    while (ret === undefined) {
        deasync.sleep(100);
    }
}
```

### JSON Web Tokens <a href="#json-web-tokens" id="json-web-tokens"></a>

JSON web tokens are gaining popularity as an authorization mechanism. IOTIFY tests support creating JWTs by integrating the [jsonwebtoken](https://github.com/auth0/node-jsonwebtoken) NPM library.

```javascript
{
  var token = jwt.sign({ foo: 'bar' }, privateKey, { algorithm: 'RS256' });
}
```

### Geolib

[Geolib](https://github.com/manuelbieh/Geolib) is a useful library for geospatial operations or for manipulating locations. For example, to get the distance from Delhi to a specified coordinate, use the following code snippet:

```javascript
{
   var distance = geolib.getDistance( 
   location('Delhi'), 
   {latitude: 51.519475, longitude: 7.46694444});
}
```

### Geohash

[Geohash](https://github.com/sunng87/node-geohash) allows the conversion of Latitude and Longitude pairs to a geohash and vice versa.&#x20;

```javascript
{
    let hash = geohash.encode(37.8324, 112.5584);
    var latlon = geohash.decode('ww8p1r4t8');
}
```

### Native built-in objects <a href="#native-builtin-object" id="native-builtin-object"></a>

There are several built-in modules available in the function body. [Math](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math) is one of them which is quite useful for arithmetic operations.


# IoTIFY Helper Functions

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

{% content-ref url="/pages/gzdGrEUDnXWusnGiS8hK" %}
[Job Functions](/additional-helpers/iotify-helpers/job-functions)
{% endcontent-ref %}

{% content-ref url="/pages/YWBqUxjfjJ6nHgqxFO82" %}
[Messaging Functions](/additional-helpers/iotify-helpers/messaging-functions)
{% endcontent-ref %}

{% content-ref url="/pages/ZR0a74r84H1xieJRltQv" %}
[Glob Functions](/additional-helpers/iotify-helpers/glob-functions)
{% endcontent-ref %}

{% content-ref url="/pages/J2FVWPxhfR4cfCyTENev" %}
[Metrics Functions](/additional-helpers/iotify-helpers/metrics-functions)
{% endcontent-ref %}

{% content-ref url="/pages/IqNQX9ZKs1NlYpCwQ1Wr" %}
[Mailbox Functions](/additional-helpers/iotify-helpers/mailbox-functions)
{% endcontent-ref %}

{% content-ref url="/pages/3UiDPLCScn1x9FQPlGWh" %}
[Data Generation Functions](/additional-helpers/iotify-helpers/data-generation-functions)
{% endcontent-ref %}


# Job Functions

The Job functions allow you to get information on the currently running job so that you can create tests that can work dynamically in relation to the current state of the simulation.

The various functions are listed below:

#### **`getRunSettings()`**

Use the `getRunSettings()` function to retrieve the run settings for the currently running job. The function returns an object with all the data pertaining to the run settings.

{% code title="Function:" %}

```javascript
getRunSettings()            //no arguments are required

console.log("The current run setting is "+getRunSettings().name)

//returns an object with the full run settings
```

{% endcode %}

{% code title="Response:" %}

```json
{
	id: '6246fbe5fdee1fd07c3bb331',
	name: 'Default',
	interval: 10000,
	iteration: 10,
	clients: 10,
	totalClients: 10,
	clientIdOffset: 0,
	clientGroupSize: 1000,
	maxParallelClients: 0,
	maxMessagesPerSecond: 0,
	captureLogs: true,
	captureState: true,
	capturePayload: false,
	interClientGap: 0,
	interGroupGap: 0,
	externalSync: true,
	strategy: 'Default',
	groupIndex: 0
}

The current run setting is Default
```

{% endcode %}

#### **`jobClients()`**

This function returns the total number of clients that are being simulated in the current job.

{% code title="Function:" %}

```javascript
jobClients()            //no arguments are required

console.log("Total clients for the job are "+jobClients())
//returns a number with the number of clients
```

{% endcode %}

{% code title="Response:" %}

```json
10

Total clients for the job are 10
```

{% endcode %}

#### **`jobId()`**

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

{% code title="Function:" %}

```javascript
jobId()                    //no arguments are required

console.log("The current running job is "+jobId())

//returns a string with the job name generated by the system
```

{% endcode %}

{% code title="Response:" %}

```json
ebaf0e09-7d8a-4b53-8182-55a2d3dc2230

The current running job is ebaf0e09-7d8a-4b53-8182-55a2d3dc2230
```

{% endcode %}

#### **`jobInterval()`**

Returns the time interval in seconds between each iteration.

{% code title="Function: " %}

```javascript
jobInterval()            //no arguments are required

console.log("There is a gap of "+jobInterval()+" seconds between iterations")

//returns a number with the time interval in seconds
```

{% endcode %}

{% code title="Response:" %}

```json
10000

There is a gap of 10000 seconds between iterations
```

{% endcode %}

#### **`jobRepeat()`**

Returns the total number of iterations specified in the job.

{% code title="Function:" %}

```javascript
jobRepeat()                //no arguments are required

console.log("The job will repeat "+jobRepeat()+" times")

//returns a number with the amount of times the simulation will repeat
```

{% endcode %}

{% code title="Response:" %}

```json
10

The job will repeat 10 times
```

{% endcode %}

#### `index() or iteration()`

For the simulations, you will specify the number of iterations that a test should run for. To get the value of the current iteration that the simulation is in, you can use the **index()** or **iteration()** functions

{% code title="Function:" %}

```javascript
index()                    //no arguments are required
iteration()                //no arguments are required

console.log("The job is currently in iteration number "+iteration())

//returns a number with the current iteration
```

{% endcode %}

{% code title="Response:" %}

```json
3
3

The job is currently in iteration number 3
```

{% endcode %}

#### `client()`

For the simulations, you may need to implement client-specific behaviours. The current client ID can be determined within the test by using the **client() function**.

{% code title="Function:" %}

```javascript
client()                    //no arguments are required

console.log("The current client ID is "+client())

//returns a number with the current client ID
```

{% endcode %}

{% code title="Response:" %}

```json
15

The current client ID is 15
```

{% endcode %}

#### `assert()`

Usually, an iteration for a client will be marked as failed, when the 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 are not met.&#x20;

When using IoTIFY for testing, you could force a test iteration to be failed even if message sending is successful using test assertion with the **`assert()`** function.

The function takes two parameters:

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

For example, the following statement checks for an assertion failure in your template and marks the test result as failed, if `retval` does not equal to 123.

```
//Takes a boolean condition and a string message as arguments
assert(condition, message)

assert(retval == 123, "Return value doesn't equal "+123);

```


# Messaging Functions

### HTTP REST APIs

Within your device template, you could call a REST API and get data from an external source, or push data to an external service.&#x20;

#### GET Requests

```javascript
//requires the resource URL as the argument
rest.get({url: ''})  

rest.get({url:'https://httpbin.org/get'})

//you can also create a separate object for the argument and pass it to the API 
//headers are also supported
let options = {
	url: "https:https://httpbin.org/get",
	headers: {
		'content-type': 'application/json'
	}
}

rest.get(options)  
```

#### POST Requests

```javascript
//requires the resource URL and a message object as the arguments
rest.post({url: '', json: {}})

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

//you can also create a separate object for the arguments and pass it to the API  
let obj = {
	username: "test_user",
	password: "dontusethis"
}

//headers are also supported
let options = {
	url: "https://httpbin.org/post",
	json: obj,
	headers: {
		'content-type': 'application/json'
	}
}

rest.post(options);
```

#### PUT Requests

```javascript
//requires the resource URL and a message object as the arguments
rest.put({url: '', json: {}})

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

//you can also create a separate object for the arguments and pass it to the API  
let options = {
	url: "https://httpbin.org/put",
	json: { hello: 'world'},
	headers: {
		'content-type': 'application/json'
	}
}

rest.put(options);
```

#### PATCH Requests

```javascript
//requires the resource URL and a message object as the arguments
rest.patch({url: '', json: {}})

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

//you can also create a separate object for the arguments and pass it to the API  
let options = {
	url: "https://httpbin.org/patch",
	json: { hello: 'world'},
}

rest.patch(options);
```

#### DELETE Requests

```javascript
//requires the resource URL the argument
rest.delete({url: ''})

rest.delete({url:'https://httpbin.org/delete'})

//you can also create a separate object for the arguments and pass it to the API  
let options = {
	url: "https://httpbin.org/delete",
	headers: {
		'content-type': 'application/json'
	}
}

rest.delete(options);
```

### MQTT APIs

Within the device template, you can use the MQTT APIs to interact with the MQTT connections.

#### Publish

To publish a message to an MQTT endpoint, you can use the following function.

```javascript
//requires a payload object and a topic string as arguments
mqtt.publish(payload, topic)

let payload = {
    hello: 'world'
}

let topic = "testTopic"

mqtt.publish(payload, topic)
```

#### Resubscribe

To resubscribe to multiple topics use the following function.

```javascript
//requires an array of topics as the argument
mqtt.resubscribe([topics])

mqtt.resubscribe([topic1, topic2, topic3])
```

#### Force Disconnect

To disconnect from all MQTT topics and close all connections, use the following function.&#x20;

```javascript
//no arguments are required for this function
mqtt.forceDisconect()
```

#### Force Connect

To connect to all previously connected MQTT connections, use the following function.

```javascript
//no arguments are required for this function
mqtt.forceConect()
```


# Glob Functions

IoTIFY provides a simple, fast and persistent key-value storage that is private to your workspace and accessible to all your running jobs. The key-value storage could be used for multiple purposes, For example, to sync between multiple jobs, control the simulation behaviour dynamically or revert back from the last state of the device.&#x20;

The different functions that you can use to interact with the Glob are:

#### SET

```javascript
//requires a string key and a value which can be of any type
glob.set(key, value)

glob.set('key1', 55);
glob.set('key2', "Hello World");
glob.set('key3', {"Hello" : "World"});
```

#### GET

```javascript
//requires a string key as an argument
glob.get(key)

let val1 = glob.get('key1'); 
let val2 = glob.get('key2'); 
let val3 = glob.get('key3'); 

console.log("value 1: "+ val1)
console.log("value 2: "+ val2)
console.log("value 3: "+ JSON.stringify(val3))
```

{% code title="Response:" %}

```json
value 1: 55 value 2: Hello World value 3: {"Hello":"World"}
```

{% endcode %}

#### DELETE

```javascript
//requires a string key as an argument
glob.delete(key)

glob.delete('key1');
```


# Metrics Functions

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

To create any custom metric, use the following function.

```javascript
//requires a string key parameter and an optional value parameter as arguments
metric.add(key, ?value)

metric.add('latency', 55);
metric.add('count');          // Default value of 1 is taken
```

{% hint style="info" %}
If no value is passed to the function, a default value of 1 is taken.
{% endhint %}

These metrics can be visualized and aggregated in the **Metrics** tab on the Sidebar. Metrics will also be available via APIs.&#x20;


# Mailbox Functions

The mailbox API allows us to have an internal message bus for our tests. The mailbox is a key value store in which each key can store an array of values. It acts as a Last in, first out (LIFO) stack, so the last message that was posted to the mailbox will be popped the first.

You can use the following functions to interact with the Mailbox.

#### POST

This function will add a new value to the specified key.

```javascript
//this function takes a string key and a value of any type as arguments
mailbox.post(key, value)

mailbox.post("key1", 33)
mailbox.post("key1", "Hello World")
mailbox.post("key1", {"Hello" : "World"})
```

#### POP

This function will pop the last data that was added to the key.

```javascript
//this function takes a string key as an argument
mailbox.pop(key)

mailbox.pop("key1")
mailbox.pop("key1")
```

{% code title="Response:" %}

```json
{ Hello: 'World' }
Hello World
```

{% endcode %}

#### COUNT

This function gives a count of the number of values with the current key.

```javascript
//this function takes a string key as an argument
mailbox.count(key)

//Example
mailbox.post("key1", 33)
mailbox.post("key1", "Hello World")

mailbox.count("key1")
```

{% code title="Response:" %}

```json
2
```

{% endcode %}

#### DUMP

This function dumps all the content inside the key instead of popping the values one by one.

It returns an array with all the values.

```javascript
//this function takes a string key as an argument
mailbox.dump(key)

//Example
mailbox.post("key1", 33)
mailbox.post("key1", "Hello World")

mailbox.dump("key1")
```

{% code title="Response:" %}

```json
[{ Hello: 'World' }, 'Hello World']
```

{% endcode %}

#### DELETE

This function deletes all the data for the mentioned key.

```javascript
//this function takes a string key as an argument
mailbox.delete(key)

mailbox.delete("key1")
```


# Data Generation Functions

There are several functions available inside the tests which allow you to generate data points for different purposes.

### Simulate moving vehicles&#x20;

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:

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

The above template will generate driving coordinates starting from Munich to Berlin in real-time traffic conditions. Upon each iteration, the function will automatically output the updated GPS coordinates.&#x20;

{% hint style="warning" %}
You should never call this function within a loop. &#x20;
{% endhint %}

Following are the input parameters:

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

```javascript
{
    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 the actual coordinate.
* `key`: Provide your own Google maps direction key, if required.&#x20;

**The output format of the 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:<br>

{% code title="Response:" %}

```json
{ 
    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
}
```

{% endcode %}

{% hint style="info" %}
Once the `drive()` function has been finished, the output will contain an additional field called **finished** set to **true** to indicate that the current drive has been finished.&#x20;

Use the **finished** field to calculate the next set of drive parameters or return.
{% endhint %}

### Get GPS location

The location function converts an address to its GPS coordinates, with a given accuracy parameter.

```javascript
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 the `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 the location() function is following:

{% code title="Response:" %}

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

{% endcode %}

### Get the real-world weather

`weather.temperature()` and `weather.humidity()` functions will query weather API to get the current weather of a city. For example:

```javascript
{ 
   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 degrees Fahrenheit and relative humidity in percentages.&#x20;

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 usages of a running system in percentage points.

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

### **Simulating continuous variables**

A volatile variable is useful while modelling a complex value such as stock prices or temperature. The value of the volatile variable is dependent upon its last value and can move up or down to max +/- delta steps from the last value at random.&#x20;

```javascript
{ 
   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.

Let's understand it with an example:

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

In the above example, chart will be initialized to a value of 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 the 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.&#x20;


# AWS IoT Connector

## Introduction  <a href="#introducing-aws-iotify-connector" id="introducing-aws-iotify-connector"></a>

AWS IoT is one of the most popular IoT platforms out there. With its native integration with a large set of AWS IoT services, it’s one of the most comprehensive offerings amongst IoT platforms available today.\
Security is built-in from the ground up in AWS, and therefore, it's no surprise that the preferred method of connecting IoT devices to AWS IoT is MQTTS with certificate-based authentication. AWS strongly recommends using individual certificates for each device, which also makes the testing and prototyping complicated for a large set of devices. Not anymore.

## Introducing AWS IoTIFY connector <a href="#introducing-aws-iotify-connector" id="introducing-aws-iotify-connector"></a>

AWS IoT connector from IoTIFY simplifies the entire process of Things creation, certificate enrollment and template creation. All you need is an IAM credential and you are good to deploy and test as many virtual IoT devices as you need on the AWS IoT platform.

With IoTIFY Connector for AWS, managing and deploying certificates for your virtual IoT devices becomes a breeze. All you need is to pass the right IAM credentials and IoTIFY will automatically manage things creation, provisioning, certificate enrollment, policy attachment and all other steps required to create a functional IoT simulation environment. Here’s how it works:-

![](/files/-Lv_ymWr1UcMZ0ouMONX)

## Step 1. Specification <a href="#step-1-specification" id="step-1-specification"></a>

To get started head to the AWS console and create our new user. Go to the IAM service. Now go to the Users page and click on Add Users.&#x20;

<figure><img src="/files/Jz0nFUMYKIDewStt4m9K" alt=""><figcaption></figcaption></figure>

On the page that opens, write IoTIFY for the user name and click next. On the next page choose the Attach policies directly option and then select the Create policy button.&#x20;

<figure><img src="/files/De0lXXh56SjhoWNSKvqM" alt=""><figcaption></figcaption></figure>

Now switch to the JSON tab and paste the following JSON snippet.

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "iot:DetachThingPrincipal",
                "iot:CreateThing",
                "iot:DeleteThing",
                "iot:AttachThingPrincipal",
                "iot:DeleteCertificate",
                "iot:AttachPolicy",
                "iot:AddThingToThingGroup",
                "iot:CreatePolicy",
                "iot:DescribeEndpoint",
                "iot:CreateThingGroup",
                "iot:ListPrincipalThings",
                "iot:DetachPrincipalPolicy",
                "iot:CreateThingType",
                "iot:CreateKeysAndCertificate",
                "iot:UpdateCertificate",
                "iot:ListCertificates"
            ],
            "Resource": "*"
        }
    ]
}
```

<figure><img src="/files/lDdpoeXGjvKGB2PtGh5V" alt=""><figcaption></figcaption></figure>

Now click Next, we can skip the Tags page so click on Next again. Finally, on the Review policy page give the policy a name. Let’s call this the IoTIFY\_Policy. Now click on Create Policy and the policy will be created.

<figure><img src="/files/V2dAqVYROLt2MOBE8Fou" alt=""><figcaption></figcaption></figure>

Now go back to the page where we were attaching a policy to our user. While still on the Attach policies directly option, click on the reload button so that the new policy we just created is available in the list. Once the list is reloaded, search for IoTIFY and select the policy and click Next.&#x20;

<figure><img src="/files/9QSrmh8hf3SGPnRaRHum" alt=""><figcaption></figcaption></figure>

Finally, on the review page check the details and click on Create User.

<figure><img src="/files/9Pk8OFpmJZy4XNFSd61C" alt=""><figcaption></figcaption></figure>

Now that our user is created we will generate an access key so that the IoTIFY AWS connector can have permission to talk to AWS.&#x20;

In the list of users, click on the user we just created. This will open all the settings related to the user. Go to the Security credentials tab and click on the Create access key button.&#x20;

<figure><img src="/files/jCUXPh7C6H9zekzvyF3Q" alt=""><figcaption></figcaption></figure>

Now a setup wizard will guide you through the process on the first page select the Other option and click on Next. On the second page, you can provide a description for the access key, or leave it blank and click on the Next button. Now our Access key and Secret access key are ready. You can download the CSV file for ease. Once you have stored both keys, click on Done.

{% hint style="danger" %}
Please save the IAM user’s Access key ID and Secret access key and store them somewhere safe. You won’t be able to retrieve the secret key after this step.
{% endhint %}

Click on the Create from Sample button on IoTIFY in the top right corner. Then choose the aws-iot-connector sample from the list. Now click on the Create button.&#x20;

<figure><img src="/files/jTTyXDxLpY37DUEQFuaX" alt=""><figcaption></figcaption></figure>

This will open up a sidebar. Paste the Access Key and the Secret access key here along with the AWS region you are using. Click on Create and the IoTIFY AWS connector will be created.

<figure><img src="/files/h6MvhxyZPMeQaxaK4K6A" alt=""><figcaption></figcaption></figure>

Now all we need to do is run this connector and it will automatically create our devices on AWS IoT. Before running it though it is a good idea to create a Run Setting for the same. Click on the Run Settings option on the left bar. Now edit the default Run Setting and change the number of Clients to the number of devices you want to register (In this case we will set it as 5) and keep the number of Iterations to 5 (which is the minimum required to run the connector). Now click on the Save button on the top right.&#x20;

<figure><img src="/files/YoCcfUSXwALRmhvI65pG" alt=""><figcaption></figcaption></figure>

Go back to the Tests page and open the newly created aws-iot-connector. Now we can run this connector as is. You can also go to the createThing stage and change the name of the things that will be registered on AWS IoT (leave the client() option as it adds a number after the thing name so that they are unique). Now just wait for the test to complete, you can check the Result section for the current status of the test.

Once the test has been completed, you can check the glob to see the certificates for the devices. Note the “aws\_iot\_endpoint” entry in the glob as you will have to replace this in the protocol tab of the devices you want to connect to AWS.

## Under the hood <a href="#step-2-provisioning" id="step-2-provisioning"></a>

Upon receiving the request to provision AWS IoT devices in the specified region, IoTIFY will do the following steps:-

1. IoTIFY will create a new device type **iotify\_type** in the AWS IoT region.
2. IoTIFY will create a new Thing group **iotify** in the backend. This group will be associated with all virtual devices.
3. A new certificate policy **IOTIFY\_AUTOMATED\_POLICY** will be created which will be subsequently attached to all newly created certificates.
4. A new AWS IoT thing will be created with the name iotify\_\[deviceId] and will have a device certificate enrolled and attached to it.
5. The certificate’s private key for each new thing will be stored in IoTIFY glob storage with the key pattern **aws\_iotify\_%d\_key**. The certificate itself will be stored as **aws\_iotify\_%d\_cert**, where **%d** will be the client index, starting from 0.

## Step 2. Device Models <a href="#step-3-template" id="step-3-template"></a>

To connect any devices to AWS, we need to use the keys and certificates of those devices that were provisioned by AWS. To do this, you can follow these steps:

In the Protocol tab of the device template, choose Certificate under the Security section. Now set the Private key as  {{state.\_\_$key}} and Certificate as {{state.\_\_$cert}}. What does this do?\
It means that the value of the private key and certificate will be dynamically populated once the template starts running. How? Add the following piece of code in the init stage of your device model. This will fetch the private keys and certificates from the glob and add them to the authentication parameters.

```
{ 
  state.__$key = glob.get( "aws_iotify_"+client()+"_key");    
  state.__$cert = glob.get( "aws_iotify_"+client()+"_cert");    
}
```

This will fetch the private keys and certificates from the glob and add them to the authentication parameters. Since each certificate and key is unique, a client() function is used to retrieve the current index of the client and populate the specific data for it.

The use of \_\_$ pattern ensures that key and certificate objects are not displayed in the state object in the result. If you would like to see the values, you could change the pattern with something else.


# Smart City


# Smart Home


# Overview

What are the main testing areas of IoT platform? Let's have a deeper look at IoT testing

![](/files/-M7w-kDiPEd8xMJ7DTca)

To understand the role of testing in IoT, let’s have a look at the overall IoT solution architecture. An IoT solution consists of many components and stacks which are depicted in the above figure with vertical line partitions. All these stacks have a software and hardware module that performs a specific functionality.&#x20;

The sensors in the hardware layer capture data which flows through the gateway WAN, up to the cloud server, where it gets processed and analysed and then displayed in the user interface. Since each component handles the data in a unique way, the testing requirement for each layer is quite different. This is what defines the testing areas of IoT.&#x20;

Each testing area targets one layer within the entire IoT system architecture and addresses its functionality towards realizing the end-to- end IoT use case. Let’s briefly cover each one of these testing areas.

### Sensor Hardware Testing&#x20;

The very first layer of IoT is the hardware which senses and interact with the physical environment. It could be a temperature sensor, a wearable heart-rate monitor. Hardware testing involves testing the hardware interfaces, peripherals, connectivity, power handling and other device functionalities. Due to it’s nature, the testing is done mostly manually and involves working with the hardware board with tools such as oscilloscopes, multimeters and signal generators. The software running on this hardware is called embedded firmware. From a software perspective, the focus is more on validating hardware-software interfaces, the accuracy of sensing and actuation mechanism and handling system failure scenarios such as malfunctioning flash or sensor data, software upgrade etc.

### Gateway Device Testing

The gateway device sits on the edge and gathers data from multiple sensors and sends it to the cloud. The gateway testing requires validation of connectivity with the sensors and the business logic at the edge. Various IoT platforms provide docker based agents which can be deployed on edge devices with a centrally managed way.&#x20;

### Network Simulation Testing

The objective of Network simulation testing is to understand the effect of network conditions on the connectivity protocol and test the resiliency of the cloud side software stack against network failure, packet loss and delays. It tests the cloud server functionality against real world situations such as a surge of traffic from gateways, DNS amplification attack, excessive packet losses, frequent disconnections and reconnection attempts. Testing on UDP based protocol is more interesting here as TCP has already a built-in mechanism to provide a reliable service. The testing requires sophisticated tools to model the network conditions and also the volume of traffic coming from hundreds of thousands of sensors.

### Cloud Platform Testing

The cloud platforms are provided by service providers such as AWS, Azure, IBM and are responsible for ingesting and analysing data at scale. The key criteria for cloud testing are functional correctness of application, along with testing for performance, analytics and scalability. One of the key challenges of testing the cloud applications is to understand the large set of inputs which can be generated by sensor and network conditions. The focus of our documentation will be primarily on this area of IoT testing.

### Business Application Testing

Business applications are hosted on the cloud and are critical to how the user interacts with the system via the web, mobile and other external APIs. These are also responsible for presenting the data to users in a suitable form of visualization to make sure that the users get the correct information about system behaviour. Testing of Mobile Apps and end-to-end user experience is also included in this.

### Security Testing

Security testing is not an independent area but encompasses all other layers of IoT stack. At the hardware layer, security testing must ensure that there are no exposed open ports or telnet servers which are subjected to brute force attacks. Validating the secure boot, software download functionality and private key management for certificates is also critical. At the network and cloud layer, focus changes to ACLs, firewalls and providing role-based access to various system users.


# Feed offline sensor data from Google Sheets to your IoT platform

Replay offline sensor data stored in google sheets in real time to your cloud platform via network simulator.

Majority of the installations in IoT are currently brownfield, i.e. scenarios where a lot of equipment is already installed and need to be connected to the internet. Many of these existing older devices already collect some data, however, the data captured by sensors may be stored in offline log files such as CSV or excel. If you are an organization building an IoT solution and already have a lot of such data available, you may want to replay the offline data in real time through our virtual sensors, therefore creating a pseudo-real IoT sensor environment.

![](/files/-Lva7tS6POS8j2QIZjX_)

In this tutorial, we will focus on replaying sensor data stored in google sheets via the network simulator. The purpose of this tutorial is to showcase the flexibility of the network simulator in consuming data from various online and offline sources as well as generating intelligent synthetic datasets for your testing. Let’s get started.

## Step 1: Enable Google Sheet APIs <a href="#step-1-enable-google-sheet-apis" id="step-1-enable-google-sheet-apis"></a>

Let’s upload your existing sensor data to the Google sheets. Then, we need to enable Google Sheet APIs through which you could access the data. In order to do that, go to the Google cloud console admin page Dashboard [here](https://console.developers.google.com/apis/dashboard). If you have not previously created a project, you may need to create one.

Once in the dashboard, click enable API and services button and select Google Sheets APIs. Simply enable the API via the enable button and then go to Credential settings.

Create a new API key which would now be used to access the Google Sheet APIs. Please note that it may take a couple of minutes before the API becomes available.

Once you have the API keys, next step is to enable link sharing of the Sheet so that IoTIFY template could read from it.

## Step 2: Populate Google sheet and prepare for sharing <a href="#step-2-populate-google-sheet-and-prepare-for-sharing" id="step-2-populate-google-sheet-and-prepare-for-sharing"></a>

Let’s put all the data we have in the Google sheet and enable sharing with View access. To share this, simply click on the Share button on the right hand side of the sheet and change the share settings to “Anyone who has the link can view”.\
Remember, we are only going to read from the sheet at the moment.

Make sure you populate first row in the sheet as the header, i.e. containing the name of the columns.

Now extract the sheet ID from the URL as follows:

*<https://docs.google.com/spreadsheets/d/\\[YOUR\\_SHEET\\_ID\\_HERE]/edit>*

The sheet ID is the alphanumeric string between d/ and /edit keyword as shown above.

Now you have your sheet ID and API key ready, it's time to create the network template in the Network Simulator.

## Step 3. Prepare the template <a href="#step-3-prepare-the-template" id="step-3-prepare-the-template"></a>

Now you could prepare a network simulator template and fill the settings to connect with your IoT platform. Note that this process is independent of the connectivity protocol chosen and cloud provider.\
The content of the template below should be copied to the Message function in any template

```
{ 
    
  var sheet_id = "1Gv_GkPp3S8qTq1G4htCQaJTZl8Q9a9os5mur46Oed30";
  var key = "YOUR_API_KEY_HERE";
  var page_name = "Sheet1";
  
  // We are currently playing data from Col A to D. You could change it. 
  var col_begin = "A";
  var col_end =   "D";

  var prepareDataUrl = function(row) {
      var url = "https://sheets.googleapis.com/v4/spreadsheets/";
      url += sheet_id;
      url += "/values/"+page_name+ "!"+ col_begin+row+ ":"+ col_end+row;
      url += "?key="+key;       
      return encodeURI(url);
   }

  // populates the information about the sheet e.g. rows and columns.
  var getRowColumns = function() {
      var url = "https://sheets.googleapis.com/v4/spreadsheets/";
      url += sheet_id;
      url += "/?fields=sheets.properties";
      url += "&key="+key;       
      var prop = JSON.parse(get({url: url}));
      state.rows = prop.sheets[0].properties.gridProperties.rowCount;
      state.cols = prop.sheets[0].properties.gridProperties.columnCount;
   }

  // beginning of the simulation, retrieve the header names
  if (state.cur_row === undefined){
    state.cur_row = 1;
    var url = prepareDataUrl(state.cur_row);
    state.headers = JSON.parse(get({url: url})).values[0];
    getRowColumns();
  }
  
  state.cur_row++;

  var url = prepareDataUrl(state.cur_row);  
  var response = JSON.parse(get( {url: url}));
  var item; 

  // If retrieved row as valid data values
  if (response.values && response.values.length){
      item = response.values[0];
  }
  // Otherwise reverse back to first row
  else{
      state.cur_row = 2;
      url = prepareDataUrl(state.cur_row);  
      items = JSON.parse(get( {url: url})).values[0];      
  }
  // arrange rows into JSON object
  var data = {};
  state.headers.forEach(function (key, index){
      data[key] = items[index];
  });
  return JSON.stringify(data);
  
}
```

Remember to replace your API Keys above in the template as obtained from Step 1.

The template code will populate the current header rows and use them as JSON object keys. Afterwards, on every iteration, it will read a row and construct a JSON object from the values.\
This JSON object will be sent to your cloud platform as a string. You could of course modify these values and change anything which you need.

Once all the rows have been read, the code will reset the cursor to the beginning of the sheet. You could change this behavior as well by not incrementing the state.cur\_row and keep it fixed to the last element.

Remember that sheet should contain header row which contains the name of the column value. Do not include any space in the header because they will be used as the key to JSON object.

## Simulating multiple sensors from the same sheet <a href="#simulating-multiple-sensors-from-the-same-sheet" id="simulating-multiple-sensors-from-the-same-sheet"></a>

In order to simulate multiple sensors from the same sheet, you could introduce some variation in the read sensor values. E.g. while constructing the data payload, you could add a variance in the numbers.

```
var data = {};
state.headers.forEach(function (key, index){
    data[key] = (1+Math.random())*items[index];
});
```

## Troubleshooting <a href="#troubleshooting" id="troubleshooting"></a>

Facing some issues? Make sure your sheet ID is correct and API key is working. To ensure that simply go to your browser and paste following text in the address URL\
*<https://sheets.googleapis.com/v4/spreadsheets/[SHEET_ID_HERE]/values/Sheet1!A0:D0?key=[API_KEY_HERE>]*

If everything is correct you will see following response in the browser:

![](/files/-Lva9s8TgYxv2MtqHczA)

In case your APIs don’t work, you will see the error cause above.


# Functional Testing

In this guide we will focus on developing functional test cases for your IoT platform

In functional testing, we focus on validating IoT platform correctness against the data sent by our simulated devices. The simulator is capable of validating server responses, and also fetching data via REST APIs in order to query system correctness. Let's have a few examples:-

* In [Basic Functional Test](/iot-testing/iot-functional-testing/basic-iot-platform-functional-test), we will learn how to send a simple data to a server and validate the server response with using **assert()** function.&#x20;
* In [Geofencing ](/iot-testing/iot-functional-testing/geofencing-validation)example, we will see how server disables ignition of a driving vehicle, if the vehicle move beyond 1000 meter radius of its starting position.&#x20;

&#x20;


# Basic functional test

In this example, we will ensure that the server responds when a trigger condition is met.

Functional testing an IoT platform required developing test methods to ascertain the validity of the cloud platform response with respect to sensor data. A cloud platform may either respond by alerting human user or by controlling the device itself. Let's have an example.&#x20;

Let's consider a device model for a fire alarm. In real life, the device will have a microcontroller to automatically trigger a fire alarm when the temperature exceeds a certain threshold. However, for the sake of demo, let's assume that the alarm trigger functionality is offloaded to a cloud platform.  So the device would simply send measured temperature value to the could platform and expect the cloud platform to trigger an alarm whenever device temperature exceeds a threshold.&#x20;

![](/files/-M8Mq-b8Wxq_7eagGIE0)

We will simulate a simple client using IoTIFY and launch a simple MQTT server application which is supposed to be system under test. Let's go-&#x20;

### Create a Client Template&#x20;

The first step in building a basic test is to create a device template, which will validate the server functionality.&#x20;

#### Step 1. Build a Device Model

{% hint style="info" %}
You could skip this step and import the client template used in this example directly. Go to the template menu, select the import template button on the right hand side and provide following URL for Import.&#x20;

<https://raw.githubusercontent.com/iotify/nsim-examples/master/functional-testing/functest1.json>

Once the template has been imported, you could skip step 1. Do not forget to change the MQTT topic in Step 2 .
{% endhint %}

1. Create a blank template and with MQTT protocol as a backend. Name this template **functest1**
2. Provide the following code into the Init function

```
{
  state.temperature = 75;  // set temperature value to 75 degree
  state.alarm = false;  // Alarm is Off by default
}
```

Provide the following code into the message function

```
{
    const threshold = 80;
    if (state.temperature > threshold)
    {
        assert(state.alarm === true, "Alarm not triggered when temperature exceeded "+threshold)
    }
    // Increase the temperature randomly by max 10 degrees on each iteration
	  state.temperature = volatile({min:60, max: 100, delta:10, key:'myvariable'})
    
    return JSON.stringify(state);
}
```

What is happening above? In line 9, we declare temperature to be a volatile variable, whose values lies in the range between 60 and 100 and can change at max 10 in each step from the last step. In line 4, we assert that when temperature exceeds 80 degree, the alarm must have been raised. (The alarm is raised as a result of server initiated response)&#x20;

Provide the following code into Response Handler function which will handle any command received from the server.&#x20;

```
{ 
  console.log("Command Received", response);              
  
  let cmd = JSON.parse(response);
  if (cmd.alarm)
  {
      console.log("Alarm is triggered by the server")      
      state.alarm = true;
  }
  else  {
      console.log("Alarm is Switched off")      
      state.alarm = false;
  }
}

```

Above, we parse the payload received by server and set the alarm state as received.&#x20;

We expect that the server should immediately send the alarm:true condition as soon as it receives payload with temperature value exceeding the threshold.&#x20;

#### Step 2. Specify MQTT Protocol

Now go to the MQTT protocol setting and leave default settings as it is. Only change the MQTT Topic and Subscription ID to the following

**Topic**: /**\[unique\_topic\_id]**/temperature/{{client()}}

**Subscribe**: /**\[unique\_topic\_id]**/command/{{client()}}

Make sure to check the subscribe checkbox as well. This should look something line as follows

![](/files/-M8MsgNuX8cxLOtyswV8)

{% hint style="info" %}
The topic id must be set to a sufficiently random string as we are using a public MQTT broker where anyone could listen and publish. If more than one user tries with the same ID, they will end sending messages to each other. Therefore create a unique topic string and make sure to provide it in the server example as well.&#x20;
{% endhint %}

That's it. Our client simulator will now publish the temperature on MQTT Topic **/qwerty321/temperature/0** and will receive any command back from the server on topic **/qwerty321/command/0**

#### Step 3. Security Settings

Security settings should be left default.

Preview the template to make sure everything is looking good and then **Save the template.**&#x20;

### Create the Server Application&#x20;

In a real world, you will have an enterprise business application which would listen on MQTT topic for every device and will send a response based on some complex logic. For this demo we will use a simple Javascript program which will act as our own mini server and will respond to the temperature messages received over MQTT.&#x20;

{% hint style="info" %}
Copy the unique MQTT topic key you used in the client simulator and make sure to change the MQTT topic in the server code, before you run it.&#x20;
{% endhint %}

The sample code for the server side application and instructions to run this server could be found at

{% embed url="<https://iotify.github.io/nsim-examples/functional-testing/>" %}

Once the MQTT topic has been changed to match the client, you could run the server code. You should see the following logs in the server console.

```
"Running Simple MQTT test server"
"Subscribed to topic."
```

### Run the Test

Once the server program runs in the above code, lets start our IoTIFY client simulator. Click on simulate button and choose the template on the left hand side drop down screen. Set as following:&#x20;

**Number of clients :**&#x31;

**Repeat Message:** 5

**Gap between iteration:** 10

![](/files/-M8N8r2GHb_fyTCCUS6f)

That's it. The client simulator is now running and will send messages to the server page. Check the logs of the server application. You should see incoming temperature messages from our client.&#x20;

Some of the test cases may fail if the server doesn't send a response in time for the next iteration to trigger. Those cases will be marked as failed, and counted as red.

{% hint style="info" %}
The server code runs for approx 60 seconds only. You may see evaluation timed out error. If this happens, simple rerun the server via green button. &#x20;
{% endhint %}

### Optional Assignments

* [ ] Plot the value of temperature sent via [metrics.add](/additional-helpers/iotify-helpers#metric-add-time-series-metrics-api)() API
* [ ] Change the server code so that it sends the alarm true, if the temperature value remains high for at least 3 consecutive measurements. Make sure to change the assert condition in the client template to reflect the same behavior.&#x20;

Comgratulations! Now you have learnt how to perform a basic functional test with IOTIFY. Let's see some more advanced use cases.&#x20;


# Geofencing Validation

Simulate a connected car with IoTIFY and validate the functionality of a simple geofencing server.

Geofencing is a technique to trigger specific action when an object enters or leave a particular area of interest. It is used extensively to push location based action such as targeted advertising. In this example, we will use it to restrict the movement of a simulated vehicle leaving a city.&#x20;

The objective of the test would be to ensure that a car is stopped by ignition override remotely if it moves beyond a certain radial distance from its starting point. We have provided you with an IOTIFY device template to simulate a vehicle moving on the streets of Paris. We have also provided a sample server side application based on Node.js and Vue.js which you could use to monitor the car position and manually initiate ignition override as the car moves beyond the geofencing circle. Following are the details of this scenario -&#x20;

The IoTIFY device template will simulate a vehicle traveling from Paris to Lille in France.&#x20;

The device will send an HTTP post message to our server application with the current GPS location, odometer and ignition state.&#x20;

The server application will respond to POST message with ignition status sent as a response. If the vehicle is within the expected geographical radius, the ignition value will be set to true, else it is supposed to be false.&#x20;

The Vue.js based web application will allow user to manually disable the ignition value of the car by a switch in the UI. The application will also plot the path vehicle has traveled and also the radial distance moved from its first reported location.&#x20;

An assert condition in the device model could be enabled, to mark the test as failed, if the vehicle has moved beyond 1000 meter radial distance from its starting position. This is to make sure that the functionality of server application is correct as expected.&#x20;

### Step 1: Launch the server Application

The code of the sample server side application is available on [github](https://github.com/iotify/geofencing-server-demo). You are free to try it on your own infrastructure, however for this demo, we will use a online IDE workspace at codesandbox.io&#x20;

Click on the link below to automatically load the git repository into a new online workspace

<https://codesandbox.io/embed/github/iotify/geofencing-server-demo/tree/master/?autoresize=1&fontsize=14&hidenavigation=1&theme=dark&view=preview>

Once the application has been loaded and running, you should see a web application page on the right hand side as follows. Note that by default the application will show Not Connected, as it awaits the first message being posted by the device simulator.&#x20;

![](/files/-M8fiYTngPRXb55mJCfT)

Copy the codebox server URL of this application. The server hostname will be used in the HTTP server settings in next step.&#x20;

### Step 2: Prepare the IOTIFY client simulator

Signup with IOTIFY Network Simulator and go to the template menu. Click on the button Import Template on the right hand side to import the template from Github.&#x20;

The code for IoTIFY template used in this simulation is available at

<https://raw.githubusercontent.com/iotify/nsim-examples/master/functional-testing/geofencing.json>

Once the template is imported, a new template with name geofencing will be created in your workspace. Make sure to update HTTP protocol section with the server hostname in Step 1. E.g.&#x20;

![The HTTP Host should be updated to reflect your actual workspace](/files/-M8fJa1QRhaJowBdUgcH)

In the case above, our server application was running in codebox workspace named (<https://x2kru.sse.codesandbox.io/>) so we copied **x2kru.sse.codesandbox.io** as the hostname in our template. The path of the HTTP should be **/endpoint**&#x20;

Once the template has been updated, **save** it and run the simulation with the following settings

Number of Clients: **1**

Repeat Messages: **50**

Gap between each message: **10** seconds

As soon as the template runs, you will see that the server side application will show the initial location of the vehicle within the city of Paris. A circle will be drawn around it, which will show the geofence radius, beyond which vehicle is not allowed to travel.&#x20;

![A connected dashboard for geofencing application](/files/-M8fk0TvExPwTHDHPPyN)

You could adjust the geofencing radius in the settings. The vehicle will slowly move beyond this radius at some time, and as soon as that happens, **click** on ignition switch to turn the ignition off. This should result in a message sent to the vehicle to disable its ignition upon next POST, and the vehicle will no longer update its position after being stopped.

Clicking on the vehicle Icon will display the last received data from it.&#x20;

&#x20;If the ignition stopping doesn't occur in time, vehicle will move beyond the geofencing radius and simulation iterations will be marked as failed.&#x20;

### Optional Exercises

* [ ] Change the server side application to automatically trigger the ignition to OFF if the vehicle moves beyond geofencing.&#x20;
* [ ] Change the logic so that geofencing is triggered based on odometer value and not the radial distance.&#x20;


# Performance Testing

IoT platform performance testing ensures that your infrastructure could handle Millions of devices at scale without deteriorating underlying services.

IoT cloud solutions are designed for scalability, but no one knows what will happen when we actually reach that scale. It may take a few years before your platform reaches the desired scale and capacity and if there are some critical design flaws, they wouldn't show up until its too late in the system. So it is important to test your platform for full scalability as soon as possible. The problem is how?

Orchestrating a large scale test comes with its own challenges. First, you have to synchronize the execution, so that most of clients start at once. Then you have to perform individual tests and collect results into a nice visualization to understand. Lastly, if something doesn't work, you will need to dig down deeper and triage who was at fault. All of this, could create significant work load on your test teams.

IoTIFY provides a neat and elegant solution to performance testing challenges at scale out of the box. Here is how: -

**Seamless scalability**: The scalability is just a number when it comes to orchestration. We manage all the challenges required to orchestrate upto a million endpoints, so for you it's a no brainer. Simply spawn the devices you want to be simulated and we take care of the rest.&#x20;

**Out of the box measurement**: The basic performance metrics such as message sending delays, message generation delays are measured out of the box by the tool. By adding some simple logic, you could also measure application level latencies with IoTIFY and visualize them in nice graphs via metrics() API.&#x20;

**Detailed Result Capture:** Each client and iteration is captured in detail by IoTIFY. You could go and drill down to exact payload sent by each client, how long did it took for the iteration to complete, any received messages from the cloud, and total time it took to complete that iteration. As a result you could always find out what happened wrong, when triaging a situation.&#x20;

**Advanced Analysis**: Thanks to in built REST APIs within the template, your template could also measure some internal parameters of the cloud platform (such as CPU usage, message queue congestion) and save them in correlation with device data. Furthermore, your payload contents could be changed dynamically based on the cloud response, therefore making your test even more smarter.&#x20;

Let's have a look at some more performance testing example to understand the functionality.&#x20;


# MQTT end to end latency Measurement

Testing the latency of your MQTT broker? In this guide we explain MQTT protocol topologies and several tests focused on measuring latency of MQTT brokers.

MQTT brokers are the heart of a connected IoT application. And just as functioning of the heart is critical for the human body, a reliable and performant MQTT broker is critical for IoT operations. We know that health of the human heart could be measured in average beats per minute, but how do you measure the performance of an MQTT broker? How do you differentiate between a reliable vs bad performance? Two key metrics to measure broker performance are end to end **delivery latency** and **packet loss** rate.&#x20;

For those who are beginner to MQTT protocol, an MQTT broker acts as a bridge connecting different publishers and subscribers. The publishers send messages on certain topics, and subscriber could listen to any number of topics of interest. The MQTT broker latency consists of&#x20;

* Time taken to establish a connection with publisher (Only in case of dynamic connections)
* Time taken to accept a message from publisher
* Time taken to distribute the message to all connected subscribers

We calculate the end to end latency by calculating the sum of all three intervals above. In case of multiple subscriber subscribing to a common topic, we calculate the average of the latencies measured by all of the connected subscribers.&#x20;

<figure><img src="/files/wW5f2goQKNoQtItH9SMT" alt=""><figcaption><p>MQTT latency measurement for Single publisher, multiple subscribers</p></figcaption></figure>

The calculation of the MQTT communication latency may vary significantly depending upon the communication topology. Lets consider the following topologies in MQTT latency testing

* Single publisher, multiple Subscriber (**1 to N)**
* Multiple publishers, single subscriber (**N to 1)**
* Single publisher, Single Subscriber, high throughput (**1 to 1)**&#x20;
* Multiple Publisher, Multiple Subscriber (**N to N - Random topics)**&#x20;
* Loopback publisher/subscriber (**N to N - Loopback)**

All of these topologies could then further be evaluated with QoS 0, 1 and 2 as well. Note that the QoS settings ensures the delivery of message to the broker, but doesn't guarantee the end to end delivery to the subscriber. For the purpose of calculating delivery failure (due to subscriber disconnect or queue overflow), we will also add certain metrics to the test which count the total packets received at all of the clients.&#x20;

For this guide, let's get started with testing the basic scenario of single publisher, multiple consumer (**1 to N** scenario). In this scenario, the MQTT broker under test will receive a publish from a single client and replicate the received messages to multiple connected subscribers, including the original sender. The publishing client will put a timestamp in the outgoing message payload. All receivers will calculate the time in flight of the message by measuring the difference between arrival timestamp vs sending timestamp in the payload. The latency measured would be logged as a metric parameter and can be seen in the IOTIFY Metrics Dashboard.&#x20;

### Steps to measure MQTT 1-to-N message latency

1. If you haven't, create an account with IOTIFY. The trial account creation is free and you don't require a credit card for signup.

2\. Import the following template into your IoTIFY workspace.&#x20;

{% file src="/files/QUb5CnKn1VGiq31LVshr" %}
MQTT 0 Latency test
{% endfile %}

3\. The template currently connects to **broker.hivemq.com**. You could change the settings of your MQTT broker if required in the protocol tab. Note that the broker must be public as we don't support localhost broker or private IPs.&#x20;

4\. Update the default run setting for the required number of clients. (We use 1000 Clients for this step), each sending message 10 second apart for 30 messages.&#x20;

<figure><img src="/files/iaTJDRiJZUUU8spliHZG" alt=""><figcaption></figcaption></figure>

5\. Run the imported MQTT test with the newly created run setting.&#x20;

The status of the test would be visible in Results tab. Once the test is finished, we could go to Metrics page and plot **mqtt\_0\_latency** parameter for last run test.

<figure><img src="/files/ZU8CXz0ck9xylsIjs8xc" alt=""><figcaption><p>MQTT End to end latency measurement with 1K clients QoS 0</p></figcaption></figure>

6\. Now change the Run settings to run the test with more clients (10,000 clients in this case).

7\. Let's plot the latency again with the newer number of clients.&#x20;

<figure><img src="/files/2reAcawVtuX4otMcjEG3" alt=""><figcaption><p>MQTT end to end delivery latency measurement with 10K clients QoS 0</p></figcaption></figure>

As we could see, the average latency changes from roughly 1700 ms for 1K clients to roughly 2500 ms for 10K clients. That's approx 50% increase for a scale of 10x.&#x20;

Let's also measure the packet loss in all cases by plotting mqtt\_*0*\_rx parameter.

### Summary&#x20;

Measurement of end to end delivery latency for MQTT broker is important for benchmarking the scalability of your solution. As we see in this experiment, a 10x scale up of connected clients resulted in almost 50% increment in end to end latency. The test could now be adopted to test different communication topologies.&#x20;


# Security Testing


# Load Testing


# Test Automation & CI/CD integration

Testing is a crucial part of any development process. However, it is often overlooked. Be it because the developer overlooked it or they simply forgot about it. This may save time at the moment, but it can lead to headaches down the line.

Thus it makes sense to automate the testing of new builds and have this automated testing as a part of your CI/CD pipeline. In this guide, we will show you how easy it is to automate the testing of new builds using the Simulation APIs on IoTIFY.

Before we can run a test, first we need to write the test which models the behaviour of the device or usage. For this, simply navigate to IoTIFY and create a new test. If you are not familiar with tests on IoTIFY, you can follow the guide linked below.

{% content-ref url="/pages/-Li8yZMslZ0s5TO-ev-F" %}
[Understanding Tests](/concepts/understanding-a-test)
{% endcontent-ref %}

Now that we have our test ready, we can use the Simulation APIs to start and monitor the results of this test. However, before we can start using the APIs, we need to generate an API key which we will use to authorise these API calls.

Navigate to IoTIFY and click on the settings in the lower left corner. This will take you to your account settings.

<figure><img src="/files/zAUaqGUQA6GvejeGfHVM" alt=""><figcaption></figcaption></figure>

Here, click on `API Keys` in the left menu. This will open the API keys page, here you can see your already provisioned API keys and also create new ones. To create a new API key, click on the `Create New` button in the top-right corner of the screen. A new API Key will be created and displayed on the page.

<figure><img src="/files/B2NM6Z9o4x1FJy9r5BM3" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/tIeNN8GIrkbNXakWf7B5" alt=""><figcaption></figcaption></figure>

Now you are ready to use the APIs. You can go to the page linked below to get more details about the APIs. Here we will use simple curl commands to call these APIs.

{% content-ref url="/pages/-M7rCclYEoudpbt8TqjH" %}
[Simulation API](/api/simulation)
{% endcontent-ref %}

Run the following curl command below to start a test via the API. Here replace `$KEY` with the API key, `$JOBNAME`with the any name for the job (this has to be unique) and $TESTID with the test you want to run. You can also change the runsettings parameters as required with the clients and iterations.

{% code overflow="wrap" %}

```javascript
curl -X POST -H "Accept: application/json" -H "Content-Type: application/json" -H "key:$KEY" -H "domain:nsim.iotify.io" -d '{"jobName":"$JOBNAME","runSettings":{"interval":1000,"iteration":150,"clients":10,"totalClients":5,"clientIdOffset":0}}' nsim.iotify.io/api/test/$TESTID/run
```

{% endcode %}

The command will return a success along with a job ID which we will use to check the status of that job.

<figure><img src="/files/S09VadqLGGjkFk8lwcnm" alt=""><figcaption></figcaption></figure>

Run the following curl command to get the current status of a running job. Here replace `$KEY` with the API key, `$WORKSPACE` with the workspace ID and `$JOB` with the job ID.

{% code overflow="wrap" %}

```javascript
curl -X GET -H "Accept: application/json" -H "Content-Type: application/json" -H "key:$KEY" -H "domain:nsim.iotify.io" nsim.iotify.io/api/jobs/$WORKSPACE/$JOB
```

{% endcode %}

The command will return an object with the results and status of the job.

<figure><img src="/files/s1z9JKiB0cvlVDrDNxdB" alt=""><figcaption></figcaption></figure>

So now you can use the Simulation APIs from IoTIFY to automate your testing and make your CI/CD pipeline more robust.


# Simulation API

## Run a template

<mark style="color:green;">`POST`</mark> `https://nsim.iotify.io/api/test/:testID/run`

This endpoint allows you to run a test with the required run settings.

#### Path Parameters

| Name                                     | Type | Description                          |
| ---------------------------------------- | ---- | ------------------------------------ |
| testID<mark style="color:red;">\*</mark> |      | The ID of the test that needs to run |

#### Headers

| Name                                           | Type | Description                                |
| ---------------------------------------------- | ---- | ------------------------------------------ |
| Content-Type<mark style="color:red;">\*</mark> |      | application/json                           |
| key<mark style="color:red;">\*</mark>          |      | API token for the account                  |
| domain<mark style="color:red;">\*</mark>       |      | The domain under which your account exists |

#### Request Body

| Name                                            | Type    | Description                                                 |
| ----------------------------------------------- | ------- | ----------------------------------------------------------- |
| runSettings<mark style="color:red;">\*</mark>   | Object  | Defines the parameters for the simulation                   |
| jobName<mark style="color:red;">\*</mark>       |         | Unique name identifying the currently running job           |
| rS: clients<mark style="color:red;">\*</mark>   | Number  | Total number of clients                                     |
| rS: iteration<mark style="color:red;">\*</mark> | Number  | Total number of iterations                                  |
| rs: interval<mark style="color:red;">\*</mark>  | Number  | Interval between two iterations                             |
| rS: captureLogs                                 | Boolean | Capture all the log data to display on the results page     |
| rS: captureState                                | Boolean | Capture all the state data to display on the results page   |
| rS: capturePayload                              | Boolean | Capture all the payload data to display on the results page |

{% tabs %}
{% tab title="201: Created Test simulation successfully run" %}

```json
{
    "success": true,
    "jobId": "$jobID",
    "jobName": "$jobName"
}
```

{% endtab %}

{% tab title="400: Bad Request Failed to launch the test simulation " %}

```json
{
    "statusCode": 400,
    "message": "Error message",
    "error": "Error reason"
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
The parameters marked as `rS: $parameter` are parameters under the runSettings object.

For a list of all additional runSettings parameter you can use, check the Run Settings page of the documentation.
{% endhint %}

{% code overflow="wrap" %}

```javascript
// Example curl command

curl -X POST -H "Accept: application/json" -H "Content-Type: application/json" -H "key:$KEY" -H "domain:nsim.iotify.io" -d '{"jobName":"$JOBNAME","runSettings":{"interval":1000,"iteration":150,"clients":10}}' nsim.iotify.io/api/test/$TESTID/run
```

{% endcode %}

## Get Job Status

<mark style="color:blue;">`GET`</mark> `https://nsim.iotify.io/api/jobs/:workspaceID/:jobID`

This API returns the status and results of the simulation job&#x20;

#### Query Parameters

| Name                                          | Type | Description                                                                                             |
| --------------------------------------------- | ---- | ------------------------------------------------------------------------------------------------------- |
| workspaceID<mark style="color:red;">\*</mark> |      | WorkspaceID for the workspace you're a part of                                                          |
| jobID<mark style="color:red;">\*</mark>       |      | Simulation ID as seen in the UI or returned by API while launching the simulation through the POST API. |

#### Headers

| Name                                           | Type   | Description                                |
| ---------------------------------------------- | ------ | ------------------------------------------ |
| Accept<mark style="color:red;">\*</mark>       |        | application/json                           |
| Content-Type<mark style="color:red;">\*</mark> | String | application/json                           |
| key<mark style="color:red;">\*</mark>          | String | API token for the account                  |
| domain<mark style="color:red;">\*</mark>       | String | The domain under which your account exists |

{% tabs %}
{% tab title="200 Simulation status and results" %}

```json
{
    "jobId": "$jobID",
    "testId": "$testID",
    "jobName": "$jobName",
    "workspaceId": "$workspaceID",
    "submitterId": "$submitterID",
    "runSettings": {
        "name": "Default",
        "interval": 1000,
        "iteration": 150,
        "clients": 10,
        "totalClients": 5,
        "clientIdOffset": 0
    },
    "currentInstance": 0,
    "results": {
        "result": {
            "total": 750,
            "success": 750,
            "failure": 0,
            "startAt": 1667282175065.829,
            "endAt": 1667282327070.1438,
            "duration": 152004.31469726562,
            "status": "finished",
            "eta": 0
        },
        "instances": {
            "0": {
                "result": {
                    "total": 750,
                    "success": 750,
                    "failure": 0,
                    "startAt": 1667282175065.829,
                    "endAt": 1667282327070.1438,
                    "duration": 152004.31469726562,
                    "status": "finished",
                    "eta": 0
                },
                "iterations": {
                    "0": {
                        "result": {
                            "total": 5,
                            "success": 5,
                            "failure": 0,
                            "startAt": 1667282175065.829,
                            "endAt": 1667282177692.3975,
                            "duration": 2626.568359375,
                            "status": "finished",
                            "eta": 0
                        }
                    },
                    
                    .............
                    
                    "149": {
                        "result": {
                            "total": 5,
                            "success": 5,
                            "failure": 0,
                            "startAt": 1667282327068.5632,
                            "endAt": 1667282327070.1438,
                            "duration": 1.58056640625,
                            "status": "finished",
                            "eta": 0
                        }
                    }
                }
            }
        }
    }
}
```

{% endtab %}

{% tab title="400 Simulation results not found" %}

```json
{
    "statusCode": 400,
    "message": "Error message"
}
```

{% endtab %}
{% endtabs %}

{% code overflow="wrap" %}

```javascript
// Example curl command

curl -X GET -H "Accept: application/json" -H "Content-Type: application/json" -H "key:$KEY" -H "domain:nsim.iotify.io" nsim.iotify.io/api/jobs/$WORKSPACE/$JOB
```

{% endcode %}


# Glob APIs

Glob are fast key value stores which could be controlled to change the simulation behavior.

Glob APIs could be used in the template to access the global key-value store. These values are useful to enable interaction between templates and control the behaviour of simulation through the user.&#x20;

## Create a new Glob entry or update an existing Glob entry

<mark style="color:green;">`POST`</mark> `https://nsim.iotify.io/api/datastore/:workspaceId/glob`

This endpoint allows you to create/update a Glob entry

#### Path Parameters

| Name                                          | Type   | Description                        |
| --------------------------------------------- | ------ | ---------------------------------- |
| workspaceId<mark style="color:red;">\*</mark> | String | The Workspace ID where the Glob is |

#### Headers

| Name                                           | Type   | Description                                |
| ---------------------------------------------- | ------ | ------------------------------------------ |
| Content-Type<mark style="color:red;">\*</mark> | String | application/json                           |
| domain<mark style="color:red;">\*</mark>       | String | The domain under which your account exists |
| key <mark style="color:red;">\*</mark>         | String | API token for the account                  |

#### Request Body

| Name                                    | Type   | Description                  |
| --------------------------------------- | ------ | ---------------------------- |
| key<mark style="color:red;">\*</mark>   | String | The key for the Glob entry   |
| value<mark style="color:red;">\*</mark> | String | The value for the Glob entry |

{% tabs %}
{% tab title="201: Created Glob successfully created" %}

```json
true
```

{% endtab %}

{% tab title="400: Bad Request Glob could not be created" %}

```javascript
{
    // Response
}
```

{% endtab %}
{% endtabs %}

{% code overflow="wrap" %}

```javascript
// Example curl command

curl -X POST -H "Accept: application/json" -H "Content-Type: application/json" -H "key:$KEY" -H "domain:nsim.iotify.io" -d '{"key":"$GLOBKEY","value":"$GLOBVALUE"}' nsim.iotify.io/api/datastore/$WORKSPACE/glob
```

{% endcode %}

## Get a Glob object

<mark style="color:blue;">`GET`</mark> `https://nsim.iotify.io/api/datastore/:workspaceId/glob/item/:globKey`

#### Path Parameters

| Name                                          | Type   | Description                                                  |
| --------------------------------------------- | ------ | ------------------------------------------------------------ |
| workspaceId<mark style="color:red;">\*</mark> | string | The workspace ID for the workspace where the Glob is present |
| globKey<mark style="color:red;">\*</mark>     | String | The key for the glob entry to be fetched                     |

#### Headers

| Name                                           | Type   | Description                                |
| ---------------------------------------------- | ------ | ------------------------------------------ |
| key<mark style="color:red;">\*</mark>          | string | API token for the account                  |
| Content-Type<mark style="color:red;">\*</mark> | String | application/json                           |
| domain<mark style="color:red;">\*</mark>       | String | The domain under which your account exists |

{% tabs %}
{% tab title="200 Glob Fetched" %}

```json
{
    "key": "CurlTest",
    "value": "Testing"
}
```

{% endtab %}
{% endtabs %}

{% code overflow="wrap" %}

```javascript
// Example curl command

curl -X GET -H "Accept: application/json" -H "Content-Type: application/json" -H "key:$KEY" -H "domain:nsim.iotify.io" nsim.iotify.io/api/datastore/$WORKSPACE/glob/item/$GLOBKEY
```

{% endcode %}

## Get all the Glob keys

<mark style="color:blue;">`GET`</mark> `nsim.iotify.io/api/datastore/:workspaceId/glob/keys`

#### Path Parameters

| Name                                          | Type   | Description                                                  |
| --------------------------------------------- | ------ | ------------------------------------------------------------ |
| workspaceId<mark style="color:red;">\*</mark> | String | The workspace ID for the workspace where the Glob is present |

#### Headers

| Name                                           | Type   | Description                                |
| ---------------------------------------------- | ------ | ------------------------------------------ |
| Content-Type<mark style="color:red;">\*</mark> | String | application/json                           |
| domain<mark style="color:red;">\*</mark>       | String | The domain under which your account exists |
| key<mark style="color:red;">\*</mark>          | String | API token for the account                  |

{% tabs %}
{% tab title="200: OK " %}

```javascript
key1, key2, key3, key4, key5
```

{% endtab %}
{% endtabs %}

{% code overflow="wrap" %}

```javascript
// Example curl command

curl -X GET -H "Accept: application/json" -H "Content-Type: application/json" -H "key:$KEY" -H "domain:nsim.iotify.io" nsim.iotify.io/api/datastore/$WORKSPACE/glob/keys
```

{% endcode %}

## Glob Delete

<mark style="color:red;">`DELETE`</mark> `nsim.iotify.io/api/datastore/:workspaceId/glob/item/:globKey`

Deletes the key value pair of the glob

#### Path Parameters

| Name                                          | Type   | Description                                                  |
| --------------------------------------------- | ------ | ------------------------------------------------------------ |
| globKey<mark style="color:red;">\*</mark>     | string | The key for the glob entry to be deleted                     |
| workspaceId<mark style="color:red;">\*</mark> | String | The workspace ID for the workspace where the Glob is present |

#### Headers

| Name         | Type   | Description                                |
| ------------ | ------ | ------------------------------------------ |
| Content-Type | string | application/json                           |
| key          | String | API token for the account                  |
| domain       | String | The domain under which your account exists |

{% tabs %}
{% tab title="200 " %}

```
true
```

{% endtab %}
{% endtabs %}

{% code overflow="wrap" %}

```javascript
// Example curl command

curl -X GET -H "Accept: application/json" -H "Content-Type: application/json" -H "key:$KEY" -H "domain:nsim.iotify.io" nsim.iotify.io/api/datastore/$WORKSPACE/glob/item/$GLOBKEY
```

{% endcode %}


# Metrics API

Metrics allow you to add and visualize time series data for your performance testing.

## Get a list of available metrics

<mark style="color:blue;">`GET`</mark> `nsim.iotify.io/api/datastore/:workspaceId/metric/list`

#### Path Parameters

| Name                                          | Type   | Description                                                          |
| --------------------------------------------- | ------ | -------------------------------------------------------------------- |
| workspaceId<mark style="color:red;">\*</mark> | string | WorkspaceID for the workspace whose metrics list needs to be fetched |

#### Headers

| Name                                           | Type   | Description                                |
| ---------------------------------------------- | ------ | ------------------------------------------ |
| Accept<mark style="color:red;">\*</mark>       | String | application/json                           |
| key<mark style="color:red;">\*</mark>          | String | API token for the account                  |
| domain<mark style="color:red;">\*</mark>       | String | The domain under which your account exists |
| Content-Type<mark style="color:red;">\*</mark> | String | application/json                           |

{% tabs %}
{% tab title="200 " %}

```json
[{
    "key": "Metric_0"
}, {
    "key": "Metric_1"
}, {
    "key": "Metric_2"
}, {
    "key": "Metric_3"
}, {
    "key": "Metric_4"
}]
```

{% endtab %}
{% endtabs %}

{% code overflow="wrap" %}

```javascript
// Example curl command

curl -X POST -H "Accept: application/json" -H "Content-Type: application/json" -H "key:$KEY" -H "domain:nsim.iotify.io" nsim.iotify.io/api/datastore/$WORKSPACEID/metric/list
```

{% endcode %}

## Get the data for a metric

<mark style="color:green;">`POST`</mark> `nsim.iotify.io/api/datastore/:workspaceId/metric/list/:metricKey`

#### Path Parameters

| Name                                          | Type   | Description                                           |
| --------------------------------------------- | ------ | ----------------------------------------------------- |
| metricKey<mark style="color:red;">\*</mark>   | String | The key for the metric                                |
| workspaceId<mark style="color:red;">\*</mark> | String | WorkspaceID for the workspace where the metric exists |

#### Headers

| Name         | Type   | Description                                |
| ------------ | ------ | ------------------------------------------ |
| Accept       | String | application/json                           |
| key          | String | API token for the account                  |
| domain       | String | The domain under which your account exists |
| Content-Type | String | application/json                           |

#### Request Body

| Name                                           | Type   | Description                                                              |
| ---------------------------------------------- | ------ | ------------------------------------------------------------------------ |
| timeInterval<mark style="color:red;">\*</mark> | Number | Metrics aggregated over time interval                                    |
| aggregateBy<mark style="color:red;">\*</mark>  | String | The aggregation function to be used                                      |
| timeUnit<mark style="color:red;">\*</mark>     | String | The unit of time for the time interval                                   |
| entityId                                       | String | The ID for the simulation job (If you want metrics only for a fixed job) |

{% tabs %}
{% tab title="201: Created " %}

```javascript
[
    [1671190292000, 77],
    [1671190302000, 77],
    [1671190312000, 78],
    [1671190322000, 70],
    [1671190332000, 72],
    [1671190342000, 70],
    [1671190352000, 68],
    [1671190362000, 68],
    [1671190372000, 66],
    [1671190382000, 67],
    [1671190392000, 69],
    [1671190402000, 68]
]
```

{% endtab %}
{% endtabs %}

{% code overflow="wrap" %}

```javascript
// Example curl command

curl -X POST -H "Accept: application/json" -H "Content-Type: application/json" -H "key:$KEY" -H "domain:nsim.iotify.io" -d '{"timeInterval":"1","timeUnit":"s","aggregateBy":"AVG","entityId":"fbe7933c-b27e-4397-8214-21a82e2e011b"}' nsim.iotify.io/api/datastore/$WORKSPACEID/metric/$METRICKEY
```

{% endcode %}


# Glossary


# Getting Started

Getting Started with IoTIFY is simple. Just signup with us and follow the guides below

We have prepared guides on how to best utilize IoTIFY for your needs. Choose the profile which matches you the best.

## Beginner (Learning about IoT)

Want to learn more about the world of IoT and how to build amazing IoT applications. Use the following guide for resources and tools to understand and learn about IoT development.

{% content-ref url="/pages/-MA63\_BGOfx7o3JknmIw" %}
[Beginner](/temp/getting-started/beginner)
{% endcontent-ref %}

## Developer (Building an IoT solution)

IoTIFY is a cloud-based device simulator, which is scalable and customizable to your requirements. Use the following guides to understand the basics of how IoTIFY works, and then move forward.

{% content-ref url="/pages/-MA6E1ilgVuwxrbwNf0U" %}
[Developer](/temp/getting-started/developer)
{% endcontent-ref %}

## Tester (Looking to benchmark our IoT solution)

Need to benchmark your IoT solution? Talk to us to set up a fully scalable IoT performance testing solution for your custom needs.&#x20;

{% content-ref url="/pages/-MA6I74QJJ0\_fQeI2NIH" %}
[Tester](/temp/getting-started/tester)
{% endcontent-ref %}


# Beginner

You are learning IoT and want to get started

Welcome to IoTIFY, we're happy to help you along the way as you learn more about IoT. Unfortunately, IoTIFY Network Simulator requires some understanding of IoT fundamentals and knowledge of Javascript. It would be a good idea to first learn more about these and then return to Network Simulator. We have added a few resources to help you with the same.&#x20;

### IoT

If you want to learn more about how to build IoT systems using devices such as Arduino Uno or the Raspberry Pi, you can use our **IoTIFY Virtual Lab.** With IoTIFY Virtual Lab, you can build your IoT projects in the cloud easily, without worrying about different components.

To learn more about IoTIFY Virtual Lab, go to the page linked below. You can follow the guides to build exciting projects and learn about IoT systems.

{% embed url="<https://docs.vlab.iotify.io>" %}

You can sign up for **IoTIFY Virtual Lab** at <https://vlab.iotify.io/>

To learn more about IoT fundamentals, you can refer to the ebooks linked below.&#x20;

{% embed url="<https://www.leverege.com/ebooks/iot-intro-ebook>" %}

{% embed url="<https://www.scribd.com/document/452629733/iot-open-eu-EN>" %}

### Javascript

You can use the following resources to learn more about Javascript since we will be using Javascript to define our device templates.

{% embed url="<https://www.theodinproject.com/paths/foundations/courses/foundations#javascript-basics>" %}

{% embed url="<https://www.w3schools.com/js>" %}

Once you have knowledge about building IoT systems and are comfortable with Javascript, move to the Developer section, where we explain how to use IoTIFY Network Simulator.


# Developer

If you are already familiar with IoT development, IoTIFY is an indispensable tool to have in your IoT arsenal.

IoTIFY is a cloud based device simulator. If you are already familiar with IoT concepts and want to use IoTIFY to talk to your IoT platform, we recommend getting started with&#x20;

{% content-ref url="/pages/-Li8yZMslZ0s5TO-ev-F" %}
[Understanding Tests](/concepts/understanding-a-test)
{% endcontent-ref %}

{% content-ref url="/pages/-Li9MPI2Yri\_Ej4QEMME" %}
[Broken mention](broken://pages/-Li9MPI2Yri_Ej4QEMME)
{% endcontent-ref %}

Then lets jump right into our platform and check few sample templates to get yourself familiar with helper APIs.&#x20;

{% content-ref url="/pages/-LiCu8ogKSie-Jx9vOnH" %}
[IoTIFY Helper Functions](/additional-helpers/iotify-helpers)
{% endcontent-ref %}

{% content-ref url="/pages/-M7w0lYphyFqUVQc5lO\_" %}
[Functional Testing](/iot-testing/iot-functional-testing)
{% endcontent-ref %}


# Tester

Using IoTIFY for your IoT performance testing is simple.

If you are looking to use IoTIFY to benchmark your IoT platform, we have a dedicated section for you.&#x20;

{% content-ref url="/pages/-LiD1\_1ZYzHB0T1t52lJ" %}
[Overview](/iot-testing/iot-testing-overview)
{% endcontent-ref %}


# Walkthrough

A simple walkthrough of the IoTIFY platform

Welcome to IoTIFY, your one-stop solution for all your IoT testing needs. This guide will take you through the different parts of our platform and help you in getting started with the same.

When you first log into IoTIFY, you will be greeted into the interface. It's divided into two parts, The left pane, and the work area.

The left pane houses the Workspace Selector, the navigational shortcuts to move from one part of the platform to another, and the profile menu. This pane can also be minimized by clicking on the arrow in the profile menu so that the full screen can be utilized for work.

![](/files/DzVjq7czueFtnMtmqIXe)

The right side of the screen is what we will call the work area. The contents of this change according to the part of the interface we are in. If we are in the Tests interface, it shows a list of all the tests created in the workspace, if we click on any of these, it will open the test editor. We will take a more in-depth look at the test editor in the `Fundamentals` section.

{% content-ref url="/pages/-Li8yZMslZ0s5TO-ev-F" %}
[Understanding Tests](/concepts/understanding-a-test)
{% endcontent-ref %}

<figure><img src="/files/hsADHmFLd6u5I7yduwfS" alt=""><figcaption></figcaption></figure>

The next part of the interface we will look at is the Results section. This is used to store and visualize all the test runs in the particular workspace. It provides an overview of all the currently running and recent tests. You can also dig deeper into individual test results by clicking on the `Show Result` button on the right of each test run.&#x20;

To understand how to make proper use of the results, head to the `Analyzing Results` section.

{% content-ref url="/pages/-LiD1Ti4DeSWfUqqiiDv" %}
[Analyze the results](/getting-started/analyze-the-results)
{% endcontent-ref %}

<figure><img src="/files/UDKJGd6HbB5lNnuh5SG5" alt=""><figcaption></figcaption></figure>

Next, we move to the Run Settings sections, here you can create and edit different run settings which define the scale and behavior of our simulations. Here you can choose the number of clients, iterations, interval between clients and so on.

We will do a more in-depth look at run settings in the `Fundamentals` section.

{% content-ref url="/pages/-LiD1P6eqybBsLUftYvP" %}
[Run Settings](/concepts/run-settings)
{% endcontent-ref %}

<figure><img src="/files/GjFAoTqBwwnx8IhjYPYL" alt=""><figcaption></figcaption></figure>

Next, we move on to the Glob storage, which acts as the persistent storage for all our tests. It is a key-value store that can be accessed by all the tests in the workspace. The Glob can be used to save data about the state of a device, certificates, and so on. Glob storage also allows you to take an offline backup of all the data and the ability to restore that backup. You can also choose to connect the Glob storage to a cloud store like AWS S3 and have your backups in the cloud.

To know more about Glob Storage and how you can use it with your tests, head to the `Glob Storage` Page.

{% content-ref url="/pages/jjZVbVZzFT2KtdSD4FTh" %}
[Glob Storage](/concepts/glob-storage)
{% endcontent-ref %}

<figure><img src="/files/ZF2wwROr2pxBYGGuQuXI" alt=""><figcaption></figcaption></figure>

We also have a robust Metrics engine that keeps a track of many important metrics throughout all test runs, with the ability to add custom metrics as well. The Metrics can then be visualized using the Metrics section on IoTIFY. Graphs can be generated with a multitude of filters to better understand how the system has been performing.

![](/files/DAcJogo6WrK7sqbhJUnL)

We also have an automation engine called Scenarios, which will help you in orchestrating complex testing scenarios. You can use an easy-to-use editor to create these workflows and then run them with one click.&#x20;

To know more about Scenarios and how it can make your life easier, head to the `Scenarios` page.

{% content-ref url="/pages/qzeyljRWGZJCk86z2Rik" %}
[Scenarios](/concepts/scenarios)
{% endcontent-ref %}

![](/files/3egj98h98MetyzkTF0UB)

Now that you are familiar with our platform, let's move forward with using the platform for your use case. Depending on your experience with IoT, you can choose the different tracks in the `Getting Started` section


# Protocol Settings

IoTIFY Supports multiple protocols to connect with cloud platforms. Let's discuss each of these protocols in detail.

To learn how to use MQTT with IoTIFY, refer to this page:

{% content-ref url="/pages/-M8PO4VkU-3B2r5\_87Eb" %}
[MQTT](/concepts/protocol-settings/mqtt)
{% endcontent-ref %}

To learn how to use HTTP with IoTIFY, refer to this page:

{% content-ref url="/pages/-M8PVcRU98GQb6KywZO7" %}
[HTTP](/concepts/protocol-settings/http)
{% endcontent-ref %}

To learn how to use CoAPwith IoTIFY, refer to this page:

{% content-ref url="/pages/-M8PY2wmu8el6DOL-N-8" %}
[CoAP](/temp/protocol-settings/coap)
{% endcontent-ref %}

To learn how to use Raw TCP/UDP/TLS/DTLS with IoTIFY, refer to this page:

{% content-ref url="/pages/-M8Pe-f7Zc6ayRp2bGt1" %}
[Raw (TCP/UDP/TLS/DTLS)](/temp/protocol-settings/raw-tcp-udp-tls-dtls)
{% endcontent-ref %}

To learn how to use LWM2M with IoTIFY, refer to this page:

{% content-ref url="/pages/-M8PgWb22mb-lr7i7DIp" %}
[LWM2M](/temp/protocol-settings/lwm2m)
{% endcontent-ref %}

We also support a special None protocol when you don't want the simulated device to directly connect to a server. Refer to this page to learn more about it:


# CoAP

Constrained Application Protocol remains one of the most efficient protocol for low power devices. Let's see how CoAP is implemented with IOTIFY

CoAP is based on UDP and has built in mechanism for ensuring reliable delivery. For a good overview of CoAP, please see the following guides

{% embed url="<http://www.programmingwithreason.com/article-iot-coap.html>" %}

Another interesting tutorial

{% embed url="<https://dzone.com/articles/coap-protocol-step-by-step-guide>" %}

In IoTIFY CoAP protocol settings we allow following fields to be configured

![](/files/-M8P_Dvd4S-yXiGpaevM)

**Method:** CoAP method, which could be GET/POST/PUT/DELETE

**Host:** The CoAP Host name or IP address, followed by the port number (if not default)

**Path:** The CoAP server URL, where the message should be sent to. If you are using a query string, that must be the part of URL itself.&#x20;

**Confirm:** Whether the message should be sent as (Conformable) CON or (Unacknowledged) NON

**Observe:** Whether the resource should be observed and any changes should be sent back to the client. The response handler function will be invoked if a change is detected.&#x20;

**Additional Headers:** Any additional header which must be sent along with the payload.&#x20;

**Timeout:** The timeout value to wait before declaring a non confirmed message a failure.&#x20;


# Raw (TCP/UDP/TLS/DTLS)

Some IoT devices could even send a raw payload to the server which is simply a binary UDP/TCP payload. IoTIFY also enables you to provide such payload with ease.

Sending a binary content or even strings over UDP/TCP is possible with IoTIFY. The motivation to use a raw protocol could be either to conserve the bandwidth or to support binary formatting of data. There isn't much to specify when using the raw protocols.&#x20;

![Settings for Raw Protocol](/files/-M8PerSKoNccl2-RXmqA)

We only need to specify the transport as well as the server endpoint along with the port number. The timeout field is only applicable in case of TCP/TLS/DTLS and specify how long should we wait for connection (as there is no concept of connection in UDP)

### Generating Binary Payload for Raw Protocol

For Raw protocol, you could choose to send a binary payload by returning a buffer Object in the Device Model message function. E.g.&#x20;

```
{
    payload = [10,20,44,46]
    
    return new Buffer.from(payload);
}
```

E.g. you could convert a string to base64 representation

```
    let payload = new Buffer('Hello World', 'binary').toString('base64')
    return payload;
```


# LWM2M

LWM2M simulator is an enterprise only feature currently limited in preview.

{% hint style="info" %}
LWM2M is currently in a preview only mode for Enterprise. Please contact us to get a demo.&#x20;
{% endhint %}

[Lightweight Machine to Machine](https://www.omaspecworks.org/what-is-oma-specworks/iot/lightweight-m2m-lwm2m/) specification is based on CoAP and is developed by the [Open Mobile Alliance](https://openmobilealliance.org/) for the Internet of Things. The advantage of LWM2M over others is that it runs on UDP/DTLS and could even use SMS in some constrained cases. The underlying protocol for LWM2M is the [Constrained Application Protocol](https://tools.ietf.org/html/rfc7252) (CoAP).&#x20;

![](/files/-M8PjeMZ4nTuXlWxtZJI)

Currently the LWM2M client settings are minimalist. The client will automatically try to register to the provided server. In order to use the LWM2M client, you must build a smartobject in your state variable in device initialization. An example of a LWM2M device initialization code is&#x20;

```
{
  state.temp = 20;
  state.led = false;
  
  state.so = new smartObject(); 
  state.so.init('temperature', 0, 
    {
        _state : state,
        sensorValue: {
        read: function (cb) {
            console.log('Read called for Sensor'); 
            cb(null,state.temp); },
        write: function (value, cb){ 
            console.log('Write called for Sensor with value', value)
            cb(null,state.temp); 
        }},
        units: 'C'	
    }); 


    // led
  state.so.init('lightCtrl', 0 , {
        _state: state,
        onOff: {
            read: function (cb) {
                cb(null, state.led);
            },
            write: function (val, cb) {
                state.led = val;
                cb(null, state.led);
            }
        }
    });


  //no need for return 
}

```

Above Function will initiate two resource objects for your device. The server could read/write and observe to these resources and the handlers will be invoked.&#x20;

The message sending functions are also a little different in case of LWM2M

```
{
    state.temp = 25+index();
    
    /* Update using a trigger method
    state.so.write('temperature', 0, 'sensorValue', state.temp , function (err, data) {
        if (err) {
            console.log(err);   // Error: 'Resource is unwritable.'
            console.log(data);  // _unwritable_
        }
    });
    */
    
    
    // Read using trigger method
    /*
    state.so.dump('temperature', 0, function (err, data) {
        console.log(data);
        
    })
    */
    
	var payload = {
        pathname: '/.well-known/core',
        payload: '</>;hb,</1/0>;obs,</3/0>;obs,</4/0>;obs,</3303/0>;obs', 
        method: 'GET', 
        waitResponse: false,
        options: { 
            'Content-Format': 'application/link-format' 
        },
        query: '' 
	}
	
    return JSON.stringify(payload);
}
```

A JSON object must be returned in stringified form, indicating the next action to be performed.&#x20;


# NONE

When you don't want a simulated device to directly connect to a server, utilise the NONE protocol.

There are certain cases when the device you are simulating does not need to directly communicate with a server. It could be that you are just testing the functionality of the device, or it is an auxiliary device that connects to the server via a Gateway device. In these cases, you can use the NONE protocol which does not create a direct connection to any server.

![](/files/J4FrFFscWOR8Dsq8F0AP)

**Loopback**: The loopback setting allows you to receive whatever payload the Sender function sends into the Receiver function. This can be useful for testing the functionality of a device.


# Under the hood

How does IoTIFY simulate your job when you submit the run? What happens behind the scene? Learn more about our orchestration strategy.

One of the key requirements of a simulator is **seamless scalability** without deteriorating simulation performance. IoTIFY is designed to be truly horizontally scalable in this regard i.e. adding more clients to the simulation without affecting the baseline performance of other clients. The architecture of IoTIFY utilizes docker containers extensively, enabling seamless global scalability. As long as the IoTIFY agents have connectivity to your IoT backend, they could run and simulate the job. However, to distribute, orchestrate and collect the results of the test, we have certain internal strategies which are worth having a look at.&#x20;

Let's follow your simulation as it is submitted from either the UI or through the API.&#x20;

### Job Submission

When a simulation job is submitted, it is sent to a job queue. Based on the current availability of the nodes and the job settings, the total numbers of clients required for simulation are further divided into smaller groups, let's say 100 clients each. Simulation for each chunk of the clients is then submitted as an individual task, i.e. if you would like to simulate 1000 clients, your first 100 clients could be simulated by one VM  while the next 100 clients could be running on another machine. Once all tasks have been distributed, the job is marked as **running**.&#x20;

### Connection Initiation

When a task is scheduled at a node agent, it calls the Device Model Init stage before establishing a connection to the server. This is particularly useful if you want to set up credentials for the connection or even dynamically control which client should connect to which server.&#x20;

When a task starts, all the clients within the task must complete the Init stage before the first message function could be run for the first client. The timeout limit specified in the template comes into play here. If a particular client could not connect to the server within the specified time, its result will be marked failed and it will not be able to send any messages to the cloud platform. So in summary, all clients must either successfully connect or definitely fail to connect before the first iteration could be executed and the first message could be sent to the server. A client who fails to connect will simply sit idle while the other clients could continue to run normally. &#x20;

{% hint style="info" %}
The connection limits/second is an advanced variable that slows down connection initiation across all the clients in all of the jobs to apply the global limit. Note that you should increase the connection timeout value if you are applying global connection limits.&#x20;
{% endhint %}

### Message Sending

Once the setup function has been run and the connection established, all clients will send messages independently to the server. The clients within the same task will all be sending messages almost simultaneously, however, the execution of the task across multiple containers may not be fully synchronized. This means that all clients in your simulation may not start exactly at the same time (which is a good thing btw) however, the interval between their message sending will be fixed. This effect also mimics the real-world behaviour of the devices which do not send data at exactly the same time.&#x20;


# Google Sheets API

Feed offline sensor data from Google Sheets to your IoT platform

Replay offline sensor data stored in google sheets in real time to your cloud platform via network simulator.

Majority of the installations in IoT are currently brownfield, i.e. scenarios where a lot of equipment is already installed and need to be connected to the internet. Many of these existing older devices already collect some data, however, the data captured by sensors may be stored in offline log files such as CSV or excel. If you are an organization building an IoT solutions and already have a lot of such data available, you may want to replay the offline data in real time through our virtual sensors, therefore creating a pseudo-real IoT sensor environment.

![](https://iotify.help/network/sheet/sheets.png)

In this tutorial, we will focus on replaying sensor data stored in google sheets via the network simulator. The purpose of this tutorial is to showcase the flexibility of the network simulator in consuming data from various online and offline sources as well as generating intelligent synthetic datasets for your testing. Let’s get started.

### Step 1: Enable Google Sheet APIs <a href="#step-1-enable-google-sheet-apis" id="step-1-enable-google-sheet-apis"></a>

Let’s upload your existing sensor data to the google sheets. Then, we need to enable Google sheet APIs through which you could access the data. In order to do that, go to the google cloud console admin page Dashboard [here](https://console.developers.google.com/apis/dashboard). If you have not previously created a project, you may need to create one.

Once in the dashboard, click enable API and services button and select Google Sheets APIs. Simply enable the API via the enable button and then go to Credential settings.

Create a new API key which would now be used to access the google sheet APIs. Please note that it may take a couple of minutes before the API becomes available.

Once you have the API keys, next step is to enable link sharing of the Sheet so that IoTIFY template could read from it.

### Step 2: Populate Google sheet and prepare for sharing <a href="#step-2-populate-google-sheet-and-prepare-for-sharing" id="step-2-populate-google-sheet-and-prepare-for-sharing"></a>

Let’s put all the data we have in the google sheet and enable sharing with View access. To share this, simply click on the Share button on the right hand side of the sheet and change the share settings to “Anyone who has the link can view”\
Remember, we are only going to read from the sheet at the moment.

Make sure you populate first row in the sheet as the header, i.e. containing the name of the columns.

Now extract the sheet ID from the URL as follows

<https://docs.google.com/spreadsheets/d/[YOUR_SHEET_ID_HERE]/edit>

The sheet ID is the alphanumeric string between d/ and edit keyword as shown above.

Now you have your sheet ID and API key ready, its time to create the network template in the Network Simulator.

### Step 3. Prepare the template <a href="#step-3-prepare-the-template" id="step-3-prepare-the-template"></a>

Now you could prepare a network simulator template and fill the settings to connect with your IoT platform. Note that this process is independent of the connectivity protocol chosen and cloud provider.\
The content of the template below should be copied to the Message function in any template

|   |
| - |

Remeber to replace your API Keys above in the template as obtained from Step 1.

The template code will populate the current header rows and use them as JSON object keys. Afterwards, on every iteration, it will read a row and construct a JSON object from the values.\
This JSON object will be sent to your cloud platform as a string. You could offcourse modify these value and change anything which you need.

Once all the rows has been read, the code will reset the cursor to the beginning of the sheet. You could change this behavior as well by not incrementing the state.cur\_row and keep it fixed to the last element.

Remember that sheet should contain header row which contains the name of the column value. Donot include any space in the header because they will be used as the key to JSON object.

### Simulating multiple sensors from the same sheet <a href="#simulating-multiple-sensors-from-the-same-sheet" id="simulating-multiple-sensors-from-the-same-sheet"></a>

In order to simulate multiple sensors from the same sheet, you could introduce some variation in the read sensor values. E.g. while constructing the data payload, you could add a variance in the numbers.

|   |
| - |

### Troubleshooting <a href="#troubleshooting" id="troubleshooting"></a>

Facing some issues? Make sure your sheet ID is correct and API key is working. To ensure that simply go to your browser and paste following text in the address URL\
<https://sheets.googleapis.com/v4/spreadsheets/[SHEET_ID_HERE]/values/Sheet1!A0:D0?key=[API_KEY_HERE]>

If everything is correct you will see following response in the browser\
![](https://iotify.help/network/sheet/correct.png)

In case your APIs don’t work, you will see the error cause above.

Hope you found this guide interesting. We would welcome your feedback and comments in the discussion board below.<br>


# Azure IoT

IoTIFY connectors make it extremely easy to manage device provisioning and testing. Learn more about how to deploy thousands of virtual IoT devices in Azure IoT Hub.

## Introduction <a href="#introduction" id="introduction"></a>

Azure IoT Hub is one of the leading IoT platforms out there. With native integration with wide set of Azure Services, Azure IoT offers compelling and easy to use solutions in IoT market.

## Introducing Azure IoTIFY connector <a href="#introducing-azure-iotify-connector" id="introducing-azure-iotify-connector"></a>

Azure IoT connector from IoTIFY simplifies the entire process of provisioning devices in IoT Hub and template creation. All you need is a Connection String and you are good to deploy and test as many virtual IoT devices as you need in Azure IoT Hub.

Let’s get started with Azure IoT Hub deployment.

## Step 1. Deploy an Azure IoT Hub Instance <a href="#step-1-deploy-an-azure-iot-hub-instance" id="step-1-deploy-an-azure-iot-hub-instance"></a>

Create an Azure IoT hub in your desired region and capacity.

## Step 2. Credentials <a href="#step-2-credentials" id="step-2-credentials"></a>

Once the Azure IoT Hub is ready, provide the primary Connection string to IoTIFY. To do that, go to **Shared Access Policies** in the left side menu and then click on the **registryReadWrite** Policy menu.

![](/files/-Lva0qz30dsDrHPrNojb)

A pop menu will open on the right side. Copy the **Connection string—primary key** from the input box. We will need this key in IoTIFY connector.

![](/files/-Lva0ztRogvo9s_m-nQm)

Now go to the Network template in IoTIFY and click on Azure Connectors. Provide the copied connection string in credentials input.

![](/files/-Lva16uEQioAYJhhQhqK)

Specify the number of devices to be deployed and then click Provision button.

What will happen in the background?

1. A new GUID will be created for authentication parameters.
2. Specified number of the new devices will be created in IoT hub registry with name pattern iotify\_%d where %d is device index
3. Credentials will be assigned to each device based on the newly generated GUID pattern, followed by device index e.g. GUID\[%d] where %d is device index
4. A sample template will be generated which could be used to simulate all of the newly provisioned devices.

## Step 3. Template <a href="#step-3-template" id="step-3-template"></a>

A new template will be automatically created by the connector Wizard. Once the wizard finishes deploying IoT things, you will be redirected to the newly created template.\
This template has couple of clever tricks to enable multiple individual Azure IoT objects being simulated in a single template.

Here is how the template works -\
The template has {{state.credentials}} macro in the place of the password field in the Authentication Tab.\
The password will be dynamically generated based on each device ID and the GUID. How? The trick is in the init function.

```
{
    var expiryEpoch = moment().add(1, 'year').unix();
    state.__$credentials = azureDevice.SharedAccessSignature.create(
    		'myazure.azure-devices.net',
    		'iotify_'+_meta.clientId,
    		new Buffer('4fc2f380-36f2-0288-4ca4-1b7038fd2568'+_meta.clientId).toString('base64'),
    expiryEpoch).toString();    
    
}
```

The init function will populate the state.\_\_$credentials once the device is initialized. The password field will then be used for authentication for Azure IoT Hub MQTT broker.

**Note** that the GUID is only available in the template. If you delete the template, the credentials will be lost.

## Cleaning up <a href="#cleaning-up" id="cleaning-up"></a>

To clean up, simply press the red button **Cleanup** instead of provision devices. It is necessary to cleanup devices if you want to provision new devices.


# Losant IoT

## Losant Connector Setup

### Losant Setup

#### Step 1 : Make a Losant Account if you don't have one already

Go to <https://www.losant.com>, Click sign-up and follow the instructions

#### Step 2 : Set up a Losant application

* Go to the **`Applications`** section of your Losant Dashboard \[ <https://app.losant.com/applications> ]
* Click on **`Add Application`**
* Either choose a Template that suits you or choose **`Blank Application`**
* Enter a name for your application and click **`Create Application`**

#### Step 3 : Create a Device Recipe

Any remote device communicating with the Losant server must be modeled in a Losant application, so that it is properly identified and the data it sends can be properly parsed. For ease of replication, we can make a Device Recipe with the required model. To create a new recipe :

* Click on **`Device Recipes`** in the Sidebar
* Click the **`Add Device Recipe`** button in the top-right corner
* Give a name for your recipe and choose `Set my own default names, tags and attributes`
* Click the **`Create Recipe`** button
* This should take you to the `Properties` tab of your Device Recipe. In this page, ensure that the **`Device Class`** is **`Standaone`**
* Now go to the `Attributes` tab. The parameters to be sent to the Losant Server have to be defined here as attributes along with a suitable data type.
* Once you have added the attributes necessary for your device, click **`Update Attributes`**.

#### Step 4 : Create Devices

* Click on the **`Devices`** tab in the sidebar.
* Click on the downward arrow beside the **`Add Device`** button in the top-right corner
* Click on **`Create from Recipe`**.
* Choose the recipe that was made in the previous step and click **`Create from Recipe`**.
* Optionally, rename the device and click **`Save Device`**

#### Step 5 : Create an access key

Any device connecting to our application will need to provide authentication credentials. In Losant, these credentials are defined in the form of an access key and a corresponding access secret. A given access key can be shared by more than one device; in our application we are going to create a single access key which will be used by all devices.

* Click on the **`Access Keys`** tab in the sidebar.
* Click the **`Add Access Key`** button in the top-right corner.
* Give a descriptive name for your Access Key.
* In the `ACCESS KEY DEVICE RESTRICTIONS` Section, select the devices that the key applies to. Choose **`All Devices`** if you are unsure.
* Click on **`Create Access Key`**
* **Save your keys** as the Secret key cannot be recovered after this. Click on **`Download to file`** to save it on your PC as a text file.
* Once saved, acknowledge that you have saved the key and close the window.

#### Step 6 : Create a Dashboard.

Losant allows creating personalized dashboards to display data coming from any device in a given application, and also to send commands to a device.

* Click on the **`Dashboards`** tab in the sidebar.
* Click the **`Add Dashboard`** button in the top-right corner.
* Enter a name for your Dashboard and click **`Create Dashboard`**
* Click on **`Add Block`**.
* Losant provides you with many templates for Dshboard blocks. Choose one that is suitable to you.
* In the block settings, choose the attributes to be used to generate the view and click on **`Add block`**

###

### IoTify Network Simulator Templates

Now that we have our Losant application and dashboard set up, we need to create a template for each device in the IoTify Network Simulator.

#### You can import our Losant Connector Template Boilerplate from the link below

`https://raw.githubusercontent.com/iotify/nsim-examples/master/connectors/losant-connector.json`

> Paste this URL in the dialog box that opens when you click **`Import a Template`** from the Network Simulator templates page \[ <https://beta.iotify.io/network/templates> ]

#### Or make your own from scratch :

* Choose a template that suits your application or click on **`Blank Template`**
* Select the **`MQTT(S)`** protocol and enter a name for your template.
* In the template editor, Go to the `MQTT` tab to set the connection parameters
  * Ensure that the protocol is **`mqtt(TCP)`**
  * Enter **`broker.losant.com`** and the `Endpoint URL`
  * In the topic field, enter **`losant/<device-id>/state`**
    * To get `device-id`, click on the devices tab of your Losant Application homepage. The device Id is listed below the Device name. Click on the button beside the ID to copy it.
  * Enter the same `device-id` in the **`ClientID`** field.
* Go to the `Security` tab and provide the authentication credentials to connect to our Losant application
  * Enter the `Access Key` as the `Username`
  * Enter the `Access Secret` as the `Password`

    > These can be found in the **`.txt`** file we downloaded while making the Access key in Losant
* Go to the `Device Model` Tab.
  * In the message generator section, define the message to be sent to simulate your device.
* Click the **`Save`** button one you are done editing the template.

### Simulation

In the simulate tab of the IoTify Network Simulator, use the newly created template to run a simulation. Ensure that the Number of clients in each simulation is set to 1.

Observe your data being populated in the Losant Dashboard.<br>


# Losant Connector


# Parking Space Management

Learn how to monitor parking space availability using simulated smart parking lots.

## Introduction <a href="#introduction" id="introduction"></a>

Finding a free parking spot when and where needed can be a real challenge, especially in large cities with sustained vehicular traffic. Not being able to easily find an available spot results in wasted time for drivers, increasing fuel consumption, CO2 emissions and traffic congestion.

Various software and hardware vendors are proposing integrated parking management solutions with the purpose of controlling and optimizing the use of parking spots. These solutions can be based on different types of sensors to detect parking space availability, for example ground sensors mounted at every parking spot, cameras attached to street lighting poles or tall buildings, and parking payment machines.

Beside the obvious advantages for drivers who are able to know if and where there are free spots in a given area at a given time, the availability of parking data in a central management system allows for other useful applications: detecting parking violations, analyzing and extracting patterns in parking space use, optimizing revenue from parking lots, etc.

This guide will demonstrate an example of how IoTIFY network simulator can be used to simulate parking lots that periodically send parking space availability data to a central server, and how these data can be displayed in an online dashboard.

## 1. Set up a Losant application <a href="#id-1-set-up-a-losant-application" id="id-1-set-up-a-losant-application"></a>

We will use [Losant](http://losant.com/) to create a simple parking space monitoring application. From the home page of your Losant account, click the **Applications** button on the left bar, then select **Add Application**; in the next screen, choose an application name (for example “Parking”) and then click the **Create Application** button.

Any remote device communicating with the Losant server must be modeled in a Losant application, so that it is properly identified and the data it sends can be properly parsed. In our parking application, each device will cover a fixed number of parking spots, like for example a parking garage where cars are detected when entering and exiting the area. Let’s create first a device recipe that models a generic parking lot, then we will instantiate devices from the recipe. To create a new recipe, click **Device Recipes** from the left menu in the application home page, then click the **Add Device Recipe** button. In the New Device Recipe screen, give a name to the recipe (for example, “Parking Lot”), and select the option “Set my own default names, tags and attributes”:

![](/files/-LiU1qHypPmlGaIXgZZK)

Click **Create Recipe**; next, in the DEVICE TYPE section select **Standalone**.\
We want our simulated parking lot to send both fixed data such as its physical location and total number of parking spots, and dynamic data such the current number of available spots and the number of cars that entered and left the area since the last update. This information can be useful for a parking management solution not only to know how many spots are available at any given time, but also to analyze parking space usage patterns. Our Losant device recipe will model all this information in the form of attributes: in the DEVICE ATTRIBUTES section, define five attributes as shown in the following screenshot:

![](/files/-LiU-vlA5x5T4330LPdG)

After saving the recipe, we can create devices from this recipe: click the **Devices** entry in the left menu, then **Add Device**; in the New Device screen, select the Parking Lot recipe and click **Create from Recipe**, then choose a name for the device and click **Save Device**:

![](/files/-LiU3eOLeAwNFIdUUrgL)

You can create additional devices from this recipe, to monitor multiple parking areas; in this example we will simulate two parking lots, and for this we need to create two Losant devices.

To define the authentication credentials needed by a simulated device to connect to the Losant platform, we need to create an access key. Refer to other articles in this section, such as the article describing a waste management application, for more information on how to create an access key.

## 2. Set up a Losant dashboard <a href="#id-2-set-up-a-losant-dashboard" id="id-2-set-up-a-losant-dashboard"></a>

To visualize graphically parking space usage data, we are going to set up a dashboard in Losant. From the home page of your Losant account, click the Dashboards item in the left menu, then click **Add Dashboard**; choose a name for your dashboard, select "Parking" as the owner application, then click **Create Dashboard**.

Since each simulated parking lot sends its physical location coordinates, in our dashboard we insert a map where this location is shown. In the Add Block screen, click **Customize** in the GPS History block; in the block definition screen, select “Last received data point” from the Duration drop-down list, select “DeviceRecipe=Parking Lot” from the “Device IDs/Tags” drop-down list, and then select the “location” attribute:

![](/files/-LiU5KpX0iO0ygKeqeqd)

With the above settings, the map will show the location of each parking lot that is sending data to the Losant application. In order to display additional information in a popup when a parking lot shown in the map is clicked by the user, we need to edit the popup template; to display the parking lot name, its total number of parking spots and the current number of free spots, insert the following content in the popup template:<br>

```
{{format deviceName}}

Capacity: {{format data.parking_spots}}

Free spots: {{format data.free_spots}}
```

![](/files/-LiU-vlX8QtztNtB5UHG)

Finally, click **Add Block** to add the map to the dashboard.

Among the various widgets offered by Losant to populate a dashboard, there is the time series graph, which visualizes historical data coming from one or more devices; we can use this widget to monitor the usage of our simulated parking lots. From the dashboard page, click **Add Block**, then select the time series graph widget; in the block settings screen, insert the name of a simulated parking lot in the header text:

![](/files/-LiU6SMcjYRpJQXJReqs)

In the Duration section, select the duration and resolution of the graph:

![](/files/-LiU6wklq_zJc2QARmU-)

Now we need to define what will actually be displayed in the graph; this is done by defining the contents of one or more segments in the dashboard block. For example, to insert in the graph the number of free spots in the parking lot, define a segment as in the following screenshot:

![](/files/-LiU7ir17n_K5vOmL0Ar)

To add a visualization of the number of cars entering and leaving the parking lot, define two additional segments where the relevant attributes of the Losant device are selected, and add the segments to the graph.\
Finally, add the graph to the dashboard by clicking the **Add Block** button.

If you want to simulate more parking lots, you can define additional graphs and add them to the dashboard in the same way.

## 3. Create IoTIFY network simulator templates <a href="#id-3-create-iotify-network-simulator-templates" id="id-3-create-iotify-network-simulator-templates"></a>

Now we are going to create simulated parking lots in IoTIFY network simulator. As always, the behavior of a simulated device is defined by a template: to create a new template, go to the IoTIFY network simulator, click on the Templates tab and then click **New Template**. In the new template screen, select MQTT(S) as connection protocol, insert a unique name for the template, and click on **CREATE**; in the template editor screen, in the MQTT parameters section, select **mqtt (TCP)** as protocol, insert “broker.losant.com” as endpoint URL, insert a string of the form “losant/\<device\_id>/state” (where “\<device\_id>” is the identifier of the first parking lot device you created in the previous steps in the Losant application) in the **Topic** field, and copy the device ID to the **ClientID** field:

![](/files/-LiU9u2W0qSX48xFze7M)

In the Credentials section, insert a valid Losant access key in the **Username** field, and the corresponding access secret in the **Password** field:

![](/files/-LiU-vlfy6fjhp5C8ugO)

In the next section, the message contents field will contain the data our simulated parking lot is going to send to the Losant server; as required by the Losant API, the message contents must be formatted using JSON, may optionally contain a “time” attribute with the current time, and must contain an attribute named “d”, which includes the real data of interest, i.e. in our case the location of the parking area, the number of parking spots and other relevant information.

To create data that simulates the usage of the parking lot by drivers, we use the `chance.integer()` random number generation function to generate the number of cars entering and leaving the area during the time interval between two successive updates sent by the parking lot, then adjust the number of free spots based on this. So our message contents will look like the following:<br>

```
{

  if (state.capacity === undefined){
    state.capacity = 150;
    state.free = state.capacity;
  }
  var myret = {};
  myret.time = { "$date" : moment.now() };
  
  var entering = chance.integer({min: 0, max: 12});
  var leaving = chance.integer({min: 0, max: 10});
  
  state.free = state.free - entering + leaving;

  if (state.free < 0 ) state.free  = 0;
  if (state.free > state.capacity ) state.free  = state.capacity;
  
  myret.data = {
    location: "48.1353, 11.5819",
    parking_spots: state.capacity,
    cars_entering: entering,
    cars_leaving: leaving,
    free_spots: state.free
  };
  
  return JSON.stringify(myret, null, 2);
}
```

In the above text, our parking lot has a capacity of 150 spots, and simulates between 0 and 12 cars entering and between 0 and 10 cars exiting at each time interval (so the parking lot will tend to fill up with time, since the average number of cars entering will be slightly higher than the number of cars exiting).

Now, save the template and you are ready to start simulating a parking lot. If you created two or more devices in the Losant application and want to simulate them all, just create other similar templates in IoTIFY network simulator, keeping in mind that each template must use a different Losant device ID.\
In our example we are going to simulate two parking lots, one with a capacity of 150 spots, and a larger one with 250 spots.

## 4. Simulate a smart parking system and see it in action <a href="#id-4-simulate-a-smart-parking-system-and-see-it-in-action" id="id-4-simulate-a-smart-parking-system-and-see-it-in-action"></a>

In IoTIFY network simulator, go to the Simulate tab, select a template representing a parking lot, select 1 as number of clients, and adjust the number of iterations and the gap between iterations to your preferred values:

![](/files/-LiUBeo5ttCVd2AAbszw)

Hit the **START SIMULATION** button and the simulated parking lot will start sending data to Losant.\
To simulate a second parking lot, repeat the above procedure, this time selecting the template for the second lot.\
Now that our simulated devices are running, we can go to the Losant dashboard we previously created and see the data coming from the parking lots:

![](/files/-LiU-vlmhpik2-kVOXhO)

When clicking on the icon for a parking lot in the map, a popup is shown, with information on the total number of spots and the currently available spots:

![](/files/-LiU-vlnV_iRVyAV6Irp)

If we hover the mouse pointer over any time point in a time series graph, data received from the corresponding parking lot at that time is displayed:

![](/files/-LiU-vlrvFvK83Q0e7EH)

You can play with different parking lot capacity values, or devise your own algorithm to model the behavior of drivers entering and exiting the parking area, for example taking into account the time of day and adjusting the number of cars accordingly; IoTIFY network simulator templates are fully customizable and allow writing arbitrary expressions to model complex scenarios.


# Waste Management

Learn how to use IoTIFY network simulator to create a waste management application for smart cities.

## Introduction <a href="#introduction" id="introduction"></a>

Waste collection is one of the most important public services in any city. Currently, most municipalities have a fixed schedule with fixed routes for collecting garbage, and this can result in various inefficiencies: sometimes garbage trucks pick up trash cans that were almost empty, and sometimes overflowing cans are left in this state for days. This is because with a traditional approach the state of a trash can is unknown until the operator goes physically where the can is located. These problems can be overcome by making the trash cans smart, i.e. placing a sensor in each can to detect the garbage fill level, and periodically sending this data to a central server: in this way, waste collection schedules and routes can be optimized based on the actual need, increasing the level of service and decreasing costs.

IoTIFY network simulator can be used to simulate any IoT device, including trash cans! The following is a step-by-step guide that illustrates this use case.

## 1. Set up a Losant application <a href="#id-1-set-up-a-losant-application" id="id-1-set-up-a-losant-application"></a>

[Losant](http://losant.com/) is an IoT platform with various tools to manage IoT applications. We are going to use it to manage our simulated trash cans. If you don’t have an account at Losant, sign up [here](https://accounts.losant.com/create-account). After logging in, click on the Applications tab in the upper menu and then **Add Application**; in the new application screen, choose a name for your application (for example “Waste Management”):

![](/files/-LiTcCCO6WWqhYEs-Qt5)

Click the **Create Application** button and you will be taken to the application home page. Our simulated trash cans will be defined in Losant by creating devices in the application. In order to facilitate the creation of multiple devices of the same type, Losant offers the possibility to create a recipe and instantiate devices from this recipe. In the Devices section of the application home page, click the **Add** button:

![](/files/-LiTdDAGNv3GIUcY8e4w)

In the CREATE FROM RECIPE section, click **Manage My Device Recipes** and then **Add Recipe**; in the next screen, give a name to the recipe (from example, “Trash Can”) and select the option “Set my own default names, tags and attributes”:

![](/files/-LiTdVuOPzn5Br811zuG)

Click **Create Recipe**; in the next screen, we are going to define the device properties, which will be used to visualize data coming from any of our simulated devices. In the DEVICE TYPE section, select **Standalone**:

![](/files/-LiTXh00b3RDQ7fz9tI8)

In the DEVICE ATTRIBUTES section, add an attribute with data type “GPS string” and name “location”, and another attribute with data type “Number” and name “level”; these attributes correspond to the data sent by each trash can, i.e. its physical location and the garbage fill level:

![](/files/-LiTXh05MfGyE8LFKPbq)

Finally, click **Save Recipe**. Now we can create multiple devices taking this recipe as starting point: go back to the application home page, click **Add** to add a new device, then in the CREATE FROM RECIPE section select the recipe just created:

![](/files/-LiTe-60EEq_M2TxrYyr)

Click **Create from Recipe**, then in the device creation screen change the device name to something unique (e.g. “TrashCan001”):

![](/files/-LiTeP_YOpQJqw7yVuqW)

Note the device ID displayed in the upper right part of the screen: it will be used later when simulating this trash can. Click **Save Device** to save the last change. Following the same procedure we can quickly create other devices; in this example, we are creating 3 devices, which will be visible in the application home screen:

![](/files/-LiTf1wb8qzokrkP6ALi)

Any device connecting to our application will need to provide authentication credentials. In Losant, these credentials are defined in the form of an access key and a corresponding access secret. A given access key can be shared by more than one device; in our application we are going to create a single access key which will be used by all trash cans.\
From the application home page, click **Access Keys** on the left menu and then click the **Add Access Key** button at the top right corner; in the key definition page, give a descriptive name to the key (for example, “Garbage Collection”), and select “All Devices” in the access restrictions section:

![](/files/-LiTg48drQvsBxPXHC02)

Click **Create Access Key**; a popup widget will appear displaying the auto-generated key and secret:

![](/files/-LiTXh0SwPxrDSzcfwif)

Make sure to copy at least the access secret (since it won’t be recoverable if you lose it), then select “I have copied my access key and secret to a safe place.” and click **Close Window**. The newly created access key is now ready to use.

## 2. Set up a Losant dashboard <a href="#id-2-set-up-a-losant-dashboard" id="id-2-set-up-a-losant-dashboard"></a>

Losant allows creating personalized dashboards to display data coming from any device in a given application, and also to send commands to a device. We are going to create a dashboard to monitor the status of the 3 trash cans we created in the previous steps and to empty the trash cans.

Click the Dashboards item in the left bar, then click **Add Dashboard**; in the next screen, choose a name for your dashboard, for example “Garbage collection”, and select "Waste Management" as owner application:

![](/files/-LiTi55ROhkr1MfUxhEM)

Click **Create Dashboard** at the bottom of the page. Now it’s time to define the contents of the dashboard; click **Add Block** and you will be shown a list of widgets to choose from:

![](/files/-LiTXh0b33rkdzgCkoQP)

Since our trash cans will be sending location and garbage level data, we are going to display a map with the location of the trash cans and a bar chart indicating the garbage level in each trash can.\
To create the map, click **Customize** in the GPS History block and you will be taken to the block definition screen; in the Duration drop-down menu, select “Last received data point” (we don’t need to track the location history, because our trash cans will always stay at the same place); in the “Device IDs/Tags” drop-down menu, select “DeviceRecipe=Trash Can”, and in the Attribute drop-down menu select “location”, so that the map will display the location of all devices created from our recipe:

![](/files/-LiTl1smQRIZ7ufWpOl7)

A Losant map can also show in a popup widget additional information on a device when clicking on it. We are going to use this feature to visualize the identifier of each trash can, its location and its garbage level; in the Popup Template text box, write the following text:<br>

```
{{format deviceName}}

Location ({{format latitude}}, {{format longitude}})

Garbage Level {{format data.level}}%
```

Note that in the last line of the above text, “level” must correspond to the name of the attribute you assigned to the device recipe to hold the garbage level value.

![](/files/-LiTXh0u5XnzZwuY88eD)

Click **Add Block** to add the map to the dashboard.

Now we going to add a bar chart with the graphic visualization of the garbage level in all trash cans. In the dashboard page, click the settings icon located at the top right corner and then click **Add Block**:

![](/files/-LiTXh0whqdZ2qNGIYL_)

Locate the Bar Chart block in the list of widgets and click its **Customize** button. In the widget editing screen, in the Duration drop-down menu select “Last received data point”; then, in the Axis Configuration section, assign a label to the axis (for example, “Garbage Level”), and insert 0 and 100 as minimum and maximum values, respectively, since we are going to express the garbage level as a percentage value:

![](/files/-LiTmJm8pIzeKVuEOGaw)

Next, we are going to add a segment for each trash can: in the BLOCK DATA section, select the first device from the “Device IDs / Tags” drop-down menu, select “level” as attribute, and insert a label. Then click **Add Segment** and do the same for the other two devices:

![](/files/-LiTXh136Tz7bSukKya6)

Finally, click **Add Block**.

Now we need a way to be able to empty each simulated trash can, just like what happens in a real-world scenario when garbage is collected; to do so, we need a widget that is able to send commands to the trash cans, and this is implemented in Losant with input controls: click **Add Block**, and choose Input Controls from the widget list; in the widget editing page, click **Add Control** and **Button Trigger**:

![](/files/-LiTncY4e9L4Ghk9EPam)

In the button definition section, assign a label to the button (for example, “Empty 001”), select “Send Device Command”, select the first device from the “Device IDs / Tags” drop-down menu, and insert the string “empty” in the Command Name text box:

![](/files/-LiTXh17nDSCnh3BoWuH)

Repeat the same procedure for the other trash cans. Finally, we want to be able to empty all trash cans with a single command, for example to simulate the event where a garbage truck is dispatched to empty all trash cans in a given street: add a new button trigger, give it an appropriate label such as “Empty All”, select “DeviceRecipe=Trash Can” in the “Device IDs / Tags” drop-down menu, and insert the string “empty” as command name:

![](/files/-LiTXh1CxDB3B2onfPxZ)

Click **Add Block** to add the buttons to the dashboard.\
Any widget in the dashboard can be moved around with drag-and-drop or resized to fit your preferences.

## 3. Set up network simulator templates <a href="#id-2-set-up-network-simulator-templates" id="id-2-set-up-network-simulator-templates"></a>

Now that we have our Losant application and dashboard set up, we need to simulate the trash cans. Each trash can will correspond to a device as defined in the Losant application, and we need to create a template for each device in the simulator.

Click on **New Template** in IoTIFY network simulator, then select MQTT(S) as connection protocol, give a unique name to the template and click **CREATE**; in the next screen, select mqtt (TCP) as protocol, and insert “broker.losant.com” as endpoint URL; in the topic field, insert a string with the format “losant/\<device-id>/state”, where \<device-id> is the device ID of our first trash can (the device ID is displayed in the upper right corner in the Losant webpage that lists the device properties); in the ClientID text box, insert the device ID:

![](/files/-LiTrbn9DgaiDldBJhPY)

Now we need to provide the authentication credentials to connect to our Losant application: expand the Provide Credentials section; in the Username field, insert the access key previously created when setting up the Losant application; in the Password field, insert the corresponding access secret:

![](/files/-LiTXh1N2GbX4-dga0s-)

In the next section, insert the following string in the Message Contents text box:<br>

```
{
  if (state.level === undefined) state.level = 0;

  var myret = {};
  myret.time = { "$date" : moment.now() };
  
  myret.data = {
    location: "47.365202, 8.538435",
    level: state.level
  }
  
  state.level = Math.max(100,  state.level + chance.integer({min:0, max:5}));
  
  return JSON.stringify(myret, null, 2);
  
}
```

In the above string, the “data” attribute of the `myret` JSON object contains two attributes: “location”, which indicates the physical location of our trash can, and “level”, which is the garbage level expressed in percentage points. While the location is fixed, the expression used for the garbage level simulates a trash can initially empty, which at each iteration fills up by a random amount between 0 and 5%, until it reaches the 100% level:

Now we need to define how a trash can reacts when we send it the “empty” command to simulate that it has been emptied. This is easy thanks to the topic subscription feature of IoTIFY MQTT client: in the template, enable the Subscription check box, insert in the topic field a string with format “losant/\<device-id>/command”, and copy in the handler function text box the following string:<br>

```
{
    var cmd_name = JSON.parse(response.toString()).name;
    if (cmd_name == 'empty')
        state.level = 0;
}
```

The semantics of the above text should be easy to understand: our client parses the JSON-formatted message sent by the Losant broker and extracts the value of the “name” attribute, which corresponds to the name of the command that we set up in the Losant dashboard input control; if the name matches the string “empty”, then the garbage level is set to 0%.

The template for our first trash can is now complete: click **Save**.

Now we can create the templates for the remaining trash cans: these will be the same as the first template, except for the following settings:

* the template name
* the ClientID field, which corresponds to the Losant device ID
* the topic used for publishing, which must match the device ID
* the topic used for subscribing, which again must match the device ID
* the value of the “location” attribute in the message JSON object; in our example, we are going to use “47.363961, 8.535817” for the second trash can and “47.363463, 8.534150” for the third trash can, so our 3 cans will all be located in the same street

## 4. Start the simulation <a href="#id-2-start-the-simulation" id="id-2-start-the-simulation"></a>

Now that we have everything in place, we can start simulating our trash cans, monitoring their status from the Losant dashboard.\
In IoTIFY network simulator, start a simulator from each of the 3 templates, making sure that the number of clients in each simulation is set to 1. Then go to the Losant dashboard: when the trash cans send data to Losant, the dashboard will be updated to reflect the current status:

![](/files/-LiU-6BXHNKnKAVSxxM4)

You can update manually the dashboad by clicking on the Refresh icon in the top right toolbar, and you can adjust the automatic refresh frequency in the dashboard settings.

If you click on any trash can in the map, you will see a popup indicating the trash can identifier, its GPS coordinates and its garbage level:

![](/files/-LiU-CPWu5_limsP-q3M)

Now we can simulate the event where one trash can is emptied: first, unlock the input controls widget by clicking the button at its top right and then clicking on **Unlock**; then, you can click any of the **Empty 001**, **Empty 002** and **Empty 003** buttons to empty the corresponding trash can:

![](/files/-LiU-GAPAYh6YT0Rn46H)

An emptied trash can will reset its garbage level to 0% and then will gradually fill up again; you can see this in the dashboard as soon as the trash can sends its next message after having been emptied.

You can empty all trash cans with a single command by clicking the **Empty All** button.


# Connected Truck

Easily simulate a connected vehicle driving on real roads with traffic conditions, thanks to IoTIFY's network simulator.

## Introduction <a href="#introduction" id="introduction"></a>

Urban mobility has become one of the key challenges for humans as more and more vehicles are daily added on the roads. It is imperative that we make our vehicle infrastructure smarter, to tackle dynamic demand and response.&#x20;

Also as factories become smarter and locate further away from the city, they want to produce goods on demand. Getting things in the hands of consumers right on time when they need them, becomes a key priority.&#x20;

In this short tutorial we will show you how you could simulate a smart connected vehicle - the basic step in doing fleet management. You could then extend your solution to the entire fleet simulation and create a real life demonstration of smart transport solution with IoTIFY. In this case, the vehicle will have following parameters tracked:

A) **GPS location**: latitude and longitude with the given accuracy\
B) **Current speed**: in meters / second\
C) **Cargo temperature**: a temperature gauge connected in cargo hold\
D) **Time**: the current timestamp

For the sake of simplicity, we will avoid any other parameter for now, but it will be very trivial to add anything else to this simulation.

## How will we track the vehicle? <a href="#how-will-we-track-the-vehicle" id="how-will-we-track-the-vehicle"></a>

The vehicle will emit the monitored parameters to an IoT platform over MQTT. In this case, we will use [Losant](https://www.losant.com/) to build a connected dashboard. However, you are free to choose any cloud platform provider of your choice and [showcase](https://iotify.slack.com/messages/showcase) your application in our slack channel.&#x20;

Overall the tutorial should not take more than 30 minutes to setup. So let’s get started.

## 1. Sign up with Losant <a href="#id-1-sign-up-with-losant" id="id-1-sign-up-with-losant"></a>

If you haven’t yet, sign up for free with Losant and create a new Application. Let’s call it **Connected truck**.

Within the application create a new device named **Truck** (when asked to choose between create from recipe and create from scratch, click on **Create Blank Device**).

Choose device type as **Standalone**. It is important to specify following attributes for the device Truck:

![](/files/-LiNWlymfl829n-4G-da)

Note that the names of parameters **(location, temperature, speed)** should exactly match as in above picture. As you might have correctly imagined, we will report above 3 parameters to the Losant platform.

Make sure you copy your Device ID from the top right corner of your device tab, which looks as follows:

![](/files/-LiNWlyouOOr_7YcAwVM)

Next, Go to the **Access Keys** menu and create an **Access Key**. The key should be restricted to the device type Truck we just created. Make sure you download the access key and secret to your local computer. We will need it later.&#x20;

At the end of this step you should have following:

A **Device ID** which looks like: 58a6c6e6217f8521311f28cd\
An **Access key** which looks like: e4fc60fe-1111-2222-8480-16710b46908d\
An **Access Secret**: XXXXXX… (A really long string)

Alright, we are finished with Losant for the moment. Let’s get to IoTIFY.

## 2. Get started with IoTIFY Network simulator <a href="#id-2-get-started-with-iotify-network-simulator" id="id-2-get-started-with-iotify-network-simulator"></a>

If you haven’t signed up yet, please get a free account with [IoTIFY.io](http://iotify.io/).  Once signed up, please go to Network simulator tab and create a new template.

Select **MQTT(S)** as connection protocol, and give a unique name to the template. We’ll call it **Losant**.

For the newly created template, in the MQTT Parameters section change the endpoint URL to following: **broker.losant.com:1883**.

The MQTT parameters should look like following:

![](/files/-LiNWlyrySWvfsppl4uF)

Further in the MQTT parameters:

In **MQTT Topic**, provide following value: losant/\[**Device ID]**/state, where \[**Device ID]** is the identifier of the device we previously created in Losant.\
E.g. The topic string will look like following:-\
losant/5d149f0c34fdb20009a7791f/state\
In the **Client ID** field, provide the Device ID as above

Here is how these parameters will look in Network Simulator template.

![](/files/-LiO5Ypx37MV-R0YyaFv)

In the Credentials section: in the **Username** field, provide the Access Key as obtained from Losant; in the **Password** field, providethe Access Secret as obtained from Losant:

![](/files/-LiO6D2yVxfaoQGjbtvG)

The next part is where most of the magic will happen.

### Message Contents <a href="#mqtt-message" id="mqtt-message"></a>

In the Message Contents tab, copy and paste the following text.

```
{ 
    state.path = drive({start:'Geneva,CH',end:'Hamburg,DE',accuracy:5});
    var retval = {};
    retval.time = { "$date" : moment.now()};
    retval.data = {};
    retval.data.location = state.path.latitude + ","+ state.path.longitude;
    retval.data.speed = state.path.speed ;
    retval.data.temperature = chance.integer({min:10, max:45});    
    
    return JSON.stringify(retval, null, 2);
}
```

What did we just do? We just called drive() function with a start and end address. Learn more about our powerful syntax for templates in our guide on how to simulate location.

To check that the template configuration is OK, click the **PREVIEW** button and check the result. If successful, you can save the template and start a simulation.

## 3. Start Simulation <a href="#id-3-start-simulation" id="id-3-start-simulation"></a>

Go to the **SIMULATE** tab in the network simulator, then choose the recently created template. The simulation ia automatically assigned a unique name, which can be changed if needed.

Set **Number of Clients** to **1**\
**(!!! Important )**&#x4D;ore than one client will cause Losant MQTT broker to drop connections to previous one.\
**Repeat Message**: As long as you like. We will set to 100.\
**Gap between Iterations**: 60 seconds.

Here is how simulation screen looks like after adding values.&#x20;

![](/files/-LiO9uGNoPSiMntNQ6Wp)

That’s it. Hit the start simulation button and you are ready to go.&#x20;

## 4. Build a beautiful Dashboard <a href="#id-4-build-a-beautiful-dashboard" id="id-4-build-a-beautiful-dashboard"></a>

Wait, simulation has started but how could you visualize it? It’s pretty easy to do that with Losant. Go to Losant Application once again and choose Dashboard Menu, then click on **Add Dashboard**. Then click on **Add Block** and you will see a list of gadgets to add.

Simply pick GPS History, Gauge and Indicator Gadgets. There are plenty of gadgets in Losant so feel free to experiment. For each gadget that you choose, you will have to specify the truck device and one of its attributes to be displayed. Here’s how final simulation will look like after a while.&#x20;

![](/files/-LiNWlyxEg4vmj8R0OnM)

## The next steps <a href="#the-next-steps" id="the-next-steps"></a>

Want to simulate driving from your home to office in real time? No worries, just provide the address in the start and end field in the drive() function and it will automatically calculate the address.

You could even adjust the accuracy of GPS Simulator, just like in real life. Play with the parameter a little.&#x20;

We are looking forward to seeing what you’ll build with IOTIFY Network Simulator. Join our Slack channel from IOTIFY application to showcase other’s what you’ve built.&#x20;


# Delivery Van

How to build a logistic application via simulating a delivery van

## Improving Transport Logistics <a href="#improving-transport-logistics" id="improving-transport-logistics"></a>

![](/files/-LiNEUIyY5pePMFjPtA8)

As e-commerce proliferates, logistic companies are under an immense pressure to deliver packages faster to more customers. Tracking the real time location and delivery performance of the vehicle in the fleet is vital to save cost and improve logistic efficiency. There are many fleet tracking solutions in the market, many of them rely on a GPS+UMTS based OBD2 dongle.

However, only monitoring these vehicles is not enough. One of the key objectives of IoT systems today is to optimize the delivery based on feedback and provide real time insights to end customer while improving the system efficiency. Imagine if your delivery company could accurately predict when the courier is going to arrive, within a 5 minute time slot. Wouldn’t that solve a big pain point in today’s system?

Modelling with such accuracy needs a lot of data to be captured from existing systems. For this purpose, accurately simulating vehicle movement under real traffic conditions is a major challenge. In this simulation exercise, we will model a package delivery van delivering parcels to various location in Zurich, Switzerland in real time.

## The Concept <a href="#the-concept" id="the-concept"></a>

We will model a situation where a delivery van driver needs to deliver 10 packets around central Zurich area.

The van will start from one address to another and deliver a packet at each location. We wouldn’t tackle the route optimization problem at the moment. The destination address is randomly chosen, upon start of each trip, with 1 km radius of current location.

The waiting time once the vehicle reaches the target location is currently fixed, implying it takes equal time to deliver packets for the driver to the door steps.\
The delivery vehicle will report its GPS location to a cloud platform every 10 seconds. We will track and monitor the vehicle’s postion live as well as number of pending delivery counts. Here’s how our dashboard is going to look like.

![](/files/-LiNEUJ1MQSGsqh_IEPd)

## Let’s get started <a href="#lets-get-started" id="lets-get-started"></a>

In this case, we are publishing the data to Losant as a cloud platform, but the simulation is generic and can be easily adapted to fit any other cloud platform.

## Configure Losant and setup the dashboard <a href="#configure-losant-and-setup-the-dashboard" id="configure-losant-and-setup-the-dashboard"></a>

If you haven’t yet, sign up for free with Losant.com and create a new Application. Let’s call it **Connected truck**.

Within the application create a new device named **Truck** (select "Create Blank Device" when asked to choose between create from recipe and create from scratch).

Choose device type as **Standalone**. It is important to specifiy following attributes for the device Truck:

* **GPS String** : location
* **Number** - speed
* **Number** - contents

Note that the names of parameters **(location, contents, speed)** should exactly match as in above. As you might have correctly imagined, we will report above 3 parameters to the losant platform.

Make sure you copy your Device ID from the top right corner of your device tab.

Next, Go to Tab **Access Keys** and create an **Access Key**. The key should be restricted to the device type Truck we just created. Make sure you download the access key and secret to your local computer. We will need it later.&#x20;

At the end of this step you should have following:

A **Device ID** which looks like: 58a6c6e6217f8521311f28cd\
An **Access key** which looks like: e4fc60fe-1111-2222-8480-16710b46908d\
An **Access Secret**: XXXXXX… (A really long string)

Now go to the Dashboards Menu, create New Dashboard. Then click **Add Block** and you will see a list of gadgets to add. Simply pick GPS History, Gauge and Indicator Gadgets. There are plenty of gadgets in Losant so feel free to experiment. For each gadget that you choose, click on **Customize**, then in the gadget configuration screen select the truck device in the **Device IDs / Tags** field and a device attribute in the **Attribute** field; finally, click on **Add Block**.

Alright, we are finished with Losant for the moment. Let’s get to IoTIFY.

## Signup with IOTIFY <a href="#signup-with-iotify" id="signup-with-iotify"></a>

If you haven’t signed up yet, please request a free account with [IoTIFY.io](https://iotify.io/). From the **Sign In / Join** menu, select **Network Simulator** and then register an account. Once signed up, please go to Network simulator tab and create a new template.

Give a unique name to the template. We’ll call it **logistics**. Set the protocol to MQTT and click on **CREATE**.

In the MQTT Parameters section, change the endpoint URL to following: **broker.losant.com:1883**; in the **Client ID** field, provide the Device ID as obtained from Losant; in the **MQTT Topic** field, provide the following value: losant/\[**Device ID]**/state\
E.g. The topic string will look like following:-\
losant/58a6c6e6217f8500018f28cd/state

In the Credentials section:\
In the **Username**: Provide access key as obtained from Losant\
In the **Password**: Provide access secret as obtained from Losant.

### Message Contents <a href="#mqtt-message" id="mqtt-message"></a>

Copy and paste following template to model a delivery van for this scenario.

```
{ 
    // change this to your city if you need
    const city= "Zurich, CH";
    
    // delivery radius around the city center
    const radius = 1000;
    
    // the very first iteration. 
    if (state.contents === undefined){
        state.contents = 10;
        state.trip = 0;
        state._$wait = 0;
        state.start = city;
        var dest = location({address:city, accuracy: radius});        
        state.dest = dest.latitude + ","+ dest.longitude;
    }
    // simply drive
    state.path = drive({start: state.start, end: state.dest});

    // if last position is equal to the new one, we have reached the current destination. 
	if (state.path.finished){
	    state._$wait++;

	    //change wait limits to stay longer for delivery
	    if (state.contents > 0 && state._$wait++ == 3){
	        state._$wait = 0;
	        console.log("Trip finished at ",state.path.latitude + ","+ state.path.longitude);
	        //increment trip index, loop to trip 0 once last trip ends
    	    state.start = state.path.latitude + ","+ state.path.longitude;
    	    var dest = location({address:city, accuracy: radius});        
    	    
            state.dest = dest.latitude.toFixed(6) + ","+ dest.longitude.toFixed(6);
    	    state.contents--;
    	    state.path = drive({start: state.start, end: state.dest});
    	    console.log("Now driving ", state.start, " to ", state.dest);
	    }
	}

	//publish our information to Losant. 
    var retval = {};
    retval.time = { "$date" : moment.now()};
    retval.data = {};
    retval.data.location = state.path.latitude + ","+ state.path.longitude;
    retval.data.speed = state.path.speed ;
    retval.data.contents = state.contents;    	
    return JSON.stringify(retval, null, 2);

}
```

The template may look like complex at a first glance but it’s quite simple actually. In the very first iteration, we will set up our state variables. The drive function will generate the GPS coordinates for vehicle. Once the drive is finished (the function will return a value with finished set to true), we will simply pick another trip after a slight wait. We will continue to drive until we have delivered all the parcels. Once all the delivery is completed, the vehicle will simply wait at the last known location.

That’s it. Hit the preview button and you should see sample message along with Success result in the preview window. If there is any error, please check you have correctly followed the above steps.

## Start the simulation. <a href="#start-the-simulation" id="start-the-simulation"></a>

Once the template is ready, hit Save and go to the **Simulate** tab. Select the network template you just created, then specify the number of clients to be 1 and number of iterations to be 100. You could reduce or increase the number of iterations if you want, usually it depends upon how many contents are to be delivered and how big is the radius of the delivery.

Make sure to enable the **Save state information for each client and iteration** checkbox so that you could monitor all the state variables in the simulation detailed result tab.

Finally, click **START SIMULATION** at the bottom of the page. That’s it. If everything works well, after a while, the delivery vehicle will be visible in the Losant Application dashboard.

Once the simulation is finished, here is how your dashboard will look like.

![](/files/-LiNEUJC-P35ifLrr_Pw)

## Modelling the real world conditions <a href="#modelling-the-real-world-conditions" id="modelling-the-real-world-conditions"></a>

Once you have played around with how the simulation works, you could add some real world conditions and add intelligence to your cloud platform to create more value for the solution. E.g.

* Analyze the route taken and suggest an optimized route.
* Slow down or accelerate the simulated vehicle speed (ask us how in the slack channel) and generate alerts when driver is driving too fast.
* Create an app which predicts the estimated arrival of delivery van to the customer.
* Change wait times at delivery stop to random values and flag excessive wait times at any stop.
* Get a delivery confirmation and put it on blockchain (moonshot, but who knows:-)).

We will be happy to hear your thoughts about what application ideas you could build on top of this simulation! Please keep your comments coming.


# Google Cloud IoT Core

Learn how to use IoTIFY's network simulator to connect a virtual device to the Google Cloud IoT Core platform.

## Introduction <a href="#introduction" id="introduction"></a>

Google Cloud IoT Core is Google’s offering in the IoT cloud platform provider marketplace. It supports MQTT and HTTP as communication protocol. This guide describes how to use IoTIFY network simulator to create virtual devices that communicate with Google Cloud IoT Core.

The official documentation for integration can be found at <https://cloud.google.com/iot/docs/how-tos/>\
This guide is prepared specifically for integrating IoTIFY to Google Cloud IoT Core infrastructure.

## 1. Sign up with Google Cloud IoT Core and create a new IoT Registry <a href="#id-1-sign-up-with-google-cloud-iot-core-and-create-a-new-iot-registry" id="id-1-sign-up-with-google-cloud-iot-core-and-create-a-new-iot-registry"></a>

In Google cloud console, click on the IoT Core project. You will have to enable billing in order to create this project. The IoT Core menu item can be found under Big Data section on the left hand side menu. The very first step is to create an IoT device registry.

![](/files/-LiOBi2TNiFpmgAeks9E)

Let’s create a new registry named **myregistry** and choose the region as **europe-west1**. You will also need to specify the default cloud pub-sub topics for sending events and state from this registry. We just created two default topics for event and state as follows:

![](/files/-LiOBi2_MyiGygJc68LJ)

These topics will be used later in Step 8 to monitor data coming from IoT devices.

## 2. Generate public/private key for your device <a href="#id-2-generate-public-private-key-for-your-device" id="id-2-generate-public-private-key-for-your-device"></a>

In order to configure authentication for devices in Google Cloud IoT core, we need to generate a public and private key pair. You could use any tool to create those key pairs, for this guide we will use openssl command-line tool on a Linux machine. Run following two commands to generate a public and private key pairs in RSA 256. Following are the parameters for generating these key pairs.

```
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
openssl rsa -pubout -in private_key.pem -out public_key.pem
```

These two commands will produce private\_key.pem and public\_key.pem files in the current folder.

## 3. Configure our device in IoT Core <a href="#id-3-configure-our-device-in-iot-core" id="id-3-configure-our-device-in-iot-core"></a>

Now let's go back to our registry page and click add device button to add our new virtual device. Lets call it **iotify\_0**

![](/files/-LiOBi2esQRQeK0HwMC2)

We will keep all the default values. In the text field named **public key value** we will add our newly generated public key file **public\_key.pem** contents.

That’s it. The device has now been provisioned in Google cloud IoT Core platform. Let’s take note of following 4 values which we will need into IOTIFY template.

**Project ID:** This is the top level project ID for your IoT Project. Notice that project ID is different than project Name. The ID can be retrieved by clicking the project name on the top blue bar on the Google Cloud console web page. It is also visible in your default telemetry topics while creating registry in step 1. In our example, the project ID is **iotify-200307**

**Region:** This is the region where you created your IoT registry. It is set to **europe-west1** in our case.

**Registry name:** This is the name of the registry we just created in step 1. It is set to **myregistry** in our case.

**Device ID:** This is the name of the new device which we just provisioned a while ago. It is set to **iotify\_0** in our case.

**Private key:** This is the content of the private\_key.pem file which we just generated.

These four parameters will now be used to configure our IoTIFY template.

## 4. IoTIFY HTTP Template. <a href="#id-4-create-a-new-iotify-http-template" id="id-4-create-a-new-iotify-http-template"></a>

You can import our IoTify HTTP Boilerplate from the link below

**`https://raw.githubusercontent.com/iotify/nsim-examples/master/connectors/GCloud-HTTP.json`**

Or, Make your own from scratch

Once we have all the information, it's time to create a device template in IoTIFY. Let’s create a new HTTP(S) template and set following parameters:-

**Protocol:** Set to HTTPS (TLS 1.2)

**Host:** Set to **cloudiotdevice.googleapis.com**

**Path:** Path should be set in a specific format of\
`/v1/projects/`**`[Project ID]`**`/locations/`**`[Region]`**`/registries/`**`[Registry Name]`**`/devices/`**`[DeviceID]`**`:publishEvent`

&#x20;E.g. in our case the path would be as follows:

/v1/projects/iotify-200307/locations/europe-west1/registries/myregistry/devices/iotify\_0:publishEvent

**Method:** Change the HTTP method to **POST**

**Additional Headers**: In order to authenticate with Google Cloud IoT core, we will need to have a bearer Token in HTTP header. Add following two header fields as follows:

&#x20;authorization: Bearer {{state.token}}

&#x20;Content-Type: application/json

&#x20;Remember that {{state.token}} is a dynamic field, which will be calculated at run time.

This is how our new template will look like

![](/files/-LiOKDxIi1uAy2qJmnem)

Let’s now create our authentication parameters.

## 5. Generate JWT token <a href="#id-5-generate-jwt-token" id="id-5-generate-jwt-token"></a>

Google Cloud IoT Core needs JWT token for authentication. The JWT token can be created in the Device Setup function.

Click on the Tab **Device setup** in our template and paste following contents.

```
{
  var private_key = `
---- Paste the entire contents of your private_key.pem file here including the
---- header and footer line
  `;
  
  var token = {
        'iat': parseInt(moment().valueOf() / 1000),
        'exp': parseInt(moment().valueOf() / 1000) + 60 * 60 * 24,  // 24 hours is the maximum validity time. The token could be cached if performance of jwt.sign is a problem
        
        // ****** Important: Replace your Project ID below as well*****        
        'aud': 'iotify-200307' 
   };
      
   state.token = jwt.sign(token, private_key, { algorithm: 'RS256' });

  //no need for return 
}
```

Copy the entire content of your private\_key.pem file and paste it into the string value of the `private_key` variable in the above code. The setup function code will use the private key to generate a JSON Web token and save it into state.token field, which will be reused later.

**Make sure** that you change your project ID in the `aud` field as well.

## 6. Specify the payload <a href="#id-6-specify-the-payload" id="id-6-specify-the-payload"></a>

Once the authentication parameters are set, it's time to specify the payload. Unlike other cloud platforms, Google IoT Core is very specific when it comes to payload formatting. You will need to supply the content into a particular format and any violation will generate HTTP Error 400. Nevertheless, paste following contents in the **Specify Message Contents** tab

```
{ 
  // Contents has your actual message
  var content = { hello: "world"};
  
  // you could also specify a subfolder pattern here. 
  var subfolder = {};

  var payload = {};

  // we need to base64 encode the values for each of the two keys separately
  payload.binary_data = Buffer.from(JSON.stringify(content)).toString('base64');
  payload.sub_folder = Buffer.from(JSON.stringify(subfolder)).toString('base64');
  
  //return a string value which will be sent as the message payload
  return JSON.stringify(payload, null, 2);
}
```

That’s it. Click preview button and you should see the content has been posted successfully.

![](/files/-LiOBi2pWiNJW4W2Qdek)

Once the preview is successful, you could go and simulate the template. Remember to specify the number of clients as 1 as we have only configured 1 device in GCP. You could also change the message content to generate contents more dynamically.

## 7. Use MQTT Template (Optional) <a href="#id-7-use-mqtt-template-optional" id="id-7-use-mqtt-template-optional"></a>

It is also possible to use the MQTT(S) protocol to connect with Google IoT Core. The **Device Setup** function content and **Specify Message Contents** value can be reused from the HTTP template above.\
The only change required is in the MQTT Connection settings as follows:-

**Protocol**: `mqtts (TLS 1.2)`

**Endpoint**: `mqtt.googleapis.com:8883`

**Topic**: use the following format:  `/devices/`**`[deviceID]`**`/events`

**ClientId**: `projects/`**`[projectiD]`**`/locations/`**`[location]`**`/registries/`**`[Registryname]`**`/devices/`**`[DeviceID]`**

E.g. in our setup, the clientID will be as follows:

`projects/iotify-200307/locations/europe-west1/registries/myregistry/devices/iotify_0`

**Username**: `dummy`

**Password:** `{{state.token}}`

That’s it. Your virtual device should now be able to connect to GCP IoT Core via MQTT. Click on the preview tab to verify this.

## 8. Monitoring the published Contents from Google Cloud <a href="#id-8-monitoring-the-published-contents-from-google-cloud" id="id-8-monitoring-the-published-contents-from-google-cloud"></a>

Now once your device is ready and publishing successfully to the cloud, it's time to monitor the contents on the pub/sub. For this, we will use the built on google cloud shell console which can be invoked directly from your GCP webpage. Click on the terminal icon on the top bar right hand side.

![](/files/-LiOBi2s1-AYjnWdhPzf)

This will provision a google Cloud console. Enter following commands to subscribe to your newly published topic.

```
gcloud pubsub subscriptions create --topic projects/iotify-200307/topics/events  mySubscription         

gcloud pubsub subscriptions pull --auto-ack mySubscription
```

Once you publish a new message via our simulated device, you will be able to see the message contents in the console output.

![](/files/-LiOBi2vY6INSZyeZpGG)

## Summary <a href="#summary" id="summary"></a>

In this guide we connected a single device to Google Cloud IoT Core. In future, we will update this guide to enable automated provisioning of devices and scale to a higher number. You could learn more about how to generate dynamic contents [here](https://docs.iotify.io/understanding-template).


# IBM Cloud

Learn how to configure IoTIFY's network simulator to connect virtual devices to IBM Cloud via IBM's MQTT broker.

## &#x20;<a href="#introduction" id="introduction"></a>


# Simple Messaging

## Introduction <a href="#introduction" id="introduction"></a>

IBM Cloud is a cloud service that offers, among other things, an IoT platform that lets IoT devices connect and send data that can later be analyzed using IBM cloud services. This IoT platform offers a REST API as well as an MQTT broker interface. In this tutorial we will learn how to set up IBM Cloud and connect to it using our network simulator.

## 1. Sign up with IBM Cloud <a href="#id-1-sign-up-with-ibm-bluemix" id="id-1-sign-up-with-ibm-bluemix"></a>

Before starting, sign up for a free IBM Cloud account at <https://www.ibm.com/cloud>, and then log in to your account. You will be asked to create an organization and a space: follow the instructions and then you will be taken to your account’s dashboard. Click **Catalog** in the top menu, then the **Internet of Things** category in the left menu, and then **Internet of Things Platform**:

![](/files/-LiOYweN5UBJxwH_oKg1)

Now you have to create a service: insert a name for the service (for example: IoTIFY) and then click **Create**; then, on the welcome page click **Launch**. You are now taken to the IBM Watson IoT Platform dashboard.

## 2. Create a Device in IBM Cloud <a href="#id-2-create-a-device-in-bluemix" id="id-2-create-a-device-in-bluemix"></a>

Once the service is launched, the next step is to create a device type: on the left menu, click **Devices**, activate the **Device Types** tab, and then click the **Add Device Type** button; on the next screen, enter a name for your type and click **Next**. You can optionally define template data or add metadata to the device type, but this is not mandatory, and you can simply skip these steps when creating the device type. Click **Finish** to complete the device type registration.

Now you can go to the **Browse** tab, click on **Add Device**; in the **Device Type** field, select the previously created device type from the drop-down menu. The only mandatory data to insert for a new device is the device ID: choose an ID for your device, then go through the following steps and finally click **Finish**.&#x20;

The next screen shows all the info for your device, including an authentication token: take note of this token now, since it will be needed when setting up the IoTIFY network simulator:

![](/files/-LiOcxukG01Qvhx3D_Vj)

The setup phase in IBM Cloud is completed: now it’s time to send data to it from our network simulator.&#x20;

## 3. Create a template in IoTIFY network simulator <a href="#id-3-create-a-template-in-iotify-network-simulator" id="id-3-create-a-template-in-iotify-network-simulator"></a>

You can start by importing our predefined template from the link below

```
https://raw.githubusercontent.com/iotify/nsim-examples/master/connectors/ibm-connector.json
```

Or, You can create one yourself.

* To create a new template, go to the `TEMPLATES` tab of IoTIFY Network Simulator and click on `New Template`
* Then, select `MQTT(S)` as connection protocol, give the template a name of your choice (for example, IBMcloud) and click on `CREATE`.
* The next screen allows you to customize the template. In the MQTT parameters section, do the following configuration:
  * select `MQTTS (TCP)` as protocol
  * insert a string with the format `<org-id>.messaging.internetofthings.ibmcloud.com` as endpoint URL, where `<org-id>` is the identifier of your organization in your IBM Cloud account. You can find this information on the top right of your IBM Watson IoT Platform dashboard, below your account's IBM ID.&#x20;
  * The topic of the MQTT messages sent by the devices must be of the form `iot-2/evt/<event_id>/fmt/json` , where  is a name of your choice that identifies the events published by a device.&#x20;
  * Then, as`ClientID` you have to insert a string with the format `d:<org-id>:<device_type>:<device_id>`, where&#x20;
    * `<org-id>` is the same as above
    * `<device_type>` is the name of the device type associated to your device in IBM IoT Platform
    * `<device_id>` is the identifier of your device.

![](/files/-LiSmYkaR5dnzdDYb2hD)

In the credentials ections, you have to supply authentication credentials: insert **`use-token-auth`**&#x61;s username, and the authentication token assigned when you created your device as password:

![](/files/-LiSn8UXHc7-PurUfM8t)

The MQTT message contents must be formatted in JSON and must contain a single top-level property called *d*. For example:

```
{
    var mystate = {
        d: {
            "true Power": chance.integer({min: 100, max: 3000 }),
            "time": moment.now()
        }
    };
    return JSON.stringify(mystate)
}
```

Click on **PREVIEW** to verify if your template has been configured correctly; then, if the preview is successful, save your template and you are all set up to send data to IBM Cloud.

## 4. Send data to IBM Cloud <a href="#id-4-send-data-to-bluemix" id="id-4-send-data-to-bluemix"></a>

In IoTIFY Network Simulator, launch a new simulation, and as your virtual devices start sending MQTT messages you will be able to see your generated data in the IBM IoT Platform dashboard: click on your device in the dashboard, and you will see events as they come in from our simulator:

![](/files/-LiSo2DFFfnvcQZrdmPK)

Clicking on an event will show you the corresponding message contents, generated by the simulator according to your template:

![](/files/-LiSo7kUffFrrnbYXCuv)

That’s it! Enjoy using our network simulator with IBM Cloud!


# IBM Bluemix: Monitoring Energy Consumption

Learn how to simulate an office building energy meter with IoTIFY network simulator and how to monitor power usage with IBM Cloud.

## Introduction <a href="#introduction" id="introduction"></a>

IoTIFY network simulator with its powerful templates can be used to simulate a large variety of processes, either deterministic or with random components, and as such it is a valuable tool to understand how a real-world deployment of connected devices will look like. Data sent to the cloud by a simulated device can be monitored and analyzed, just like data sent by real-world devices, using your preferred data analytics tools. This tutorial will demonstrate these concepts with a practical example of an office building energy meter that sends power consumption data to the IBM Cloud IoT platform.

## 1. Set up a template in IoTIFY network simulator <a href="#id-1-set-up-a-template-in-iotify-network-simulator" id="id-1-set-up-a-template-in-iotify-network-simulator"></a>

Network simulator templates specify properties of network messages that simulated devices will send during a simulation. In this example, we are going to send messages from an energy meter to IBM Cloud. In our article “Integration: IBM Cloud” we explained how to set up IoT devices in IBM Cloud and how to configure a network simulator template so that a simulated device will connect to IBM Cloud using the MQTT protocol: refer to that article for information on how to configure MQTT parameters in the template. To simulate an energy meter, in this article we will use different message contents for our template: specifically, we will dynamically calculate the current temperature based on the time of day, estimate power consumption by the HVAC system to reach a desired temperature, and calculate total power consumption by adding a random value to the consumption by the HVAC system.\
As explained in our article “Integration: IBM Cloud”, MQTT message contents must be formatted usin JSON and must contain a top-level attribute named “d”, under which the data of interest are located. Our simulated energy meter will send the following data in each MQTT message:

* current outside temperature
* power drawn by the HVAC system to keep temperature inside the building at a desired level
* total power drawn in the building, which will include the HVAC power and add to it a random component

To simulate the outside temperature at a given time, we use a simplified model where temperature ranges between a minimum and maximum value, increasing linearly from midnight to noon, and decreasing linearly from noon to midnight.

To keep things simple, we vary our simulated temperature at the top of each hour, so we are only interested in the hours of the current time. In our example we use an UTC+1 time zone (via `moment().utcOffset(60)`), i.e. we specify a 60 minute offset from the UTC reference time.

Next, we define a range for the simulated temperature, and a formula (using Javascript code) to calculate the temperature based on the current time; for example:

```
const minTemp = 10;
const maxTemp = 20;
var clockHour = hours % 12;
var range = maxTemp - minTemp;
var factor = clockHour * range / 12;
state.temperature = (hours < 12) ? (minTemp + factor) : (maxTemp - factor);
```

Given the outside temperature, the power needed by the HVAC system to keep the temperature inside the office at a given level (for example, 20 °C) is estimated to vary linearly with the difference between outside and inside temperature; in addition, we assume that the HVAC system is operated only during office hours, from 9:00 AM to 6:00 PM:

```
// HVAC is turned off except office hours, so power will be zero
state.hvac_power = ( hours < 9 || hours > 18) ? 0 : (20 - state.temperature) * 1000;
```

Finally, the total energy consumed in the building is calculated by adding a random component to the HVAC power; to do this, we use the `normal()` function of the chance.js library, with a mean value of 1000 and a standard deviation of 500:

```
// Add some random variation
state.total_power = state.hvac_power + chance.normal({mean: 1000, dev: 500});
```

The complete message contents in our template are as below:

```
{
    // get current hour in GMT + 1
    var hours = moment().utcOffset(60).hours();
    const minTemp = 10;
    const maxTemp = 20;
    var clockHour = hours % 12;
    var range = maxTemp - minTemp;
    
    var factor = clockHour * range / 12;
    
    state.temperature = (hours < 12) ? (minTemp + factor) : (maxTemp - factor);
    
    // HVAC is turned off except office hours, so power will be zero
    state.hvac_power = ( hours < 9 || hours > 18) ? 0 : (20 - state.temperature) * 1000;
    
    // Add some random variation
    state.total_power = state.hvac_power +chance.normal({mean: 1000, dev: 500});
    
    var myret = {
        d: state
    };
    return JSON.stringify(myret)
}
```

## 2. Set up data visualization in IBM Cloud <a href="#id-2-set-up-data-visualization-in-ibm-bluemix" id="id-2-set-up-data-visualization-in-ibm-bluemix"></a>

We are now going to set up IBM Cloud so that data coming from our simulated energy meter will be displayed graphically.\
For information on how to set up IoT devices in IBM Cloud you can refer to our article “Integration: IBM Cloud”. Once the basic setup is done, from the IBM Watson IoT Platform dashboard expand the left menu and click **Boards**:

![](/files/-LiTLrX25elMCzHt0a6m)

Click **Create New Board**, then assign a name of your choice (for example, "IoTIFY") to the board, then click **Next** and then **Submit**. The newly created board will appear in the list of boards. Now, select the new board and click on **Add New Card**:

![](/files/-LiTFFWUDcAgmzS-dpc5)

First, we are going to add a graphical visualization of temperature data coming from our simulator. Click **Line chart**: in the dialog window that appears, select the IoT device you previously configured and click **Next**:

![](/files/-LiTFFWbXa1LOsLDUgcb)

In the next screen, click **Connect new data set** and insert the information needed to identify the temperature property in the data sent by the simulated device; specifically, the event name (in this example, "power\_usage") must be consistent with the MQTT topic in the simulator template (in this example, "iot-2/evt/power\_usage/fmt/json"), and the property name must equal the corresponding attribute name in the JSON object specified in the message contents:

![](/files/-LiTFFWcW0tOTAI-j1W2)

Click **Next**, then go through the following steps of the card creation wizard keeping the default settings; at the end of this procedure, the new card will appear in the board (with no data if the network simulator is not running yet).\
To add visualization of power consumption data, follow the same procedure as done for the temperature, but specifying the HVAC and total power properties as data sets:

![](/files/-LiTFFWrE2i8Bmb4w4dZ)

![](/files/-LiTFFWuxTVcYZESBgA0)

We can also add another card that will list all the attributes (hvac\_power, temperature, total\_power) of the device in numeric format; to do this, create a new card of type "Device Properties", then select our IoTIFY device as data source and connect 3 data sets, one for each attribute.

Now we are ready to start our simulation.

## 3. Start energy meter simulation <a href="#id-3-start-energy-meter-simulation" id="id-3-start-energy-meter-simulation"></a>

We can now start simulating our energy meter using the template we created in step 1. In the IoTIFY network simulator, define simulation parameters by selecting 1 as number of clients, and choosing a number of iterations and the gap between iterations, then start the simulation.\
As soon as the simulated device starts sending data, you can see this data visualized in IBM Watson IoT Platform:

![](/files/-LiTFFWw854jxouM7xFS)


# Dweet.io

Learn how to simulate devices that send out periodic dweets.

## Introduction <a href="#introduction" id="introduction"></a>

[dweet.io](https://dweet.io/) is an IoT platform where connected devices can send messages: according to its creators, “it’s like Twitter for social machines”.\
IoTIFY network simulator can easily simulate devices (or “things”) that send “dweets”; this article will guide you through the simple steps involved in setting up the simulator and will show how information extracted from these generated dweets can be visualized in a graphic dashboard. We will be simulating a car that sends periodically dweets containing information such as its current location, speed and fuel level.

## 1. Create a template for the network simulator <a href="#id-1-create-a-template-for-the-network-simulator" id="id-1-create-a-template-for-the-network-simulator"></a>

The network simulator template we are going to create will contain information such as the name of the simulated thing and the contents of the dweets sent by the thing.\
In the template creation dialog, select **HTTP(S)** (the messaging protocol used by dweet.io uses HTTP as application level protocol), and give your template a unique name.\
Then, in the template editing screen, in the HTTP parameters section select **http (TCP)** as protocol and insert “dweet.io” in the host field. The path of HTTP requests for sending out dweets has the format */dweet/for/\<thing-name>*, where *\<thing-name>* is an arbitrary name chosen to identify your thing. There is no need to sign up to get a name for your thing, just choose a name of your liking, but keep in mind that some other thing somewhere else may be using the same name! So it is best to choose a name unlikely to be chosen by someone else. In the HTTP method field, select **POST**.\
The following figure shows an example configuration for our dweeting car:

![](/files/-LiSp0xPXMO2BaO5ZRJS)

Finally, in the message content section specify what the simulated device is going to dweet. dweet.io supports sending data in JSON format, so our dweets will contains a JSON object with a few attributes. In our example we will be simulating a car traveling from one city to another that dweets its current location, speed and fuel level. For location and speed, we can use the drive() function, which allows specifying a start and end location and generates a corresponding driving route. For fuel level, we will assume an initial value of 100% (filled tank) which decreases by a fixed amount at each successive dweet; by using the **last** keyword along with minimal Javascript code we can easily specify the initial value (i.e. the value sent at the first dweet) and successive values computed as a function of previous values. The following figure shows the contents of our example template, for which we choose a route from Hamburg to Frankfurt:

```
{
    
    if (!state.fuel) state.fuel = 100;
    
    var mystate = drive({start:'Zurich,CH',end:'Hamburg,DE',accuracy:5});
	mystate.fuel = Math.max(state.fuel--,  0);
	
    return JSON.stringify(mystate, null, 2);
}
```

## 2. Create a dashboard with freeboard <a href="#id-2-create-a-dashboard-with-freeboard" id="id-2-create-a-dashboard-with-freeboard"></a>

[freeboard](http://freeboard.io/) is a website that allows creating graphic dashboards with simple drag and drop actions; a dashboard is populated from one or more data sources specified when the dashboard is created, and dweet.io is among the supported data sources.\
To begin using freeboard, sign up for a free account at [freeboard.io](http://freeboard.io/). Then, go to <https://freeboard.io/account> to create a new dashboard: after choosing a name for your dashboard, click **Create New** and you will be taken to the editing screen:

![](/files/-LiSoQeIhaS6mfeIgKS_)

Click **Add** in the datasources section, then select **Dweet.io** as type, give a name to the data source, and insert the name you previously chose as your thing name:

![](/files/-LiSoQeLkNOJfQiVtt_8)

Save the data source, then start building your dashboard by adding panes and widgets; for each widget, you can access data from your data source by specifying the name of attributes in the JSON object sent in each dweet, using the notation **datasources\[“\<data\_source>”]\[“\<attribute>”]**, where **\<data\_source>** is the name of your data source, and **\<attribute>** is the name of the attribute holding the data of interest. For example, the following figure shows the configuration for a widget that takes latitude and longitude values from relevant attributes of the data source (which must correspond to the names used in the network simulator template), and draws the path of the route on Google maps:

![](/files/-LiSpQ0lKRZTw6lBPHmv)

You can then add new panes and widgets to display speed and fuel level values, using for example gauge widgets. Inside the **Value** field of each widget, you can insert arbitrary Javascript expressions, for example to truncate a value of a certain number of decimal digits:

![](/files/-LiSoQePbeUbObxsuIQp)

## 3. Start dweeting! <a href="#id-3-start-dweeting" id="id-3-start-dweeting"></a>

Once you are happy with the contents and layout of your dashboard, you can use the network simulator template you defined in step 1 to start a simulation: give a unique name to the simulation, select 1 as number of clients, then choose a number of iterations and the gap between iterations according to how long you want your simulation to last:

![](/files/-LiSpjHHjMzSX6dGeag0)

As soon as the simulated device start sending messages, you will see the dashboard update in real time its contents:

![](/files/-LiSoQeYnhGImF4KSb_F)

You can choose to keep you dashboard public, in which case it will be accessible to anyone who has its link, or make it private: just go to <https://freeboard.io/account> and click **Edit** next to the dashboard name to edits its properties.


# JMeter and why it fails at IoT

IoT testing has been a space which has been quite overlooked in the past with no real testing platforms being built to tackle the problems specific to IoT testing. In such a case, a lot of teams have to settle down with a legacy tool like JMeter which was built to test web applications. While JMeter is an easier path than creating your own set of scripts to automate these testing scenarios, it leaves much to be desired, especially concerning IoT. This is where IoTIFY comes into the picture, it is a testing platform built from scratch to **utilize** the newest technologies, built with IoT testing in mind. Now you don’t have to choose between ease of use and a robust testing platform which can tackle complex problems specific to IoT testing,

Here are some of the features that set IoTIFY apart from other legacy web application testing tools.

* Create a truly realistic digital twin of your device
* Stateful device models to accommodate complex behaviors&#x20;
* Bi-directional communication so that you can test server-initiated functions like OTA updates
* Device-to-device communication, so you can model a full IoT system&#x20;
* Extremely scalable to millions of concurrent devices at once&#x20;
* Extensible JavaScript-based scripting with full npm support&#x20;
* Easy provisioning of devices with our cloud connectors&#x20;
* In-depth tracking of metrics and payloads so you can track any issues&#x20;
* Automate complex workflows with ease using a graphical interface&#x20;
* Easy to collaborate with your team with workspaces

**Let’s take a more in-depth look at some of these issues that IoTIFY solves.**

## Test a device’s complete lifecycle&#x20;

An IoT device will have multiple states, where it will behave differently, there are cases where the server may want to initiate an action on the device. These are all complex device interactions where tools like JMeter fail. With IoTIFY, you can create stateful device twins of your physical device and model behavior that can be as granular as required. Tools like JMeter can simulate MQTT payloads, but the communication isn’t bidirectional. This severely limits the scope of testing that can be done on these tools.

Another issue is the fact that JMeter virtual devices lack support for things like device states, memory and so on, which are basic requirements for IoT devices.

With IoTIFY, you get a true digital representation of your device, which allows you to test each and every complex workflow at scale.

## Full IoT system orchestration with LAN communication between devices&#x20;

IoT systems often not only communicate with a central server but also between devices on the local networks. This multichannel communication is a problem for legacy testing tools to simulate, however with IoTIFY you can have edge devices communicating with gateways which in turn communicate with a central server. This is a scenario unique to IoT systems and is often not viable to simulate owing to the complexity of having multiple different devices all communicating differently.

## Scaling up the IoT systems to a million scale&#x20;

In an IoT system, the scale can go to millions of unique devices all working at the same time and having their own memory and states. This can be extremely difficult to test with tools such as JMeter. However IoTIFY was built with scale in mind, so scaling your tests to a million nodes is as easy as clicking a button. Another advantage is the fact that, unlike simple load generators which will at best simulate a fixed scenario, IoTIFY device twins are true-life representations of the devices, which means that they can create a meaningful simulation of how the system will work in production. With full bidirectional communication and each node being a unique device with its individual memory and states, you can simulate a real-world usage of your system.

## Provisioning and maintaining devices with cloud providers&#x20;

A lot of IoT systems nowadays use cloud providers such as AWS or Azure to maintain the identity and data for their IoT devices. When creating a testing workflow, it can be a task to provision these devices and orchestrate the individual device identity and memory. Take into account the fact that the scale can move to millions and it can become a truly time and resource-consuming endeavor. With IoTIFY, using our cloud connectors, it becomes a matter of a few clicks. Our cloud connectors make it a painless task to provision and maintain millions of devices on cloud providers saving time and resources.

## Quality metrics and their necessity&#x20;

When dealing with any IoT system, it can be rather important to know and understand exactly what is happening with each individual device at any given time. This becomes increasingly necessary in case of any problems or bugs while testing an IoT system. Such granular data is not available with legacy testing tools such as JMeter, which will mostly provide high-level data like success and failure rates. With IoTIFY you get an insight into the workings, payloads and states of each individual device at all time intervals making it a very powerful tool for understanding what went wrong in any given test run. Tracking of test assertions, latencies and such are also taken care of by default. A powerful metrics engine also allows you to define any custom metric and easily visualize the data in graphs and charts.

## Automate complex workflows easily&#x20;

It can become quite a challenge to create very complex scenarios where multiple different devices are working together and each one depends on another simulation. It can become a nightmare to create such complex scenarios with legacy testing tools. However, with IoTIFY, you can easily automate such workflows using our graphical tool. The powerful scenario composer allows you to create such scenarios using a drag-and-drop tool. So it becomes a task which can be completed in minutes.

## Collaborate with ease&#x20;

While working in teams it is important that everyone has access to resources like the code base, the historical results and such. This can be a hassle with a tool like JMeter. However, IoTIFY was bult with collaboration at its core. Working with team members is as easy as sending them an invite by email. Once the accept the invite, they are added to a shared workspace. This makes it much more convenient to work and share resources.


