Back
Loading views...CoAP
CoAP
Category: Networking/IoT
Overview
CoAP (Constrained Application Protocol) is a lightweight RESTful protocol designed for constrained IoT devices. It uses UDP (optionally DTLS for security) and follows a request/response model similar to HTTP but with much smaller overhead, making it ideal for 6LoWPAN, NB-IoT, and other low-bandwidth networks.
1. Theory & Fundamentals
- REST-based: GET, POST, PUT, DELETE methods like HTTP
- Transport: UDP (unreliable) with reliability built into CoAP (CON/NON/ACK/RST)
- Port: 5683 (CoAP), 5684 (CoAPS with DTLS)
- Header: Only 4 bytes fixed header
- Max payload: Fits in single UDP datagram (typically <1KB)
- Observe: Server pushes updates to subscribed clients (like MQTT subscribe)
- Block-wise: Transfer large resources in blocks (RFC 7959)
2. Frame / Packet Structure
CoAP Message Format:
Ver(2b) | T(2b) | TKL(4b) | Code(8b) | Message ID(16b)
Token (0โ8 bytes)
Options (delta-encoded)
0xFF | Payload
T (Type): 0=CON, 1=NON, 2=ACK, 3=RST
Code: class.detail (e.g., 2.05 = Content, 4.04 = Not Found)
Request codes: 0.01=GET, 0.02=POST, 0.03=PUT, 0.04=DELETE
Response: 2.01=Created, 2.05=Content, 4.00=Bad Request, 5.00=Internal Error
Options (key ones):
If-Match, Uri-Host, ETag, Uri-Path, Content-Format, Max-Age, Uri-Query, Accept, Location-Path, Block2, Block1, Size2, Observe
3. Protocol Mechanics
- CON (Confirmable): Retransmitted until ACK; reliable delivery
- NON (Non-Confirmable): Fire and forget; less overhead
- Piggy-backed ACK: Response included in ACK (same message)
- Separate response: ACK first, then response (for slow processing)
- Observe: Client sends GET with Observe=0; server pushes updates with Observe counter
- DTLS: CoAP + DTLS (UDP-based TLS) for security
4. Hardware Implementation
- Any MCU with UDP/IP stack: ESP32, nRF52, STM32 + LwIP
- 6LoWPAN devices: Contiki-NG, Zephyr with CoAP
- NB-IoT modules: Some have built-in CoAP client (Quectel BC66)
- Libraries: libcoap (C), aiocoap (Python), Californium (Java)
5. Register-Level / Configuration
// Using libcoap on embedded Linux or Contiki-NG
#include <coap3/coap.h>
coap_context_t *ctx = coap_new_context(NULL);
coap_address_t dst;
coap_address_init(&dst);
dst.addr.sin.sin_family = AF_INET;
inet_pton(AF_INET, "192.168.1.100", &dst.addr.sin.sin_addr);
dst.addr.sin.sin_port = htons(5683);
coap_session_t *session = coap_new_client_session(ctx, NULL, &dst, COAP_PROTO_UDP);
coap_pdu_t *pdu = coap_new_pdu(session);
coap_pdu_set_type(pdu, COAP_MESSAGE_CON);
coap_pdu_set_code(pdu, COAP_REQUEST_CODE_GET);
coap_add_option(pdu, COAP_OPTION_URI_PATH, 11, (uint8_t*)"temperature");
coap_send(session, pdu);
6. Driver / Software Development
// CoAP server resource handler (Contiki-NG)
RESOURCE(temperature, "title="Temperature";rt="Temperature"",
temperature_get_handler, NULL, NULL, NULL);
void temperature_get_handler(coap_message_t *req, coap_message_t *res,
uint8_t *buf, uint16_t len, int32_t *offset) {
int temp = read_temperature(); // Your sensor read
int n = snprintf((char*)buf, len, "%d.%02d", temp/100, temp%100);
coap_set_payload(res, buf, n);
coap_set_header_content_format(res, APPLICATION_JSON);
}
7. Debugging & Testing
- coap-client / coap-server (libcoap CLI tools)
- Copper (Cu) Firefox plugin (legacy) or CoAP Explorer
- Wireshark: CoAP dissector built-in
- Common issues: Retransmission causing duplicate processing; Observe notifications not received; Block-wise not aligned
8. Real-World Applications
- IoT sensor data (temperature, humidity, energy) over 6LoWPAN
- NB-IoT device data submission
- Smart building device control (lights, HVAC)
- Industrial SCADA over constrained networks
- OMA LwM2M uses CoAP as transport
9. Advanced Topics & Edge Cases
- CoAP over TCP (RFC 8323): For reliable transport; used in LwM2M
- OSCORE: Object Security for CoAP (encrypt without DTLS per-hop)
- Multicast: CoAP group communication over IPv6 multicast
- Resource Directory: Devices register resources for discovery
10. Standards & Variants
| RFC | Feature |
|---|---|
| RFC 7252 | Core CoAP |
| RFC 7641 | Observe extension |
| RFC 7959 | Block-wise transfers |
| RFC 8613 | OSCORE security |
| RFC 8323 | CoAP over TCP/TLS |
๐ก Practical Examples
Example 1: GET temperature
coap-client -m get coap://192.168.1.1/temperature
# Returns: 23.50
Example 2: Observe resource
coap-client -m get -s 60 coap://192.168.1.1/temperature # Subscribe 60s
# Server pushes updates every time value changes
Example 3: POST actuator
coap-client -m post -e '{"state":"on"}' coap://device/led
๐งช Practice Questions
Beginner
- What transport does CoAP use?
- What is the difference between CON and NON messages?
- What is CoAP Observe?
- What is the default CoAP port?
- How is CoAP similar to HTTP?
Intermediate
- Implement a CoAP GET server on Contiki-NG.
- Explain CoAP block-wise transfer.
- How does DTLS secure CoAP?
- Implement CoAP Observe subscription.
- How does CoAP handle reliability over UDP?
Advanced
- Implement OSCORE for end-to-end CoAP encryption.
- Build a Resource Directory for CoAP device discovery.
- Implement CoAP multicast for group control.
- Compare CoAP vs MQTT for NB-IoT sensor data.
- Build CoAP proxy/gateway to HTTP REST.
Hands-on Projects
- CoAP Sensor Server: 6LoWPAN device serves temperature/humidity via CoAP.
- CoAP Dashboard: Python client polls all CoAP devices, displays on web.
- LwM2M Device: Implement OMA LwM2M management over CoAP.
Checklist
- [ ] Explain CoAP message types (CON, NON, ACK, RST)
- [ ] Implement CoAP GET server resource
- [ ] Implement CoAP client GET/POST
- [ ] Use CoAP Observe for push updates
- [ ] Implement block-wise for large resources
- [ ] Secure with DTLS or OSCORE
- [ ] Debug with Wireshark CoAP dissector
- [ ] Deploy on constrained device (Contiki/Zephyr)
- [ ] Build CoAP-to-HTTP gateway
- [ ] Implement LwM2M device management