Concepts of LoRaWAN Payload Decoders on Datacake

A Simple Guide to Creating LoRaWAN Decoders on the Datacake Platform

Intro

LoRaWAN decoders are essential for interpreting raw data transmitted by sensors into a format that is understandable and usable by users. On the Datacake platform, decoders are written in JavaScript, and the result is a JSON object containing the decoded data.

Below, we provide examples and explanations to help you understand how to create simple and effective decoders.

Simple Decoder for Temperature Measurements

This simple decoder assumes that the sensor's payload contains a temperature measurement. The temperature is sent as an integer in hundredths of degrees Celsius. The decoder converts this value into degrees Celsius.

/**
 * Simple Decoder for Temperature Measurements
 *
 * @product ExampleSensor
 */
function Decoder(bytes, port) {
    // Object that contains the decoded values
    var decoded = {};

    // Check if the message was sent via Port 1
    if(port === 1) {
        // Decode the temperature
        decoded.temperature = bytes[0] / 100;
    }

    return decoded;
}

Explanation

  • bytes[0] / 100: The first byte of the payload (bytes[0]) is divided by 100 to obtain the temperature in degrees Celsius.

  • decoded.temperature: This field contains the decoded temperature value.

  • port === 1: The decoder checks if the message was sent via Port 1. Different ports can be used for different data types or functions.

Example Output

Suppose the sensor sends the byte 0x1E via Port 1. The decoder interprets this as 30/100 = 0.3°C. The output of the decoder would be:

{
    "temperature": 0.3
}

Concepts

Using Timestamps for Aggregated Measurements

Some LoRaWAN devices collect measurements over a period (e.g., an hour) and send them in a single message. This conserves energy and bandwidth. In such cases, it is essential to timestamp each measurement to indicate when it occurred. Timestamps allow for precise historical recording and analysis of the data.

Example: Aggregated Temperature Measurements with Timestamps

Imagine a sensor that collects temperature readings every five minutes for an hour and then sends 12 temperature values in a single message. Each of these values can be written to the same field but with its own timestamp indicating when the measurement was taken.

Here is a sample decoder to handle these aggregated measurements:

/**
 * Decoder for Aggregated Temperature Measurements with Timestamps
 *
 * @product ExampleSensor
 */
function Decoder(bytes, port) {
    var decoded = [];

    // Check if the message was sent via Port 1
    if (port === 1) {
        for (var i = 0; i < bytes.length; i += 2) {
            // Extract the temperature value
            var tempValue = bytes[i] / 100;

            // Calculate the timestamp for each measurement
            // Example: The first measurement is at the start of the hour, each subsequent measurement every 5 minutes
            var timestamp = Math.floor(Date.now() / 1000) - ((12 - i / 2) * 300);

            // Add the measurement and its timestamp to the decoded results
            decoded.push({
                field: "temperature",
                value: tempValue,
                timestamp: timestamp
            });
        }
    }

    return decoded;
}

Explanation:

  • decoded: A list of objects, with each object containing a temperature value and its corresponding timestamp.

  • tempValue = bytes[i] / 100: The current temperature value is decoded from the byte data structure and converted into degrees Celsius.

  • timestamp: The timestamp is calculated by subtracting the elapsed seconds since the measurement from the current timestamp. This example assumes measurements were taken at five-minute intervals (5 minutes = 300 seconds).

Example Output

If the sensor sends 12 temperature readings collected every five minutes over an hour, the decoder output might look like this:

[
    {
        "field": "temperature",
        "value": 20.3,
        "timestamp": 1693190400
    },
    {
        "field": "temperature",
        "value": 20.4,
        "timestamp": 1693190700
    },
    {
        "field": "temperature",
        "value": 20.5,
        "timestamp": 1693191000
    },
    // More measurements here...
]

Key Concepts for Writing Decoders on the Datacake Platform

When creating decoders on the Datacake platform, it's essential to follow some basic rules and be aware of specific constraints. These rules ensure that decoders work efficiently, consistently, and are compatible with Datacake's infrastructure. Below are these concepts explained in detail.

1. Naming Conventions for Field Identifiers

To maintain a consistent structure and readability of the decoded data, all field identifiers must be written in uppercase letters, and spaces should be replaced with underscores. This convention ensures that all fields are uniformly named and easily identifiable.

  • Use Uppercase Letters: All field names should be written in uppercase to distinguish them from variables and other elements in the code.

  • Use Underscores Instead of Spaces: Use underscores (_) instead of spaces between words to improve readability.

Examples:

  • Instead of TemperatureOutside or temperature outside, use TEMPERATURE_OUTSIDE.

  • Instead of HumidityLevel or humidity level, use HUMIDITY_LEVEL.

These naming conventions not only make the code easier to maintain and read but also help establish consistent standards across the platform.

2. Specifics of the Datacake Decoding Engine

The Datacake Decoding Engine is designed for high scalability and reliability. It runs in a sandbox environment and is executed hundreds of times per second. This high scalability requires specific restrictions on the programming languages and methods used:

  • Simple JavaScript Version (ES5): To ensure smooth operation and compatibility, decoders should be written in simple JavaScript ES5. This means that modern JavaScript features (like ES6) and special JavaScript libraries are not supported. Only basic JavaScript functions and syntax should be used.

  • No Special Libraries or Objects: Due to scalability and security, the sandbox environment allows only simple JavaScript without additional libraries, external objects, or special JavaScript features. This excludes creating classes, using arrow functions, or importing external modules.

  • No Object or Class Instantiation: To maximize efficiency and conserve resources, creating custom classes or complex object instances is not allowed. All decoding operations should rely on basic JavaScript data structures like arrays, objects, and primitive data types.

Why These Restrictions?

The Datacake platform is designed to efficiently process data from various devices. To ensure scalability and maintain platform stability under heavy load (currently decoding approx. hundreds of messages per second), the above restrictions are implemented.

Using simple JavaScript syntax allows for fast processing of decoders and reduces potential error sources from complex or unsupported JavaScript features.

Summary

  • Always use uppercase letters and underscores for field identifiers (e.g., TEMPERATURE_OUTSIDE).

  • Write your decoders in simple JavaScript (ES5) without using additional libraries, complex objects, or classes.

  • Keep your code simple and efficient to support the scalability and reliability of the Datacake platform.

By following these guidelines, you ensure that your decoders operate efficiently on the Datacake platform and are easy to understand and maintain.

Advanced Topics

Beyond basic decoding, Datacake provides advanced features that allow decoders to perform more complex data processing and device management. These features are designed to enhance flexibility, scalability, and customization, making it easier to manage large fleets of devices and perform in-depth data analysis. Below, we explore these advanced options:

1. Database Access

Datacake decoders have the ability to access database values. This feature allows decoders to read existing measurements from the database for advanced preprocessing. With database access, you can implement functionalities such as:

  • Counters: Track how often a certain event occurs. For example, a motion sensor could count the number of times it detects movement.

  • Evaluations: Perform logical evaluations or comparisons using historical data. This could involve checking if the latest temperature reading is higher than the average over the past day.

  • Averages: Calculate averages or other statistical measures using past data. This is useful for smoothing out fluctuations and providing more stable readings.

  • More Complex Data Processing: Implement algorithms that rely on historical context or aggregate data to make informed decisions or actions.

Example Use Case:

A temperature sensor could use database access to compare the current temperature reading with the average temperature over the past hour. If the current reading is significantly higher, the decoder could trigger an alert or log the anomaly.

Read More:

Access Measurements

2. Configuration Fields

In Datacake, decoders are assigned to a product, and any devices added to that product will inherit the same decoder. This setup ensures that the same decoding logic applies uniformly across all devices associated with a product. However, managing large fleets or devices with varying calibration needs might require specific configuration adjustments. This is where configuration fields come into play:

  • Uniform Decoder Application: The decoder assigned to a product applies to all devices within that product. Any changes made to the decoder will automatically apply to all associated devices, ensuring consistency and ease of management.

  • Configuration Fields for Customization: Each device can have configuration fields that hold default values but can be overridden for individual devices. This is ideal for cases where certain devices need specific calibration, thresholds, or static values that differ from the product-wide defaults. Configuration fields enable:

    • Fleet Management: Easily manage and update configurations across a large number of devices without altering the core decoder logic.

    • Calibration: Devices can be individually calibrated by adjusting the configuration fields, ensuring accurate measurements specific to each device's environment.

    • Flexibility: Allows for dynamic adjustment of static values, enabling decoders to adapt to different use cases without rewriting the decoder code.

Example Use Case:

Imagine you have a fleet of humidity sensors deployed across different geographic locations. Each location may have a different baseline humidity level. By using configuration fields, you can set a default baseline humidity but adjust it per device to match local conditions, ensuring that the sensor readings are accurate and relevant to each location.

Read more:

Configuration Fields

Summary of Advanced Features

  • Database Access: Allows decoders to read historical data from the database, enabling advanced data processing like counting events, evaluations, and calculating averages.

  • Configuration Fields: Provide a mechanism to apply uniform decoder logic across all devices in a product while allowing individual customization. This is essential for managing large fleets, calibrating devices, and handling specific configurations.

These advanced features make the Datacake platform highly flexible and scalable, suitable for a wide range of IoT applications. They empower users to implement sophisticated data processing, device management, and customization with ease, enabling more intelligent and responsive IoT solutions.

Last updated