Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle resource instances in Read, Write, and Observe. #435

Merged
merged 8 commits into from
Nov 20, 2020
2 changes: 1 addition & 1 deletion core/bootstrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ uint8_t bootstrap_handleCommand(lwm2m_context_t * contextP,
}
else
{
result = object_write(contextP, uriP, format, message->payload, message->payload_len);
result = object_write(contextP, uriP, format, message->payload, message->payload_len, false);
if (uriP->objectId == LWM2M_SECURITY_OBJECT_ID
&& result == COAP_204_CHANGED)
{
Expand Down
19 changes: 10 additions & 9 deletions core/data.c
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,8 @@ void lwm2m_data_include(lwm2m_data_t * subDataP,
dataP->type = LWM2M_TYPE_OBJECT;
break;
default:
return;
dataP->type = LWM2M_TYPE_MULTIPLE_RESOURCE;
break;
}
dataP->value.asChildren.count = count;
dataP->value.asChildren.array = subDataP;
Expand Down Expand Up @@ -655,13 +656,13 @@ int lwm2m_data_parse(lwm2m_uri_t * uriP,
{
case LWM2M_CONTENT_TEXT:
if (!LWM2M_URI_IS_SET_RESOURCE(uriP)) return 0;
#ifndef LWM2M_VERSION_1_0
// TODO: Support resource instance
if (LWM2M_URI_IS_SET_RESOURCE_INSTANCE(uriP)) return 0;
#endif
*dataP = lwm2m_data_new(1);
if (*dataP == NULL) return 0;
(*dataP)->id = uriP->resourceId;
#ifndef LWM2M_VERSION_1_0
if (LWM2M_URI_IS_SET_RESOURCE_INSTANCE(uriP))
(*dataP)->id = uriP->resourceInstanceId;
#endif
(*dataP)->type = LWM2M_TYPE_STRING;
res = prv_setBuffer(*dataP, buffer, bufferLen);
if (res == 0)
Expand All @@ -673,13 +674,13 @@ int lwm2m_data_parse(lwm2m_uri_t * uriP,

case LWM2M_CONTENT_OPAQUE:
if (!LWM2M_URI_IS_SET_RESOURCE(uriP)) return 0;
#ifndef LWM2M_VERSION_1_0
// TODO: Support resource instance
if (LWM2M_URI_IS_SET_RESOURCE_INSTANCE(uriP)) return 0;
#endif
*dataP = lwm2m_data_new(1);
if (*dataP == NULL) return 0;
(*dataP)->id = uriP->resourceId;
#ifndef LWM2M_VERSION_1_0
if (LWM2M_URI_IS_SET_RESOURCE_INSTANCE(uriP))
(*dataP)->id = uriP->resourceInstanceId;
#endif
(*dataP)->type = LWM2M_TYPE_OPAQUE;
res = prv_setBuffer(*dataP, buffer, bufferLen);
if (res == 0)
Expand Down
4 changes: 2 additions & 2 deletions core/internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ int uri_toString(const lwm2m_uri_t * uriP, uint8_t * buffer, size_t bufferLen, u
// defined in objects.c
uint8_t object_readData(lwm2m_context_t * contextP, lwm2m_uri_t * uriP, int * sizeP, lwm2m_data_t ** dataP);
uint8_t object_read(lwm2m_context_t * contextP, lwm2m_uri_t * uriP, const uint16_t * accept, uint8_t acceptNum, lwm2m_media_type_t * formatP, uint8_t ** bufferP, size_t * lengthP);
uint8_t object_write(lwm2m_context_t * contextP, lwm2m_uri_t * uriP, lwm2m_media_type_t format, uint8_t * buffer, size_t length);
uint8_t object_write(lwm2m_context_t * contextP, lwm2m_uri_t * uriP, lwm2m_media_type_t format, uint8_t * buffer, size_t length, bool partial);
uint8_t object_create(lwm2m_context_t * contextP, lwm2m_uri_t * uriP, lwm2m_media_type_t format, uint8_t * buffer, size_t length);
uint8_t object_execute(lwm2m_context_t * contextP, lwm2m_uri_t * uriP, uint8_t * buffer, size_t length);
uint8_t object_delete(lwm2m_context_t * contextP, lwm2m_uri_t * uriP);
Expand Down Expand Up @@ -366,7 +366,7 @@ lwm2m_data_t * json_extendData(lwm2m_data_t * parentP);
int json_dataStrip(int size, lwm2m_data_t * dataP, lwm2m_data_t ** resultP);
lwm2m_data_t * json_findDataItem(lwm2m_data_t * listP, size_t count, uint16_t id);
uri_depth_t json_decreaseLevel(uri_depth_t level);
int json_findAndCheckData(const lwm2m_uri_t * uriP, uri_depth_t level, size_t size, const lwm2m_data_t * tlvP, lwm2m_data_t ** targetP);
int json_findAndCheckData(const lwm2m_uri_t * uriP, uri_depth_t baseLevel, size_t size, const lwm2m_data_t * tlvP, lwm2m_data_t ** targetP, uri_depth_t *targetLevelP);
#endif

// defined in discover.c
Expand Down
37 changes: 21 additions & 16 deletions core/json.c
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,10 @@ int json_parse(lwm2m_uri_t * uriP,
}
else
{
/* Base name may have a trailing "/" on a multiple instance
* resource. This isn't valid for a URI string in LWM2M 1.0.
* Strip off any trailing "/" to avoid an error. */
if (buffer[bnStart + bnLen - 1] == '/') bnLen -= 1;
res = lwm2m_stringToUri((char *)buffer + bnStart, bnLen, &baseURI);
if (res < 0 || (size_t)res != bnLen) goto error;
baseUriP = &baseURI;
Expand Down Expand Up @@ -700,18 +704,10 @@ int json_parse(lwm2m_uri_t * uriP,
targetP = resultP + i;
if (targetP->id == uriP->resourceId)
{
if (targetP->type == LWM2M_TYPE_MULTIPLE_RESOURCE)
{
resP = targetP->value.asChildren.array;
size = targetP->value.asChildren.count;
}
else
{
size = json_dataStrip(1, targetP, &resP);
if (size <= 0) goto error;
lwm2m_data_free(count, parsedP);
parsedP = NULL;
}
size = json_dataStrip(1, targetP, &resP);
if (size <= 0) goto error;
lwm2m_data_free(count, parsedP);
parsedP = NULL;
}
}
if (resP == NULL) goto error;
Expand Down Expand Up @@ -774,7 +770,7 @@ static int prv_serializeValue(lwm2m_data_t * tlvP,
bufferLen - head,
tlvP->value.asBuffer.buffer,
tlvP->value.asBuffer.length);
if (!res) return -1;
if (tlvP->value.asBuffer.length != 0 && res == 0) return -1;
head += res;

if (bufferLen - head < JSON_ITEM_STRING_END_SIZE) return -1;
Expand Down Expand Up @@ -988,6 +984,7 @@ int json_serialize(lwm2m_uri_t * uriP,
uint8_t baseUriStr[URI_MAX_STRING_LEN];
int baseUriLen;
uri_depth_t rootLevel;
uri_depth_t baseLevel;
int num;
lwm2m_data_t * targetP;
const uint8_t *parentUriStr = NULL;
Expand All @@ -1011,13 +1008,21 @@ int json_serialize(lwm2m_uri_t * uriP,
}
#endif

baseUriLen = uri_toString(uriP, baseUriStr, URI_MAX_STRING_LEN, &rootLevel);
baseUriLen = uri_toString(uriP, baseUriStr, URI_MAX_STRING_LEN, &baseLevel);
if (baseUriLen < 0) return -1;
rootLevel = json_decreaseLevel(rootLevel);

num = json_findAndCheckData(uriP, rootLevel, size, tlvP, &targetP);
num = json_findAndCheckData(uriP, baseLevel, size, tlvP, &targetP, &rootLevel);
if (num < 0) return -1;

if (baseLevel >= URI_DEPTH_RESOURCE
&& rootLevel == baseLevel
&& baseUriLen > 1)
{
/* Remove the ID from the base name */
while (baseUriLen > 1 && baseUriStr[baseUriLen - 1] != '/') baseUriLen--;
if (baseUriLen > 1 && baseUriStr[baseUriLen - 1] == '/') baseUriLen--;
}

while (num == 1
&& (targetP->type == LWM2M_TYPE_OBJECT
|| targetP->type == LWM2M_TYPE_OBJECT_INSTANCE
Expand Down
109 changes: 73 additions & 36 deletions core/json_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -599,11 +599,12 @@ uri_depth_t json_decreaseLevel(uri_depth_t level)
}
}

int json_findAndCheckData(const lwm2m_uri_t * uriP,
uri_depth_t level,
size_t size,
const lwm2m_data_t * tlvP,
lwm2m_data_t ** targetP)
static int prv_findAndCheckData(const lwm2m_uri_t * uriP,
uri_depth_t desiredLevel,
size_t size,
const lwm2m_data_t * tlvP,
lwm2m_data_t ** targetP,
uri_depth_t *targetLevelP)
{
size_t index;
int result;
Expand Down Expand Up @@ -640,12 +641,13 @@ int json_findAndCheckData(const lwm2m_uri_t * uriP,

*targetP = NULL;
result = -1;
switch (level)
switch (desiredLevel)
{
case URI_DEPTH_OBJECT:
if (tlvP[0].type == LWM2M_TYPE_OBJECT)
{
*targetP = (lwm2m_data_t*)tlvP;
*targetLevelP = URI_DEPTH_OBJECT;
result = (int)size;
}
break;
Expand All @@ -658,11 +660,13 @@ int json_findAndCheckData(const lwm2m_uri_t * uriP,
{
if (tlvP[index].id == uriP->objectId)
{
return json_findAndCheckData(uriP,
level,
tlvP[index].value.asChildren.count,
tlvP[index].value.asChildren.array,
targetP);
*targetLevelP = URI_DEPTH_OBJECT_INSTANCE;
return prv_findAndCheckData(uriP,
desiredLevel,
tlvP[index].value.asChildren.count,
tlvP[index].value.asChildren.array,
targetP,
targetLevelP);
}
}
break;
Expand All @@ -683,11 +687,13 @@ int json_findAndCheckData(const lwm2m_uri_t * uriP,
{
if (tlvP[index].id == uriP->objectId)
{
return json_findAndCheckData(uriP,
level,
tlvP[index].value.asChildren.count,
tlvP[index].value.asChildren.array,
targetP);
*targetLevelP = URI_DEPTH_OBJECT_INSTANCE;
return prv_findAndCheckData(uriP,
desiredLevel,
tlvP[index].value.asChildren.count,
tlvP[index].value.asChildren.array,
targetP,
targetLevelP);
}
}
break;
Expand All @@ -696,11 +702,12 @@ int json_findAndCheckData(const lwm2m_uri_t * uriP,
{
if (tlvP[index].id == uriP->instanceId)
{
return json_findAndCheckData(uriP,
level,
tlvP[index].value.asChildren.count,
tlvP[index].value.asChildren.array,
targetP);
*targetLevelP = URI_DEPTH_RESOURCE;
return prv_findAndCheckData(uriP,
desiredLevel,
tlvP[index].value.asChildren.count,
tlvP[index].value.asChildren.array,
targetP, targetLevelP);
}
}
break;
Expand All @@ -719,11 +726,13 @@ int json_findAndCheckData(const lwm2m_uri_t * uriP,
{
if (tlvP[index].id == uriP->objectId)
{
return json_findAndCheckData(uriP,
level,
tlvP[index].value.asChildren.count,
tlvP[index].value.asChildren.array,
targetP);
*targetLevelP = URI_DEPTH_OBJECT_INSTANCE;
return prv_findAndCheckData(uriP,
desiredLevel,
tlvP[index].value.asChildren.count,
tlvP[index].value.asChildren.array,
targetP,
targetLevelP);
}
}
break;
Expand All @@ -732,11 +741,13 @@ int json_findAndCheckData(const lwm2m_uri_t * uriP,
{
if (tlvP[index].id == uriP->instanceId)
{
return json_findAndCheckData(uriP,
level,
tlvP[index].value.asChildren.count,
tlvP[index].value.asChildren.array,
targetP);
*targetLevelP = URI_DEPTH_RESOURCE;
return prv_findAndCheckData(uriP,
desiredLevel,
tlvP[index].value.asChildren.count,
tlvP[index].value.asChildren.array,
targetP,
targetLevelP);
}
}
break;
Expand All @@ -745,11 +756,13 @@ int json_findAndCheckData(const lwm2m_uri_t * uriP,
{
if (tlvP[index].id == uriP->resourceId)
{
return json_findAndCheckData(uriP,
level,
tlvP[index].value.asChildren.count,
tlvP[index].value.asChildren.array,
targetP);
*targetLevelP = URI_DEPTH_RESOURCE_INSTANCE;
return prv_findAndCheckData(uriP,
desiredLevel,
tlvP[index].value.asChildren.count,
tlvP[index].value.asChildren.array,
targetP,
targetLevelP);
}
}
break;
Expand All @@ -767,4 +780,28 @@ int json_findAndCheckData(const lwm2m_uri_t * uriP,
return result;
}

int json_findAndCheckData(const lwm2m_uri_t * uriP,
uri_depth_t baseLevel,
size_t size,
const lwm2m_data_t * tlvP,
lwm2m_data_t ** targetP,
uri_depth_t *targetLevelP)
{
uri_depth_t desiredLevel = json_decreaseLevel(baseLevel);
if (baseLevel < URI_DEPTH_RESOURCE)
{
*targetLevelP = desiredLevel;
}
else
{
*targetLevelP = baseLevel;
}
return prv_findAndCheckData(uriP,
desiredLevel,
size,
tlvP,
targetP,
targetLevelP);
}

#endif
11 changes: 9 additions & 2 deletions core/liblwm2m.h
Original file line number Diff line number Diff line change
Expand Up @@ -434,9 +434,16 @@ int lwm2m_decode_TLV(const uint8_t * buffer, size_t buffer_len, lwm2m_data_type_

typedef struct _lwm2m_object_t lwm2m_object_t;

typedef enum
{
LWM2M_WRITE_PARTIAL_UPDATE, // Write should add or update resources and resource instances.
LWM2M_WRITE_REPLACE_RESOURCES, // Write should replace resources entirely.
LWM2M_WRITE_REPLACE_INSTANCE, // Write should replace the entire instance.
} lwm2m_write_type_t;

typedef uint8_t (*lwm2m_read_callback_t) (uint16_t instanceId, int * numDataP, lwm2m_data_t ** dataArrayP, lwm2m_object_t * objectP);
typedef uint8_t (*lwm2m_discover_callback_t) (uint16_t instanceId, int * numDataP, lwm2m_data_t ** dataArrayP, lwm2m_object_t * objectP);
typedef uint8_t (*lwm2m_write_callback_t) (uint16_t instanceId, int numData, lwm2m_data_t * dataArray, lwm2m_object_t * objectP);
typedef uint8_t (*lwm2m_write_callback_t) (uint16_t instanceId, int numData, lwm2m_data_t * dataArray, lwm2m_object_t * objectP, lwm2m_write_type_t writeType);
typedef uint8_t (*lwm2m_execute_callback_t) (uint16_t instanceId, uint16_t resourceId, uint8_t * buffer, int length, lwm2m_object_t * objectP);
typedef uint8_t (*lwm2m_create_callback_t) (uint16_t instanceId, int numData, lwm2m_data_t * dataArray, lwm2m_object_t * objectP);
typedef uint8_t (*lwm2m_delete_callback_t) (uint16_t instanceId, lwm2m_object_t * objectP);
Expand Down Expand Up @@ -779,7 +786,7 @@ void lwm2m_set_monitoring_callback(lwm2m_context_t * contextP, lwm2m_result_call
// Device Management APIs
int lwm2m_dm_read(lwm2m_context_t * contextP, uint16_t clientID, lwm2m_uri_t * uriP, lwm2m_result_callback_t callback, void * userData);
int lwm2m_dm_discover(lwm2m_context_t * contextP, uint16_t clientID, lwm2m_uri_t * uriP, lwm2m_result_callback_t callback, void * userData);
int lwm2m_dm_write(lwm2m_context_t * contextP, uint16_t clientID, lwm2m_uri_t * uriP, lwm2m_media_type_t format, uint8_t * buffer, int length, lwm2m_result_callback_t callback, void * userData);
int lwm2m_dm_write(lwm2m_context_t * contextP, uint16_t clientID, lwm2m_uri_t * uriP, lwm2m_media_type_t format, uint8_t * buffer, int length, bool partialUpdate, lwm2m_result_callback_t callback, void * userData);
int lwm2m_dm_write_attributes(lwm2m_context_t * contextP, uint16_t clientID, lwm2m_uri_t * uriP, lwm2m_attributes_t * attrP, lwm2m_result_callback_t callback, void * userData);
int lwm2m_dm_execute(lwm2m_context_t * contextP, uint16_t clientID, lwm2m_uri_t * uriP, lwm2m_media_type_t format, uint8_t * buffer, int length, lwm2m_result_callback_t callback, void * userData);
int lwm2m_dm_create(lwm2m_context_t * contextP, uint16_t clientID, lwm2m_uri_t * uriP, int numData, lwm2m_data_t * dataP, lwm2m_result_callback_t callback, void * userData);
Expand Down
Loading