62 #include "net/rpl/rpl.h"
65 #define DEBUG DEBUG_NONE
68 #ifndef LWM2M_ENGINE_CLIENT_ENDPOINT_PREFIX
69 #ifdef LWM2M_DEVICE_MODEL_NUMBER
70 #define LWM2M_ENGINE_CLIENT_ENDPOINT_PREFIX LWM2M_DEVICE_MODEL_NUMBER
72 #define LWM2M_ENGINE_CLIENT_ENDPOINT_PREFIX "Contiki-"
76 #ifdef LWM2M_ENGINE_CONF_MAX_OBJECTS
77 #define MAX_OBJECTS LWM2M_ENGINE_CONF_MAX_OBJECTS
79 #define MAX_OBJECTS 10
82 #define REMOTE_PORT UIP_HTONS(COAP_DEFAULT_PORT)
83 #define BS_REMOTE_PORT UIP_HTONS(5685)
85 static const lwm2m_object_t *objects[MAX_OBJECTS];
86 static char endpoint[32];
87 static char rd_data[128];
89 PROCESS(lwm2m_rd_client,
"LWM2M Engine");
91 static uip_ipaddr_t server_ipaddr;
92 static uint16_t server_port = REMOTE_PORT;
93 static uip_ipaddr_t bs_server_ipaddr;
94 static uint16_t bs_server_port = BS_REMOTE_PORT;
96 static uint8_t use_bootstrap = 0;
97 static uint8_t has_bootstrap_server_info = 0;
98 static uint8_t use_registration = 0;
99 static uint8_t has_registration_server_info = 0;
100 static uint8_t registered = 0;
101 static uint8_t bootstrapped = 0;
107 static const lwm2m_instance_t *get_first_instance_of_object(uint16_t
id, lwm2m_context_t *
context);
108 static const lwm2m_instance_t *get_instance(
const lwm2m_object_t *
object, lwm2m_context_t *
context,
int depth);
109 static const lwm2m_resource_t *get_resource(
const lwm2m_instance_t *instance, lwm2m_context_t *
context);
112 client_chunk_handler(
void *response)
114 #if (DEBUG) & DEBUG_PRINT
115 const uint8_t *chunk;
117 int len = coap_get_payload(response, &chunk);
119 PRINTF(
"|%.*s\n", len, (
char *)chunk);
124 index_of(
const uint8_t *data,
int offset,
int len, uint8_t c)
129 for(; offset < len; offset++) {
130 if(data[offset] == c) {
138 has_network_access(
void)
140 #if UIP_CONF_IPV6_RPL
141 if(rpl_get_any_dag() ==
NULL) {
149 lwm2m_engine_use_bootstrap_server(
int use)
151 use_bootstrap = use != 0;
158 lwm2m_engine_use_registration_server(
int use)
160 use_registration = use != 0;
161 if(use_registration) {
167 lwm2m_engine_register_with_server(
const uip_ipaddr_t *server, uint16_t port)
173 server_port = REMOTE_PORT;
175 has_registration_server_info = 1;
177 if(use_registration) {
183 update_registration_server(
void)
185 if(has_registration_server_info) {
189 #if UIP_CONF_IPV6_RPL
194 dag = rpl_get_any_dag();
197 server_port = REMOTE_PORT;
207 lwm2m_engine_register_with_bootstrap_server(
const uip_ipaddr_t *server,
212 bs_server_port = port;
214 bs_server_port = BS_REMOTE_PORT;
216 has_bootstrap_server_info = 1;
225 update_bootstrap_server(
void)
227 if(has_bootstrap_server_info) {
231 #if UIP_CONF_IPV6_RPL
236 dag = rpl_get_any_dag();
239 bs_server_port = REMOTE_PORT;
250 static coap_packet_t request[1];
255 printf(
"RD Client started with endpoint '%s'\n", endpoint);
263 if(!has_network_access()) {
265 }
else if(use_bootstrap && bootstrapped == 0) {
266 if(update_bootstrap_server()) {
268 coap_init_message(request, COAP_TYPE_CON, COAP_POST, 0);
269 coap_set_header_uri_path(request,
"/bs");
270 coap_set_header_uri_query(request, endpoint);
272 printf(
"Registering ID with bootstrap server [");
273 uip_debug_ipaddr_print(&bs_server_ipaddr);
274 printf(
"]:%u as '%s'\n", uip_ntohs(bs_server_port), endpoint);
276 COAP_BLOCKING_REQUEST(&bs_server_ipaddr, bs_server_port, request,
277 client_chunk_handler);
280 }
else if(use_bootstrap && bootstrapped == 1) {
282 const lwm2m_instance_t *instance =
NULL;
283 const lwm2m_resource_t *rsc;
284 const uint8_t *first;
287 PRINTF(
"*** Bootstrap - checking for server info...\n");
290 instance = get_first_instance_of_object(LWM2M_OBJECT_SECURITY_ID, &context);
291 if(instance !=
NULL) {
293 context.resource_id = LWM2M_SECURITY_SERVER_URI;
294 rsc = get_resource(instance, &context);
295 first = lwm2m_object_get_resource_string(rsc, &context);
296 len = lwm2m_object_get_resource_strlen(rsc, &context);
297 if(first !=
NULL && len > 0) {
303 PRINTF(
"**** Found security instance using: %.*s\n", len, first);
307 secure = strncmp((
const char *)first,
"coaps:", 6) == 0;
310 start = index_of(first, 0, len,
'[');
311 end = index_of(first, start, len,
']');
312 if(start > 0 && end > start &&
314 if(first[end + 1] ==
':' &&
315 lwm2m_plain_text_read_int(first + end + 2, len - end - 2, &port)) {
321 port = COAP_DEFAULT_PORT;
323 port = COAP_DEFAULT_PORT;
325 PRINTF(
"Server address ");
327 PRINTF(
" port %" PRId32
"%s\n", port, secure ?
" (secure)" :
"");
329 printf(
"Secure CoAP requested but not supported - can not bootstrap\n");
331 lwm2m_engine_register_with_server(&addr,
336 printf(
"** failed to parse URI %.*s\n", len, first);
341 if(bootstrapped == 1) {
346 }
else if(use_registration && !registered &&
347 update_registration_server()) {
353 coap_init_message(request, COAP_TYPE_CON, COAP_POST, 0);
354 coap_set_header_uri_path(request,
"/rd");
355 coap_set_header_uri_query(request, endpoint);
359 for(i = 0; i < MAX_OBJECTS; i++) {
360 if(objects[i] !=
NULL) {
361 for(j = 0; j < objects[i]->count; j++) {
362 if(objects[i]->instances[j].flag & LWM2M_INSTANCE_FLAG_USED) {
363 len = snprintf(&rd_data[pos],
sizeof(rd_data) - pos,
364 "%s<%d/%d>", pos > 0 ?
"," :
"",
365 objects[i]->
id, objects[i]->instances[j].
id);
366 if(len > 0 && len <
sizeof(rd_data) - pos) {
374 coap_set_payload(request, (uint8_t *)rd_data, pos);
376 printf(
"Registering with [");
377 uip_debug_ipaddr_print(&server_ipaddr);
378 printf(
"]:%u lwm2m endpoint '%s': '%.*s'\n", uip_ntohs(server_port),
379 endpoint, pos, rd_data);
380 COAP_BLOCKING_REQUEST(&server_ipaddr, server_port, request,
381 client_chunk_handler);
391 lwm2m_engine_init(
void)
393 #ifdef LWM2M_ENGINE_CLIENT_ENDPOINT_NAME
395 snprintf(endpoint,
sizeof(endpoint) - 1,
396 "?ep=" LWM2M_ENGINE_CLIENT_ENDPOINT_NAME);
403 char client[
sizeof(endpoint)];
405 len = strlen(LWM2M_ENGINE_CLIENT_ENDPOINT_PREFIX);
407 if(len >
sizeof(client) - 13) {
408 len =
sizeof(client) - 13;
410 memcpy(client, LWM2M_ENGINE_CLIENT_ENDPOINT_PREFIX, len);
414 for(i = 0; i < UIP_DS6_ADDR_NB; i++) {
424 for(i = 0; i < 6; i++) {
426 uint8_t b = ipaddr->u8[10 + i];
427 client[len++] = (b >> 4) > 9 ?
'A' - 10 + (b >> 4) :
'0' + (b >> 4);
428 client[len++] = (b & 0xf) > 9 ?
'A' - 10 + (b & 0xf) :
'0' + (b & 0xf);
435 snprintf(endpoint,
sizeof(endpoint) - 1,
"?ep=%s", client);
444 lwm2m_engine_register_default_objects(
void)
452 parse_next(
const char **path,
int *path_len, uint16_t *value)
460 while(*path_len > 0) {
463 *path_len = *path_len - 1;
464 if(c >=
'0' && c <=
'9') {
465 *value = *value * 10 + (c -
'0');
466 }
else if(c ==
'/') {
477 lwm2m_engine_parse_context(
const lwm2m_object_t *
object,
478 const char *path,
int path_len,
485 memset(context, 0,
sizeof(lwm2m_context_t));
488 ret += parse_next(&path, &path_len, &context->object_id);
489 ret += parse_next(&path, &path_len, &context->object_instance_id);
490 ret += parse_next(&path, &path_len, &context->resource_id);
493 context->reader = &lwm2m_plain_text_reader;
494 context->writer = &oma_tlv_writer;
499 const lwm2m_object_t *
500 lwm2m_engine_get_object(uint16_t
id)
503 for(i = 0; i < MAX_OBJECTS; i++) {
504 if(objects[i] !=
NULL && objects[i]->
id ==
id) {
512 lwm2m_engine_register_object(
const lwm2m_object_t *
object)
516 for(i = 0; i < MAX_OBJECTS; i++) {
517 if(objects[i] ==
NULL) {
524 (
char *)object->path);
528 static const lwm2m_instance_t *
529 get_first_instance_of_object(uint16_t
id, lwm2m_context_t *context)
531 const lwm2m_object_t *object;
534 object = lwm2m_engine_get_object(
id);
541 memset(context, 0,
sizeof(lwm2m_context_t));
542 context->object_id = id;
544 for(i = 0; i <
object->count; i++) {
545 if(object->instances[i].flag & LWM2M_INSTANCE_FLAG_USED) {
546 context->object_instance_id =
object->instances[i].id;
547 context->object_instance_index = i;
548 return &
object->instances[i];
554 static const lwm2m_instance_t *
555 get_instance(
const lwm2m_object_t *
object, lwm2m_context_t *context,
int depth)
559 PRINTF(
"lwm2m: searching for instance %u\n", context->object_instance_id);
560 for(i = 0; i <
object->count; i++) {
561 PRINTF(
" Instance %d -> %u (used: %d)\n", i, object->instances[i].id,
562 (object->instances[i].flag & LWM2M_INSTANCE_FLAG_USED) != 0);
563 if(object->instances[i].id == context->object_instance_id &&
564 object->instances[i].flag & LWM2M_INSTANCE_FLAG_USED) {
565 context->object_instance_index = i;
566 return &
object->instances[i];
573 static const lwm2m_resource_t *
574 get_resource(
const lwm2m_instance_t *instance, lwm2m_context_t *context)
577 if(instance !=
NULL) {
578 PRINTF(
"lwm2m: searching for resource %u\n", context->resource_id);
579 for(i = 0; i < instance->count; i++) {
580 PRINTF(
" Resource %d -> %u\n", i, instance->resources[i].id);
581 if(instance->resources[i].id == context->resource_id) {
582 context->resource_index = i;
583 return &instance->resources[i];
591 write_rd_link_data(
const lwm2m_object_t *
object,
592 const lwm2m_instance_t *instance,
593 char *buffer,
size_t size)
595 const lwm2m_resource_t *resource;
598 PRINTF(
"<%d/%d>", object->id, instance->id);
599 rdlen = snprintf(buffer, size,
"<%d/%d>",
600 object->id, instance->id);
601 if(rdlen < 0 || rdlen >= size) {
605 for(i = 0; i < instance->count; i++) {
606 resource = &instance->resources[i];
607 PRINTF(
",<%d/%d/%d>", object->id, instance->id, resource->id);
609 len = snprintf(&buffer[rdlen], size - rdlen,
610 ",<%d/%d/%d>", object->id, instance->id, resource->id);
612 if(len < 0 || rdlen >= size) {
620 write_rd_json_data(
const lwm2m_context_t *context,
621 const lwm2m_object_t *
object,
622 const lwm2m_instance_t *instance,
623 char *buffer,
size_t size)
625 const lwm2m_resource_t *resource;
630 rdlen = snprintf(buffer, size,
"{\"e\":[");
631 if(rdlen < 0 || rdlen >= size) {
635 for(i = 0, len = 0; i < instance->count; i++) {
636 resource = &instance->resources[i];
638 if(lwm2m_object_is_resource_string(resource)) {
639 const uint8_t *value;
641 value = lwm2m_object_get_resource_string(resource, context);
642 slen = lwm2m_object_get_resource_strlen(resource, context);
644 PRINTF(
"%s{\"n\":\"%u\",\"sv\":\"%.*s\"}", s,
645 resource->id, slen, value);
646 len = snprintf(&buffer[rdlen], size - rdlen,
647 "%s{\"n\":\"%u\",\"sv\":\"%.*s\"}", s,
648 resource->id, slen, value);
650 }
else if(lwm2m_object_is_resource_int(resource)) {
652 if(lwm2m_object_get_resource_int(resource, context, &value)) {
653 PRINTF(
"%s{\"n\":\"%u\",\"v\":%" PRId32
"}", s,
654 resource->id, value);
655 len = snprintf(&buffer[rdlen], size - rdlen,
656 "%s{\"n\":\"%u\",\"v\":%" PRId32
"}", s,
657 resource->id, value);
659 }
else if(lwm2m_object_is_resource_floatfix(resource)) {
661 if(lwm2m_object_get_resource_floatfix(resource, context, &value)) {
662 PRINTF(
"%s{\"n\":\"%u\",\"v\":%" PRId32
"}", s, resource->id,
663 value / LWM2M_FLOAT32_FRAC);
664 len = snprintf(&buffer[rdlen], size - rdlen,
665 "%s{\"n\":\"%u\",\"v\":", s, resource->id);
667 if(len < 0 || rdlen >= size) {
671 len = lwm2m_plain_text_write_float32fix((uint8_t *)&buffer[rdlen],
673 value, LWM2M_FLOAT32_BITS);
684 }
else if(lwm2m_object_is_resource_boolean(resource)) {
686 if(lwm2m_object_get_resource_boolean(resource, context, &value)) {
687 PRINTF(
"%s{\"n\":\"%u\",\"bv\":%s}", s, resource->id,
688 value ?
"true" :
"false");
689 len = snprintf(&buffer[rdlen], size - rdlen,
690 "%s{\"n\":\"%u\",\"bv\":%s}", s, resource->id,
691 value ?
"true" :
"false");
695 if(len < 0 || rdlen >= size) {
703 len = snprintf(&buffer[rdlen], size - rdlen,
"]}");
705 if(len < 0 || rdlen >= size) {
725 context->writer = &oma_tlv_writer;
727 case LWM2M_TEXT_PLAIN:
729 context->writer = &lwm2m_plain_text_writer;
732 case APPLICATION_JSON:
733 context->writer = &lwm2m_json_writer;
736 PRINTF(
"Unknown Accept type %u, using LWM2M plain text\n", accept);
737 context->writer = &lwm2m_plain_text_writer;
739 accept = LWM2M_TEXT_PLAIN;
754 switch(content_format) {
756 context->reader = &oma_tlv_reader;
758 case LWM2M_TEXT_PLAIN:
760 context->reader = &lwm2m_plain_text_reader;
763 PRINTF(
"Unknown content type %u, using LWM2M plain text\n",
accept);
764 context->reader = &lwm2m_plain_text_reader;
770 lwm2m_engine_handler(
const lwm2m_object_t *
object,
771 void *request,
void *response,
772 uint8_t *buffer, uint16_t preferred_size,
779 unsigned int content_type;
783 const lwm2m_instance_t *instance;
784 #if (DEBUG) & DEBUG_PRINT
785 const char *method_str;
788 method = REST.get_method_type(request);
790 len = REST.get_url(request, &url);
791 if(!REST.get_header_content_type(request, &format)) {
792 PRINTF(
"No format given. Assume text plain...\n");
793 format = LWM2M_TEXT_PLAIN;
794 }
else if(format == TEXT_PLAIN) {
796 format = LWM2M_TEXT_PLAIN;
798 if(!REST.get_header_accept(request, &accept)) {
799 PRINTF(
"No Accept header, using same as Content-format...\n");
803 depth = lwm2m_engine_parse_context(
object, url, len, &context);
804 PRINTF(
"Context: %u/%u/%u found: %d\n", context.object_id,
805 context.object_instance_id, context.resource_id, depth);
811 #if (DEBUG) & DEBUG_PRINT
813 if(method == METHOD_GET) {
815 }
else if(method == METHOD_POST) {
817 }
else if(method == METHOD_PUT) {
819 }
else if(method == METHOD_DELETE) {
820 method_str =
"DELETE";
822 method_str =
"UNKNOWN";
824 PRINTF(
"%s Called Path:%.*s Format:%d ID:%d bsize:%u\n", method_str, len,
825 url, format, object->id, preferred_size);
826 if(format == LWM2M_TEXT_PLAIN) {
829 int plen = REST.get_request_payload(request, &data);
831 PRINTF(
"Data: '%.*s'\n", plen, (
char *)data);
836 instance = get_instance(
object, &context, depth);
839 if(depth > 1 && instance ==
NULL) {
840 if(method != METHOD_PUT && method != METHOD_POST) {
841 PRINTF(
"Error - do not have instance %d\n", context.object_instance_id);
842 REST.set_response_status(response, NOT_FOUND_4_04);
846 int i, len, plen, pos;
848 PRINTF(
">>> CREATE ? %d/%d\n", context.object_id,
849 context.object_instance_id);
851 for(i = 0; i <
object->count; i++) {
852 if((object->instances[i].flag & LWM2M_INSTANCE_FLAG_USED) == 0) {
854 object->instances[i].flag |= LWM2M_INSTANCE_FLAG_USED;
855 object->instances[i].id = context.object_instance_id;
856 context.object_instance_index = i;
857 PRINTF(
"Created instance: %d\n", context.object_instance_id);
858 REST.set_response_status(response, CREATED_2_01);
859 instance = &
object->instances[i];
864 if(instance ==
NULL) {
866 REST.set_response_status(response, NOT_ACCEPTABLE_4_06);
870 plen = REST.get_request_payload(request, &data);
876 for(i = 0; i < plen; i++) {
877 PRINTF(
"%02x", data[i]);
883 len = oma_tlv_read(&tlv, (uint8_t *)&data[pos], plen - pos);
884 PRINTF(
"Found TLV type=%u id=%u len=%lu\n",
885 tlv.type, tlv.id, (
unsigned long)tlv.length);
887 if(tlv.type == OMA_TLV_TYPE_RESOURCE) {
888 context.resource_id = tlv.id;
889 const lwm2m_resource_t *rsc = get_resource(instance, &context);
892 if(lwm2m_object_is_resource_string(rsc)) {
893 PRINTF(
" new string value for /%d/%d/%d = %.*s\n",
894 context.object_id, context.object_instance_id,
895 context.resource_id, (
int)tlv.length, tlv.value);
896 lwm2m_object_set_resource_string(rsc, &context,
897 tlv.length, tlv.value);
898 }
else if(lwm2m_object_is_resource_int(rsc)) {
899 PRINTF(
" new int value for /%d/%d/%d = %" PRId32
"\n",
900 context.object_id, context.object_instance_id,
901 context.resource_id, oma_tlv_get_int32(&tlv));
902 lwm2m_object_set_resource_int(rsc, &context,
903 oma_tlv_get_int32(&tlv));
904 }
else if(lwm2m_object_is_resource_floatfix(rsc)) {
906 if(oma_tlv_float32_to_fix(&tlv, &value, LWM2M_FLOAT32_BITS)) {
907 PRINTF(
" new float value for /%d/%d/%d = %" PRId32
"\n",
908 context.object_id, context.object_instance_id,
909 context.resource_id, value >> LWM2M_FLOAT32_BITS);
910 lwm2m_object_set_resource_floatfix(rsc, &context, value);
912 PRINTF(
" new float value for /%d/%d/%d: FAILED\n",
913 context.object_id, context.object_instance_id,
914 context.resource_id);
916 }
else if(lwm2m_object_is_resource_boolean(rsc)) {
917 PRINTF(
" new boolean value for /%d/%d/%d = %" PRId32
"\n",
918 context.object_id, context.object_instance_id,
919 context.resource_id, oma_tlv_get_int32(&tlv));
920 lwm2m_object_set_resource_boolean(rsc, &context,
921 oma_tlv_get_int32(&tlv) != 0);
926 }
while(len > 0 && pos < plen);
932 const lwm2m_resource_t *resource = get_resource(instance, &context);
933 size_t content_len = 0;
934 if(resource ==
NULL) {
935 PRINTF(
"Error - do not have resource %d\n", context.resource_id);
936 REST.set_response_status(response, NOT_FOUND_4_04);
940 if(method == METHOD_PUT) {
941 if(lwm2m_object_is_resource_callback(resource)) {
942 if(resource->value.callback.write !=
NULL) {
944 if(format == LWM2M_TEXT_PLAIN) {
947 int plen = REST.get_request_payload(request, &data);
948 context.reader = &lwm2m_plain_text_reader;
949 PRINTF(
"PUT Callback with data: '%.*s'\n", plen, data);
951 content_len = resource->value.callback.write(&context, data, plen,
952 buffer, preferred_size);
953 PRINTF(
"content_len:%u\n", (
unsigned int)content_len);
954 REST.set_response_status(response, CHANGED_2_04);
956 PRINTF(
"PUT callback with format %d\n", format);
957 REST.set_response_status(response, NOT_ACCEPTABLE_4_06);
960 PRINTF(
"PUT - no write callback\n");
961 REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05);
964 PRINTF(
"PUT on non-callback resource!\n");
965 REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05);
968 }
else if(method == METHOD_GET) {
969 if(lwm2m_object_is_resource_string(resource)) {
970 const uint8_t *value;
971 value = lwm2m_object_get_resource_string(resource, &context);
973 uint16_t len = lwm2m_object_get_resource_strlen(resource, &context);
974 PRINTF(
"Get string value: %.*s\n", (
int)len, (
char *)value);
975 content_len = context.writer->write_string(&context, buffer,
976 preferred_size, (
const char *)value, len);
978 }
else if(lwm2m_object_is_resource_int(resource)) {
980 if(lwm2m_object_get_resource_int(resource, &context, &value)) {
981 content_len = context.writer->write_int(&context, buffer, preferred_size, value);
983 }
else if(lwm2m_object_is_resource_floatfix(resource)) {
985 if(lwm2m_object_get_resource_floatfix(resource, &context, &value)) {
987 PRINTF(
"Exporting %d-bit fix as float: %" PRId32
"\n",
988 LWM2M_FLOAT32_BITS, value);
989 content_len = context.writer->write_float32fix(&context, buffer,
990 preferred_size, value, LWM2M_FLOAT32_BITS);
992 }
else if(lwm2m_object_is_resource_callback(resource)) {
993 if(resource->value.callback.read !=
NULL) {
994 content_len = resource->value.callback.read(&context,
995 buffer, preferred_size);
997 REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05);
1001 if(content_len > 0) {
1002 REST.set_response_payload(response, buffer, content_len);
1003 REST.set_header_content_type(response, content_type);
1006 REST.set_response_status(response, INTERNAL_SERVER_ERROR_5_00);
1009 }
else if(method == METHOD_POST) {
1010 if(lwm2m_object_is_resource_callback(resource)) {
1011 if(resource->value.callback.exec !=
NULL) {
1012 const uint8_t *data;
1013 int plen = REST.get_request_payload(request, &data);
1014 PRINTF(
"Execute Callback with data: '%.*s'\n", plen, data);
1015 content_len = resource->value.callback.exec(&context,
1017 buffer, preferred_size);
1018 REST.set_response_status(response, CHANGED_2_04);
1020 PRINTF(
"Execute callback - no exec callback\n");
1021 REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05);
1024 PRINTF(
"Resource post but no callback resource\n");
1025 REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05);
1028 }
else if(depth == 2) {
1030 if(method != METHOD_GET) {
1031 REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05);
1032 }
else if(instance ==
NULL) {
1033 REST.set_response_status(response, NOT_FOUND_4_04);
1036 if(accept == APPLICATION_LINK_FORMAT) {
1037 rdlen = write_rd_link_data(
object, instance,
1038 (
char *)buffer, preferred_size);
1040 rdlen = write_rd_json_data(&context,
object, instance,
1041 (
char *)buffer, preferred_size);
1044 PRINTF(
"Failed to generate instance response\n");
1045 REST.set_response_status(response, SERVICE_UNAVAILABLE_5_03);
1048 REST.set_response_payload(response, buffer, rdlen);
1049 if(accept == APPLICATION_LINK_FORMAT) {
1050 REST.set_header_content_type(response, REST.type.APPLICATION_LINK_FORMAT);
1052 REST.set_header_content_type(response, LWM2M_JSON);
1059 lwm2m_engine_delete_handler(
const lwm2m_object_t *
object,
void *request,
1060 void *response, uint8_t *buffer,
1061 uint16_t preferred_size, int32_t *offset)
1067 len = REST.get_url(request, &url);
1068 PRINTF(
"*** DELETE URI:'%.*s' called... - responding with DELETED.\n",
1070 len = lwm2m_engine_parse_context(
object, url, len, &context);
1071 PRINTF(
"Context: %u/%u/%u found: %d\n", context.object_id,
1072 context.object_instance_id, context.resource_id, len);
1074 REST.set_response_status(response, DELETED_2_02);
void process_poll(struct process *p)
Request a process to be polled.
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
static void start(void)
Start measurement.
Header file for the Contiki OMA LWM2M TLV reader
Header file for the Contiki OMA LWM2M device
static uip_ds6_addr_t * addr
Pointer to a router list entry.
Header file for IPv6-related data structures.
rest_resource_flags_t
Resource flags for allowed methods and special functionalities.
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
void etimer_set(struct etimer *et, clock_time_t interval)
Set an event timer.
#define PROCESS_END()
Define the end of a process.
#define PROCESS(name, strname)
Declare a process.
Header file for the Contiki OMA LWM2M object API
PROCESS_THREAD(lwm2m_rd_client, ev, data)
An abstraction layer for RESTful Web services (Erbium).
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
static struct sicslowpan_addr_context * context
Addresses contexts for IPHC.
Collection of constants specified in the CoAP standard.
Header file for the Contiki OMA LWM2M TLV writer
void rest_activate_resource(resource_t *resource, char *path)
Makes a resource available under the given URI path.
Header file for the Contiki OMA LWM2M engine
#define NULL
The null pointer.
static unsigned int lwm2m_engine_select_writer(lwm2m_context_t *context, unsigned int accept)
Set the writer pointer to the proper writer based on the Accept: header.
#define PROCESS_YIELD()
Yield the currently running process.
int etimer_expired(struct etimer *et)
Check if an event timer has expired.
void lwm2m_security_init(void)
void rest_init_engine(void)
Initializes and starts the REST Engine process.
#define ADDR_TENTATIVE
Possible states for the an address (RFC 4862)
#define CLOCK_SECOND
A second, measured in system clock time.
Header file for the Contiki OMA LWM2M plain text reader / writer
void process_start(struct process *p, process_data_t data)
Start a process.
#define uiplib_ipaddrconv
Convert a textual representation of an IP address to a numerical representation.
Header file for the Contiki OMA LWM2M TLV
A set of debugging macros for the IP stack
void lwm2m_device_init(void)
uip_ds6_netif_t uip_ds6_if
The single interface.
static void lwm2m_engine_select_reader(lwm2m_context_t *context, unsigned int content_format)
Set the reader pointer to the proper reader based on the Content-format: header.
void lwm2m_server_init(void)
static uint8_t accept(uint8_t in)
Processes an incoming or outgoing multicast message and determines whether it should be dropped or ac...
CoAP implementation for the REST Engine.
Header file for the Contiki OMA LWM2M JSON writer
#define PROCESS_BEGIN()
Define the beginning of a process.