LwM2M Server


The LwM2M Server module enables the management of LwM2M-compatible IoT devices directly via the virtual devices in niotix. It provides a complete LwM2M server and makes it possible to manage and monitor devices seamlessly.

The module solves key challenges in IoT device management:

  1. No LwM2M server from the NB-IoT provider: niotix provides an integrated LwM2M server so that IoT devices can be directly integrated and managed regardless of the connectivity provider.
  2. Centralised management of DTLS keys: niotix’s integrated management of DTLS keys eliminates the need for a separate platform, simplifies workflow automation and increases security.
  3. Avoiding manufacturer-specific dependencies: The module uses the open LwM2M standard and avoids dependencies on manufacturer-specific solutions, enabling flexible, vendor-independent integration.
  4. More efficient alternative to MQTT: Compared to MQTT, LwM2M offers up to 70% better energy efficiency, which is particularly crucial for battery-powered IoT devices, and enables centralised configuration, firmware updates and DTLS encryption.

Communication overview

%%{ init: { 'theme': 'base', 'themeVariables': { 'primaryColor': '#FFFFFF', 'primaryTextColor': '#031403', 'primaryBorderColor': '#606060', 'lineColor': '#606060', 'secondaryColor': '#2fcbff', 'tertiaryColor': '#E7E6E6', 'primary_font' : 'Poppins:wght@300;400;500;600;700;800', 'primary_font_type' : 'sans-serif' } } }%% flowchart TB H([ LwM2M Device ]) -->| NB-IoT| A([ NB-IoT Provider])-->|"CoAP(s)"| B H <-.->|LwM2M| B subgraph niotix direction TB B([ Lwm2m Server]) <--> I([ Connector: LwM2M Server]) --> C([ Virtual Device]) end

What is LwM2M?

Lightweight Machine-to-Machine (LwM2M) is a communication protocol designed specifically for IoT devices. It is based on the CoAP protocol and is suitable for devices with limited power and bandwidth, such as sensors or meters. LwM2M enables remote management, monitoring and configuration of such devices. LwM2M offers the following advantages:

  • Efficient: Reduces data load and transmission time, ideal for battery-powered devices.
  • Easy remote management: Enables configuration and firmware updates.
  • Secure: Supports security standards such as DTLS for protected data transmission.
  • Compatible: Uses standardised object and resource models to ensure interoperability between different devices and manufacturers.

Functional overview

The LwM2M module in niotix offers the following core functions:

1. niotix connector

The following functions are available from niotix:

  • Device management and data reception: Functions for creating, reading, updating and deleting LwM2M devices directly via niotix and automated data reception
  • DTLS management: Centralised management of DTLS keys to ensure data security.
  • Security and connection modes:
    • Security modes: Support for no encryption or DTLS (Datagram Transport Layer Security).
    • Connection modes: Choose between bootstrap server and management server.

2. LwM2M server

The LwM2M backend offers the following additional functions:

  • LwM2M server: A fully featured LwM2M server supporting LwM2M V1.0, V1.1 and V1.2.
  • Firmware update management:
    • Over-the-air (OTA) updates: Enables secure, centralised firmware updates.
    • Version control and rollbacks: Includes a version history and the option to reset firmware in the event of problems.
  • Data model definition:
    • Support for standardised LwM2M data models.
    • Customisable data models for specific requirements, upload as.xml file.
  • Device configuration:
    • Remote configuration and parameter management.
    • Profile creation for mass, uniform configuration of device groups.
  • Automated task management:
    • Scheduling for routine tasks such as device checks or updates.
    • Batch operations for mass updates or configurations.

Device configuration

Configuration of the LwM2M device

Lwm2m devices usually offer different configuration options. The following settings are required to connect to the niotix LwM2M server:

  • Connection type: Bootstrap or Management Server. Bootstrap Server is generally recommended
  • Encryption: Choose between Pre-Shared Key (PSK) with DTLS encryption or without encryption. We generally recommend DTLS
  • Device Key: The PSK key used to authenticate the device; this can be in string or hex format, depending on the device

The server address and port must be set in the device, depending on the selected connection type and encryption:

Connection type with DTLS without encryption
Bootstrap Server coaps://lwm2m.niotix.io:5694 coap://lwm2m.niotix.io:5693
Management Server coaps://lwm2m.niotix.io:5684 coap://lwm2m.niotix.io:5683

Configuration of the Virtual Device in niotix

  • External ID: The unique identifier of the device, such as IMEI or EUI, is used for authentication at the LwM2M server.
  • Connection Server Type: Indicates whether the device connects to a bootstrap or management server.
  • Security Mode: Choose between Pre-Shared Key (PSK) and no security.
  • Device Key: The PSK key in hex format used to authenticate the device.

Data format in the virtual device

Incoming data in the virtual device (‘_RAW’ data point) follows this format when the default template is selected in the connector:

  • Structure: {LwM2M-Resource-URL: Value}
  • Example: {"/3/0/3": "BC66NBR01A11"}
  • Timestamp handling: The platform uses the timestamp of the incoming LwM2M server to assign the data points in time.

    If a device uses an individual data model, this must first be added to the LwM2M backend and the data forwarding configured in the LwM2M backend.

Using the device data in the device driver

The resources from the LwM2M object can be converted into data points with meaningful variable names using a Javascript function parser. Depending on the device, a measurement telegram can also be converted there, for example. Example of a simple function parser for LwM2M standard object 3:

// Define the URL-to-name table
const urlNameTable = {
    // Resources for LwM2M Object 3 (Device Object)
    "/3/0/0": "Manufacturer",
    "/3/0/1": "Model Number",
    "/3/0/2": "Serial Number",
    "/3/0/3": "Firmware Version",
    "/3/0/4": "Reboot",
    "/3/0/5": "Factory Reset",
    "/3/0/6": "Available Power Sources",
    "/3/0/7": "Power Source Voltage",
    "/3/0/8": "Power Source Current",
    "/3/0/9": "Battery Level",
    "/3/0/10": "Memory Free",
    "/3/0/11": "Error Code",
    "/3/0/12": "Reset Error Code",
    "/3/0/13": "Current Time",
    "/3/0/14": "UTC Offset",
    "/3/0/15": "Timezone",
    "/3/0/16": "Supported Binding and Modes",
    "/3/0/17": "Device Type",
    "/3/0/18": "Hardware Version",
    "/3/0/19": "Software Version",
    "/3/0/20": "Battery Status",
    "/3/0/21": "Memory Total",

    // Other objects and resources can be added here
};

// Function to sanitize the resource name into camel case format
function sanitizeResourceName(name) {
    return name
        .toLowerCase()
        .replace(/[^a-zA-Z0-9]+(.)/g, (match, chr) => chr.toUpperCase()); // Convert to camel case
}

// Decode function to map URL to camel-case JavaScript variable name and value
module.exports = function (payload, meta) {
    // Extract the first (and only) key-value pair from the input object
    const [url, value] = Object.entries(payload)[0];

    // Look up the human-readable name directly in the URL name table
    const resourceName = urlNameTable[url];

    // If resource is not found, throw an error or handle it (here we return an empty object)
    if (!resourceName) {
        throw new Error(`Resource with URL ${url} not found in the table.`);
    }

    // Sanitize the resource name to camel case format
    const sanitizedResourceName = sanitizeResourceName(resourceName);

    // Return the result object with the sanitized camel-case name and value
    return {
        [sanitizedResourceName]: value
    };
}