diff --git a/apps/oma-lwm2m/lwm2m-engine.c b/apps/oma-lwm2m/lwm2m-engine.c index e2f6bba7c..3728e3505 100644 --- a/apps/oma-lwm2m/lwm2m-engine.c +++ b/apps/oma-lwm2m/lwm2m-engine.c @@ -50,6 +50,7 @@ #include "er-coap-constants.h" #include "er-coap-engine.h" #include "oma-tlv.h" +#include "oma-tlv-reader.h" #include "oma-tlv-writer.h" #include "net/ipv6/uip-ds6.h" #include @@ -707,6 +708,59 @@ write_rd_json_data(const lwm2m_context_t *context, return rdlen; } /*---------------------------------------------------------------------------*/ +/** + * @brief Set the writer pointer to the proper writer based on the Accept: header + * + * @param[in] context LWM2M context to operate on + * @param[in] accept Accept type number from CoAP headers + * + * @return The content type of the response if the selected writer is used + */ +static unsigned int +lwm2m_engine_select_writer(lwm2m_context_t *context, unsigned int accept) +{ + switch(accept) { + case LWM2M_TLV: + context->writer = &oma_tlv_writer; + break; + case LWM2M_TEXT_PLAIN: + case TEXT_PLAIN: + context->writer = &lwm2m_plain_text_writer; + break; + default: + PRINTF("Unknown Accept type %u, using LWM2M plain text\n", accept); + context->writer = &lwm2m_plain_text_writer; + /* Set the response type to plain text */ + accept = LWM2M_TEXT_PLAIN; + break; + } + return accept; +} +/*---------------------------------------------------------------------------*/ +/** + * @brief Set the reader pointer to the proper reader based on the Content-format: header + * + * @param[in] context LWM2M context to operate on + * @param[in] content_format Content-type type number from CoAP headers + */ +static void +lwm2m_engine_select_reader(lwm2m_context_t *context, unsigned int content_format) +{ + switch(content_format) { + case LWM2M_TLV: + context->reader = &oma_tlv_reader; + break; + case LWM2M_TEXT_PLAIN: + case TEXT_PLAIN: + context->reader = &lwm2m_plain_text_reader; + break; + default: + PRINTF("Unknown content type %u, using LWM2M plain text\n", accept); + context->reader = &lwm2m_plain_text_reader; + break; + } +} +/*---------------------------------------------------------------------------*/ void lwm2m_engine_handler(const lwm2m_object_t *object, void *request, void *response, @@ -716,6 +770,8 @@ lwm2m_engine_handler(const lwm2m_object_t *object, int len; const char *url; unsigned int format; + unsigned int accept; + unsigned int content_type; int depth; lwm2m_context_t context; rest_resource_flags_t method; @@ -734,11 +790,19 @@ lwm2m_engine_handler(const lwm2m_object_t *object, /* CoAP content format text plain - assume LWM2M text plain */ format = LWM2M_TEXT_PLAIN; } + if(!REST.get_header_accept(request, &accept)) { + PRINTF("No Accept header, using same as Content-format...\n"); + accept = format; + } depth = lwm2m_engine_parse_context(object, url, len, &context); PRINTF("Context: %u/%u/%u found: %d\n", context.object_id, context.object_instance_id, context.resource_id, depth); + /* Select reader and writer based on provided Content type and Accept headers */ + lwm2m_engine_select_reader(&context, format); + content_type = lwm2m_engine_select_writer(&context, accept); + #if (DEBUG) & DEBUG_PRINT /* for debugging */ if(method == METHOD_GET) { @@ -861,7 +925,7 @@ lwm2m_engine_handler(const lwm2m_object_t *object, if(depth == 3) { const lwm2m_resource_t *resource = get_resource(instance, &context); - size_t tlvlen = 0; + size_t content_len = 0; if(resource == NULL) { PRINTF("Error - do not have resource %d\n", context.resource_id); REST.set_response_status(response, NOT_FOUND_4_04); @@ -879,9 +943,9 @@ lwm2m_engine_handler(const lwm2m_object_t *object, context.reader = &lwm2m_plain_text_reader; PRINTF("PUT Callback with data: '%.*s'\n", plen, data); /* no specific reader for plain text */ - tlvlen = resource->value.callback.write(&context, data, plen, + content_len = resource->value.callback.write(&context, data, plen, buffer, preferred_size); - PRINTF("tlvlen:%u\n", (unsigned int)tlvlen); + PRINTF("content_len:%u\n", (unsigned int)content_len); REST.set_response_status(response, CHANGED_2_04); } else { PRINTF("PUT callback with format %d\n", format); @@ -899,48 +963,39 @@ lwm2m_engine_handler(const lwm2m_object_t *object, } else if(method == METHOD_GET) { if(lwm2m_object_is_resource_string(resource)) { const uint8_t *value; - uint16_t len; value = lwm2m_object_get_resource_string(resource, &context); - len = lwm2m_object_get_resource_strlen(resource, &context); if(value != NULL) { + uint16_t len = lwm2m_object_get_resource_strlen(resource, &context); PRINTF("Get string value: %.*s\n", (int)len, (char *)value); - /* TODO check format */ - REST.set_response_payload(response, value, len); - REST.set_header_content_type(response, LWM2M_TEXT_PLAIN); - /* Done */ - return; + content_len = context.writer->write_string(&context, buffer, + preferred_size, (const char *)value, len); } } else if(lwm2m_object_is_resource_int(resource)) { int32_t value; if(lwm2m_object_get_resource_int(resource, &context, &value)) { - /* export INT as TLV */ - tlvlen = oma_tlv_write_int32(resource->id, value, buffer, preferred_size); - PRINTF("Exporting int as TLV: %" PRId32 ", len: %u\n", - value, (unsigned int)tlvlen); + content_len = context.writer->write_int(&context, buffer, preferred_size, value); } } else if(lwm2m_object_is_resource_floatfix(resource)) { int32_t value; if(lwm2m_object_get_resource_floatfix(resource, &context, &value)) { - /* export FLOATFIX as TLV */ + /* export FLOATFIX */ PRINTF("Exporting %d-bit fix as float: %" PRId32 "\n", LWM2M_FLOAT32_BITS, value); - tlvlen = oma_tlv_write_float32(resource->id, - value, LWM2M_FLOAT32_BITS, - buffer, preferred_size); - PRINTF("Exporting as TLV: len:%u\n", (unsigned int)tlvlen); + content_len = context.writer->write_float32fix(&context, buffer, + preferred_size, value, LWM2M_FLOAT32_BITS); } } else if(lwm2m_object_is_resource_callback(resource)) { if(resource->value.callback.read != NULL) { - tlvlen = resource->value.callback.read(&context, + content_len = resource->value.callback.read(&context, buffer, preferred_size); } else { REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05); return; } } - if(tlvlen > 0) { - REST.set_response_payload(response, buffer, tlvlen); - REST.set_header_content_type(response, LWM2M_TLV); + if(content_len > 0) { + REST.set_response_payload(response, buffer, content_len); + REST.set_header_content_type(response, content_type); } else { /* failed to produce output - it is an internal error */ REST.set_response_status(response, INTERNAL_SERVER_ERROR_5_00); @@ -952,7 +1007,7 @@ lwm2m_engine_handler(const lwm2m_object_t *object, const uint8_t *data; int plen = REST.get_request_payload(request, &data); PRINTF("Execute Callback with data: '%.*s'\n", plen, data); - tlvlen = resource->value.callback.exec(&context, + content_len = resource->value.callback.exec(&context, data, plen, buffer, preferred_size); REST.set_response_status(response, CHANGED_2_04); @@ -973,7 +1028,7 @@ lwm2m_engine_handler(const lwm2m_object_t *object, REST.set_response_status(response, NOT_FOUND_4_04); } else { int rdlen; - if(format == APPLICATION_LINK_FORMAT) { + if(accept == APPLICATION_LINK_FORMAT) { rdlen = write_rd_link_data(object, instance, (char *)buffer, preferred_size); } else { @@ -986,10 +1041,10 @@ lwm2m_engine_handler(const lwm2m_object_t *object, return; } REST.set_response_payload(response, buffer, rdlen); - if(format == APPLICATION_LINK_FORMAT) { + if(accept == APPLICATION_LINK_FORMAT) { REST.set_header_content_type(response, REST.type.APPLICATION_LINK_FORMAT); } else { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + REST.set_header_content_type(response, LWM2M_JSON); } } }