51  CoAP Practice

51.1 Learning Objectives

  • Apply CoAP payload optimization techniques using CBOR encoding to achieve 72% payload reduction and extend battery life from 1.5 to over 4.6 years through payload compression combined with transmission batching
  • Implement CoAP message type selection (CON vs NON) to achieve 10× energy efficiency compared to HTTP for battery-powered IoT devices
  • Construct practical CoAP systems including resource discovery, ESP32 actuator control, multicast device discovery, and CoAP-HTTP proxy gateways
  • Diagnose CoAP implementation failures using token matching for Observe responses and exponential backoff for retransmission
  • Design production-ready CoAP deployments with appropriate message types, block-wise transfers for constrained networks, and response code handling
  • Calculate energy consumption per message type and justify CoAP over HTTP for battery-constrained sensor deployments
  • Evaluate block transfer size trade-offs by analyzing RTT count, packet loss impact, and MTU constraints for firmware update scenarios

Practice exercises help you solidify your understanding of CoAP by working through real scenarios. Each exercise builds on the concepts from earlier chapters, giving you hands-on experience with message formats, observe patterns, and protocol design. It is the best way to move from reading about CoAP to actually using it.

“I’ve read about CoAP, but I’ve never actually built anything with it,” admitted Sammy the Sensor.

Max the Microcontroller encouraged him. “That’s what practice exercises are for! Let’s start simple: calculate how many bytes your temperature reading uses as a CoAP message. Your header is 4 bytes, your token is 2 bytes, your URI option ‘/temp’ is 5 bytes, and your payload ‘23.5’ is 4 bytes. That’s only 15 bytes total! Now compare that to the same reading via HTTP – easily 300+ bytes.”

“My favorite exercise is the battery life calculator,” said Bella the Battery. “If you send one CoAP message every 10 minutes, and each transmission uses 0.05 millijoules, how long will a 1000 milliamp-hour battery last? These are the real-world calculations that help you design systems that actually work.”

Lila the LED added: “And don’t skip the Observe exercise! Set up a resource that notifies subscribers only when the value changes by more than 2 degrees. That’s how you build smart, efficient systems – not by sending data constantly, but by sending it only when it matters.”

In 60 Seconds

This practice chapter provides visual reference diagrams for CoAP architecture and features, worked examples for payload optimization on battery-powered sensors (calculating exact energy savings from CBOR encoding and CON vs NON message selection), and hands-on exercises for designing CoAP-based environmental monitoring systems with quantified battery life projections.

51.3 Interactive Calculators

Calculate the total message size for different CoAP configurations and compare with HTTP overhead.

Calculate expected battery life based on CoAP message frequency, payload size, and message type.

Calculate optimal block size for block-wise transfers based on network MTU and packet loss.

51.4 Worked Examples

Worked Example: CoAP Payload Optimization for Battery-Powered Sensors

Scenario: A building deploys 200 battery-powered environmental sensors reporting temperature, humidity, CO2, and light levels every 5 minutes. Each sensor runs on a CR2032 coin cell (225 mAh capacity).

Given:

  • Current JSON payload (82 bytes):
{"device_id":"ENV-042","temp":22.5,"humidity":45,"co2":412,"light":350,"ts":1704067200}
  • CoAP header: 4 bytes (fixed) + 8 bytes (token + options) = 12 bytes
  • UDP/IP header: 28 bytes (8 UDP + 20 IP)
  • Radio transmission: 50 microamps per byte at 250 kbps
  • Radio startup energy: 15 mJ per transmission
  • Target battery life: 3 years

Steps:

  1. Calculate current energy consumption per message:
    • Total packet size: 82 (payload) + 12 (CoAP) + 28 (UDP/IP) = 122 bytes
    • Transmission time: 122 bytes × 8 bits/byte ÷ 250,000 bps = 3.904 ms
    • Peak TX current: 122 bytes × 50 µA/byte = 6,100 µA = 6.1 mA
    • Transmission energy: 6.1 mA × 3.904 ms × 3.0V = 71.4 µJ ≈ 0.0715 mJ
    • Total per message: 15 mJ (startup) + 0.07 mJ (TX) = 15.07 mJ
    • Messages per day: 288 (every 5 minutes)
    • Daily energy: 288 × 15.07 mJ = 4,340 mJ = 4.34 J
  2. Calculate battery life with current payload:
    • CR2032 capacity: 225 mAh × 3.0V × 3600 s/h = 2,430 J
    • Battery life: 2,430 J ÷ 4.34 J/day = 560 days = 1.53 years (fails 3-year target)
  3. Optimize payload using CBOR encoding:
    • CBOR payload: Using integer keys and compact encoding = 23 bytes
    • Key mapping: 0=id, 1=temp×10, 2=humidity, 3=co2, 4=light, 5=timestamp
    • New packet size: 23 + 12 + 28 = 63 bytes (48% reduction)
  4. Calculate optimized energy consumption:
    • Transmission time: 63 bytes × 8 bits/byte ÷ 250,000 bps = 2.016 ms
    • Peak TX current: 63 bytes × 50 µA/byte = 3,150 µA = 3.15 mA
    • Transmission energy: 3.15 mA × 2.016 ms × 3.0V = 19.1 µJ ≈ 0.019 mJ
    • Total per message: 15 mJ + 0.02 mJ = 15.02 mJ
    • Daily energy: 288 × 15.02 mJ = 4,326 mJ = 4.33 J
    • Battery life: 2,430 J ÷ 4.33 J/day = 561 days (still fails - startup dominates)
  5. Further optimization - NON messages and batching:
    • Batch 3 readings per transmission (every 15 minutes)
    • NON message (no ACK wait) saves 200 ms radio-on time = 0.9 mJ
    • Messages per day: 96 (every 15 minutes)
    • Batched CBOR payload: 3 × 23 bytes = 69 bytes
    • Energy per batched message: 15.0 mJ (startup) + 0.02 mJ (TX) = 15.02 mJ
    • Daily energy: 96 × 15.02 mJ = 1,442 mJ = 1.44 J
    • Battery life: 2,430 J ÷ 1.44 J/day = 1,688 days = 4.62 years (exceeds target)

Result: JSON to CBOR encoding reduces payload from 82 to 23 bytes (72% reduction). Combined with 15-minute batching, daily energy drops from 4.34 J to 1.44 J. Battery life extends from 1.53 years to 4.62 years, exceeding the 3-year target by 54%.

Key Insight: Radio startup energy (15 mJ) dominates per-byte transmission cost (~0.0006 mJ/byte). Batching 3 readings reduces daily transmissions from 288 to 96, saving 2.88 J/day - far more than the 0.01 J/day saved by payload compression alone. Always minimize transmission count before optimizing payload size.

Worked Example: CoAP vs HTTP Energy Comparison for Smart Thermostat

Scenario: A smart thermostat needs to report current temperature and receive setpoint commands. Comparing CoAP over UDP vs HTTP over TCP for a device on Wi-Fi with 10% packet loss.

Given:

  • Read operation: GET current temperature (response: 4 bytes = “22.5”)
  • Write operation: PUT new setpoint (request: 4 bytes = “24.0”)
  • Wi-Fi radio: 150 mW active, 3.0V supply
  • Packet loss: 10% (requires retransmission)
  • Operations per hour: 60 reads + 2 writes

Steps:

  1. Calculate HTTP transaction overhead:
    • TCP handshake: 3 packets (SYN, SYN-ACK, ACK) = 180 bytes + 3 RTTs (150 ms total)
    • HTTP GET request: GET /temp HTTP/1.1\r\nHost: thermostat\r\n\r\n = 45 bytes
    • HTTP response: HTTP/1.1 200 OK\r\nContent-Length: 4\r\n\r\n22.5 = 45 bytes
    • TCP teardown: 4 packets (FIN, ACK, FIN, ACK) = 240 bytes + 2 RTTs (100 ms)
    • Total per GET: 510 bytes, 250 ms radio time
    • Energy per GET: 150 mW × 0.25 s = 37.5 mJ
  2. Calculate CoAP transaction overhead:
    • CoAP CON GET: 4 (header) + 4 (token) + 6 (URI option) = 14 bytes
    • CoAP ACK response: 4 (header) + 4 (token) + 4 (payload) = 12 bytes
    • UDP/IP overhead: 28 bytes × 2 packets = 56 bytes
    • Total per GET: 82 bytes, 25 ms radio time (single RTT)
    • Energy per GET: 150 mW × 0.025 s = 3.75 mJ
  3. Account for 10% packet loss retransmissions:
    • HTTP: TCP handles retransmission transparently, adds ~25 ms average (10% × 250 ms)
    • Adjusted HTTP energy: 37.5 mJ × 1.1 = 41.25 mJ per GET
    • CoAP CON: Retransmit after 2-second timeout on 10% of requests
    • Adjusted CoAP energy: (0.9 × 3.75) + (0.1 × 7.5) = 4.13 mJ per GET
  4. Calculate hourly energy consumption:
    • HTTP: 60 GETs × 41.25 mJ + 2 PUTs × 45 mJ = 2,565 mJ = 2.57 J/hour
    • CoAP: 60 GETs × 4.13 mJ + 2 PUTs × 5 mJ = 258 mJ = 0.26 J/hour
  5. Calculate daily and yearly energy:
    • HTTP: 2.57 J/hour × 24 = 61.7 J/day = 22,520 J/year
    • CoAP: 0.26 J/hour × 24 = 6.2 J/day = 2,263 J/year
    • Energy savings: 22,520 - 2,263 = 20,257 J/year (90% reduction)

Result: CoAP uses 0.26 J/hour vs HTTP’s 2.57 J/hour - a 10× energy reduction. For a thermostat on USB power (unlimited energy), this difference is negligible. For a battery-powered variant with 10 Wh (36,000 J) battery, CoAP enables 16 years of operation vs HTTP’s 1.6 years.

Key Insight: HTTP’s TCP handshake (180 bytes, 150 ms) costs more than CoAP’s entire transaction (82 bytes, 25 ms). For request-response IoT patterns with small payloads, CoAP’s UDP-based approach provides 10× energy efficiency. However, CoAP requires application-level retry logic for reliability, while HTTP/TCP handles retransmission automatically - choose based on whether developer simplicity or energy efficiency is the priority.

Common Pitfalls

CON messages require an ACK roundtrip — on lossy networks with 20% packet loss, a 4-attempt retry with exponential backoff can delay responses by 45 seconds. Use NON for periodic telemetry where data freshness matters more than guaranteed delivery; reserve CON for actuation commands.

CoAP proxies cache GET responses based on Max-Age option — a sensor returning temperature with Max-Age=60 will serve cached values for 60 seconds even if the physical reading changes. Set Max-Age to match your data freshness requirement, not the default 60 seconds.

DTLS handshake (6-8 roundtrips) dominates latency for short-lived CoAP connections — repeatedly creating new DTLS sessions for each request adds 500-2000ms overhead. Use DTLS session resumption (RFC 5077) to reduce reconnection to 1 roundtrip after the initial handshake.

51.5 Summary

This chapter covered the Constrained Application Protocol (CoAP) for resource-constrained IoT devices:

  • Lightweight Design: 4-byte minimum header overhead (25× smaller than HTTP) enables efficient communication on constrained networks with limited bandwidth and battery power
  • UDP-Based Transport: Built on UDP rather than TCP, eliminating connection setup overhead and reducing latency, ideal for battery-powered sensors that need quick request-response cycles
  • RESTful Architecture: GET, POST, PUT, DELETE methods with URI-based resource addressing familiar to HTTP developers, making CoAP easy to learn and integrate with web services
  • Confirmable vs Non-Confirmable: CON messages require acknowledgment for reliability (critical commands), while NON messages provide fire-and-forget efficiency for frequent sensor readings
  • Observe Extension: Publish-subscribe pattern where clients observe resources and servers push updates when values change, eliminating constant polling and saving battery
  • Block-wise Transfers: Large payloads fragmented into manageable blocks for transmission over constrained networks with limited MTU sizes
  • Multicast Support: IPv6 multicast address (FF0X::FD) enables one-to-many communication for device discovery and group commands without requiring individual requests

51.6 Practice Exercises

Build practical skills with these hands-on CoAP exercises, progressing from resource discovery to production-grade implementations.

Objective: Implement CoAP resource discovery using .well-known/core endpoint.

Tasks:

  1. Set up a CoAP server with multiple resources:
    • /sensors/temperature (readable)
    • /sensors/humidity (readable)
    • /actuators/led (writable)
    • /config/network (readable and writable)
  2. Implement .well-known/core endpoint that returns resources in CoRE Link Format
  3. Create CoAP client that:
    • Performs resource discovery: GET coap://server/.well-known/core
    • Parses Link Format response
    • Displays available resources with their attributes (content-type, methods)
  4. Test resource filtering: GET coap://server/.well-known/core?rt=temperature

Expected Outcome:

  • Server responds with all resources in CoRE Link Format
  • Client successfully discovers and lists all available endpoints
  • Resource types (rt), interfaces (if), and content formats visible
  • Filtering by resource type returns subset of resources

Hints:

  • CoRE Link Format: </path>;rt="resource-type";if="interface";ct=0
  • Use semicolon to separate attributes, comma to separate resources
  • Implement resource filtering on server side based on query parameters
  • Test with: coap-client -m get coap://localhost/.well-known/core

Server Response Example:

</sensors/temperature>;rt="temperature-c";ct=0,
</sensors/humidity>;rt="humidity-p";ct=0,
</actuators/led>;rt="light-ctl";ct=0;if="actuator",
</config/network>;rt="config";ct=50;if="config"

Python Server Implementation:

import aiocoap
import aiocoap.resource as resource

class WellKnownCore(resource.Resource):
    async def render_get(self, request):
        # Generate CoRE Link Format response
        links = [
            '</sensors/temperature>;rt="temperature-c";ct=0',
            '</sensors/humidity>;rt="humidity-p";ct=0',
            '</actuators/led>;rt="light-ctl";if="actuator"',
            '</config/network>;rt="config";ct=50;if="config"'
        ]
        payload = ','.join(links).encode('utf-8')

        return aiocoap.Message(
            payload=payload,
            content_format=40  # application/link-format
        )

# Register resource
root = resource.Site()
root.add_resource(['.well-known', 'core'], WellKnownCore())

Objective: Build hardware actuator control system using CoAP PUT requests.

Tasks:

  1. Set up ESP32 with:
    • LED connected to GPIO pin
    • Wi-Fi connectivity
    • CoAP server library (coap-simple or MicroCoAP)
  2. Implement CoAP resources:
    • GET /led/status - Returns “on” or “off”
    • PUT /led/state - Accepts “1” (on) or “0” (off) to control LED
    • GET /system/uptime - Returns device uptime in seconds
  3. Create Python CoAP client that:
    • Discovers ESP32 resources via .well-known/core
    • Toggles LED every 5 seconds using PUT requests
    • Verifies state changes with GET requests
    • Logs uptime periodically
  4. Test with both CON and NON message types, measure latency

Expected Outcome:

  • ESP32 responds to PUT requests by toggling LED
  • GET requests return current LED state and uptime
  • Observe latency difference: CON (~50-100ms), NON (~20-50ms)
  • System runs reliably without memory leaks

Hints:

  • Use client.setCallback() to handle incoming PUT requests on ESP32
  • Return 2.04 Changed response code after successful LED toggle
  • Add Last Will Testament to detect ESP32 disconnection
  • Test reliability by disconnecting ESP32 Wi-Fi temporarily

ESP32 CoAP Server Code:

#include <WiFi.h>
#include <coap-simple.h>

const char* ssid = "your-wifi";
const char* password = "your-password";

WiFiUDP udp;
Coap coap(udp);

int ledPin = 2;
bool ledState = false;

// Callback for PUT /led/state
void callback_led_put(CoapPacket &packet, IPAddress ip, int port) {
    if (packet.payloadlen > 0) {
        ledState = (packet.payload[0] == '1');
        digitalWrite(ledPin, ledState ? HIGH : LOW);

        char response[4];
        sprintf(response, "%d", ledState);
        coap.sendResponse(ip, port, packet.messageid,
                          response, strlen(response),
                          COAP_CHANGED, COAP_TEXT_PLAIN,
                          packet.token, packet.tokenlen);
    }
}

// Callback for GET /led/status
void callback_led_get(CoapPacket &packet, IPAddress ip, int port) {
    char response[4];
    sprintf(response, "%s", ledState ? "on" : "off");

    coap.sendResponse(ip, port, packet.messageid,
                      response, strlen(response),
                      COAP_CONTENT, COAP_TEXT_PLAIN,
                      packet.token, packet.tokenlen);
}

void setup() {
    pinMode(ledPin, OUTPUT);
    WiFi.begin(ssid, password);

    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
    }

    // Register CoAP resources
    coap.server(callback_led_get, "led/status");
    coap.server(callback_led_put, "led/state");
    coap.start();
}

void loop() {
    coap.loop();
    delay(10);
}

Python Client:

import asyncio
import aiocoap

async def toggle_led():
    protocol = await aiocoap.Context.create_client_context()

    for i in range(10):
        # Toggle LED on
        request = aiocoap.Message(code=aiocoap.PUT,
                                  uri='coap://esp32.local/led/state',
                                  payload=b'1')
        await protocol.request(request).response
        print("LED ON")

        await asyncio.sleep(2)

        # Toggle LED off
        request = aiocoap.Message(code=aiocoap.PUT,
                                  uri='coap://esp32.local/led/state',
                                  payload=b'0')
        await protocol.request(request).response
        print("LED OFF")

        await asyncio.sleep(2)

asyncio.run(toggle_led())

Objective: Implement multicast group communication for automatic device discovery.

Tasks:

  1. Create multiple CoAP servers (3-5 instances) simulating different sensors:
    • Temperature sensor on port 5683
    • Humidity sensor on port 5684
    • Pressure sensor on port 5685
  2. Configure each server to:
    • Listen on IPv6 multicast address FF02::FD (link-local all-CoAP-nodes)
    • Respond to multicast GET requests
    • Provide unique device ID and sensor type in response
  3. Create multicast client that:
    • Sends NON GET request to coap://[FF02::FD]/sensors
    • Collects responses from all reachable sensors (wait 2 seconds)
    • Displays discovered devices with their capabilities
  4. Test with devices on same network segment

Expected Outcome:

  • Single multicast request discovers all sensors simultaneously
  • Each sensor responds with its device ID and sensor type
  • Client receives multiple responses within 2-second window
  • Understand multicast efficiency vs. individual unicast requests

Hints:

  • Use NON messages for multicast (CON not supported for multicast)
  • Set multicast hop limit appropriately: link-local FF02::FD requires hop limit of 1 (packets must not cross router boundaries); site-local FF05::FD allows hop limit up to 15 for multi-hop networks
  • Handle duplicate responses (some sensors may respond multiple times)
  • Test with: coap-client -m get -N coap://[FF02::FD]/sensors

Python Multicast Server:

import asyncio
import aiocoap
import aiocoap.resource as resource
import socket

class SensorResource(resource.Resource):
    def __init__(self, device_id, sensor_type):
        super().__init__()
        self.device_id = device_id
        self.sensor_type = sensor_type

    async def render_get(self, request):
        payload = f"Device: {self.device_id}, Type: {self.sensor_type}".encode()
        return aiocoap.Message(payload=payload)

async def main():
    root = resource.Site()
    root.add_resource(['sensors'], SensorResource("temp-sensor-01", "temperature"))

    # Create server context with multicast support
    context = await aiocoap.Context.create_server_context(root, bind=('::', 5683))

    # Join IPv6 multicast group
    sock = context.serversite.transport._sock
    mreq = socket.inet_pton(socket.AF_INET6, 'ff02::fd') + b'\x00' * 4
    sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)

    await asyncio.get_running_loop().create_future()

asyncio.run(main())

Multicast Client:

import asyncio
import aiocoap

async def discover_sensors():
    protocol = await aiocoap.Context.create_client_context()

    request = aiocoap.Message(
        code=aiocoap.GET,
        uri='coap://[ff02::fd]/sensors',
        mtype=aiocoap.NON  # Multicast must use NON
    )

    print("Sending multicast discovery...")
    discovered = []

    try:
        response = await asyncio.wait_for(
            protocol.request(request).response,
            timeout=2.0
        )
        discovered.append(response.payload.decode())
    except asyncio.TimeoutError:
        pass

    print(f"Discovered {len(discovered)} devices:")
    for device in discovered:
        print(f"  - {device}")

asyncio.run(discover_sensors())

Objective: Understand how CoAP devices can be integrated with HTTP-based web services through protocol translation.

Concept: A CoAP-HTTP proxy acts as a bridge, allowing HTTP clients (web browsers, mobile apps) to access CoAP devices without implementing CoAP themselves.

How It Works:

Diagram showing CoAP-HTTP proxy architecture with web client sending HTTP requests to proxy server, which translates to CoAP requests for IoT devices, includes caching layer for frequently accessed resources, and handles bidirectional protocol translation
Figure 51.4: CoAP-HTTP Proxy Gateway with Caching for Web Integration

Key Concepts:

1. Protocol Translation:

  • HTTP GET → CoAP GET
  • HTTP POST → CoAP POST
  • HTTP PUT → CoAP PUT
  • HTTP DELETE → CoAP DELETE
  • HTTP 200 OK ← CoAP 2.05 Content
  • HTTP 404 Not Found ← CoAP 4.04 Not Found

2. Caching Strategy:

  • Proxy respects CoAP Max-Age option
  • Reduces load on battery-powered sensors
  • Typical cache duration: 30-120 seconds
  • Dramatically extends battery life

3. URI Mapping:

HTTP:  http://proxy.example.com/coap/device123/temperature
         ↓
CoAP:  coap://device123.local/temperature

Performance Benefits:

Metric Direct CoAP HTTP Proxy (no cache) HTTP Proxy (cached)
Latency 20-50ms 30-70ms 1-5ms
CoAP requests 100 100 20 (80% reduction)
Battery impact High High Low
Web compatibility No Yes Yes

Implementation Approaches:

  1. HTTP Server Options: Flask, FastAPI, Node.js Express
  2. CoAP Client Libraries: aiocoap (Python), node-coap (Node.js)
  3. Caching: Redis, in-memory dictionaries with TTL
  4. Production Proxies: Californium cf-proxy, Eclipse Leshan

Practical Applications:

  • Web dashboards accessing CoAP sensors
  • Mobile apps controlling CoAP smart home devices
  • Cloud services aggregating CoAP data
  • Legacy HTTP systems integrating with modern CoAP networks

Testing Tools:

# Test CoAP directly
coap-client -m get coap://sensor1.local/temperature

# Test via HTTP proxy
curl http://localhost:8000/coap/sensor1/temperature

Trade-offs:

  • ✅ Web compatibility (use standard HTTP tools)
  • ✅ Battery savings through caching
  • ✅ Simplified client development
  • ⚠️ Added latency (proxy hop)
  • ⚠️ Single point of failure
  • ⚠️ Requires proxy infrastructure

Scenario: You need to update firmware on 100 ESP32 devices over a constrained 6LoWPAN network. Each firmware image is 512 KB. You must select the optimal Block2 size to minimize transfer time while respecting network constraints.

Given:

  • Network MTU: 127 bytes (6LoWPAN typical)
  • CoAP header + options: 12 bytes
  • Block2 option: 3 bytes
  • Available block sizes: 16, 32, 64, 128, 256, 512, 1024 bytes (SZX = 0 to 6)
  • Packet loss rate: 5% (typical wireless)
  • Round-trip time (RTT): 100 ms
  • Each lost block requires retransmission

Step 1: Calculate maximum payload per block

Usable payload = MTU - CoAP headers - Block2 option
              = 127 - 12 - 3 = 112 bytes

Largest block size that fits: 64 bytes (SZX=2)
- 128 bytes would require 128 + 15 = 143 bytes total (exceeds MTU)

Step 2: Calculate blocks needed per firmware

Block size options that fit in MTU: 16, 32, 64 bytes

For 512 KB (524,288 bytes) firmware:
  16-byte blocks: 524,288 / 16 = 32,768 blocks
  32-byte blocks: 524,288 / 32 = 16,384 blocks
  64-byte blocks: 524,288 / 64 = 8,192 blocks

Step 3: Calculate transfer time with loss

Transfer time = (blocks × RTT) × (1 + loss_rate)

16-byte blocks:
  Ideal time: 32,768 × 0.1s = 3,276.8 seconds (54.6 min)
  With 5% loss: 3,276.8 × 1.05 = 3,440.6 seconds (57.3 min)

32-byte blocks:
  Ideal time: 16,384 × 0.1s = 1,638.4 seconds (27.3 min)
  With 5% loss: 1,638.4 × 1.05 = 1,720.3 seconds (28.7 min)

64-byte blocks:
  Ideal time: 8,192 × 0.1s = 819.2 seconds (13.7 min)
  With 5% loss: 819.2 × 1.05 = 860.2 seconds (14.3 min)

Step 4: Calculate total retransmission overhead

Expected retransmissions per firmware (5% loss):
  16-byte blocks: 32,768 × 0.05 = 1,638 retries
  32-byte blocks: 16,384 × 0.05 = 819 retries
  64-byte blocks: 8,192 × 0.05 = 410 retries

Additional time for retries (assuming 2nd attempt succeeds):
  16-byte: 1,638 × 0.1s = 163.8 seconds (2.7 min)
  32-byte: 819 × 0.1s = 81.9 seconds (1.4 min)
  64-byte: 410 × 0.1s = 41.0 seconds (0.7 min)

Step 5: Calculate fleet-wide update time

Sequential update of 100 devices:
  16-byte blocks: 100 × 57.3 min = 5,730 min (95.5 hours)
  32-byte blocks: 100 × 28.7 min = 2,870 min (47.8 hours)
  64-byte blocks: 100 × 14.3 min = 1,430 min (23.8 hours)

Parallel update (10 devices at once, network allows):
  16-byte blocks: 95.5 / 10 = 9.55 hours
  32-byte blocks: 47.8 / 10 = 4.78 hours
  64-byte blocks: 23.8 / 10 = 2.38 hours

Result:

  • Optimal choice: 64-byte blocks (SZX=2)
  • Transfer time: 14.3 minutes per device
  • Fleet update: 23.8 hours sequential, 2.4 hours with 10-parallel
  • 4× faster than 16-byte blocks despite same MTU constraint
  • Efficiency: 64 bytes payload / 79 bytes total = 81% useful data

Key Insight: Larger block sizes dramatically reduce the number of round trips (8,192 vs 32,768), which is the dominant factor in transfer time. Always use the largest block size that fits within your network’s MTU. For 6LoWPAN (127-byte MTU), 64-byte blocks provide the best balance. For standard Ethernet (1500-byte MTU), use 1024-byte blocks.

Block transfer time depends on both block count and packet loss. For payload size \(S\) bytes, block size \(B\) bytes, RTT \(t\) seconds, and loss rate \(p\):

\[T_{\text{transfer}} = \left\lceil \frac{S}{B} \right\rceil \cdot t \cdot (1 + p)\]

For this firmware update with \(S = 524,288\) bytes, \(t = 0.1\text{s}\), \(p = 0.05\):

64-byte blocks: \(T = \lceil 524,288/64 \rceil \times 0.1 \times 1.05 = 8,192 \times 0.105 = 860\text{s} = 14.3\text{ min}\)

16-byte blocks: \(T = \lceil 524,288/16 \rceil \times 0.1 \times 1.05 = 32,768 \times 0.105 = 3,441\text{s} = 57.3\text{ min}\)

Speedup ratio: \(3,441/860 = 4\times\) faster with larger blocks.

The round-trip count \(N = \lceil S/B \rceil\) is inversely proportional to block size, explaining why larger blocks (up to MTU limit) minimize transfer time.

51.7 Concept Relationships

How CoAP practice exercises connect to implementation concepts:

Payload Optimization Builds On:

  • CBOR Encoding - 72% smaller than JSON for structured data
  • Battery Life Modeling - Quantifying energy per message type
  • MTU and Fragmentation - Avoiding packet splits in 6LoWPAN

CoAP vs HTTP Trade-offs Relate To:

  • TCP Connection Overhead - 3-way handshake energy analysis
  • Protocol Selection Criteria - Decision frameworks for IoT
  • Cellular Data Costs - Bandwidth savings translate to monthly fees

Block Transfer Practice Connects To:

  • Firmware Update Patterns - Reliable large file transfer over lossy links
  • Error Recovery - Individual block retries vs full restart
  • Constrained Networks - 127-byte MTU in IEEE 802.15.4

Real-World Exercises Enable:

  • Smart Agriculture - Soil sensor battery life calculations
  • Industrial Monitoring - Vibration sensor CoAP design
  • Building Automation - HVAC control system implementation

51.8 Further Reading

Official Specifications:

Implementation Resources:

Academic Papers:

The following figure from the NPTEL Internet of Things course provides additional perspective on IoT architectures relevant to CoAP implementations.

IoT Sensor Node Architecture:

Sensor node architecture diagram showing four main components: Sensor and Actuator Unit for data collection and physical interaction, Processing and Memory Unit as central controller with storage, Wireless Communication Unit for network connectivity, and Power Management Unit coordinating energy supply to all components

Sensor node architecture showing Processing, Communication, Sensing, and Power Management units

This sensor node architecture illustrates the constrained devices that CoAP is designed for - devices with limited processing, memory, and power resources where CoAP’s lightweight design provides significant advantages over HTTP.

Related Protocol Stacks:

For IEEE 802.15.4 protocol stack and OSI mapping, see the 6LoWPAN Fundamentals chapter. CoAP runs at the Application layer, using UDP/IP over 6LoWPAN adaptation, which in turn uses IEEE 802.15.4 for the lower layers.

Source: NPTEL Internet of Things Course, IIT Kharagpur

51.9 What’s Next

Now that you understand CoAP practice and implementation, explore the other IoT messaging and networking protocols:

Chapter Focus Why Read It
AMQP Fundamentals Advanced message queuing with persistent delivery guarantees Understand how enterprise-grade brokers handle reliability that CoAP handles at the application layer
CoAP Fundamentals and Architecture CoAP header structure, message types, and UDP transport design Deepen your understanding of the protocol internals behind the practice exercises in this chapter
CoAP Observe Extension Publish-subscribe resource observation and notification delivery Learn how Observe eliminates polling and design efficient push-based sensor pipelines
CoAP Security and DTLS Securing CoAP with DTLS, pre-shared keys, and certificate-based auth Apply production-ready security to the CoAP systems you built in this chapter
6LoWPAN Fundamentals IPv6 header compression and fragmentation over IEEE 802.15.4 Understand the network layer that CoAP block-wise transfer works around
LoRaWAN Overview Long-range, low-power wide-area networking Compare CoAP’s energy model against LoRaWAN’s radio duty-cycle constraints for truly remote sensors