Observe Option: CoAP extension enabling publish/subscribe: client registers to receive notifications on resource changes
Block-wise Transfer: Fragmentation mechanism for transferring payloads larger than a single CoAP datagram
Token: Client-generated value matching responses to requests — enables concurrent request/response pairing
DTLS: Datagram TLS — CoAP’s security layer providing encryption and authentication over UDP
44.2 In 60 Seconds
CoAP supports four REST methods mirroring HTTP: GET (retrieve), POST (create), PUT (update/create), and DELETE (remove), with GET, PUT, and DELETE being idempotent. Beyond basic REST, CoAP adds multicast support for group operations (e.g., turning off all lights), resource discovery via /.well-known/core, and the Observe extension that enables server-push notifications – reducing energy consumption by up to 99% compared to polling.
For Beginners: What is CoAP?
Think about how you communicate with friends. You might send a long email with lots of details, or you might send a quick text message with just the essential information. Both get the message across, but text messages are faster and use less data especially important when you have limited battery or a slow connection.
CoAP is like the text message version of web communication for IoT devices. Regular websites use HTTP, which is like sending detailed emails with lots of extra information in headers and metadata. That works great for powerful computers and smartphones with strong batteries and fast internet. But tiny sensors running on coin batteries can’t afford that luxury. CoAP strips away all the unnecessary extras and keeps just the essential parts: what you want to do, which resource you’re accessing, and the actual data.
The magic is that CoAP still works like the web you know. You can GET data from a sensor, PUT a new setting to a device, or POST a command just like with regular websites. But instead of using hundreds of bytes of overhead like HTTP, CoAP uses just 4 bytes for its header. This means a temperature sensor can report readings for years on a single battery instead of months, and devices can communicate even over slow, unreliable networks where every byte matters.
Sensor Squad: The Four Magic Words
“CoAP has four magic words that do everything!” announced Max the Microcontroller. “GET means ‘tell me your value.’ PUT means ‘change your setting to this.’ POST means ‘do this action.’ And DELETE means ‘remove this thing.’”
Sammy the Sensor demonstrated: “When the dashboard sends me a GET, I reply with my temperature. When someone sends a PUT to change my sampling rate from 10 to 30 seconds, I update my setting and confirm. It’s just like asking and answering questions!”
“And multicast is the coolest feature!” added Lila the LED. “Instead of asking each sensor one by one – ‘Sammy, what’s your temperature? Bella, what’s your voltage?’ – you shout to ALL sensors at once: ‘Everyone, report your temperature!’ One message, fifty replies. Imagine how much time and energy that saves in a building with hundreds of sensors!”
Bella the Battery loved that. “One multicast GET instead of fifty individual GETs means I save 98% of my radio energy for discovery. It’s like a teacher taking attendance by saying ‘raise your hand if you’re here’ instead of calling each name individually!”
import asynciofrom aiocoap import*class TemperatureResource(resource.Resource):"""Example resource for temperature readings"""asyncdef render_get(self, request):"""Handle GET requests""" temperature =22.5# Simulated sensor reading payload =f"{temperature}".encode('utf-8')return Message( code=Code.CONTENT, payload=payload, content_format=0# text/plain )asyncdef render_put(self, request):"""Handle PUT requests to update config"""print(f'Received: {request.payload}')return Message(code=Code.CHANGED)asyncdef main():# Create CoAP server root = resource.Site()# Add temperature resource root.add_resource( ['temperature'], TemperatureResource() )# Start serverawait Context.create_server_context(root)print("CoAP server started on port 5683")await asyncio.get_running_loop().create_future()if__name__=="__main__": asyncio.run(main())
Install: pip install aiocoap
44.4.2 Python CoAP Client
import asynciofrom aiocoap import*asyncdef get_temperature():"""Fetch temperature from CoAP server"""# Create CoAP client protocol protocol =await Context.create_client_context()# Build GET request request = Message( code=Code.GET, uri='coap://localhost/temperature' )try:# Send request response =await protocol.request(request).responseprint(f'Response Code: {response.code}')print(f'Temperature: {response.payload.decode("utf-8")}°C')exceptExceptionas e:print(f'Failed to fetch: {e}')asyncdef update_config():"""Send PUT request to update configuration""" protocol =await Context.create_client_context() request = Message( code=Code.PUT, uri='coap://localhost/config', payload=b'{"interval": 30}' ) response =await protocol.request(request).responseprint(f'Update result: {response.code}')# Run clientasyncio.run(get_temperature())
NON messages skip acknowledgment, saving approximately 21% energy per transaction (45 bytes vs 57 bytes for CON + ACK round-trip)
CON messages require an ACK response, adding 12 bytes of overhead and an additional receive window — increasing per-message energy by ~27% compared to NON
For sensors with reliable links, NON can extend battery life by years
Use CON only when guaranteed delivery is critical
🎮 Interactive Simulator: CoAP-Style UDP Communication
What This Simulates: ESP32 demonstrating CoAP’s lightweight UDP request/response pattern
CoAP Communication Pattern:
CoAP UDP pattern
Figure 44.1: CoAP request/response communication pattern showing lightweight UDP exchange between ESP32 client and server with minimal 4-byte header overhead.
How to Use:
Click ▶️ Start Simulation
Watch Serial Monitor show UDP request/response cycle
Observe message types (CON, NON, ACK)
See CoAP-style resource addressing
Monitor round-trip times (RTT)
💡 Learning Points
What You’ll Observe:
UDP Transport - Connectionless, lightweight communication
4-Byte Headers - Minimal overhead compared to HTTP
Request/Response - RESTful pattern like HTTP GET
Message IDs - Tracking requests and responses
No Handshake - Direct communication without TCP overhead
CoAP Message Structure (Simplified):
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Ver| T | TKL | Code | Message ID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Ver = Version (2 bits)
T = Type (CON, NON, ACK, RST)
TKL = Token Length
Code = Method (GET) or Response (2.05 Content)
Real-World Applications:
Smart Home - Light bulbs responding to GET/PUT requests
Industrial IoT - Sensors publishing data via RESTful interface
Building Automation - HVAC systems with RESTful control
Energy Management - Smart meters with resource discovery
Wearables - Health sensors with minimal power consumption
Experiments to Try:
Change Request Frequency - Modify delay() to see network load
Add More Resources - Simulate /humidity, /pressure endpoints
What This Simulates: ESP32 CoAP server with automatic resource discovery via /.well-known/core
Resource Discovery Flow:
Step 1: Client queries server
GET coap://device/.well-known/core
Step 2: Server responds with resource list
</temperature>;rt="sensor";if="core.s",
</humidity>;rt="sensor";if="core.s",
</led>;rt="actuator";if="core.a"
Step 3: Client accesses specific resource
GET coap://device/temperature
Response: "23.5"
Automatic Discovery - Devices announce capabilities without manual configuration
Standard Endpoint - /.well-known/core is CoAP convention (RFC 6690)
Resource Attributes - Metadata describes resource type and interface
Self-Describing - Servers advertise what they offer
Plug-and-Play - New devices integrate without central registry
Resource Link Format:
</path>;attribute1=value1;attribute2=value2
Common Attributes:
rt = Resource Type (e.g., "temperature-sensor")
if = Interface Description (e.g., "sensor", "actuator")
ct = Content Type (0=text/plain, 50=application/json)
sz = Maximum Size
obs = Observable (supports observe pattern)
Example Resource Advertisement:
CoAP resource format
Figure 44.2: CoAP resource link format showing the structure of a resource advertisement with path, resource type, interface description, observability, and content type attributes.
Real-World Applications:
Smart Building - HVAC units discover sensors automatically
Add New Resources - Implement /pressure, /battery endpoints
Resource Attributes - Add obs for observable resources
Content Types - Support JSON (ct=50) and XML (ct=41)
Filtering - Query specific resource types: ?rt=sensor
Observe Pattern - Implement push notifications when resource changes
Discovery vs Hardcoding:
Without Discovery (Hardcoded):
- Client: GET coap://192.168.1.100/temp ❌ Must know IP & path
- Brittle: Breaks if device IP changes
With Discovery:
- Client: Multicast GET /.well-known/core ✅ Finds all devices
- Response: Server at 192.168.1.100 offers /temp
- Robust: Adapts to network changes
CoAP Resource Discovery Benefits:
Zero configuration networking
Dynamic topology adaptation
Service versioning support
Reduces integration time by ~80%
Knowledge Check: Match and Sequence
Match each CoAP concept to its correct definition or use case:
Arrange the following steps of a CoAP resource discovery and subscription workflow in the correct order:
44.10 Protocol Comparison
44.10.1 CoAP vs HTTP: Concrete Performance Numbers
Feature
CoAP
HTTP
CoAP Advantage
Transport
UDP
TCP
No handshake overhead
Header Size
4 bytes
100-200 bytes
96% reduction
Total On-Wire Size
40-60 bytes
250-600 bytes
85-93% smaller
Connection Setup
None (UDP)
3-way handshake
Saves 1+ RTT + ~180 bytes
Methods
GET, POST, PUT, DELETE
Same + more
Focused on IoT needs
Discovery
Built-in (/.well-known/core)
No standard
Zero-config networking
Multicast
Yes (FF0X::FD)
No
One-to-many efficiency
Observe
Yes (push notifications)
Server-Sent Events
99% less polling traffic
Security
DTLS
TLS
UDP-optimized
Power per Message
3-5 mJ
30-50 mJ
10x more efficient
Battery Life Impact
2-5 years
2-6 months
10x longer life
Real Numbers Example - Temperature Reading:
Scenario: Send “22.5C” (5 bytes payload) from sensor to server
Figure 44.3: CoAP versus HTTP comparison for a temperature reading showing significantly lower bandwidth and energy usage for CoAP due to its 4-byte header versus HTTP’s verbose header format
Putting Numbers to It
Total message overhead directly affects both bandwidth and battery life. For payload \(P\) bytes:
With CR2032 battery (675 mWh = 2,430 J): CoAP enables 7.7 years vs HTTP’s 0.8 years of TX-only battery life. The 9.4× overhead ratio translates directly to a 9.4× difference in radio energy per day. Note: real-world battery life will be shorter due to sleep/idle current, MCU processing, and other loads; this model isolates the protocol overhead contribution.