Only this pageAll pages
Powered by GitBook
1 of 7

Guides

Loading...

Integrations

Loading...

Loading...

Functions & Data Processing

Loading...

Loading...

How to Use JavaScript for Custom Rule Conditions in Qubitro

By following this guide, you can customize Qubitro rule functions using JavaScript to create dynamic conditions.

This guide explains how to use JavaScript within Qubitro’s rule functions to define custom conditions and automate actions based on real-time data.

A few notes to remember:

Rule Functions operate only on real-time data – They cannot query historical data from the database.

Each Rule Function executes a single pre-configured action – It does not support executing multiple actions within one function.

Actions are predefined during function setup – The trigger() function executes only the action assigned when creating the rule.


Although the examples here focus on environmental monitoring and geofencing, the same approach applies to any scenario requiring event-driven automation.

Accessing Data with Predefined Keys

Qubitro provides a simple way to access sensor values in JavaScript using predefined keys. These keys allow you to reference the latest device data without complex parsing.

Syntax and Usage

Define variables using predefined keys:

function run(){
    let temperature = ${{TEMPERATURE}};
    let humidity = ${{HUMIDITY}};
    let light = ${{LIGHT}};
    let motion = ${{MOTION}};
    let voltage = ${{VDD}};
}

Each variable directly pulls the corresponding real-time value from the incoming data.

Writing Rule Conditions

With variables defined, you can create logical conditions to decide when the function should trigger an action.

Example: Trigger an Action Based on Temperature and Humidity

This function triggers an action if the temperature is above 25°C and humidity exceeds 70%.

The trigger() function is used to execute predefined action when conditions are met.

This example ensures that a device does not enter a restricted assembly area. If it does, the function triggers an alert.

Utilizing the trigger() Function

Example: Alert When Temperature and Humidity Are Too High

Practical Implementations

Example 1: Geofencing a Restricted Area

Example 2: Advanced Environmental Monitoring

function run() {
    let temperature = ${{TEMPERATURE}};
    let humidity = ${{HUMIDITY}};

    if (temperature > 25 && humidity > 70) {
        trigger(); // Executes the pre-configured action
    }
}
function run() {
    let temperature = ${{TEMPERATURE}};
    let humidity = ${{HUMIDITY}};

    if (temperature > 30 && humidity > 80) {
        trigger(); // This executes the pre-configured action (e.g., send a notification)
    }
}
function run() {
    let coordinates = ${{coordinates}}; // Assuming format [latitude, longitude]

    // Convert coordinates array to an object
    let incomingLocation = {
        lat: coordinates[0],
        lon: coordinates[1]
    };

    // Define the restricted zone (assembly area)
    const restrictedZone = {
        A: { lat: 40.822608, lon: 29.352864 },
        B: { lat: 40.822652, lon: 29.353246 },
        C: { lat: 40.822289, lon: 29.352890 },
        D: { lat: 40.822327, lon: 29.353346 }
    };

    // Check if the incoming coordinates fall within the restricted area
    const isInsideRectangle = (point, rect) => {
        const minLat = Math.min(rect.A.lat, rect.B.lat, rect.C.lat, rect.D.lat);
        const maxLat = Math.max(rect.A.lat, rect.B.lat, rect.C.lat, rect.D.lat);
        const minLon = Math.min(rect.A.lon, rect.B.lon, rect.C.lon, rect.D.lon);
        const maxLon = Math.max(rect.A.lon, rect.B.lon, rect.C.lon, rect.D.lon);

        return point.lat >= minLat && point.lat <= maxLat && point.lon >= minLon && point.lon <= maxLon;
    };

    if (isInsideRectangle(incomingLocation, restrictedZone)) {
        trigger(); // Triggers the predefined alert (e.g., send a warning notification)
    }
}
function run() {
    let temperature = ${{TEMPERATURE}};
    let humidity = ${{HUMIDITY}};
    let lightLevel = ${{LIGHT}};
    let co2Level = ${{CO2}};

    // Trigger alert if temperature is too high and humidity is too low
    if (temperature > 28 && humidity < 40) {
        trigger(); // Executes the pre-configured alert
    }

    // Trigger alert if light levels drop too low while CO2 is high
    if (lightLevel < 200 && co2Level > 1000) {
        trigger(); // Executes the pre-configured alert
    }

    // Immediate action required for extreme conditions
    if (temperature > 35 || humidity > 80 || co2Level > 1500) {
        trigger(); // Executes the pre-configured alert
    }
}

How to Publish and Decode Multiple Hex Payloads via MQTT on Qubitro

Learn how to publish multiple hex payloads using MQTTX and decode them using Qubitro’s Decoder Function. This guide walks you through secure MQTT setup, payload formatting, and real-time data decoding

This guide shows how to:

  • ✅ Send multiple hex payloads using MQTTX

  • ✅ Use a custom Qubitro to decode GPS and sensor data

  • ✅ View structured decoded data in the Qubitro portal


  • A

  • An existing Device

  • Your device's MQTT credentials


  1. Go to your device in the Qubitro Portal

  2. Click the MQTT Credentials tab

  3. Copy:

    • Device ID (used as Username


Open MQTTX and configure your connection as shown below:

  • Name: broker.qubitro.com

  • Host: mqtts://broker.qubitro.com

  • Port: 8883


1. Go to your device → Functions tab

2. Click Add Function → Choose Decoder Function

3. Paste the following JavaScript code:

  1. Save and activate the function.

  1. Go to the Publish tab in MQTTX.

  2. In the topic field, paste your Device ID.

  3. Set the payload type to JSON.

  4. Use the following payload:

  1. Click the green send button to publish the message.

Open the Storage tab in your Qubitro device and you’ll see structured decoded values like:


You’ve successfully:

• Connected MQTTX to Qubitro securely

• Published multiple hex payloads

• Used a custom decoder to parse sensor/GPS values

• Verified decoded output in Qubitro

and topic)
  • Device Token (used as Password)

  • Host: broker.qubitro.com

  • Port: 8883 (SSL) or 1883 (non-SSL)

  • Topic: Device ID

  • Client ID: (same as Device ID)

  • Username: Device ID

  • Password: Device Token

  • SSL/TLS: ✅ Enabled

  • SSL Secure: ✅ Enabled

  • Certificate: CA signed server certificate

  • function decoder(input) {
      const longitude = ((input.bytes[0] << 24) | (input.bytes[1] << 16) | (input.bytes[2] << 8) | (input.bytes[6] & 0xC0)) /1000000;
      const latitude = ((input.bytes[3] << 24) | (input.bytes[4] << 16) | (input.bytes[5] << 8) | ((input.bytes[6] & 0x30) << 2)) /1000000;
      const hMSL32 = ((((input.bytes[6] & 0x0F) << 8 ) + input.bytes[7]) * 2) - 191;
      const hAccCoeff = (input.bytes[8] & 0xE0) >> 5;
      const vAccCoeff = (input.bytes[8] & 0x1C) >> 2;
      const heading = ((input.bytes[8] & 0x03) << 2) + ((input.bytes[9] & 0xC0) >> 6);
      const speed = (input.bytes[9] & 0x3F);
      const battery = ((input.bytes[10]*256) + input.bytes[11]);
      const year = (input.bytes[12] >> 2) + 2000;
      const month = ((input.bytes[12] & 0x03) << 2) + ((input.bytes[13] & 0xC0) >> 6);
      const day = (input.bytes[13] & 0x3E) >> 1;
      const hour = ((input.bytes[13] & 0x01) << 4) + ((input.bytes[14] & 0xF0) >> 4);
      const minute = ((input.bytes[14] & 0x0F) << 2) + ((input.bytes[15] & 0xC0) >> 6);
      const second = (input.bytes[15] & 0x3F);
      const timestampSeconds = Math.floor(new Date(year, month, day, hour, minute, second).getTime() / 1000);
    
      return {
        longitude,
        latitude,
        coordinates: [latitude, longitude],
        hMSL32,
        hAccCoeff,
        vAccCoeff,
        heading,
        speed,
        battery,
        time: timestampSeconds
      };
    }
    {
      "payload_hex": "00C08802808560A184000FFB648EAD0F,00c088028085909784000ffb648ead46,00c089028085109284000ffe648ead89,00c088028085e09c84000ffe648eadcb"
    }

    🧩 Prerequisites

    Step 1: Get Your Qubitro MQTT Credentials

    Step 2: Configure MQTTX (Secure Connection)

    Click Connect to establish a secure MQTT connection.

    Step 3: Add Decoder Function in Qubitro

    You can also test a single hex payload on the Qubitro Portal to verify your decoder.

    Step 4: Publish Multiple Hex Payloads

    Step 5: View Decoded Data

    Qubitro account
    MQTTX Desktop App

    How to Decode Uplink Messages with Qubitro Decoder Functions

    By following this guide, you can customize Qubitro decoder functions to decode various sensor payloads and extract valuable network metrics from any LNS integration.

    This guide explains how to use Qubitro’s decoder functions to parse raw uplink messages received via LNS integrations—such as The Things Stack, Loriot, and others.

    Although the examples here refer to decoding sensor data (like temperature or humidity), these functions work the same way for any LNS provider.

    Key Concepts

    Decoder Function

    A custom function that Qubitro automatically invokes with an input object containing the uplink message’s raw data, the fPort, and additional metadata.

    Input Properties

    • bytes: A byte array representing the raw data payload.

    • fPort: The port number used for the uplink message.

    • metadata: Rich network details from the LNS (e.g., signal quality, gateway information), regardless of the provider.

    How It Works

    Qubitro supplies the decoder function with an input object that includes all necessary properties.

    Your function should extract the required sensor values by converting raw bytes into human-readable data. You can also extract network metrics—like RSSI and SNR—from the metadata.

    Create a simple decoder function that extracts the raw bytes, fPort, and metadata:

    In this example, assume that the sensor sends temperature data encoded in two bytes. The function converts these bytes into a decimal temperature value:

    This example demonstrates handling multiple sensor readings. The function first checks if the payload is long enough and then extracts temperature and humidity from the last four bytes:

    Decoder functions can also extract network metrics (such as SNR and RSSI) from the metadata. This example demonstrates how to do so:

    Accessing Input Properties

    Decoding a Temperature Sensor Message

    Decoding Temperature and Humidity Data

    Accessing Metadata for Network Metrics

    function decoder(input) {
      var bytes = input.bytes;       // Retrieve the raw data payload
      var fPort = input.fPort;       // Retrieve the fPort number
      var metadata = input.metadata; // Retrieve LNS metadata
    
      return {}; // Customize and return a JSON object as needed
    }
    function decoder(input) {
      const bytes = input.bytes;
      const fPort = input.fPort;
    
      // Combine two bytes into one number and adjust the scale (divide by 100)
      const temperature = ((bytes[0] << 8) + bytes[1]) / 100;
    
      return {
        "bytes": bytes,
        "fPort": fPort,
        "temperature": temperature,
      };
    }
    function decoder(input) {
      var bytes = input.bytes;
      var fPort = input.fPort;
      var data = {};
    
      // Ensure the payload contains enough data for both sensors
      if (bytes.length < 4) {
        return { error: 'Payload too short' };
      }
    
      // Extract bytes for temperature and humidity
      var temperatureBytes = bytes.slice(bytes.length - 4, bytes.length - 2);
      var humidityBytes = bytes.slice(bytes.length - 2);
    
      // Convert the byte arrays into 16-bit integers and scale accordingly
      var temperature = ((temperatureBytes[0] << 8) | temperatureBytes[1]) / 100.0;
      var humidity = ((humidityBytes[0] << 8) | humidityBytes[1]) / 100.0;
    
      data["temperature"] = temperature;
      data["humidity"] = humidity;
    
      return data;
    }
    function decoder(input) {
      var bytes = input.bytes;       // Sensor data payload
      var fPort = input.fPort;       // fPort value
      var metadata = input.metadata; // LNS metadata from the uplink
      var snr, rssi;
    
      // Extract network metrics if available (works with any LNS provider)
      if (metadata && metadata.gws && metadata.gws.length > 0) {
        snr = metadata.gws[0].snr;   // SNR from the first gateway
        rssi = metadata.gws[0].rssi; // RSSI from the first gateway
      }
    
      // Additionally decode sensor-specific data (example calculations)
      return {
        STATUS: bytes[0] & 0x01, // Sensor status
        BATTERY: (25 + (bytes[1] & 0x0f)) / 10, // Battery level estimate
        COUNT: (bytes[7] << 16) | (bytes[6] << 8) | bytes[5], // Count extracted from multiple bytes
        SNR: snr,   // Signal-to-noise ratio from metadata
        RSSI: rssi  // Received signal strength indicator from metadata
      };
    }

    Guides

    Explore the recommended guides below to quickly familiarize yourself with core platform features and workflows.

    Getting Started with Qubitro

    This page helps you quickly get started with Qubitro by recommending essential guides and documentation. Follow these steps to set up your first project, connect devices, and explore core features.

    🚦 Start Here

    Creating Your First Project

    Start your IoT journey by setting up your project in Qubitro.

    Adding Your First Device

    Easily add, configure, and manage IoT devices.

    Visualizing Data with Dashboards

    Build interactive dashboards to monitor real-time device data.

    🛠️ Essential Features

    Understanding Time Series Storage

    Learn about data storage and retrieval options.

    Working with Functions

    Automate tasks using Decoder, Transformation, Rule, and Scheduled functions.

    Managing API and External Credentials

    Securely integrate Qubitro with other services.

    Developers

    Need more help? Visit our complete documentation or contact .

    Decoder Function
    rectangle-historyProject
    No-Code Integrations
    tower-broadcastMQTT
    brackets-curlyHTTP
    chart-mixedMonitoring
    Time Series Storage
    Functions
    support

    How to Use JSONata for Real-Time Data Transformation in Qubitro

    This guide explains how to use JSONata expressions in Qubitro Transformation Functions to manipulate and structure real-time data before it is stored or used for automated actions.

    JSONata provides a flexible, lightweight way to filter, calculate, and restructure data without writing traditional code.

    A few things to remember:

    Data can be modified on-the-fly before storage and automation.

    TF applies immediately to incoming data, whether raw or already decoded.

    How Transformation Functions Work in Qubitro

    Once a device sends data, TF automatically applies the JSONata expression configured by the user.

    If a Decoder Function exists, it will process raw data first, and then TF will apply JSONata expressions on the decoded output. If there is no decoder, TF will apply transformations directly to the published data.

    Basic JSONata Syntax

    Here are some core JSONata concepts:

    • Mathematical functions: $sum(values), $average(values), $max(values), $min(values).

    • Ternary operators: condition ? trueValue : falseValue.

    • String and numeric literals: "text" for strings, 42 for numbers.

    • Using the root object: $ refers to the root JSON object.

    • Accessing fields: fieldname retrieves a specific property.

    Convert a multi-level JSON object into a flat structure for better Qubitro compatibility.

    1
    2

    JSONata Expression:

    3

    Transformed Data:

    Transform an array of objects into structured key-value pairs.

    1
    2

    JSONata Expression:

    3

    Transformed Data:

    Use JSONata to compute sums, averages, and find min/max values dynamically.

    1
    2

    JSONata Expression:

    3

    Transformed Data:

    Modify timestamps into human-readable formats or compute durations.

    1
    2

    JSONata Expression:

    3

    Transformed Data:

    This method is useful when field names may change dynamically.

    1
    2

    JSONata Expression:

    3

    Transformed Data:

    {
      "sensor": {
        "type": "temperature",
        "readings": {
          "current": 22,
          "average": 21
        }
      }
    }
    {
      "sensor_type": sensor.type,
      "current_temperature": sensor.readings.current,
      "average_temperature": sensor.readings.average
    }
    {
      "sensor_type": "temperature",
      "current_temperature": 22,
      "average_temperature": 21
    }
    {
      "sensors": [
        {"type": "temperature", "value": 22},
        {"type": "humidity", "value": 55}
      ]
    }
    {
      "temperature_value": sensors[type='temperature'].value,
      "humidity_value": sensors[type='humidity'].value
    }
    {
      "temperature_value": 22,
      "humidity_value": 55
    }
    {
      "values": [5, 10, 15, 20, 25]
    }
    {
      "sum": $sum(values),
      "average": $average(values),
      "max": $max(values),
      "min": $min(values)
    }
    {
      "sum": 75,
      "average": 15,
      "max": 25,
      "min": 5
    }
    {
      "event": {
        "start_time": "2020-01-01T08:00:00Z",
        "end_time": "2020-01-01T12:00:00Z"
      }
    }
    {
      "start_date": $fromMillis($toMillis(event.start_time), '[Y0001]-[M01]-[D01]'),
      "end_date": $fromMillis($toMillis(event.end_time), '[Y0001]-[M01]-[D01]'),
      "duration_hours": ($toMillis(event.end_time) - $toMillis(event.start_time)) / (1000*60*60) & " hours"
    }
    {
      "start_date": "2020-01-01",
      "end_date": "2020-01-01",
      "duration_hours": "4 hours"
    }
    {
      "sensorData": {
        "temperature": 22,
        "humidity": 78
      }
    }
    {
      "temp_value": $lookup(sensorData, 'temperature'),
      "humidity_value": $lookup(sensorData, 'humidity')
    }
    {
      "temp_value": 22,
      "humidity_value": 78
    }

    Practical Implementations

    Example 1: Flattening Nested JSON

    Incoming Data:

    Example 2: Extracting Values from Arrays

    Incoming Data:

    Example 3: Performing Mathematical Calculations

    Incoming Data:

    Example 4: Time Formatting and Duration Calculation

    Incoming Data:

    Example 5: Dynamically Accessing Data Using $lookup()

    Incoming Data:

    spinner