Skip to content

Commit

Permalink
Add support of Partial Update to WRITE on multi-instance resources
Browse files Browse the repository at this point in the history
  • Loading branch information
sbernard31 committed Jun 30, 2021
1 parent d5f3f1b commit 01376d8
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -289,15 +289,20 @@ public void handlePOST(CoapExchange exchange) {

// Manage Execute Request
if (path.isResource()) {
byte[] payload = exchange.getRequestPayload();
ExecuteResponse response = nodeEnabler.execute(identity,
new ExecuteRequest(URI, payload != null ? new String(payload) : null, coapRequest));
if (response.getCode().isError()) {
exchange.respond(toCoapResponseCode(response.getCode()), response.getErrorMessage());
} else {
exchange.respond(toCoapResponseCode(response.getCode()));
// execute request has no content format at all or a TEXT concent format for parameters.
if (!exchange.getRequestOptions().hasContentFormat()
|| ContentFormat.fromCode(exchange.getRequestOptions().getContentFormat()) == ContentFormat.TEXT) {
byte[] payload = exchange.getRequestPayload();

ExecuteResponse response = nodeEnabler.execute(identity,
new ExecuteRequest(URI, payload != null ? new String(payload) : null, coapRequest));
if (response.getCode().isError()) {
exchange.respond(toCoapResponseCode(response.getCode()), response.getErrorMessage());
} else {
exchange.respond(toCoapResponseCode(response.getCode()));
}
return;
}
return;
}

// handle content format for Write (Update) and Create request
Expand All @@ -313,6 +318,22 @@ public void handlePOST(CoapExchange exchange) {
}
LwM2mModel model = new StaticModel(nodeEnabler.getObjectModel());

// manage partial update of multi-instance resource
if (path.isResource()) {
try {
LwM2mNode lwM2mNode = decoder.decode(exchange.getRequestPayload(), contentFormat, path, model);
WriteResponse response = nodeEnabler.write(identity,
new WriteRequest(Mode.UPDATE, contentFormat, URI, lwM2mNode, coapRequest));
if (response.getCode().isError()) {
exchange.respond(toCoapResponseCode(response.getCode()), response.getErrorMessage());
} else {
exchange.respond(toCoapResponseCode(response.getCode()));
}
} catch (CodecException e) {
handleInvalidRequest(exchange.advanced(), "Unable to decode payload on WRITE", e);
}
return;
}
// Manage Update Instance
if (path.isObjectInstance()) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,8 @@ protected WriteResponse doWrite(ServerIdentity identity, WriteRequest request) {

// Manage Resource case
if (path.getResourceInstanceId() == null) {
return instance.write(identity, true, path.getResourceId(), (LwM2mResource) request.getNode());
return instance.write(identity, request.isReplaceRequest(), path.getResourceId(),
(LwM2mResource) request.getNode());
}

// Manage Resource Instance case
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -299,23 +299,25 @@ public WriteRequest(int objectId, int objectInstanceId, int resourceId, Map<Inte
}

/**
* Request to write a specific resource instance from a client.
* Request to write a <b>Multi-Instance Resource</b> using the TLV content format.
*
* @param mode the mode of the request : replace or update.
* @param contentFormat Format of the payload (TLV or JSON).
* @param objectId the object ID of the resource
* @param objectInstanceId the object instance ID
* @param resourceId the (individual) resource's ID
* @param resourceInstanceId the resource instance's ID
* @param value the resource instance (id-&gt;value) to write.
* @param objectId the id of the object to write.
* @param objectInstanceId the id of the object instance to write.
* @param resourceId the id of the resource to write.
* @param values the list of resource instance (id-&gt;value) to write.
* @param type the data type of the resource.
* @exception InvalidRequestException if parameters are invalid.
*/
public WriteRequest(Mode mode, ContentFormat contentFormat, int objectId, int objectInstanceId, int resourceId,
int resourceInstanceId, Object value, Type type) {
this(mode, contentFormat, new LwM2mPath(objectId, objectInstanceId, resourceId, resourceInstanceId),
LwM2mResourceInstance.newInstance(resourceInstanceId, value, type), null);
Map<Integer, ?> values, Type type) throws InvalidRequestException {
this(mode, ContentFormat.TLV, new LwM2mPath(objectId, objectInstanceId, resourceId),
LwM2mMultipleResource.newResource(resourceId, values, type), null);
}

// ***************** write resource instance****************** //

/**
* Request to write a specific resource instance from a client, MODE = REPLACE.
*
Expand Down Expand Up @@ -387,7 +389,8 @@ public WriteRequest(Mode mode, ContentFormat format, LwM2mPath target, LwM2mNode
throw new InvalidRequestException("new node value is mandatory for %s", target);

// Validate Mode
if (getPath().isResource() && mode == Mode.UPDATE)
if (getPath().isResource() && mode == Mode.UPDATE
&& (node instanceof LwM2mSingleResource || node instanceof LwM2mResourceInstance))
throw new InvalidRequestException("Invalid mode for '%s': update is not allowed on resource", target);

// Validate node and path coherence
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,13 +214,15 @@ public void can_write_multi_instance_objlnk_resource_in_tlv() throws Interrupted
@Test
public void can_write_object_resource_instance() throws InterruptedException {

// --------------------------------
// write (replace) multi instance
// --------------------------------
Map<Integer, String> values = new HashMap<>();
values.put(10, "value10");
values.put(20, "value20");

// write multi instance
WriteResponse response = helper.server.send(helper.getCurrentRegistration(),
new WriteRequest(contentFormat, IntegrationTestHelper.TEST_OBJECT_ID, 0,
new WriteRequest(Mode.REPLACE, contentFormat, IntegrationTestHelper.TEST_OBJECT_ID, 0,
IntegrationTestHelper.STRING_RESOURCE_INSTANCE_ID, values, Type.STRING));

// Verify Write result
Expand All @@ -239,6 +241,59 @@ public void can_write_object_resource_instance() throws InterruptedException {
LwM2mMultipleResource resourceInstance = (LwM2mMultipleResource) readResponse.getContent();
assertEquals("value10", resourceInstance.getInstance(10).getValue());
assertEquals("value20", resourceInstance.getInstance(20).getValue());
}

// --------------------------------
// write (update) multi instance
// --------------------------------
Map<Integer, String> newValues = new HashMap<>();
newValues.put(20, "value200");
newValues.put(30, "value30");
response = helper.server.send(helper.getCurrentRegistration(),
new WriteRequest(Mode.UPDATE, contentFormat, IntegrationTestHelper.TEST_OBJECT_ID, 0,
IntegrationTestHelper.STRING_RESOURCE_INSTANCE_ID, newValues, Type.STRING));

// Verify Write result
assertEquals(ResponseCode.CHANGED, response.getCode());
assertNotNull(response.getCoapResponse());
assertThat(response.getCoapResponse(), is(instanceOf(Response.class)));

// read multi instance
readResponse = helper.server.send(helper.getCurrentRegistration(), new ReadRequest(contentFormat,
IntegrationTestHelper.TEST_OBJECT_ID, 0, IntegrationTestHelper.STRING_RESOURCE_INSTANCE_ID));

// verify result
assertEquals(CONTENT, readResponse.getCode());
assertContentFormat(contentFormat, readResponse);

resourceInstance = (LwM2mMultipleResource) readResponse.getContent();
assertEquals("value200", resourceInstance.getInstance(20).getValue());
assertEquals("value30", resourceInstance.getInstance(30).getValue());
assertEquals("value10", resourceInstance.getInstance(10).getValue());

// --------------------------------
// write (replace) multi instance
// --------------------------------
newValues = new HashMap<>();
newValues.put(1, "value1");
response = helper.server.send(helper.getCurrentRegistration(),
new WriteRequest(Mode.REPLACE, contentFormat, IntegrationTestHelper.TEST_OBJECT_ID, 0,
IntegrationTestHelper.STRING_RESOURCE_INSTANCE_ID, newValues, Type.STRING));

// Verify Write result
assertEquals(ResponseCode.CHANGED, response.getCode());
assertNotNull(response.getCoapResponse());
assertThat(response.getCoapResponse(), is(instanceOf(Response.class)));

// read multi instance
readResponse = helper.server.send(helper.getCurrentRegistration(), new ReadRequest(contentFormat,
IntegrationTestHelper.TEST_OBJECT_ID, 0, IntegrationTestHelper.STRING_RESOURCE_INSTANCE_ID));

// verify result
assertEquals(CONTENT, readResponse.getCode());
assertContentFormat(contentFormat, readResponse);

resourceInstance = (LwM2mMultipleResource) readResponse.getContent();
assertEquals(1, resourceInstance.getInstances().size());
assertEquals("value1", resourceInstance.getInstance(1).getValue());
}
}

0 comments on commit 01376d8

Please sign in to comment.