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.
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.
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.
So how are these device models executed? Let's understand this with the help of the picture given below.
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.
The other components of the tests are as follows :
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.
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:
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:
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.
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.
Now we have a good overview of what a test is, let's jump to the finer details of these tests.