API Change: Modify object callbacks

Hide the TLV complexity from the objects.
Checks for instance existence is done in the core.
Also fixes some small bugs.

Signed-off-by: David Navarro <david.navarro@intel.com>
This commit is contained in:
David Navarro 2014-04-28 18:48:29 +02:00
parent 72fdc0a410
commit 59dad50bfc
9 changed files with 628 additions and 789 deletions

View File

@ -347,6 +347,7 @@ char * coap_get_multi_option_as_string(multi_option_t * option)
memmove(output + i, opt->data, opt->len);
i += opt->len;
}
output[i] = 0;
}
return output;
@ -683,13 +684,13 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
/* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */
// coap_merge_multi_option( (char **) &(coap_pkt->uri_path), &(coap_pkt->uri_path_len), current_option, option_length, 0);
coap_add_multi_option( &(coap_pkt->uri_path), current_option, option_length, 1);
PRINTF("Uri-Path [%.*s]\n", coap_pkt->uri_path_len, coap_pkt->uri_path);
PRINTF("Uri-Path [%.*s]\n", sizeof(multi_option_t), coap_pkt->uri_path);
break;
case COAP_OPTION_URI_QUERY:
/* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */
// coap_merge_multi_option( (char **) &(coap_pkt->uri_query), &(coap_pkt->uri_query_len), current_option, option_length, '&');
coap_add_multi_option( &(coap_pkt->uri_query), current_option, option_length, 1);
PRINTF("Uri-Query [%.*s]\n", coap_pkt->uri_query_len, coap_pkt->uri_query);
PRINTF("Uri-Query [%.*s]\n", sizeof(multi_option_t), coap_pkt->uri_query);
break;
case COAP_OPTION_LOCATION_PATH:

View File

@ -112,7 +112,6 @@ int lwm2m_boolToPlainText(bool data, char ** bufferP);
#define LWM2M_TYPE_MULTIPLE_RESSOURCE 0x01
#define LWM2M_TYPE_RESSOURCE_INSTANCE 0x02
#define LWM2M_TYPE_OBJECT_INSTANCE 0x03
#define LWM2M_TYPE_MASK 0x03
/*
* Bitmask for the lwm2m_tlv_t::flag
@ -146,6 +145,8 @@ int lwm2m_tlv_parse(char * buffer, size_t bufferLen, lwm2m_tlv_t ** dataP);
int lwm2m_tlv_serialize(int size, lwm2m_tlv_t * tlvP, char ** bufferP);
void lwm2m_tlv_free(int size, lwm2m_tlv_t * tlvP);
void lwm2m_tlv_encode_int(int64_t data, lwm2m_tlv_t * tlvP);
int lwm2m_tlv_decode_int(lwm2m_tlv_t * tlvP, int64_t * dataP);
/*
* These utility functions fill the buffer with a TLV record containing
@ -195,15 +196,19 @@ int lwm2m_stringToUri(char * buffer, size_t buffer_len, lwm2m_uri_t * uriP);
/*
* LWM2M Objects
*
* For the read callback, if *numDataP is not zero, *dataArrayP is pre-allocated
* and contains the list of resources to read.
*
*/
typedef struct _lwm2m_object_t lwm2m_object_t;
typedef uint8_t (*lwm2m_read_callback_t) (lwm2m_uri_t * uriP, char ** bufferP, int * lengthP, lwm2m_object_t * objectP);
typedef uint8_t (*lwm2m_write_callback_t) (lwm2m_uri_t * uriP, char * buffer, int length, lwm2m_object_t * objectP);
typedef uint8_t (*lwm2m_execute_callback_t) (lwm2m_uri_t * uriP, char * buffer, int length, lwm2m_object_t * objectP);
typedef uint8_t (*lwm2m_create_callback_t) (lwm2m_uri_t * uriP, char * buffer, int length, lwm2m_object_t * objectP);
typedef uint8_t (*lwm2m_delete_callback_t) (uint16_t id, lwm2m_object_t * objectP);
typedef uint8_t (*lwm2m_read_callback_t) (uint16_t instanceId, int * numDataP, lwm2m_tlv_t ** dataArrayP, lwm2m_object_t * objectP);
typedef uint8_t (*lwm2m_write_callback_t) (uint16_t instanceId, int numData, lwm2m_tlv_t * dataArray, lwm2m_object_t * objectP);
typedef uint8_t (*lwm2m_execute_callback_t) (uint16_t instanceId, uint16_t resourceId, char * buffer, int length, lwm2m_object_t * objectP);
typedef uint8_t (*lwm2m_create_callback_t) (uint16_t instanceId, int numData, lwm2m_tlv_t * dataArray, lwm2m_object_t * objectP);
typedef uint8_t (*lwm2m_delete_callback_t) (uint16_t instanceId, lwm2m_object_t * objectP);
typedef void (*lwm2m_close_callback_t) (lwm2m_object_t * objectP);

View File

@ -59,8 +59,8 @@ coap_status_t handle_dm_request(lwm2m_context_t * contextP,
result = object_create(contextP, uriP, message->payload, message->payload_len);
if (result == COAP_201_CREATED)
{
//longest uri is /65535/65535 =12 + 1 (null) chars
char location_path[12] = "";
//longest uri is /65535/65535 = 12 + 1 (null) chars
char location_path[13] = "";
//instanceId expected
if ((uriP->flag & LWM2M_URI_FLAG_INSTANCE_ID) == 0)
{

View File

@ -48,32 +48,122 @@ coap_status_t object_read(lwm2m_context_t * contextP,
char ** bufferP,
int * lengthP)
{
coap_status_t result;
switch (uriP->objectId)
{
case LWM2M_SECURITY_OBJECT_ID:
return NOT_FOUND_4_04;
result = NOT_FOUND_4_04;
break;
case LWM2M_SERVER_OBJECT_ID:
return object_server_read(contextP, uriP, bufferP, lengthP);
result = object_server_read(contextP, uriP, bufferP, lengthP);
break;
default:
{
lwm2m_object_t * targetP;
lwm2m_tlv_t * tlvP = NULL;
int size = 0;
targetP = prv_find_object(contextP, uriP->objectId);
if (NULL == targetP)
if (NULL == targetP) return NOT_FOUND_4_04;
if (NULL == targetP->readFunc) return METHOD_NOT_ALLOWED_4_05;
if (targetP->instanceList == NULL)
{
return NOT_FOUND_4_04;
// this is a single instance object
if (LWM2M_URI_IS_SET_INSTANCE(uriP) && (uriP->instanceId != 0))
{
return COAP_404_NOT_FOUND;
}
}
if (NULL == targetP->readFunc)
else
{
return METHOD_NOT_ALLOWED_4_05;
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;
}
}
return targetP->readFunc(uriP, bufferP, lengthP, targetP);
// 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;
}
coap_status_t object_write(lwm2m_context_t * contextP,
@ -81,32 +171,51 @@ coap_status_t object_write(lwm2m_context_t * contextP,
char * buffer,
int length)
{
coap_status_t result;
switch (uriP->objectId)
{
case LWM2M_SECURITY_OBJECT_ID:
return NOT_FOUND_4_04;
result = NOT_FOUND_4_04;
break;
case LWM2M_SERVER_OBJECT_ID:
return object_server_write(contextP, uriP, buffer, length);
result = object_server_write(contextP, uriP, buffer, length);
break;
default:
{
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 (NULL == targetP)
if (LWM2M_URI_IS_SET_RESOURCE(uriP))
{
return NOT_FOUND_4_04;
}
if (NULL == targetP->writeFunc)
{
return METHOD_NOT_ALLOWED_4_05;
}
size = 1;
tlvP = lwm2m_tlv_new(size);
if (tlvP == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
return targetP->writeFunc(uriP, buffer, length, targetP);
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;
}
coap_status_t object_execute(lwm2m_context_t * contextP,
@ -127,18 +236,10 @@ coap_status_t object_execute(lwm2m_context_t * contextP,
lwm2m_object_t * targetP;
targetP = prv_find_object(contextP, uriP->objectId);
if (NULL == targetP) return NOT_FOUND_4_04;
if (NULL == targetP->executeFunc) return METHOD_NOT_ALLOWED_4_05;
if (NULL == targetP)
{
return NOT_FOUND_4_04;
}
if (NULL == targetP->executeFunc)
{
return METHOD_NOT_ALLOWED_4_05;
}
return targetP->executeFunc(uriP, buffer, length, targetP);
return targetP->executeFunc(uriP->instanceId, uriP->resourceId, buffer, length, targetP);
}
}
}
@ -164,20 +265,39 @@ coap_status_t object_create(lwm2m_context_t * contextP,
default:
{
lwm2m_object_t * targetP;
lwm2m_tlv_t * tlvP = NULL;
int size = 0;
uint8_t result;
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 (NULL == targetP)
if (LWM2M_URI_IS_SET_INSTANCE(uriP))
{
return NOT_FOUND_4_04;
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;
}
if (NULL == targetP->createFunc)
{
return METHOD_NOT_ALLOWED_4_05;
}
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;
return targetP->createFunc(uriP, buffer, length, targetP);
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;
}
}
}
@ -198,15 +318,8 @@ coap_status_t object_delete(lwm2m_context_t * contextP,
lwm2m_object_t * targetP;
targetP = prv_find_object(contextP, uriP->objectId);
if (NULL == targetP)
{
return NOT_FOUND_4_04;
}
if (NULL == targetP->deleteFunc)
{
return METHOD_NOT_ALLOWED_4_05;
}
if (NULL == targetP) return NOT_FOUND_4_04;
if (NULL == targetP->deleteFunc) return METHOD_NOT_ALLOWED_4_05;
return targetP->deleteFunc(uriP->instanceId, targetP);
}

View File

@ -248,7 +248,7 @@ void lwm2m_resource_value_changed(lwm2m_context_t * contextP,
{
coap_packet_t message[1];
coap_init_message(message, COAP_TYPE_ACK, COAP_204_CHANGED, 0);
coap_init_message(message, COAP_TYPE_NON, COAP_204_CHANGED, 0);
coap_set_payload(message, buffer, length);
for (watcherP = listP->item->watcherList ; watcherP != NULL ; watcherP = watcherP->next)

View File

@ -156,26 +156,43 @@ static void prv_change(char * buffer,
{
if (lwm2mH->objectList[i]->writeFunc != NULL)
{
if (COAP_204_CHANGED == lwm2mH->objectList[i]->writeFunc(&uri,
buffer, strlen(buffer),
lwm2mH->objectList[i]))
lwm2m_tlv_t * tlvP;
tlvP = lwm2m_tlv_new(1);
if (tlvP == NULL)
{
lwm2m_resource_value_changed(lwm2mH, &uri);
fprintf(stdout, "Internal allocation failure !\n");
return;
}
tlvP->flags = LWM2M_TLV_FLAG_STATIC_DATA | LWM2M_TLV_FLAG_TEXT_FORMAT;
tlvP->id = uri.resourceId;
tlvP->length = strlen(buffer);
tlvP->value = buffer;
if (COAP_204_CHANGED != lwm2mH->objectList[i]->writeFunc(uri.instanceId,
1, tlvP,
lwm2mH->objectList[i]))
{
fprintf(stdout, "Failed to change value !\n");
}
else
{
lwm2m_resource_value_changed(lwm2mH, &uri);
}
lwm2m_tlv_free(1, tlvP);
return;
}
fprintf(stdout, "Failed to change value !");
return;
}
i++;
}
fprintf(stdout, "Object not found !");
fprintf(stdout, "Object not found !\n");
}
return;
syntax_error:
fprintf(stdout, "Syntax error !");
fprintf(stdout, "Syntax error !\n");
}
int main(int argc, char *argv[])

View File

@ -49,7 +49,6 @@
#define PRV_OFFSET_MAXLEN 7 //+HH:MM\0 at max
#define PRV_TLV_BUFFER_SIZE 128
typedef struct
{
int64_t time;
@ -57,43 +56,6 @@ typedef struct
} device_data_t;
static void prv_output_buffer(uint8_t * buffer,
int length)
{
int i;
uint8_t array[16];
i = 0;
while (i < length)
{
int j;
fprintf(stderr, " ");
memcpy(array, buffer+i, 16);
for (j = 0 ; j < 16 && i+j < length; j++)
{
fprintf(stderr, "%02X ", array[j]);
}
while (j < 16)
{
fprintf(stderr, " ");
j++;
}
fprintf(stderr, " ");
for (j = 0 ; j < 16 && i+j < length; j++)
{
if (isprint(array[j]))
fprintf(stderr, "%c ", array[j]);
else
fprintf(stderr, ". ");
}
fprintf(stderr, "\n");
i += 16;
}
}
// basic check that the time offset value is at ISO 8601 format
// bug: +12:30 is considered a valid value by this function
static int prv_check_time_offset(char * buffer,
@ -135,427 +97,306 @@ static int prv_check_time_offset(char * buffer,
return 1;
}
static int prv_get_object_tlv(char ** bufferP,
device_data_t* dataP)
static uint8_t prv_set_value(lwm2m_tlv_t * tlvP,
device_data_t * devDataP)
{
int length = 0;
int result;
char temp_buffer[16];
int temp_length;
// 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;
*bufferP = (uint8_t *)malloc(PRV_TLV_BUFFER_SIZE);
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;
if (NULL == *bufferP) return 0;
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;
result = lwm2m_opaqueToTLV(TLV_RESSOURCE,
PRV_MANUFACTURER, strlen(PRV_MANUFACTURER),
0,
*bufferP + length, PRV_TLV_BUFFER_SIZE - length);
if (0 == result) goto error;
length += result;
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;
result = lwm2m_opaqueToTLV(TLV_RESSOURCE,
PRV_MODEL_NUMBER, strlen(PRV_MODEL_NUMBER),
1,
*bufferP + length, PRV_TLV_BUFFER_SIZE - length);
if (0 == result) goto error;
length += result;
case 4:
return COAP_405_METHOD_NOT_ALLOWED;
result = lwm2m_opaqueToTLV(TLV_RESSOURCE,
PRV_SERIAL_NUMBER, strlen(PRV_SERIAL_NUMBER),
2,
*bufferP + length, PRV_TLV_BUFFER_SIZE - length);
if (0 == result) goto error;
length += result;
case 5:
return COAP_405_METHOD_NOT_ALLOWED;
result = lwm2m_opaqueToTLV(TLV_RESSOURCE,
PRV_FIRMWARE_VERSION, strlen(PRV_FIRMWARE_VERSION),
3,
*bufferP + length, PRV_TLV_BUFFER_SIZE - length);
if (0 == result) goto error;
length += result;
case 6:
{
lwm2m_tlv_t * subTlvP;
subTlvP = lwm2m_tlv_new(2);
result = lwm2m_intToTLV(TLV_RESSOURCE_INSTANCE, PRV_POWER_SOURCE_1, 0, temp_buffer, 16);
if (0 == result) goto error;
temp_length = result;
result = lwm2m_intToTLV(TLV_RESSOURCE_INSTANCE, PRV_POWER_SOURCE_2, 1, temp_buffer+result, 16-result);
if (0 == result) goto error;
temp_length += result;
result = lwm2m_opaqueToTLV(TLV_MULTIPLE_INSTANCE,
temp_buffer, temp_length,
6,
*bufferP + length, PRV_TLV_BUFFER_SIZE - length);
if (0 == result) goto error;
length += result;
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;
}
result = lwm2m_intToTLV(TLV_RESSOURCE_INSTANCE, PRV_POWER_VOLTAGE_1, 0, temp_buffer, 16);
if (0 == result) goto error;
temp_length = result;
result = lwm2m_intToTLV(TLV_RESSOURCE_INSTANCE, PRV_POWER_VOLTAGE_2, 1, temp_buffer+result, 16-result);
if (0 == result) goto error;
temp_length += result;
result = lwm2m_opaqueToTLV(TLV_MULTIPLE_INSTANCE,
temp_buffer, temp_length,
7,
*bufferP + length, PRV_TLV_BUFFER_SIZE - length);
if (0 == result) goto error;
length += result;
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;
}
result = lwm2m_intToTLV(TLV_RESSOURCE_INSTANCE, PRV_POWER_CURRENT_1, 0, temp_buffer, 16);
if (0 == result) goto error;
temp_length = result;
result = lwm2m_intToTLV(TLV_RESSOURCE_INSTANCE, PRV_POWER_CURRENT_2, 1, temp_buffer+result, 16-result);
if (0 == result) goto error;
temp_length += result;
result = lwm2m_opaqueToTLV(TLV_MULTIPLE_INSTANCE,
temp_buffer, temp_length,
8,
*bufferP + length, PRV_TLV_BUFFER_SIZE - length);
if (0 == result) goto error;
length += result;
tlvP->flags = 0;
tlvP->type = LWM2M_TYPE_MULTIPLE_RESSOURCE;
tlvP->length = 2;
tlvP->value = (uint8_t *)subTlvP;
result = lwm2m_intToTLV(TLV_RESSOURCE,
PRV_BATTERY_LEVEL,
9,
*bufferP + length, PRV_TLV_BUFFER_SIZE - length);
if (0 == result) goto error;
length += result;
return COAP_205_CONTENT;
}
result = lwm2m_intToTLV(TLV_RESSOURCE,
PRV_MEMORY_FREE,
10,
*bufferP + length, PRV_TLV_BUFFER_SIZE - length);
if (0 == result) goto error;
length += result;
case 7:
{
lwm2m_tlv_t * subTlvP;
result = lwm2m_intToTLV(TLV_RESSOURCE_INSTANCE, PRV_ERROR_CODE, 0, temp_buffer, 16);
if (0 == result) goto error;
temp_length = result;
result = lwm2m_opaqueToTLV(TLV_MULTIPLE_INSTANCE,
temp_buffer, temp_length,
11,
*bufferP + length, PRV_TLV_BUFFER_SIZE - length);
if (0 == result) goto error;
length += result;
subTlvP = lwm2m_tlv_new(2);
result = lwm2m_intToTLV(TLV_RESSOURCE,
dataP->time,
13,
*bufferP + length, PRV_TLV_BUFFER_SIZE - length);
if (0 == result) goto error;
length += result;
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;
}
result = lwm2m_opaqueToTLV(TLV_RESSOURCE,
dataP->time_offset, strlen(dataP->time_offset),
14,
*bufferP + length, PRV_TLV_BUFFER_SIZE - length);
if (0 == result) goto error;
length += result;
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;
}
result = lwm2m_opaqueToTLV(TLV_RESSOURCE,
PRV_BINDING_MODE, strlen(PRV_BINDING_MODE),
15,
*bufferP + length, PRV_TLV_BUFFER_SIZE - length);
if (0 == result) goto error;
length += result;
tlvP->flags = 0;
tlvP->type = LWM2M_TYPE_MULTIPLE_RESSOURCE;
tlvP->length = 2;
tlvP->value = (uint8_t *)subTlvP;
fprintf(stderr, "TLV (%d bytes):\r\n", length);
prv_output_buffer(*bufferP, length);
return COAP_205_CONTENT;
}
return length;
case 8:
{
lwm2m_tlv_t * subTlvP;
error:
fprintf(stderr, "TLV generation failed:\r\n");
free(*bufferP);
*bufferP = NULL;
return 0;
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;
}
}
static uint8_t prv_device_read(lwm2m_uri_t * uriP,
char ** bufferP,
int * lengthP,
static uint8_t prv_device_read(uint16_t instanceId,
int * numDataP,
lwm2m_tlv_t ** dataArrayP,
lwm2m_object_t * objectP)
{
*bufferP = NULL;
*lengthP = 0;
uint8_t result;
int i;
// this is a single instance object
if (LWM2M_URI_IS_SET_INSTANCE(uriP) && uriP->instanceId != 0)
if (instanceId != 0)
{
return COAP_404_NOT_FOUND;
}
// is the server asking for the full object ?
if (!LWM2M_URI_IS_SET_RESOURCE(uriP))
if (*numDataP == 0)
{
*lengthP = prv_get_object_tlv(bufferP, (device_data_t*)(objectP->userData));
if (0 != *lengthP)
uint16_t resList[] = {0, 1, 2, 3, 6, 7, 8, 9, 10, 11, 13, 14, 15};
int nbRes = sizeof(resList)/sizeof(uint16_t);
*dataArrayP = lwm2m_tlv_new(nbRes);
if (*dataArrayP == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
*numDataP = nbRes;
for (i = 0 ; i < nbRes ; i++)
{
return COAP_205_CONTENT;
}
else
{
return COAP_500_INTERNAL_SERVER_ERROR;
(*dataArrayP)[i].id = resList[i];
}
}
// else a simple switch structure is used to respond at the specified resource asked
switch (uriP->resourceId)
i = 0;
do
{
case 0:
*bufferP = strdup(PRV_MANUFACTURER);
if (NULL != *bufferP)
{
*lengthP = strlen(*bufferP);
return COAP_205_CONTENT;
}
else
{
return COAP_500_INTERNAL_SERVER_ERROR;
}
case 1:
*bufferP = strdup(PRV_MODEL_NUMBER);
if (NULL != *bufferP)
{
*lengthP = strlen(*bufferP);
return COAP_205_CONTENT;
}
else
{
return COAP_500_INTERNAL_SERVER_ERROR;
}
case 2:
*bufferP = strdup(PRV_SERIAL_NUMBER);
if (NULL != *bufferP)
{
*lengthP = strlen(*bufferP);
return COAP_205_CONTENT;
}
else
{
return COAP_500_INTERNAL_SERVER_ERROR;
}
case 3:
*bufferP = strdup(PRV_FIRMWARE_VERSION);
if (NULL != *bufferP)
{
*lengthP = strlen(*bufferP);
return COAP_205_CONTENT;
}
else
{
return COAP_500_INTERNAL_SERVER_ERROR;
}
case 4:
return COAP_405_METHOD_NOT_ALLOWED;
case 5:
return COAP_405_METHOD_NOT_ALLOWED;
case 6:
{
char buffer1[16];
char buffer2[16];
int result;
int instance_length;
result = lwm2m_intToTLV(TLV_RESSOURCE_INSTANCE, PRV_POWER_SOURCE_1, 0, buffer1, 16);
if (0 == result) return COAP_500_INTERNAL_SERVER_ERROR;
instance_length = result;
result = lwm2m_intToTLV(TLV_RESSOURCE_INSTANCE, PRV_POWER_SOURCE_2, 1, buffer1+result, 16-result);
if (0 == result) return COAP_500_INTERNAL_SERVER_ERROR;
instance_length += result;
*lengthP = lwm2m_opaqueToTLV(TLV_MULTIPLE_INSTANCE, buffer1, instance_length, 6, buffer2, 16);
if (0 == *lengthP) return COAP_500_INTERNAL_SERVER_ERROR;
*bufferP = (char *)malloc(*lengthP);
if (NULL == *bufferP) return COAP_500_INTERNAL_SERVER_ERROR;
memmove(*bufferP, buffer2, *lengthP);
fprintf(stderr, "TLV (%d bytes):\r\n", *lengthP);
prv_output_buffer(*bufferP, *lengthP);
return COAP_205_CONTENT;
}
case 7:
{
char buffer1[16];
char buffer2[16];
int result;
int instance_length;
result = lwm2m_intToTLV(TLV_RESSOURCE_INSTANCE, PRV_POWER_VOLTAGE_1, 0, buffer1, 16);
if (0 == result) return COAP_500_INTERNAL_SERVER_ERROR;
instance_length = result;
result = lwm2m_intToTLV(TLV_RESSOURCE_INSTANCE, PRV_POWER_VOLTAGE_2, 1, buffer1+result, 16-result);
if (0 == result) return COAP_500_INTERNAL_SERVER_ERROR;
instance_length += result;
*lengthP = lwm2m_opaqueToTLV(TLV_MULTIPLE_INSTANCE, buffer1, instance_length, 7, buffer2, 16);
if (0 == *lengthP) return COAP_500_INTERNAL_SERVER_ERROR;
*bufferP = (char *)malloc(*lengthP);
if (NULL == *bufferP) return COAP_500_INTERNAL_SERVER_ERROR;
memmove(*bufferP, buffer2, *lengthP);
fprintf(stderr, "TLV (%d bytes):\r\n", *lengthP);
prv_output_buffer(*bufferP, *lengthP);
return COAP_205_CONTENT;
}
case 8:
{
char buffer1[16];
char buffer2[16];
int result;
int instance_length;
result = lwm2m_intToTLV(TLV_RESSOURCE_INSTANCE, PRV_POWER_CURRENT_1, 0, buffer1, 16);
if (0 == result) return COAP_500_INTERNAL_SERVER_ERROR;
instance_length = result;
result = lwm2m_intToTLV(TLV_RESSOURCE_INSTANCE, PRV_POWER_CURRENT_2, 1, buffer1+result, 16-result);
if (0 == result) return COAP_500_INTERNAL_SERVER_ERROR;
instance_length += result;
*lengthP = lwm2m_opaqueToTLV(TLV_MULTIPLE_INSTANCE, buffer1, instance_length, 8, buffer2, 16);
if (0 == *lengthP) return COAP_500_INTERNAL_SERVER_ERROR;
*bufferP = (char *)malloc(*lengthP);
if (NULL == *bufferP) return COAP_500_INTERNAL_SERVER_ERROR;
memmove(*bufferP, buffer2, *lengthP);
fprintf(stderr, "TLV (%d bytes):\r\n", *lengthP);
prv_output_buffer(*bufferP, *lengthP);
return COAP_205_CONTENT;
}
case 9:
*lengthP = lwm2m_int8ToPlainText(PRV_BATTERY_LEVEL, bufferP);
if (0 != *lengthP)
{
return COAP_205_CONTENT;
}
else
{
return COAP_500_INTERNAL_SERVER_ERROR;
}
case 10:
*lengthP = lwm2m_int8ToPlainText(PRV_MEMORY_FREE, bufferP);
if (0 != *lengthP)
{
return COAP_205_CONTENT;
}
else
{
return COAP_500_INTERNAL_SERVER_ERROR;
}
case 11:
*lengthP = lwm2m_int8ToPlainText(PRV_ERROR_CODE, bufferP);
if (0 != *lengthP)
{
return COAP_205_CONTENT;
}
else
{
return COAP_500_INTERNAL_SERVER_ERROR;
}
case 12:
return COAP_405_METHOD_NOT_ALLOWED;
case 13:
*lengthP = lwm2m_int64ToPlainText(((device_data_t*)(objectP->userData))->time, bufferP);
if (0 != *lengthP)
{
return COAP_205_CONTENT;
}
else
{
return COAP_500_INTERNAL_SERVER_ERROR;
}
case 14:
*bufferP = strdup(((device_data_t*)(objectP->userData))->time_offset);
if (NULL != *bufferP)
{
*lengthP = strlen(*bufferP);
return COAP_205_CONTENT;
}
else
{
return COAP_500_INTERNAL_SERVER_ERROR;
}
case 15:
*bufferP = strdup(PRV_BINDING_MODE);
if (NULL != *bufferP)
{
*lengthP = strlen(*bufferP);
return COAP_205_CONTENT;
}
else
{
return COAP_500_INTERNAL_SERVER_ERROR;
}
default:
return COAP_404_NOT_FOUND;
}
result = prv_set_value((*dataArrayP) + i, (device_data_t*)(objectP->userData));
i++;
} while (i < *numDataP && result == COAP_205_CONTENT);
return result;
}
static uint8_t prv_device_write(lwm2m_uri_t * uriP,
char * buffer,
int length,
static uint8_t prv_device_write(uint16_t instanceId,
int numData,
lwm2m_tlv_t * dataArray,
lwm2m_object_t * objectP)
{
int i;
uint8_t result;
// this is a single instance object
if (LWM2M_URI_IS_SET_INSTANCE(uriP) && uriP->instanceId != 0)
if (instanceId != 0)
{
return COAP_404_NOT_FOUND;
}
if (!LWM2M_URI_IS_SET_RESOURCE(uriP)) return COAP_501_NOT_IMPLEMENTED;
i = 0;
switch (uriP->resourceId)
do
{
case 13:
if (1 == lwm2m_PlainTextToInt64(buffer, length, &((device_data_t*)(objectP->userData))->time))
switch (dataArray[i].id)
{
return COAP_204_CHANGED;
case 13:
if (1 == lwm2m_tlv_decode_int(dataArray + i, &((device_data_t*)(objectP->userData))->time))
{
result = COAP_204_CHANGED;
}
else
{
result = COAP_400_BAD_REQUEST;
}
break;
case 14:
if (1 == prv_check_time_offset(dataArray[i].value, dataArray[i].length))
{
strncpy(((device_data_t*)(objectP->userData))->time_offset, dataArray[i].value, dataArray[i].length);
((device_data_t*)(objectP->userData))->time_offset[dataArray[i].length] = 0;
result = COAP_204_CHANGED;
}
else
{
result = COAP_400_BAD_REQUEST;
}
break;
default:
result = COAP_405_METHOD_NOT_ALLOWED;
}
else
{
return COAP_400_BAD_REQUEST;
}
case 14:
if (1 == prv_check_time_offset(buffer, length))
{
strncpy(((device_data_t*)(objectP->userData))->time_offset, buffer, length);
((device_data_t*)(objectP->userData))->time_offset[length] = 0;
return COAP_204_CHANGED;
}
else
{
return COAP_400_BAD_REQUEST;
}
default:
return COAP_405_METHOD_NOT_ALLOWED;
}
i++;
} while (i < numData && result == COAP_204_CHANGED);
return result;
}
static uint8_t prv_device_execute(lwm2m_uri_t * uriP,
static uint8_t prv_device_execute(uint16_t instanceId,
uint16_t resourceId,
char * buffer,
int length,
lwm2m_object_t * objectP)
{
// this is a single instance object
if (LWM2M_URI_IS_SET_INSTANCE(uriP) && uriP->instanceId != 0)
if (instanceId != 0)
{
return COAP_404_NOT_FOUND;
}
if (length != 0) return COAP_400_BAD_REQUEST;
// for execute callback, resId is always set.
switch (uriP->resourceId)
switch (resourceId)
{
case 4:
fprintf(stdout, "\n\t REBOOT\r\n\n");

View File

@ -50,216 +50,161 @@ typedef struct
} firmware_data_t;
static void prv_output_buffer(uint8_t * buffer,
int length)
static uint8_t prv_firmware_read(uint16_t instanceId,
int * numDataP,
lwm2m_tlv_t ** dataArrayP,
lwm2m_object_t * objectP)
{
int i;
uint8_t array[16];
i = 0;
while (i < length)
{
int j;
fprintf(stderr, " ");
memcpy(array, buffer+i, 16);
for (j = 0 ; j < 16 && i+j < length; j++)
{
fprintf(stderr, "%02X ", array[j]);
}
while (j < 16)
{
fprintf(stderr, " ");
j++;
}
fprintf(stderr, " ");
for (j = 0 ; j < 16 && i+j < length; j++)
{
if (isprint(array[j]))
fprintf(stderr, "%c ", array[j]);
else
fprintf(stderr, ". ");
}
fprintf(stderr, "\n");
i += 16;
}
}
static int prv_get_object_tlv(char ** bufferP,
firmware_data_t* dataP)
{
int length = 0;
int result;
*bufferP = (uint8_t *)malloc(PRV_TLV_BUFFER_SIZE);
if (NULL == *bufferP) return 0;
result = lwm2m_intToTLV(TLV_RESSOURCE, dataP->state, 3, *bufferP, PRV_TLV_BUFFER_SIZE);
if (0 == result) goto error;
length += result;
result = lwm2m_boolToTLV(TLV_RESSOURCE, dataP->supported, 4, *bufferP + length, PRV_TLV_BUFFER_SIZE - length);
if (0 == result) goto error;
length += result;
result = lwm2m_intToTLV(TLV_RESSOURCE, dataP->result, 5, *bufferP + length, PRV_TLV_BUFFER_SIZE - length);
if (0 == result) goto error;
length += result;
fprintf(stderr, "TLV (%d bytes):\r\n", length);
prv_output_buffer(*bufferP, length);
return length;
error:
fprintf(stderr, "TLV generation failed:\r\n");
free(*bufferP);
*bufferP = NULL;
return 0;
}
static uint8_t prv_firmware_read(lwm2m_uri_t * uriP,
char ** bufferP,
int * lengthP,
lwm2m_object_t * objectP)
{
*bufferP = NULL;
*lengthP = 0;
uint8_t result;
firmware_data_t * data = (firmware_data_t*)(objectP->userData);
// this is a single instance object
if (LWM2M_URI_IS_SET_INSTANCE(uriP) && uriP->instanceId != 0)
if (instanceId != 0)
{
return COAP_404_NOT_FOUND;
}
// is the server asking for the full object ?
if (!LWM2M_URI_IS_SET_RESOURCE(uriP))
if (*numDataP == 0)
{
*lengthP = prv_get_object_tlv(bufferP, (firmware_data_t*)(objectP->userData));
if (0 != *lengthP)
{
return COAP_205_CONTENT;
}
else
{
return COAP_500_INTERNAL_SERVER_ERROR;
}
}
// else a simple switch structure is used to respond at the specified resource asked
switch (uriP->resourceId)
{
case 0:
return COAP_405_METHOD_NOT_ALLOWED;
case 1:
return COAP_405_METHOD_NOT_ALLOWED;
case 2:
return COAP_405_METHOD_NOT_ALLOWED;
case 3:
// firmware update state (int)
*lengthP = lwm2m_int8ToPlainText(data->state, bufferP);
if (0 != *lengthP)
{
return COAP_205_CONTENT;
}
else
{
return COAP_500_INTERNAL_SERVER_ERROR;
}
case 4:
*lengthP = lwm2m_int8ToPlainText(data->supported, bufferP);
if (0 != *lengthP)
{
return COAP_205_CONTENT;
}
else
{
return COAP_500_INTERNAL_SERVER_ERROR;
}
case 5:
*lengthP = lwm2m_int8ToPlainText(data->result, bufferP);
if (0 != *lengthP)
{
return COAP_205_CONTENT;
}
else
{
return COAP_500_INTERNAL_SERVER_ERROR;
}
default:
return COAP_404_NOT_FOUND;
uint16_t resList[] = {0, 1, 2, 3, 6, 7, 8, 9, 10, 11, 13, 14, 15};
int nbRes = sizeof(resList)/sizeof(uint16_t);
*dataArrayP = lwm2m_tlv_new(3);
if (*dataArrayP == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
*numDataP = 3;
(*dataArrayP)[0].id = 3;
(*dataArrayP)[1].id = 4;
(*dataArrayP)[2].id = 5;
}
i = 0;
do
{
switch ((*dataArrayP)[i].id)
{
case 0:
case 1:
case 2:
result = COAP_405_METHOD_NOT_ALLOWED;
break;
case 3:
// firmware update state (int)
lwm2m_tlv_encode_int(data->state, *dataArrayP + i);
(*dataArrayP)[i].type = LWM2M_TYPE_RESSOURCE;
if (0 != (*dataArrayP)[i].length) result = COAP_205_CONTENT;
else result = COAP_500_INTERNAL_SERVER_ERROR;
break;
case 4:
lwm2m_tlv_encode_int(data->supported, *dataArrayP + i);
(*dataArrayP)[i].type = LWM2M_TYPE_RESSOURCE;
if (0 != (*dataArrayP)[i].length) result = COAP_205_CONTENT;
else result = COAP_500_INTERNAL_SERVER_ERROR;
break;
case 5:
lwm2m_tlv_encode_int(data->result, *dataArrayP + i);
(*dataArrayP)[i].type = LWM2M_TYPE_RESSOURCE;
if (0 != (*dataArrayP)[i].length) result = COAP_205_CONTENT;
else result = COAP_500_INTERNAL_SERVER_ERROR;
break;
default:
result = COAP_404_NOT_FOUND;
}
i++;
} while (i < *numDataP && result == COAP_205_CONTENT);
return result;
}
static uint8_t prv_firmware_write(lwm2m_uri_t * uriP,
char * buffer,
int length,
lwm2m_object_t * objectP)
{
// this is a single instance object
if (LWM2M_URI_IS_SET_INSTANCE(uriP) && uriP->instanceId != 0)
{
return COAP_404_NOT_FOUND;
}
if (!LWM2M_URI_IS_SET_RESOURCE(uriP)) return COAP_501_NOT_IMPLEMENTED;
firmware_data_t * data = (firmware_data_t*)(objectP->userData);
switch (uriP->resourceId)
{
case 0:
// inline firmware binary
return COAP_204_CHANGED;
case 1:
// URL for download the firmware
return COAP_204_CHANGED;
case 4:
if (1 == length && buffer[0] == '0')
{
data->supported = 0;
return COAP_204_CHANGED;
}
else if (1 == length && buffer[0] == '1')
{
data->supported = 1;
return COAP_204_CHANGED;
}
else
{
return COAP_400_BAD_REQUEST;
}
default:
return COAP_405_METHOD_NOT_ALLOWED;
}
}
static uint8_t prv_firmware_execute(lwm2m_uri_t * uriP,
char * buffer,
int length,
static uint8_t prv_firmware_write(uint16_t instanceId,
int numData,
lwm2m_tlv_t * dataArray,
lwm2m_object_t * objectP)
{
int i;
uint8_t result;
firmware_data_t * data = (firmware_data_t*)(objectP->userData);
// this is a single instance object
if (LWM2M_URI_IS_SET_INSTANCE(uriP) && uriP->instanceId != 0)
if (instanceId != 0)
{
return COAP_404_NOT_FOUND;
}
i = 0;
do
{
switch (dataArray[i].id)
{
case 0:
// inline firmware binary
result = COAP_204_CHANGED;
break;
case 1:
// URL for download the firmware
result = COAP_204_CHANGED;
break;
case 4:
if (1 == dataArray[i].length && dataArray[i].value[0] == '0')
{
data->supported = 0;
result = COAP_204_CHANGED;
}
else if (1 == dataArray[i].length && dataArray[i].value[0] == '1')
{
data->supported = 1;
result = COAP_204_CHANGED;
}
else
{
result = COAP_400_BAD_REQUEST;
}
break;
default:
result = COAP_405_METHOD_NOT_ALLOWED;
}
i++;
} while (i < numData && result == COAP_204_CHANGED);
return result;
}
static uint8_t prv_firmware_execute(uint16_t instanceId,
uint16_t resourceId,
char * buffer,
int length,
lwm2m_object_t * objectP)
{
firmware_data_t * data = (firmware_data_t*)(objectP->userData);
// this is a single instance object
if (instanceId != 0)
{
return COAP_404_NOT_FOUND;
}
if (length != 0) return COAP_400_BAD_REQUEST;
firmware_data_t * data = (firmware_data_t*)(objectP->userData);
// for execute callback, resId is always set.
switch (uriP->resourceId)
switch (resourceId)
{
case 2:
if (data->state == 1)

View File

@ -96,171 +96,57 @@ static void prv_output_buffer(uint8_t * buffer,
}
}
static uint8_t prv_read(lwm2m_uri_t * uriP,
char ** bufferP,
int * lengthP,
static uint8_t prv_read(uint16_t instanceId,
int * numDataP,
lwm2m_tlv_t ** dataArrayP,
lwm2m_object_t * objectP)
{
prv_instance_t * targetP;
int i;
*bufferP = NULL;
*lengthP = 0;
targetP = (prv_instance_t *)lwm2m_list_find(objectP->instanceList, instanceId);
if (NULL == targetP) return COAP_404_NOT_FOUND;
if (!LWM2M_URI_IS_SET_INSTANCE(uriP))
if (*numDataP == 0)
{
*bufferP = (char *)malloc(PRV_TLV_BUFFER_SIZE);
if (NULL == *bufferP) return COAP_500_INTERNAL_SERVER_ERROR;
// TLV
for (targetP = (prv_instance_t *)(objectP->instanceList); targetP != NULL ; targetP = targetP->next)
{
char temp_buffer[16];
int temp_length = 0;
int result;
result = lwm2m_intToTLV(TLV_RESSOURCE, targetP->test, 1, temp_buffer, 16);
if (0 == result)
{
*lengthP = 0;
break;
}
temp_length += result;
result = lwm2m_opaqueToTLV(TLV_OBJECT_INSTANCE, temp_buffer, temp_length, targetP->shortID, *bufferP + *lengthP, PRV_TLV_BUFFER_SIZE - *lengthP);
if (0 == result)
{
*lengthP = 0;
break;
}
*lengthP += result;
}
if (*lengthP == 0)
{
free(*bufferP);
*bufferP = NULL;
return COAP_500_INTERNAL_SERVER_ERROR;
}
prv_output_buffer(*bufferP, *lengthP);
return COAP_205_CONTENT;
*dataArrayP = lwm2m_tlv_new(1);
if (*dataArrayP == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
*numDataP = 1;
(*dataArrayP)->id = 1;
}
else
{
targetP = (prv_instance_t *)lwm2m_list_find(objectP->instanceList, uriP->instanceId);
if (NULL == targetP) return COAP_404_NOT_FOUND;
if (!LWM2M_URI_IS_SET_RESOURCE(uriP))
{
// TLV
*bufferP = (char *)malloc(PRV_TLV_BUFFER_SIZE);
if (NULL == *bufferP) return COAP_500_INTERNAL_SERVER_ERROR;
if (*numDataP != 1) return COAP_404_NOT_FOUND;
if ((*dataArrayP)->id != 1) return COAP_404_NOT_FOUND;
*lengthP = lwm2m_intToTLV(TLV_RESSOURCE, targetP->test, 1, *bufferP, PRV_TLV_BUFFER_SIZE);
if (0 == *lengthP)
{
free(*bufferP);
*bufferP = NULL;
return COAP_500_INTERNAL_SERVER_ERROR;
}
prv_output_buffer(*bufferP, *lengthP);
return COAP_205_CONTENT;
}
switch (uriP->resourceId)
{
case 1:
// we use int16 because value is unsigned
*lengthP = lwm2m_int16ToPlainText(targetP->test, bufferP);
if (*lengthP <= 0) return COAP_500_INTERNAL_SERVER_ERROR;
return COAP_205_CONTENT;
(*dataArrayP)->type = LWM2M_TYPE_RESSOURCE;
lwm2m_tlv_encode_int(targetP->test, *dataArrayP);
default:
return COAP_404_NOT_FOUND;
}
}
if ((*dataArrayP)->length == 0) return COAP_500_INTERNAL_SERVER_ERROR;
return COAP_205_CONTENT;
}
static uint8_t prv_write(lwm2m_uri_t * uriP,
char * buffer,
int length,
static uint8_t prv_write(uint16_t instanceId,
int numData,
lwm2m_tlv_t * dataArray,
lwm2m_object_t * objectP)
{
prv_instance_t * targetP;
int64_t value;
// for write, instance ID is always set
targetP = (prv_instance_t *)lwm2m_list_find(objectP->instanceList, uriP->instanceId);
targetP = (prv_instance_t *)lwm2m_list_find(objectP->instanceList, instanceId);
if (NULL == targetP) return COAP_404_NOT_FOUND;
if (!LWM2M_URI_IS_SET_RESOURCE(uriP)) return COAP_501_NOT_IMPLEMENTED;
if (numData != 1 || dataArray->id != 1) return COAP_404_NOT_FOUND;
switch (uriP->resourceId)
{
case 1:
if (1 == lwm2m_PlainTextToInt64(buffer, length, &value))
{
if (value >= 0 && value <= 0xFF)
{
targetP->test = value;
return COAP_204_CHANGED;
}
}
return COAP_400_BAD_REQUEST;
default:
return COAP_404_NOT_FOUND;
}
}
static uint8_t prv_create(lwm2m_uri_t * uriP,
char * buffer,
int length,
lwm2m_object_t * objectP)
{
prv_instance_t * targetP;
lwm2m_tlv_type_t type;
uint16_t newId;
uint16_t resID;
size_t dataIndex;
size_t dataLen;
int result;
int64_t value;
if (LWM2M_URI_IS_SET_INSTANCE(uriP))
{
targetP = (prv_instance_t *)lwm2m_list_find(objectP->instanceList, uriP->instanceId);
if (targetP != NULL) return COAP_406_NOT_ACCEPTABLE;
newId = uriP->instanceId;
}
else
{
// determine a new unique ID & send it back
newId = lwm2m_list_newId(objectP->instanceList);
//set instanceId & flag in order to send int back;
uriP->instanceId = newId;
uriP->flag |= LWM2M_URI_FLAG_INSTANCE_ID;
}
result = lwm2m_decodeTLV(buffer, length, &type, &resID, &dataIndex, &dataLen);
if (result != length)
{
// decode failure or too much data for our single ressource object
return COAP_400_BAD_REQUEST;
}
if (type != TLV_RESSOURCE || resID != 1)
if (1 != lwm2m_tlv_decode_int(dataArray, &value)
|| value < 0 || value > 0xFF)
{
return COAP_400_BAD_REQUEST;
}
result = lwm2m_opaqueToInt(buffer + dataIndex, dataLen, &value);
if (result == 0 || value < 0 || value > 255)
return COAP_400_BAD_REQUEST;
targetP->test = (uint8_t)value;
targetP = (prv_instance_t *)malloc(sizeof(prv_instance_t));
if (NULL == targetP) return COAP_500_INTERNAL_SERVER_ERROR;
memset(targetP, 0, sizeof(prv_instance_t));
targetP->shortID = newId;
targetP->test = value;
objectP->instanceList = LWM2M_LIST_ADD(objectP->instanceList, targetP);
return COAP_201_CREATED;
return COAP_204_CHANGED;
}
static uint8_t prv_delete(uint16_t id,
@ -276,15 +162,46 @@ static uint8_t prv_delete(uint16_t id,
return COAP_202_DELETED;
}
static uint8_t prv_exec(lwm2m_uri_t * uriP,
static uint8_t prv_create(uint16_t instanceId,
int numData,
lwm2m_tlv_t * dataArray,
lwm2m_object_t * objectP)
{
prv_instance_t * targetP;
uint8_t result;
targetP = (prv_instance_t *)malloc(sizeof(prv_instance_t));
if (NULL == targetP) return COAP_500_INTERNAL_SERVER_ERROR;
memset(targetP, 0, sizeof(prv_instance_t));
targetP->shortID = instanceId;
objectP->instanceList = LWM2M_LIST_ADD(objectP->instanceList, targetP);
result = prv_write(instanceId, numData, dataArray, objectP);
if (result != COAP_204_CHANGED)
{
(void)prv_delete(instanceId, objectP);
}
else
{
result = COAP_201_CREATED;
}
return result;
}
static uint8_t prv_exec(uint16_t instanceId,
uint16_t resourceId,
char * buffer,
int length,
lwm2m_object_t * objectP)
{
if (NULL == lwm2m_list_find(objectP->instanceList, uriP->instanceId)) return COAP_404_NOT_FOUND;
if (NULL == lwm2m_list_find(objectP->instanceList, instanceId)) return COAP_404_NOT_FOUND;
switch (uriP->resourceId)
switch (resourceId)
{
case 1:
return COAP_405_METHOD_NOT_ALLOWED;
@ -292,7 +209,7 @@ static uint8_t prv_exec(lwm2m_uri_t * uriP,
fprintf(stdout, "\r\n-----------------\r\n"
"Execute on %hu/%d/%d\r\n"
" Parameter (%d bytes):\r\n",
uriP->objectId, uriP->instanceId, uriP->resourceId, length);
objectP->objID, instanceId, resourceId, length);
prv_output_buffer(buffer, length);
fprintf(stdout, "-----------------\r\n\r\n");
return COAP_204_CHANGED;