Skip to content

9.3 CoAP and LwM2M Protocols

9.3.1 CoAP Fundamentals and RESTful Mapping

In IoT projects, engineers keep facing the same cost question: for a device that only reports temperature and sends a few bytes of data every few minutes, is it not an extravagant luxury to keep a long-lived TCP connection alive and send heartbeat packets on schedule? For sensors deployed in remote locations, powered by batteries, and spending most of their time on one-way reporting, the TCP keep-alive and connection-setup overhead of MQTT does carry a real engineering cost. CoAP (Constrained Application Protocol) was created precisely to resolve this tension — it compresses HTTP's request/response model into extremely compact messages over UDP, letting resource-constrained devices communicate in a standard IP-based way.

CoAP can be viewed as a mapping of HTTP onto constrained networks. It follows the client/server model: a device can act as a client issuing requests, or as a server exposing resources. This model differs fundamentally from MQTT's publish/subscribe architecture — a CoAP device communicates directly with its peer, with no broker serving as an intermediary. This determines that CoAP is better suited to one-to-one data exchange between a device and a platform.

Message Model: CON and NON

CoAP's transport layer is based on UDP, but that does not mean it is an unreliable "fire-and-forget" protocol. IETF RFC 7252 defines four message types to cover reliability needs across different scenarios. The two most widely used in engineering are CON (Confirmable, requiring acknowledgment) and NON (Non-confirmable, requiring no acknowledgment).

  • CON messages: after the sender issues a CON request, the receiver must respond with an ACK (Acknowledgment). If the sender still has not received the ACK after a timeout, it retransmits with an exponential backoff strategy until an acknowledgment arrives or the maximum retransmission count is exceeded. The confirmation logic of this mechanism resembles TCP's, but its overhead is far smaller — the acknowledgment packet itself is just a minimal empty CoAP message.
  • NON messages: send and forget. The receiver does not reply with an ACK, and the CoAP protocol layer provides no retransmission for it. Periodically reported sensor data is the typical NON case: losing one sample causes no serious consequence, because the next round of data fills the gap automatically a few seconds or minutes later.
  • RST messages: when the receiver cannot process a request — for example, it cannot recognize an option in the message — it sends an RST (Reset) message notifying the peer to terminate the exchange.

This design lets CoAP achieve two grades of reliable transport, "acknowledged" and "unacknowledged," on a single port. In engineering practice, developers must choose according to how critical the data is: alarm-type messages should use CON to ensure arrival, while periodic sampling with NON sharply reduces power consumption and network overhead.

The RESTful Mapping

CoAP directly inherits HTTP's REST (Representational State Transfer) design philosophy and supports the four request methods GET, PUT, POST, and DELETE, whose semantics correspond one-to-one with HTTP. When a CoAP client requests the current value of a server's /temperature resource, the outgoing message opens with the 4-byte fixed header — which contains a one-byte Code (a GET request is Code 0.01) and a two-byte Message ID — after the fixed header comes a Token of 0–8 bytes (its length is given by the TKL field in the fixed header; typical implementations use 4 bytes), and after that the option carrying the URL path. The entire request usually fits within a few dozen bytes.

There is, however, one essential difference between CoAP's request/response model and HTTP's: it is asynchronous. HTTP requires the client to block on the same TCP connection waiting for the response, whereas a CoAP CON message carries a Message ID through which responses are matched to requests. This means the client need not block after sending a request — it can issue multiple requests at once and distinguish them by Token when responses arrive. In UDP's connectionless environment this design is natural, and it lets CoAP support asynchronous communication in the true sense.

The immediate benefit this mapping brings developers is that they can design IoT interfaces with the familiar REST pattern, while the load of the underlying communication drops substantially.

Resource Discovery

In the HTTP ecosystem, users "see" page content through a browser. In the CoAP ecosystem, a client must know which resources a device offers before it can make further requests. The CoAP specification defines a Core Link Format: the client can issue a GET to /.well-known/core to retrieve the list of resources on a device. The response body is a compact link description:

</temp>;if="sensor";rt="temperature-celsius",
</light>;if="actuator";rt="light-control"

This self-describing capability has clear engineering value at deployment scale: when onboarding a new device, the platform need not rely on external configuration — the device can "introduce itself" after connecting. Resource attributes and the content-negotiation mechanism also help clients understand data formats. Compared with MQTT's engineering workflow of additionally defining topic naming conventions and thing-model mappings, CoAP's resource discovery provides a more self-contained standard interface.

The following is a sample CoAP client implemented with the libcoap library. It sends a CON GET request to fetch the temperature resource on a server. libcoap is the most widely used CoAP implementation in the C world, suitable for embedded Linux and RTOS environments.

c
// CoAP client: request a resource (using the libcoap library, illustrative code)
#include <coap3/coap.h>

int main(void) {
    coap_context_t *ctx = NULL;
    coap_session_t *session = NULL;
    coap_address_t dst;
    coap_uri_t uri;
    unsigned char got_data = 0;

    // Initialize the libcoap context
    coap_startup();
    ctx = coap_new_context(NULL);
    if (!ctx) return 1;

    // Parse the URI
    coap_split_uri((const uint8_t *)"coap://<device-ip>/temperature",
                   strlen("coap://<device-ip>/temperature"), &uri);
    coap_address_init(&dst);
    // ... address resolution and session creation details omitted ...

    // Send a CON GET request and register the response callback
    coap_pdu_t *pdu = coap_new_pdu(session, COAP_MESSAGE_CON,
                                   COAP_REQUEST_CODE_GET,
                                   coap_opt_new(session, &uri));
    coap_send(session, pdu);

    // Enter the event loop and wait for the response
    while (!got_data) {
        coap_io_process(ctx, COAP_IO_WAIT);
    }
    coap_free_context(ctx);
    return 0;
}

In real projects, CoAP also supports Blockwise Transfer for splitting payloads that exceed the UDP MTU (message size constrained by the IPv6 minimum MTU of 1280 bytes, RFC 8200), and DTLS (Datagram Transport Layer Security)/CoAPS (port 5684) for encrypted transport. For a temperature sensor that only needs to report a few integers, however, the simplest NON request already suffices — this is also the fundamental reason CoAP's power consumption often falls below MQTT's in typical application scenarios.

Figure 9-5 CoAP Message Format and OptionsEquivalent semantics of an HTTP text request and a compact CoAP binary message.Figure 9-5 CoAP Message Format and OptionsFor an equivalent GET, CoAP cuts constrained-network overhead with a 4-byte fixed header and variable fieldsSame semantics, far smallerHTTP request headerText format; a typical header far exceeds the CoAP fixed headerGET /temperature HTTP/1.1Host: device.example Accept: text/plainContent-Type: text/plain User-Agent: ...Typically hundreds of bytesCoAP CON GET binary layout4 B fixed header + Token + Options + optional Payload (RFC 7252)Ver2 bT2 bTKL4 bCodeGET=0.01Message ID16 bTokenVariable lengthOptions · Uri-PathRouting & content negotiation0xFFSeparatorPayloadActual payload (optional)Ver: version, currently 01T:CON=0 / NON=1Code: request method (GET=0.01)Message ID: deduplication & matchingToken: pairs request and responseOptions: path & content negotiation0xFF: payload marker only when a payload existsPayload: actual data, optionalFixed header / metadataToken / context pairingOptions / routing & negotiation0xFF separatorPayload / actual dataFigure 9-5 Size comparison of the CoAP message format versus HTTP text headers, highlighting the value of CoAP's compact binary design for constrained devices.
Figure 9-5 CoAP Message Format and Options

9.3.2 The LwM2M Protocol: Device Management and Telemetry

CoAP solves the constrained device's problem of "how to send requests and how to fetch data," but it manages only the sending, receiving, and reliable delivery of messages — not the device itself. What model is the device, what firmware version does it run, what if a configuration parameter must be changed remotely? For these device-management needs, CoAP defines neither structured extension points nor business semantics.

LwM2M (Lightweight Machine-To-Machine) is what fills this gap. Defined by the Open Mobile Alliance (OMA), it is not yet another transport protocol — it sits directly on top of CoAP. CoAP manages signaling-level request/response and the Observe mechanism; LwM2M manages the abstraction, registration, configuration, and maintenance of device capabilities. Both run over UDP, on the default port 5683, or over DTLS/CoAPS on 5684 when encrypted. In carrier-grade terminals that require remote operations — NB-IoT (Narrowband IoT) modules, smart meters, streetlight control — LwM2M is a common device-management protocol choice.

The Object Tree: Turning Device Capabilities into Addressable Paths

LwM2M's core design abstracts a device's capabilities into an object tree. The model has only three levels:

  • Object: represents a category of capability. In the OMA specifications, for example, 3 means "device," 3303 means "temperature sensor," and 6 means "location." When devices from different vendors implement the same object ID, the platform's read/write interfaces can be reused directly.
  • Object Instance: multiple copies of the same category of capability. A device carrying three temperature sensors has three /3303/ instances, numbered from 0.
  • Resource: a concrete readable/writable item within an instance. For example, /5700 is the sensor's current reading and /5601 the minimum measured value. Resources also define access rights, such as read (R), write (W), and execute (E).

To access a specific value, the path is /<objectId>/<objectInstanceId>/<resourceId>; to read the first temperature sensor's current value, for example, the path is /3303/0/5700. This path semantics aligns naturally with CoAP's URI format and needs no additional routing mapping — the device-side LwM2M client firmware only has to look the path up in a table and find the corresponding handler function.

The key to this model is standardization: for temperature sensors made by different vendors, as long as they follow the OMA-defined LwM2M object 3303, the platform's read/write interfaces are fully universal no matter how different their internal hardware, with no per-vendor adaptation needed. OMA maintains a public object registry covering hundreds of predefined objects — device management (object 3), location (object 6), sensors (temperature 3303, pressure 3323, humidity 3304), actuators, software upgrade, and more. This uniform expressive power is an important feature distinguishing LwM2M from MQTT (which requires the application layer to define its own payload format): a device's capabilities are fully described at the protocol layer rather than left to documentary convention.

Table 9-3 Common LwM2M objects and resources (based on the OMA LwM2M specification)

ObjectObject IDResourceResource IDAccessDescription
Device3Manufacturer0ReadName of the device vendor
Device3Firmware version3ReadCurrent firmware version number
Device3Reboot4ExecuteTriggers a device soft reboot
Temperature3303Sensor value5700ReadFloating-point temperature reading
Temperature3303Min measured value5601Read/WriteConfigurable lower range limit
Temperature3303Max measured value5602Read/WriteConfigurable upper range limit
Pressure3323Sensor value5700ReadFloating-point pressure value
Location6Latitude0ReadDecimal format
Location6Longitude1ReadDecimal format
Firmware update5Firmware package0WriteOTA image file
Firmware update5Firmware package URI1WriteURI from which the device downloads the firmware image
Firmware update5Perform firmware update2ExecuteTriggers the upgrade procedure
Firmware update5Firmware state3ReadUpgrade progress/status code

Bootstrap and Registration: The Standard Three Steps for Onboarding a Device

When a device first attaches to the network, it knows neither which LwM2M server to connect to nor which security credentials to use. LwM2M solves this "newborn device" problem with a Bootstrap Server. The bootstrap and registration flow divides roughly into three steps:

  1. Bootstrap: after startup, the device contacts the Bootstrap Server using factory-provisioned bootstrap information (possibly a domain name or a fixed IP). The Bootstrap Server returns the address, port, and security credentials of the primary LwM2M server (for example a pre-shared key (PSK) or the public part of a certificate), along with device-specific initial configuration parameters such as the heartbeat interval. This step occurs only when a new device powers on for the first time or after a factory reset; in normal operation the device already has this information cached.
  2. Registration: once it has the server information, the device sends a CoAP POST request to the LwM2M Server whose payload carries the list of all object IDs the device supports and its endpoint name. On receipt, the server creates a device instance and returns a CoAP 2.01 Created response.
  3. Registration update: before the Lifetime expires, the device must periodically send a CoAP POST to the registration path to renew it. If the server still has not received an update after the timeout, it declares the device offline and releases the device's registration resources.

This flow is common in battery-powered NB-IoT modules: a water meter ships with the carrier's bootstrap address built in, completes bootstrap and registration automatically on power-up, and the platform can then read the meter directly or issue meter-reading commands. The registration message itself is extremely lightweight; for NB-IoT scenarios that report only a few values a day, both the network and the energy overhead are quite low.

Observe/Notify: From Polling to Push

In plain CoAP, a client that wants data must send GET requests repeatedly. For data that changes periodically, such as temperature or pressure, polling wastes bandwidth and battery alike. LwM2M uses CoAP's Observe mechanism to implement push-style data reporting.

The flow is concise: the platform first sends the device a CoAP GET request carrying the Observe: 0 option (for example, GET /3303/0/5700 Observe: 0). On receipt, the device adds it to its observer list and immediately returns the current sensor value as the first notification. Thereafter, whenever the sensor data changes (or the preset minimum reporting period is reached), the device proactively sends the platform a CoAP response whose content is the latest resource value. When updates are no longer needed, the platform can send an RST message to cancel the observation.

In practice, the LwM2M client typically works with two parameters to decide when to report: first, a change threshold — for example, reporting only when the temperature changes by more than 0.5 °C; second, a minimum notification period — for example, at most one report every two hours. This hands the initiative in communication to the device side: the device judges for itself whether a data change is worth waking up and reporting, and the platform only receives, never prods. For deeply sleeping sensors, the device wakes for an instant after collecting the data, sends the notification, and returns to sleep — consuming far less power than maintaining a long-lived TCP connection.

The Protocol Mapping of Firmware Update and Remote Configuration

Firmware update is one of the standardized device-management capabilities LwM2M provides. At the protocol level it appears as a set of predefined resources. Taking the firmware update object (object ID 5) as an example, the upgrade process decomposes at the protocol level as follows:

  • Firmware package write: the platform writes the entire firmware image into the package resource in chunks through CoAP PUT requests. The OMA LwM2M specification supports using CoAP's block transfer (Blockwise Transfer) mechanism to complete fragmentation and reassembly automatically — the device replies with an ACK for each block received and waits for the next, and the application layer need not concern itself with packet-splitting logic.
  • Upgrade trigger: once the write completes, the platform sends a CoAP POST request to the perform-firmware-update resource (in essence an "execute" command), triggering the device to verify the image's integrity and flash the new firmware into storage.
  • Status feedback: during the upgrade, the device writes status codes back to the firmware state resource. By subscribing to that resource's changes through the Observe mechanism, the platform receives real-time progress feedback such as "upgrading 20%," "verification failed," or "success."

Remote configuration is implemented more directly. The platform sends a single CoAP PUT request to the corresponding resource in the object tree, and the device-side LwM2M client parses and applies the new value. To change a rain gauge's collection interval, for example, the platform simply PUTs the new value to the resource representing the "measurement period" under object 3303, instance 0.

This "operation = write a resource" model keeps firmware update (write firmware data → execute upgrade → read state) and remote configuration (write a configuration value → the device applies it immediately) highly unified in implementation: both are CoAP requests, differing only in the object path operated on and the data type. The device-side LwM2M client needs only to recognize the object tree's structure and look up the handler function by resource ID, rather than writing a separate state machine for each class of operation. This design greatly reduces the complexity of device firmware — one reason LwM2M can run on resource-constrained MCUs whose memory is typically only tens to a few hundred KB.

Engineering Checklist: LwM2M Deployment Essentials

  • Object-tree version alignment: the device side and the platform side must use the same version of the OMA object registry, otherwise the platform may be unable to parse the resource IDs the device reports. Fix the OMA LwM2M specification version to be used early in the project and lock down the target device firmware's implementation.
  • Bootstrap scoping: the Bootstrap Server is needed only when a new device powers on for the first time, after a factory reset, or when a certificate expires. In production, devices should not request bootstrap on every restart — otherwise an unnecessary dependency on an external bootstrap server is introduced, adding a failure point.
  • Lifetime and heartbeat interval: the Lifetime should be set with the device's power budget and network reliability in view; in NB-IoT scenarios it is typically tens of minutes to several hours. Too short increases uplink traffic and power drain; too long delays the platform's detection that a device is offline, affecting business-continuity judgments.
  • Observe/notify threshold configuration: the change threshold and the minimum notification period must be agreed between the device side and the platform side. Too small a threshold causes frequent reporting (more power and network traffic); too large, and data changes may be missed, leaving business decisions untriggered. Before production deployment, run an experimental period with real device samples to calibrate the thresholds.
  • Firmware-upgrade failure rollback: the upgrade process needs a designed fallback. The device should retain the last usable firmware version and roll back automatically after a failed upgrade or a verification error, avoiding a bricked device. The firmware state resource in the LwM2M specification (such as the firmware state resource of object 5) exists precisely to provide a standardized interface for this; the platform must subscribe to that resource's changes to perceive the upgrade result.
Figure 9-6 LwM2M Object Tree and Bootstrap/RegisterLwM2M abstracts device capabilities into an object/instance/resource tree and joins the platform via bootstrap, register, and update.Figure 9-6 LwM2M Object Tree and Bootstrap/RegisterCoAP handles message exchange; LwM2M handles capability abstraction, registration, configuration, and upkeepThree-level object tree: turning device capabilities into addressable pathsObjectOne capability class3 Device · 3303 Temperature · 6 Location · 5 Firmware UpdateSame object ID = reusable platform read/write interfaceInstanceMultiple copies of one capabilityThree temperature sensors = three /3303/ instancesNumbering starts at 0ResourceReadable/writable/executable items in an instance/5700 current reading · /5601 min rangeR read / W write / E executePath exampleRead the first temperature sensor: /3303/0/5700Path semantics align naturally with CoAP URIs; client firmware dispatches handlers by path lookupBootstrap & registration: the standard three steps to onboard① BootstrapContact the bootstrap server with factory presetsReturns server address, port, PSK/certificate, initial configOnly on first power-up / factory reset / certificate expiry② RegisterCoAP POST to the serverCarries object ID list and endpoint nameReturns CoAP 2.01 Created③ UpdatePeriodic POST renews registration before Lifetime expiryMissed update → marked offline, registration releasedAn NB-IoT water meter completes the whole flow on power-upObserve/Notify: from polling to pushPlatform sends GET + Observe:0 → device joins the observer list → change threshold / minimum notify period triggers reports → RST cancels, handing the initiative to the deviceFigure 9-6 LwM2M abstracts device capabilities into a three-level object/instance/resource tree whose paths align with CoAP URIs; devices join the platform through bootstrap, register, and update, and the observe/notify mechanism provides push-style reporting.
Figure 9-6 LwM2M Object Tree and Bootstrap/Register

9.3.3 CoAP/LwM2M in an NB-IoT Application Case

To understand the combined value of CoAP and LwM2M in NB-IoT, a curbside urban parking scenario is more intuitive than any abstract description. First, the division of labor between this section and Chapter 4: Section 4.5, using smart streetlights as its example, covered NB-IoT air-interface characteristics and the deployment of the unified access layer; this section digs down into the protocol stack inside the terminal — how CoAP message exchange and the LwM2M object model cooperate on a single NB-IoT module. The scenario: a certain city deployed over a thousand geomagnetic sensor nodes, each attached through an NB-IoT module, periodically reporting "free/occupied" status and supporting remote adjustment of billing-policy parameters (such as the free duration and peak-rate thresholds) as well as firmware upgrades. In this system, NB-IoT provides the wide-coverage, low-power physical channel, CoAP handles lightweight message exchange, and LwM2M carries device management and object standardization — the three working in concert are the key to low-power operations.

Fitting CoAP NON Messages to NB-IoT Power-Saving Mechanisms

The two NB-IoT power-saving mechanisms, PSM (Power Saving Mode) and eDRX (Extended Discontinuous Reception), were introduced in Chapter 4, Section 4.1.1, together with the air-interface characteristics — devices remain asleep most of the time, waking only in configured paging windows or to report proactively. This fits naturally with CoAP's connectionless, stateless model.

In the parking-space management scenario, the geomagnetic sensor is a typical one-way, uplink-heavy device, dominated by periodic status reports each day. Forcing MQTT onto it — even at QoS 0 with a stretched PINGREQ interval — still requires the device to maintain session state with the broker and a periodic heartbeat task between messages. For an NB-IoT module whose sleep current is extremely low but whose transmit current climbs sharply for an instant, the extra energy this maintenance costs is not negligible.

The more sensible approach: after the sensor detects a magnetic-field change, it constructs a CoAP NON (Non-confirmable) message, sends it to the platform, and immediately enters PSM deep sleep. A NON message demands no ACK, carries no retransmission cost, and keeps no session context. The device's state machine simplifies into a stateless "sample — packetize — send — sleep" loop, with no logic to handle disconnection and reconnection or heartbeat timeouts. If the scenario requires reliability guarantees for critical events such as billing deductions, it switches to CON (Confirmable) messages — CoAP's built-in exponential-backoff retransmission can guarantee delivery under moderate packet loss. From an energy standpoint, the CoAP + NON + PSM combination makes full use of NB-IoT's low-power potential, instead of, like TCP, spending periodic heartbeats fighting connection-maintenance overhead.

LwM2M Object Standardization and Device Management

CoAP solves the problem of "how to send a message," but the parking-billing operator still needs to know: which vendor supplied the sensor, what its current detection sensitivity is, how to remotely change the "free duration." These management needs fall within LwM2M's responsibilities. LwM2M abstracts device capabilities into standardized paths through the object tree. For a parking sensor, typical object instances include:

  • Object 3 (device): provides basic information such as manufacturer, model, and firmware version.
  • A custom "geomagnetic detection" object: describes the sensor type and measurement range.
  • Object 5 (firmware update): implements firmware package download, verification, and status reporting.

Operators send Write commands through the LwM2M Server; the CoAP layer converts them into CON messages to ensure reliable delivery, and the sensor updates its configuration and responds. Firmware upgrade is the most representative operation in LwM2M device management — when the operator needs to upgrade firmware in bulk to fix the geomagnetic detection algorithm, the client downloads the firmware binary in fragments via CoAP block transfer, with resume support.

The following code shows the key callback logic of an LwM2M client implementing firmware upgrade with the Anjay library; it illustrates the flow only and is not production-grade code:

c
// Illustrative code: LwM2M client firmware installation callback (Anjay library)
#include <anjay/anjay.h>
#include <anjay/fw_update.h>

static int fw_install(anjay_t *anjay, const anjay_fw_update_handle_t *handle) {
    const uint8_t *data;
    size_t size;
    anjay_fw_update_get_package(anjay, handle, &data, &size);
    if (!verify_checksum(data, size)) {
        anjay_fw_update_set_update_result(anjay, handle, 1); // 1=verification failed
        return -1;
    }
    write_firmware_to_flash(data, size);
    return 0;
}

int main(void) {
    anjay_config_t config = {
        .endpoint_name = "parking-sensor-001",
        .in_buffer_size = 1024,
        .out_buffer_size = 1024
    };
    anjay_t *anjay = anjay_new(&config);

    anjay_fw_update_config_t fw_cfg = {
        .install_callback = fw_install,
        .download_mode = ANJAY_FW_UPDATE_DOWNLOAD_MODE_COAP_BLOCKING,
        .supported_protocols = ANJAY_FW_UPDATE_PROTOCOL_COAP | ANJAY_FW_UPDATE_PROTOCOL_HTTP
    };
    anjay_fw_update_install(anjay, &fw_cfg);

    while (1) { anjay_sched_run(anjay); sleep(1); }
    anjay_delete(anjay);
}

On the server side, it is enough to write the firmware image to the corresponding resources of Object 5 over CoAP; the client callbacks start the download and installation, and the upgrade status is reported back through resources. Remote firmware operations thus cease to be a "keep the device online" problem and become a monitorable asynchronous task.

Engineering Trade-offs: NON vs CON and Block-Transfer Reliability

Using NON messages for geomagnetic sensor reports is a classic power-versus-reliability trade-off. Two packets lost in a row, and the platform may show "departed" for that period, interrupting billing. Backend systems usually tolerate a certain packet-loss rate and compensate with state-inference algorithms (such as the most recent status plus timeout reasoning). For critical commands such as billing or gate opening, CON messages must be used to guarantee delivery, but each one waits for an RTT-scale ACK, stretching the device's wake window. The engineering checkpoint is distinguishing redundancy of state from timeliness of commands.

Block-transfer reliability for firmware upgrade is more complex: the device may lose power during the download. LwM2M Object 5 supports resume, but it requires the client to persist the received-block information (for example, to Flash) — otherwise, after a power loss the server retransmits from zero, wasting large amounts of air-interface traffic. At deployment time, confirm whether the firmware-state persistence logic has been implemented.

Practical Checklist: Suitability Assessment

When evaluating whether a project suits this combination, check the following items one by one:

  1. Confirm module capability: the device's NB-IoT module must support eDRX/PSM and have a reasonable sleep-wake cycle configured. Without PSM support, battery life shrinks sharply.
  2. Tier message reliability: use NON for status reports; use CON — with reasonable retransmission timeouts — for billing, configuration, and firmware operations.
  3. Standardize LwM2M objects: prefer the standard object IDs and resource IDs defined by OMA IPSO (Internet Protocol Smart Objects) and minimize vendor-specific extensions — otherwise the platform side needs an adapter layer for every model.
  4. Persist firmware-upgrade state: enable resume, persist firmware state to non-volatile storage, and keep a rollback mechanism for failed upgrades.
  5. Allow network-coverage margin: geomagnetic sensors are often installed underground or under metal manhole covers; the extra power consumed by NB-IoT coverage enhancement should be evaluated in early testing, and NON messages should not be adopted blindly in weak-coverage areas.
  6. Preprovision the Bootstrap Server: configure Bootstrap Server information on all devices before they leave the factory, avoiding manually writing server addresses and keys into each unit in the field.

The above is derived from the example and from public standards. Specific performance figures (such as the energy of a single report, or battery life in years) should be tested against the actual chip manuals and the carrier's network configuration. The combination of CoAP/LwM2M and NB-IoT is an engineering benchmark for the low-power wide-area network (LPWAN) application layer — but its value lies in leading operations staff to understand the full chain of constraints from the radio air interface to device-management semantics, so that clear-eyed trade-offs can be made at the design stage. It does not suit scenarios requiring highly real-time bidirectional interaction or large data volumes; those scenarios are better served by MQTT or HTTP.

Figure 9-7 CoAP/LwM2M Working over NB-IoTNB-IoT supplies the low-power pipe, CoAP lightweight messages, LwM2M object standards; status uses NON, critical commands use CON.Figure 9-7 CoAP/LwM2M Working over NB-IoTCity roadside magnetic parking sensors: wide-coverage low-power connectivity + lightweight messages + object standardsThree-layer division of laborNB-IoT physical channel3GPP R13 radio accesseDRX extended discontinuous receptionPSM power-saving mode, near-zero power while asleepDeep coverage + low-power small packetsCoAP lightweight messagesConnectionless and stateless — a natural fit for sleep cyclesNON sends then sleeps, no retransmit costCON exponential-backoff retransmits guarantee deliveryDevice cycle: sample - packetize - send - sleepLwM2M object standardizationObject 3 device informationCustom magnetic-detection objectObject 5 firmware updatePrefer OMA IPSO standard object IDsMessage reliability tiers: redundant status vs. time-critical commandsStatus reports: NON (no ACK)Magnetometer detects change → build NON message → enter PSM deep sleep at onceSome loss is tolerable, compensated by latest state + timeout inferenceThe radio state machine reduces to a stateless loop — no reconnects or heartbeat timeoutsLowest energy draw, fully exploiting NB-IoT low powerCritical commands: CON (ACK required)Billing charges, gate opening, config writes, firmware opsBuilt-in exponential backoff delivers reliably at moderate loss ratesCost: waiting an RTT for the ACK stretches the wake windowFirmware updates use CoAP block transfer + resumeFit checklist (key points)Module must support eDRX/PSM · NON for status, CON for critical · prefer OMA IPSO objects · persist + roll back firmware · assess coverage-boost power cost in weak-signal areasFigure 9-7 NB-IoT provides wide-coverage low-power connectivity, CoAP handles connectionless lightweight messages, and LwM2M provides object standardization; status reports use NON for low power, while critical commands such as billing, configuration, and firmware use CON for guaranteed delivery.
Figure 9-7 CoAP/LwM2M Working over NB-IoT

From Industrial Software to AI Agents · Building a multi-protocol, cloud-native, open-source industrial IoT platform ready to evolve toward AI agents