LogoLogo
HomeSign UpGithub
  • Home
  • Release Notes
  • Getting Started
    • Create your first Test
    • Create Run Settings
    • Analyze the results
      • Job Summary
      • Logs
      • State
      • Payload
    • Look deeper with Metrics
  • Concepts
    • Workspaces
      • Role Based Access Control (RBAC)
      • Invitation Management
      • GitHub Integration
      • Deletion of Workspaces
      • System Status
    • Understanding Tests
      • Stages Management
        • Init Stage
        • Running Stage(s)
        • Finished State
      • Generating Messages
        • Scripting Environment
        • State Object
      • Response Handler
      • Preview Tests
      • Exporting/Importing Tests
        • Import OpenAPI JSON/YAML
      • Locking/Unlocking a test
    • Stateful Simulation
      • Mapping the IoT device lifecycle
    • Protocol Settings
      • MQTT
      • HTTP
      • Using other protocols
    • Run Settings
      • Network Simulation
      • Execution Strategies
      • Client Distribution
    • Scenarios
    • Glob Storage
    • Metrics
    • Mailbox
    • Licensing and Limits
    • Deployment Models
  • Additional Helpers
    • External Libraries
    • Inbuilt Libraries
    • IoTIFY Helper Functions
      • Job Functions
      • Messaging Functions
      • Glob Functions
      • Metrics Functions
      • Mailbox Functions
      • Data Generation Functions
  • platform integrations
    • AWS IoT Connector
  • Guides
    • Smart City
    • Smart Home
    • Load Testing Kafka
  • IoT Testing
    • Overview
      • Feed offline sensor data from Google Sheets to your IoT platform
    • Functional Testing
      • Basic functional test
      • Geofencing Validation
    • Performance Testing
      • MQTT end to end latency Measurement
    • Security Testing
    • Load Testing
    • Test Automation & CI/CD integration
  • API
    • Simulation API
    • Glob APIs
    • Metrics API
  • Glossary
  • Create Account
  • TEMP
    • Getting Started
      • Beginner
      • Developer
      • Tester
    • Walkthrough
    • Protocol Settings
      • CoAP
      • Raw (TCP/UDP/TLS/DTLS)
      • LWM2M
      • NONE
    • Under the hood
    • Google Sheets API
    • Azure IoT
    • Losant IoT
      • Losant Connector
      • Parking Space Management
      • Waste Management
      • Connected Truck
      • Delivery Van
    • Google Cloud IoT Core
    • IBM Cloud
      • Simple Messaging
      • IBM Bluemix: Monitoring Energy Consumption
    • Dweet.io
    • JMeter and why it fails at IoT
Powered by GitBook
On this page

Was this helpful?

  1. Concepts
  2. Understanding Tests

Generating Messages

PreviousFinished StateNextScripting Environment

Last updated 2 years ago

Was this helpful?

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.

Getting the current iteration

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.

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

{
    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:

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

Logging

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.

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

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

{
    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:

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

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