예제 #1
0
static void prv_instance_dump(lwm2m_object_t * objectP,
                              uint16_t id)
{
    int numData;
    lwm2m_tlv_t * dataArray;
    int size;
    uint8_t * buffer;
    int i;
    uint16_t res;

    numData = 0;
    res = objectP->readFunc(id, &numData, &dataArray, objectP);
    if (res != COAP_205_CONTENT)
    {
        printf("Error ");
        print_status(stdout, res);
        printf("\r\n");
        return;
    }

    dump_tlv(stdout, numData, dataArray, 0);

    size = lwm2m_tlv_serialize(numData, dataArray, &buffer);
    printf("char objectTlv[%d] = {", size);
    for (i = 0 ; i < size ; i++)
    {
        printf("0x%02X, ", buffer[i]);
    }
    printf("\b\b};\r\n");
    lwm2m_tlv_free(numData, dataArray);
    lwm2m_free(buffer);
}
예제 #2
0
파일: objects.c 프로젝트: mythfish/wakaama
coap_status_t object_create(lwm2m_context_t * contextP,
                            lwm2m_uri_t * uriP,
                            char * buffer,
                            int length)
{
    lwm2m_object_t * targetP;
    lwm2m_tlv_t * tlvP = NULL;
    int size = 0;
    uint8_t result;

    if (length == 0 || buffer == 0)
    {
        return BAD_REQUEST_4_00;
    }

    targetP = prv_find_object(contextP, uriP->objectId);
    if (NULL == targetP) return NOT_FOUND_4_04;
    if (NULL == targetP->createFunc) return METHOD_NOT_ALLOWED_4_05;

    if (LWM2M_URI_IS_SET_INSTANCE(uriP))
    {
        if (NULL != lwm2m_list_find(targetP->instanceList, uriP->instanceId))
        {
            // Instance already exists
            return COAP_406_NOT_ACCEPTABLE;
        }
    }
    else
    {
        uriP->instanceId = lwm2m_list_newId(targetP->instanceList);
        uriP->flag |= LWM2M_URI_FLAG_INSTANCE_ID;
    }

    targetP = prv_find_object(contextP, uriP->objectId);
    if (NULL == targetP) return NOT_FOUND_4_04;
    if (NULL == targetP->writeFunc) return METHOD_NOT_ALLOWED_4_05;

    size = lwm2m_tlv_parse(buffer, length, &tlvP);
    if (size == 0) return COAP_500_INTERNAL_SERVER_ERROR;

    result = targetP->createFunc(uriP->instanceId, size, tlvP, targetP);
    lwm2m_tlv_free(size, tlvP);

    return result;
}
예제 #3
0
파일: objects.c 프로젝트: mythfish/wakaama
coap_status_t object_write(lwm2m_context_t * contextP,
                           lwm2m_uri_t * uriP,
                           char * buffer,
                           int length)
{
    coap_status_t result;
    lwm2m_object_t * targetP;
    lwm2m_tlv_t * tlvP = NULL;
    int size = 0;

    targetP = prv_find_object(contextP, uriP->objectId);
    if (NULL == targetP) return NOT_FOUND_4_04;
    if (NULL == targetP->writeFunc) return METHOD_NOT_ALLOWED_4_05;

    if (LWM2M_URI_IS_SET_RESOURCE(uriP))
    {
        size = 1;
        tlvP = lwm2m_tlv_new(size);
        if (tlvP == NULL) return COAP_500_INTERNAL_SERVER_ERROR;

        tlvP->flags = LWM2M_TLV_FLAG_TEXT_FORMAT | LWM2M_TLV_FLAG_STATIC_DATA;
        tlvP->type = LWM2M_TYPE_RESSOURCE;
        tlvP->id = uriP->resourceId;
        tlvP->length = length;
        tlvP->value = buffer;
    }
    else
    {
        size = lwm2m_tlv_parse(buffer, length, &tlvP);
        if (size == 0) return COAP_500_INTERNAL_SERVER_ERROR;
    }
    result = targetP->writeFunc(uriP->instanceId, size, tlvP, targetP);
    lwm2m_tlv_free(size, tlvP);

    return result;
}
예제 #4
0
파일: decode.c 프로젝트: donatieng/wakaama
int main(int argc, char *argv[])
{
    lwm2m_tlv_t * tlvP;
    int size;
    int length;
    char * buffer;

    char buffer1[] = {0x03, 0x0A, 0xC1, 0x01, 0x14, 0x03, 0x0B, 0xC1, 0x01, 0x15, 0x03, 0x0C, 0xC1, 0x01, 0x16};
    char buffer2[] = {0xC8, 0x00, 0x14, 0x4F, 0x70, 0x65, 0x6E, 0x20, 0x4D, 0x6F, 0x62, 0x69, 0x6C, 0x65, 0x20,
                      0x41, 0x6C, 0x6C, 0x69, 0x61, 0x6E, 0x63, 0x65, 0xC8, 0x01, 0x16, 0x4C, 0x69, 0x67, 0x68,
                      0x74, 0x77 , 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x4D, 0x32, 0x4D, 0x20, 0x43, 0x6C, 0x69,
                      0x65, 0x6E, 0x74 , 0xC8, 0x02, 0x09, 0x33, 0x34, 0x35, 0x30, 0x30, 0x30, 0x31, 0x32, 0x33,
                      0xC3, 0x03, 0x31, 0x2E , 0x30, 0x86, 0x06, 0x41, 0x00, 0x01, 0x41, 0x01, 0x05, 0x88, 0x07,
                      0x08, 0x42, 0x00, 0x0E, 0xD8 , 0x42, 0x01, 0x13, 0x88, 0x87, 0x08, 0x41, 0x00, 0x7D, 0x42,
                      0x01, 0x03, 0x84, 0xC1, 0x09, 0x64 , 0xC1, 0x0A, 0x0F, 0x83, 0x0B, 0x41, 0x00, 0x00, 0xC4,
                      0x0D, 0x51, 0x82, 0x42, 0x8F, 0xC6, 0x0E, 0x2B, 0x30, 0x32, 0x3A, 0x30, 0x30, 0xC1, 0x0F, 0x55};

    printf("Buffer 1:\n");
    decode(buffer1, sizeof(buffer1), 0);
    printf("\n\nBuffer 1 using lwm2m_tlv_t:\n");
    size = lwm2m_tlv_parse(buffer1, sizeof(buffer1), &tlvP);
    dump_tlv(size, tlvP, 0);
    length = lwm2m_tlv_serialize(size, tlvP, &buffer);
    if (length != sizeof(buffer1))
    {
        printf("\n\nSerialize Buffer 1 failed: %d bytes instead of %d\n", length, sizeof(buffer1));
    }
    else if (memcmp(buffer, buffer1, length) != 0)
    {
        printf("\n\nSerialize Buffer 1 failed:\n");
        prv_output_buffer(buffer, length);
        printf("\ninstead of:\n");
        prv_output_buffer(buffer1, length);
    }
    else
    {
        printf("\n\nSerialize Buffer 1 OK\n");
    }
    lwm2m_tlv_free(size, tlvP);

    printf("\n\n============\n\nBuffer 2: \r\r\n");
    decode(buffer2, sizeof(buffer2), 0);
    printf("\n\nBuffer 2 using lwm2m_tlv_t: \r\r\n");
    size = lwm2m_tlv_parse(buffer2, sizeof(buffer2), &tlvP);
    dump_tlv(size, tlvP, 0);
    length = lwm2m_tlv_serialize(size, tlvP, &buffer);
    if (length != sizeof(buffer2))
    {
        printf("\n\nSerialize Buffer 2 failed: %d bytes instead of %d\n", length, sizeof(buffer2));
    }
    else if (memcmp(buffer, buffer2, length) != 0)
    {
        printf("\n\nSerialize Buffer 2 failed:\n");
        prv_output_buffer(buffer, length);
        printf("\ninstead of:\n");
        prv_output_buffer(buffer2, length);
    }
    else
    {
        printf("\n\nSerialize Buffer 2 OK\n\n");
    }
    lwm2m_tlv_free(size, tlvP);
}
예제 #5
0
static uint8_t prv_set_value(lwm2m_tlv_t * tlvP,
                             device_data_t * devDataP)
{
    // a simple switch structure is used to respond at the specified resource asked
    switch (tlvP->id)
    {
    case 0:
        tlvP->value = PRV_MANUFACTURER;
        tlvP->length = strlen(PRV_MANUFACTURER);
        tlvP->flags = LWM2M_TLV_FLAG_STATIC_DATA;
        tlvP->type = LWM2M_TYPE_RESSOURCE;
        return COAP_205_CONTENT;

    case 1:
        tlvP->value = PRV_MODEL_NUMBER;
        tlvP->length = strlen(PRV_MODEL_NUMBER);
        tlvP->flags = LWM2M_TLV_FLAG_STATIC_DATA;
        tlvP->type = LWM2M_TYPE_RESSOURCE;
        return COAP_205_CONTENT;

    case 2:
        tlvP->value = PRV_SERIAL_NUMBER;
        tlvP->length = strlen(PRV_SERIAL_NUMBER);
        tlvP->flags = LWM2M_TLV_FLAG_STATIC_DATA;
        tlvP->type = LWM2M_TYPE_RESSOURCE;
        return COAP_205_CONTENT;

    case 3:
        tlvP->value = PRV_FIRMWARE_VERSION;
        tlvP->length = strlen(PRV_FIRMWARE_VERSION);
        tlvP->flags = LWM2M_TLV_FLAG_STATIC_DATA;
        tlvP->type = LWM2M_TYPE_RESSOURCE;
        return COAP_205_CONTENT;

    case 4:
        return COAP_405_METHOD_NOT_ALLOWED;

    case 5:
        return COAP_405_METHOD_NOT_ALLOWED;

    case 6:
    {
        lwm2m_tlv_t * subTlvP;

        subTlvP = lwm2m_tlv_new(2);

        subTlvP[0].flags = 0;
        subTlvP[0].id = 0;
        subTlvP[0].type = LWM2M_TYPE_RESSOURCE_INSTANCE;
        lwm2m_tlv_encode_int(PRV_POWER_SOURCE_1, subTlvP);
        if (0 == subTlvP[0].length)
        {
            lwm2m_tlv_free(2, subTlvP);
            return COAP_500_INTERNAL_SERVER_ERROR;
        }

        subTlvP[1].flags = 0;
        subTlvP[1].id = 1;
        subTlvP[1].type = LWM2M_TYPE_RESSOURCE_INSTANCE;
        lwm2m_tlv_encode_int(PRV_POWER_SOURCE_2, subTlvP + 1);
        if (0 == subTlvP[1].length)
        {
            lwm2m_tlv_free(2, subTlvP);
            return COAP_500_INTERNAL_SERVER_ERROR;
        }

        tlvP->flags = 0;
        tlvP->type = LWM2M_TYPE_MULTIPLE_RESSOURCE;
        tlvP->length = 2;
        tlvP->value = (uint8_t *)subTlvP;

        return COAP_205_CONTENT;
    }

    case 7:
    {
        lwm2m_tlv_t * subTlvP;

        subTlvP = lwm2m_tlv_new(2);

        subTlvP[0].flags = 0;
        subTlvP[0].id = 0;
        subTlvP[0].type = LWM2M_TYPE_RESSOURCE_INSTANCE;
        lwm2m_tlv_encode_int(PRV_POWER_VOLTAGE_1, subTlvP);
        if (0 == subTlvP[0].length)
        {
            lwm2m_tlv_free(2, subTlvP);
            return COAP_500_INTERNAL_SERVER_ERROR;
        }

        subTlvP[1].flags = 0;
        subTlvP[1].id = 1;
        subTlvP[1].type = LWM2M_TYPE_RESSOURCE_INSTANCE;
        lwm2m_tlv_encode_int(PRV_POWER_VOLTAGE_2, subTlvP + 1);
        if (0 == subTlvP[1].length)
        {
            lwm2m_tlv_free(2, subTlvP);
            return COAP_500_INTERNAL_SERVER_ERROR;
        }

        tlvP->flags = 0;
        tlvP->type = LWM2M_TYPE_MULTIPLE_RESSOURCE;
        tlvP->length = 2;
        tlvP->value = (uint8_t *)subTlvP;

        return COAP_205_CONTENT;
    }

    case 8:
    {
        lwm2m_tlv_t * subTlvP;

        subTlvP = lwm2m_tlv_new(2);

        subTlvP[0].flags = 0;
        subTlvP[0].id = 0;
        subTlvP[0].type = LWM2M_TYPE_RESSOURCE_INSTANCE;
        lwm2m_tlv_encode_int(PRV_POWER_CURRENT_1, subTlvP);
        if (0 == subTlvP[0].length)
        {
            lwm2m_tlv_free(2, subTlvP);
            return COAP_500_INTERNAL_SERVER_ERROR;
        }

        subTlvP[1].flags = 0;
        subTlvP[1].id = 1;
        subTlvP[1].type = LWM2M_TYPE_RESSOURCE_INSTANCE;
        lwm2m_tlv_encode_int(PRV_POWER_CURRENT_2, subTlvP + 1);
        if (0 == subTlvP[1].length)
        {
            lwm2m_tlv_free(2, subTlvP);
            return COAP_500_INTERNAL_SERVER_ERROR;
        }

        tlvP->flags = 0;
        tlvP->type = LWM2M_TYPE_MULTIPLE_RESSOURCE;
        tlvP->length = 2;
        tlvP->value = (uint8_t *)subTlvP;

        return COAP_205_CONTENT;
    }

    case 9:
        lwm2m_tlv_encode_int(PRV_BATTERY_LEVEL, tlvP);
        tlvP->type = LWM2M_TYPE_RESSOURCE;

        if (0 != tlvP->length) return COAP_205_CONTENT;
        else return COAP_500_INTERNAL_SERVER_ERROR;

    case 10:
        lwm2m_tlv_encode_int(PRV_MEMORY_FREE, tlvP);
        tlvP->type = LWM2M_TYPE_RESSOURCE;

        if (0 != tlvP->length) return COAP_205_CONTENT;
        else return COAP_500_INTERNAL_SERVER_ERROR;

    case 11:
        lwm2m_tlv_encode_int(PRV_ERROR_CODE, tlvP);
        tlvP->type = LWM2M_TYPE_RESSOURCE;

        if (0 != tlvP->length) return COAP_205_CONTENT;
        else return COAP_500_INTERNAL_SERVER_ERROR;

    case 12:
        return COAP_405_METHOD_NOT_ALLOWED;

    case 13:
        lwm2m_tlv_encode_int(devDataP->time, tlvP);
        tlvP->type = LWM2M_TYPE_RESSOURCE;

        if (0 != tlvP->length) return COAP_205_CONTENT;
        else return COAP_500_INTERNAL_SERVER_ERROR;

    case 14:
        tlvP->value = devDataP->time_offset;
        tlvP->length = strlen(devDataP->time_offset);
        tlvP->flags = LWM2M_TLV_FLAG_STATIC_DATA;
        tlvP->type = LWM2M_TYPE_RESSOURCE;
        return COAP_205_CONTENT;

    case 15:
        tlvP->value = PRV_BINDING_MODE;
        tlvP->length = strlen(PRV_BINDING_MODE);
        tlvP->flags = LWM2M_TLV_FLAG_STATIC_DATA;
        tlvP->type = LWM2M_TYPE_RESSOURCE;
        return COAP_205_CONTENT;

    default:
        return COAP_404_NOT_FOUND;
    }
}
예제 #6
0
파일: objects.c 프로젝트: mythfish/wakaama
coap_status_t object_read(lwm2m_context_t * contextP,
                          lwm2m_uri_t * uriP,
                          char ** bufferP,
                          int * lengthP)
{
    coap_status_t result;
    lwm2m_object_t * targetP;
    lwm2m_tlv_t * tlvP = NULL;
    int size = 0;

    targetP = prv_find_object(contextP, uriP->objectId);
    if (NULL == targetP) return NOT_FOUND_4_04;
    if (NULL == targetP->readFunc) return METHOD_NOT_ALLOWED_4_05;
    if (targetP->instanceList == NULL)
    {
        // CDCC: Do not need to check the object instance for object which do not need register.
        // this is a single instance object
        if (targetP->needRegister && LWM2M_URI_IS_SET_INSTANCE(uriP) && (uriP->instanceId != 0))
        {
            return COAP_404_NOT_FOUND;
        }
    }
    else
    {
        if (LWM2M_URI_IS_SET_INSTANCE(uriP))
        {
            if (NULL == lwm2m_list_find(targetP->instanceList, uriP->instanceId))
            {
                return COAP_404_NOT_FOUND;
            }
        }
        else
        {
            // multiple object instances read
            lwm2m_list_t * instanceP;
            int i;

            size = 0;
            for (instanceP = targetP->instanceList; instanceP != NULL ; instanceP = instanceP->next)
            {
                size++;
            }

            tlvP = lwm2m_tlv_new(size);
            if (tlvP == NULL) return COAP_500_INTERNAL_SERVER_ERROR;

            result = COAP_205_CONTENT;
            instanceP = targetP->instanceList;
            i = 0;
            while (instanceP != NULL && result == COAP_205_CONTENT)
            {
                result = targetP->readFunc(instanceP->id, (int*)&(tlvP[i].length), (lwm2m_tlv_t **)&(tlvP[i].value), targetP);
                tlvP[i].type = LWM2M_TYPE_OBJECT_INSTANCE;
                tlvP[i].id = instanceP->id;
                i++;
                instanceP = instanceP->next;
            }

            if (result == COAP_205_CONTENT)
            {
                *lengthP = lwm2m_tlv_serialize(size, tlvP, bufferP);
                if (*lengthP == 0) result = COAP_500_INTERNAL_SERVER_ERROR;
            }
            lwm2m_tlv_free(size, tlvP);

            return result;
        }
    }

    // single instance read
    if (LWM2M_URI_IS_SET_RESOURCE(uriP))
    {
        size = 1;
        tlvP = lwm2m_tlv_new(size);
        if (tlvP == NULL) return COAP_500_INTERNAL_SERVER_ERROR;

        tlvP->type = LWM2M_TYPE_RESSOURCE;
        tlvP->flags = LWM2M_TLV_FLAG_TEXT_FORMAT;
        tlvP->id = uriP->resourceId;
    }
    result = targetP->readFunc(uriP->instanceId, &size, &tlvP, targetP);
    if (result == COAP_205_CONTENT)
    {
        if (size == 1
         && tlvP->type == LWM2M_TYPE_RESSOURCE
         && (tlvP->flags && LWM2M_TLV_FLAG_TEXT_FORMAT) != 0 )
        {
            *bufferP = (char *)malloc(tlvP->length);
            if (*bufferP == NULL)
            {
                result = COAP_500_INTERNAL_SERVER_ERROR;
            }
            else
            {
                memcpy(*bufferP, tlvP->value, tlvP->length);
                *lengthP = tlvP->length;
            }
        }
        else
        {
            *lengthP = lwm2m_tlv_serialize(size, tlvP, bufferP);
            if (*lengthP == 0) result = COAP_500_INTERNAL_SERVER_ERROR;
        }
    }
    lwm2m_tlv_free(size, tlvP);

    return result;
}
예제 #7
0
void handle_value_changed(lwm2m_context_t * lwm2mH,
                          lwm2m_uri_t * uri,
                          const char * value,
                          size_t valueLength)
{
    lwm2m_object_t * object = prv_find_object(lwm2mH, uri->objectId);

    if (NULL != object)
    {
        if (object->writeFunc != NULL)
        {
            lwm2m_tlv_t * tlvP;
            int result;
            
            tlvP = lwm2m_tlv_new(1);
            if (tlvP == NULL)
            {
                fprintf(stderr, "Internal allocation failure !\n");
                return;
            }
            tlvP->flags = LWM2M_TLV_FLAG_STATIC_DATA | LWM2M_TLV_FLAG_TEXT_FORMAT;
#ifdef LWM2M_BOOTSTRAP
            if (lwm2mH->bsState == BOOTSTRAP_PENDING) {
                tlvP->flags |= LWM2M_TLV_FLAG_BOOTSTRAPPING;
            }
#endif
            tlvP->id = uri->resourceId;
            tlvP->length = valueLength;
            tlvP->value = (uint8_t*) value;

            result = object->writeFunc(uri->instanceId, 1, tlvP, object);
            if (COAP_405_METHOD_NOT_ALLOWED == result)
            {
                switch (uri->objectId)
                {
                case LWM2M_DEVICE_OBJECT_ID:
                    result = device_change(tlvP, object);
                    break;
                default:
                    break;
                }
            }
            
            if (COAP_204_CHANGED != result)
            {
                fprintf(stderr, "Failed to change value!\n");
            }
            else
            {
                fprintf(stderr, "value changed!\n");
                lwm2m_resource_value_changed(lwm2mH, uri);
            }
            lwm2m_tlv_free(1, tlvP);
            return;
        }
        else
        {
            fprintf(stderr, "write not supported for specified resource!\n");
        }
        return;
    }
    else
    {
        fprintf(stderr, "Object not found !\n");
    }
}
예제 #8
0
static uint8_t prv_set_value(lwm2m_tlv_t * tlvP,
                             conn_m_data_t * connDataP)
{
    switch (tlvP->id)
    {
    case RES_M_NETWORK_BEARER:
        lwm2m_tlv_encode_int(VALUE_NETWORK_BEARER_GSM, tlvP);
        tlvP->type = LWM2M_TYPE_RESOURCE;
        if (0 != tlvP->length) return COAP_205_CONTENT ;
        else return COAP_500_INTERNAL_SERVER_ERROR ;
        break;

    case RES_M_AVL_NETWORK_BEARER:
    {
        int riCnt = 1;   // reduced to 1 instance to fit in one block size
        lwm2m_tlv_t * subTlvP;
        subTlvP = lwm2m_tlv_new(riCnt);
        subTlvP[0].flags = 0;
        subTlvP[0].id    = 0;
        subTlvP[0].type  = LWM2M_TYPE_RESOURCE_INSTANCE;
        lwm2m_tlv_encode_int(VALUE_AVL_NETWORK_BEARER_1, subTlvP);
        if (0 == subTlvP[0].length)
        {
            lwm2m_tlv_free(riCnt, subTlvP);
            return COAP_500_INTERNAL_SERVER_ERROR ;
        }
        lwm2m_tlv_include(subTlvP, riCnt, tlvP);
        return COAP_205_CONTENT ;
    }
        break;

    case RES_M_RADIO_SIGNAL_STRENGTH: //s-int
        lwm2m_tlv_encode_int(connDataP->signalStrength, tlvP);
        tlvP->type = LWM2M_TYPE_RESOURCE;
        if (0 != tlvP->length)
            return COAP_205_CONTENT ;
        else
            return COAP_500_INTERNAL_SERVER_ERROR ;
        break;

    case RES_O_LINK_QUALITY: //s-int
        lwm2m_tlv_encode_int(connDataP->linkQuality, tlvP);
        tlvP->type = LWM2M_TYPE_RESOURCE;
        if (0 != tlvP->length) return COAP_205_CONTENT ;
        else return COAP_500_INTERNAL_SERVER_ERROR ;
        break;

    case RES_M_IP_ADDRESSES:
    {
        int ri, riCnt = 1;   // reduced to 1 instance to fit in one block size
        lwm2m_tlv_t* subTlvP = lwm2m_tlv_new(riCnt);
        for (ri=0; ri<riCnt; ri++)
        {
            subTlvP[ri].flags  = LWM2M_TLV_FLAG_STATIC_DATA;
            subTlvP[ri].id     = 0;
            subTlvP[ri].type   = LWM2M_TYPE_RESOURCE_INSTANCE;
            subTlvP[ri].dataType = LWM2M_TYPE_STRING;
            subTlvP[ri].value  = (uint8_t*) connDataP->ipAddresses[ri];
            subTlvP[ri].length = strlen(connDataP->ipAddresses[ri]);
            if (subTlvP[ri].length == 0)
            {
                lwm2m_tlv_free(riCnt, subTlvP);
                return COAP_500_INTERNAL_SERVER_ERROR ;
            }
        }
        lwm2m_tlv_include(subTlvP, riCnt, tlvP);
        return COAP_205_CONTENT ;
    }
        break;

    case RES_O_ROUTER_IP_ADDRESS:
    {
        int ri, riCnt = 1;   // reduced to 1 instance to fit in one block size
        lwm2m_tlv_t* subTlvP = lwm2m_tlv_new(riCnt);
        for (ri=0; ri<riCnt; ri++)
        {
            subTlvP[ri].flags  = LWM2M_TLV_FLAG_STATIC_DATA;
            subTlvP[ri].id     = 0;
            subTlvP[ri].type   = LWM2M_TYPE_RESOURCE_INSTANCE;
            subTlvP[ri].dataType = LWM2M_TYPE_STRING;
            subTlvP[ri].value  = (uint8_t*) connDataP->routerIpAddresses[ri];
            subTlvP[ri].length = strlen(connDataP->routerIpAddresses[ri]);
            if (subTlvP[ri].length == 0)
            {
                lwm2m_tlv_free(riCnt, subTlvP);
                return COAP_500_INTERNAL_SERVER_ERROR ;
            }
        }
        lwm2m_tlv_include(subTlvP, riCnt, tlvP);
        return COAP_205_CONTENT ;
    }
        break;

    case RES_O_LINK_UTILIZATION:
        lwm2m_tlv_encode_int(connDataP->linkUtilization, tlvP);
        tlvP->type = LWM2M_TYPE_RESOURCE;
        if (0 != tlvP->length)
            return COAP_205_CONTENT ;
        else
            return COAP_500_INTERNAL_SERVER_ERROR ;
        break;

    case RES_O_APN:
    {
        int riCnt = 1;   // reduced to 1 instance to fit in one block size
        lwm2m_tlv_t * subTlvP;
        subTlvP = lwm2m_tlv_new(riCnt);
        subTlvP[0].flags  = LWM2M_TLV_FLAG_STATIC_DATA;
        subTlvP[0].id     = 0;
        subTlvP[0].type   = LWM2M_TYPE_RESOURCE_INSTANCE;
        subTlvP[0].dataType = LWM2M_TYPE_STRING;
        subTlvP[0].value  = (uint8_t*) VALUE_APN_1;
        subTlvP[0].length = strlen(VALUE_APN_1);
        if (0 == subTlvP[0].length)
        {
            lwm2m_tlv_free(riCnt, subTlvP);
            return COAP_500_INTERNAL_SERVER_ERROR ;
        }
        lwm2m_tlv_include(subTlvP, riCnt, tlvP);
        return COAP_205_CONTENT;
    }
        break;

    case RES_O_CELL_ID:
        lwm2m_tlv_encode_int(connDataP->cellId, tlvP);
        tlvP->type = LWM2M_TYPE_RESOURCE;
        if (0 != tlvP->length) return COAP_205_CONTENT ;
        else return COAP_500_INTERNAL_SERVER_ERROR ;
        break;

    case RES_O_SMNC:
        lwm2m_tlv_encode_int(VALUE_SMNC, tlvP);
        tlvP->type = LWM2M_TYPE_RESOURCE;
        if (0 != tlvP->length) return COAP_205_CONTENT ;
        else return COAP_500_INTERNAL_SERVER_ERROR ;
        break;

    case RES_O_SMCC:
        lwm2m_tlv_encode_int(VALUE_SMCC, tlvP);
        tlvP->type = LWM2M_TYPE_RESOURCE;
        if (0 != tlvP->length) return COAP_205_CONTENT ;
        else return COAP_500_INTERNAL_SERVER_ERROR ;
        break;

    default:
        return COAP_404_NOT_FOUND ;
    }
}