Monday, 17 Oct 2011
A Low-Power CoAP for ContikiMatthias Kovatsch, Simon Duquennoy, and Adam [email protected] [email protected] [email protected]
A Low-Power CoAP for ContikiMatthias Kovatsch – ETH Zürich 2
Internet of Things Protocol Stack
Layer Protocol
Application CoAP / REST Engine (Erbium)
Transport UDP
Network IPv6 / RPL
Adaption 6LoWPAN
MAC CSMA / link-layer bursts
Radio Duty Cycling ContikiMAC
Physical IEEE 802.15.4
A Low-Power CoAP for ContikiMatthias Kovatsch – ETH Zürich 3
Internet of Things Protocol Stack
Layer Protocol
Application CoAP / REST Engine (Erbium)
Transport UDP
Network IPv6 / RPL
Adaption 6LoWPAN
MAC CSMA / link-layer bursts
Radio Duty Cycling ContikiMAC
Physical IEEE 802.15.4
/ link-layer bursts
A Low-Power CoAP for ContikiMatthias Kovatsch – ETH Zürich
ContikiMAC
4
A
D
A
D A
ACK frame
Data frame
Radio on
Sender
Receiver
Transmission detected
DD DD
Channel check
A Low-Power CoAP for ContikiMatthias Kovatsch – ETH Zürich
Link-layer Bursts
5
A
AD
Sender
Receiver
Transmission detected
DD DD
Channel check
A
AD
D A
AD
D A
AD
D
D
A ACK frame
Data frame
Radio on
A Low-Power CoAP for ContikiMatthias Kovatsch – ETH Zürich
Constrained Application Protocol (CoAP)
RESTful Web services for networked embedded devices Idealized architectural style of the Web HTTP for the Internet of Things
6
coap://sky3/
coap://sky2/
coap://sky1/
GET /sensors/temperature
A Low-Power CoAP for ContikiMatthias Kovatsch – ETH Zürich
Implements draft-ietf-core-coap-07 Available in the Contiki repository on SourceForge
«Erbium» CoAP for Contiki
7
A Low-Power CoAP for ContikiMatthias Kovatsch – ETH Zürich
«Erbium» CoAP
Reliable UDP transport
Observing resources
Blockwise transfers
Resource discovery
Separate responses
Blocking client requests
8
/* Handle requests. */if (message->code >= COAP_GET && message->code <= COAP_DELETE) { /* Use transaction buffer for response to confirmable request. */ if ( (transaction = coap_new_transaction(message->tid, &UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport)) ) { static uint32_t block_num = 0; static uint16_t block_size = REST_MAX_CHUNK_SIZE; static uint32_t block_offset = 0; static int32_t new_offset = 0; if (message->type==COAP_TYPE_CON) { /* Reliable CON requests are answered with an ACK. */ coap_init_message(response, COAP_TYPE_ACK, CONTENT_2_05, message->tid); } else { /* Unreliable NON requests are answered with a NON as well. */ coap_init_message(response, COAP_TYPE_NON, CONTENT_2_05, coap_get_tid()); } /* resource handlers must take care of different handling (e.g., TOKEN_OPTION_REQUIRED_240) */ if (IS_OPTION(message, COAP_OPTION_TOKEN)) { coap_set_header_token(response, message->token, message->token_len); SET_OPTION(response, COAP_OPTION_TOKEN); } /* get offset for blockwise transfers */ if (coap_get_header_block2(message, &block_num, NULL, &block_size, &block_offset)) { block_size = MIN(block_size, REST_MAX_CHUNK_SIZE); new_offset = block_offset; } else { new_offset = 0; } /* Invoke resource handler. */ if (service_cbk) { /* Call REST framework and check if found and allowed. */ if (service_cbk(message, response, transaction->packet+COAP_MAX_HEADER_SIZE, block_size, &new_offset)) { /* Apply blockwise transfers. */ if ( IS_OPTION(message, COAP_OPTION_BLOCK2) ) { /* unchanged new_offset indicates that resource is unaware of blockwise transfer */ if (new_offset==block_offset) { if (block_offset >= response->payload_len) { response->code = BAD_OPTION_4_02; coap_set_payload(response, (uint8_t*)"Block out of scope", 18); } else { coap_set_header_block2(response, block_num, response->payload_len - block_offset > block_size, block_size); coap_set_payload(response, response->payload+block_offset, MIN(response->payload_len - block_offset, block_size)); } /* if (valid offset) */ } else { /* resource provides chunk-wise data */ coap_set_header_block2(response, block_num, new_offset!=-1 || response->payload_len > block_size, block_size); if (response->payload_len > block_size) coap_set_payload(response, response->payload, block_size); } /* if (resource aware of blockwise) */ } else if (new_offset!=0) { coap_set_header_block2(response, 0, new_offset!=-1, REST_MAX_CHUNK_SIZE); coap_set_payload(response, response->payload, MIN(response->payload_len, REST_MAX_CHUNK_SIZE)); } /* if (blockwise request) */ } } else { coap_error_code = INTERNAL_SERVER_ERROR_5_00; coap_error_message = "Service callback undefined"; } /* if (service callback) */ /* serialize Response. */ if ((transaction->packet_len = coap_serialize_message(response, transaction->packet))==0) { coap_error_code = PACKET_SERIALIZATION_ERROR; } } else { coap_error_code = MEMORY_ALLOC_ERR; coap_error_message = "Transaction buffer allocation failed"; } /* if (transaction buffer) */} else { /* Responses */ if (message->type==COAP_TYPE_ACK) { /* Handled by transaction layer */ } else if (message->type==COAP_TYPE_RST) { /* Cancel possible subscriptions. */ if (IS_OPTION(message, COAP_OPTION_TOKEN)) { coap_remove_observer_by_token(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, message->token, message->token_len); }}
A Low-Power CoAP for ContikiMatthias Kovatsch – ETH Zürich
«Erbium» REST Engine
Resource abstraction
RESOURCE(handle, METHODs, URI-Path, Web Linking info); Resource handler
PERIODIC_RESOURCE(handle, METHODs, URI-Path, info, period);
Additional periodic handler
EVENT_RESOURCE(handle, METHODs, URI-Path, info); Additional event handler
9
Observable
CoRE Link Formattitle="Hello world"; rt="TemperatureC";
A Low-Power CoAP for ContikiMatthias Kovatsch – ETH Zürich
«Erbium» Memory Footprint
ROM [kB] RAM [kB]CoAP REST Engine total 8.5 1.5
Measured stack usage – 0.1
REST Engine 0.7 0
CoAP-07 base 4.5 0
CoAP-07 server 1.9 0.3
CoAP-07 transport 0.4 0.9
CoAP-07 observing 0.9 0.2
CoAP-07 separate 0.1 0
10
A Low-Power CoAP for ContikiMatthias Kovatsch – ETH Zürich
Experimental Set-up
11
3 hops
2 hops1 hop
Energy data over USB
100 Requests each
Laptop withborder router
Static routing
4 hops
A Low-Power CoAP for ContikiMatthias Kovatsch – ETH Zürich
Energy vs Latency for 64B Payload
12
Number of hopsNumber of hops
Ene
rgy
[mJ]
Late
ncy
[s]
No duty cyclingContikiMAC
1 2 3 4
0
100
200
300
400
1 2 3 4
0
0.2
0.4
0.6
0.8
1.08 Hz channel check rate
0.6% RDC
A Low-Power CoAP for ContikiMatthias Kovatsch – ETH Zürich
Transmitting Large Data
13
0 128 256 384 5120
5
10
15
20
25
30
35
40
45
50
55
60
65
70
0 128 256 384 5120
0.2
0.4
0.6
0.8
1.0
1.2
1.4
1.6
1.8
Payload [Bytes]Payload [Bytes]
Ene
rgy
[mJ]
Late
ncy
[s]
Bursts avoid steps in latency
2 3 4 5 6
Steps become less noticable
4 hops2 hops1 hop
A Low-Power CoAP for ContikiMatthias Kovatsch – ETH Zürich
Transmitting Large Data
14
A
AD
Sender
Receiver
Transmission detected
DD DD
Channel check
AD
AD
AD A
AD
D
D
A ACK frame
Data frame
Radio on
AD
A Low-Power CoAP for ContikiMatthias Kovatsch – ETH Zürich
Separate Responses
15
Client ClientServer Server
Requestprocessing
Request
Retry
Retry…
Response
Requestprocessing
Response
ACKRequest
ACK
Benchmarkand switch
automatically
A Low-Power CoAP for ContikiMatthias Kovatsch – ETH Zürich
Separate Responses over 4 Hops
16
WithoutWith
0 5 10 15 20 25
25
50
75
100
125
150
Ene
rgy
[mJ]
Server processing time [s]
Savings marginal
A Low-Power CoAP for ContikiMatthias Kovatsch – ETH Zürich
Conclusion
Internet of Things stack Isolated layers with different goals work together Layered architecture lowers complexity Optimize for single fragments No need to optimize payload size once fragmented
CoAP Draft 07 implementation for Contiki Block size most important parameter for memory-constrained
devices:Exponential sizes too coarse-grained
17
A Low-Power CoAP for ContikiMatthias Kovatsch – ETH Zürich
Future Work
Extend «Erbium» CoAP Blocking resource handler for UART Hierarchical resources / URI-Path handling Improve observer handling (only one buffer)
Study RESTful approach Long-term deployment with smart appliances Separate application logic from device firmware
and combine with «Californium» App Server
18
A Low-Power CoAP for ContikiMatthias Kovatsch – ETH Zürich 19
THANK YOU
Questions?
A Low-Power CoAP for ContikiMatthias Kovatsch – ETH Zürich
Radio Duty Cycling
20
CPU (normal/LPM)
Radio (RX/TX)
Flash (R/W/idle)
Sensors (tmp./
PIR/acc.)
LEDs0
5
10
15
20
25
Cur
rent
con
sum
ptio
n (c
a.) [
mA
]
A Low-Power CoAP for ContikiMatthias Kovatsch – ETH Zürich
Constrained Application Protocol (CoAP)
RESTful Web services for networked embedded devices Idealized architectural style of the Web Usually implemented with HTTP
Central mechanisms Reliable UDP transport («confirmable») Group communication (IP multicast) Push notifications («observing») Resource discovery («CoAP link format») Larger data transport («blockwise transfers»)
21
coap://sky3/
coap://sky2/
A Low-Power CoAP for ContikiMatthias Kovatsch – ETH Zürich
Blockwise Transfers
Automatic or controlled by handler
RESOURCE(handle, METHODs, URI-Path, Web Linking info); Resource handler
handle_handler(void* request, void* response, uint8_t *buffer, uint16_t
preferred_size, int32_t *offset);
22
Unaware: fill buffer up to REST_MAX_CHUNK_SIZE
Chunk-aware: use offset and fill buffer up to preferred_size
(update offset and set to -1 when finished)
A Low-Power CoAP for ContikiMatthias Kovatsch – ETH Zürich
Observing Resources
Post-handler registers observers automatically
PERIODIC_RESOURCE(handle, METHODs, URI-Path, info, period);
Additional periodic handler
EVENT_RESOURCE(handle, METHODs, URI-Path, info); Additional event handler
int handle_event_handler(resource_t *r) { ... REST.notify_subscribers(r->url, CON/NON, seqno, buf, len);}
23
Every x-th is CON to resolve orphans
A Low-Power CoAP for ContikiMatthias Kovatsch – ETH Zürich
Erbium REST Engine
Manipulate messages with REST API REST.set_header_etag(response, etag_buf, etag_len); REST.get_query_variable(request, name, value_buffer);
Link implementation coap-03 coap-06 coap-07 … HTTP (not yet implemented for Erbium)
24
Top Related