Skip to content

Commit

Permalink
Fix ObserveResponse.getTimestampedLwM2mNode(s) behavior
Browse files Browse the repository at this point in the history
-fix list order getTimestampedLwM2mNodes when null-timestamp value is
used : null-timestamp value should be first (as considered as most
recent one)

- when "Notification Storing When Disabled or Offline" is used
getTimestampedLwM2mNode should return the most recent value. So this
could be a null-timestamp one.

see : #1553 (comment)
  • Loading branch information
sbernard31 committed Jun 7, 2024
1 parent b230e82 commit 491017d
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,9 @@ private BigDecimal computeTimestamp(BigDecimal baseTime, BigDecimal time) {
/**
* Group all JsonArrayEntry by time-stamp
*
* @return a map (relativeTimestamp => collection of JsonArrayEntry)
* @return a sorted map (relativeTimestamp => collection of JsonArrayEntry) order by descending time-stamp (most
* recent one at first place). If null time-stamp (meaning no time information) exists it always at first
* place.
*/
private SortedMap<BigDecimal, Collection<JsonArrayEntry>> groupJsonEntryByTimestamp(JsonRootObject jsonObject) {
SortedMap<BigDecimal, Collection<JsonArrayEntry>> result = new TreeMap<>(new Comparator<BigDecimal>() {
Expand All @@ -243,9 +245,9 @@ public int compare(BigDecimal o1, BigDecimal o2) {
// - supports null (time null means 0 if there is a base time)
// - reverses natural order (most recent value in first)
if (o1 == null) {
return o2 == null ? 0 : 1;
return o2 == null ? 0 : -1;
} else if (o2 == null) {
return -1;
return 1;
} else {
return o2.compareTo(o1);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -455,9 +455,9 @@ private SortedMap<BigDecimal, Collection<LwM2mResolvedSenMLRecord>> groupRecordB
public int compare(BigDecimal o1, BigDecimal o2) {
// null at first place
if (o1 == null) {
return o2 == null ? 0 : 1;
return o2 == null ? 0 : -1;
} else if (o2 == null) {
return -1;
return 1;
} else {
return o2.compareTo(o1);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,20 @@ public LwM2mChildNode getContent() {
*/
@Override
public TimestampedLwM2mNode getTimestampedLwM2mNode() {
return super.getTimestampedLwM2mNode();
if (timestampedValues != null && !timestampedValues.isEmpty()) {
return timestampedValues.get(0);
} else {
return super.getTimestampedLwM2mNode();
}
}

/**
* A list of {@link LwM2mNode} representing different state of this resources at different instant. This method
* returns value only on notification when client are using "Notification Storing When Disabled or Offline" and
* content format support it.
* <p>
* The list is sorted by descending time-stamp order (most recent one at first place). If null time-stamp (meaning
* no time information) exists it always at first place as we consider it as "now".
*
* @return a list of {@link TimestampedLwM2mNode} OR <code>null</code> if this is a error response or "Notification
* Storing When Disabled or Offline" is not used.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ public void can_observe_timestamped_resource(ContentFormat contentFormat, String
ObserveResponse response = server.waitForNotificationOf(observation);
assertThat(response).hasContentFormat(contentFormat, givenServerEndpointProvider);
assertThat(response.getContent()).isEqualTo(mostRecentNode.getNode());
assertThat(response.getTimestampedLwM2mNode()).isEqualTo(mostRecentNode);
assertThat(response.getTimestampedLwM2mNodes()).isEqualTo(timestampedNodes);
}

Expand All @@ -178,7 +179,56 @@ public void can_observe_timestamped_instance(ContentFormat contentFormat, String
new LwM2mObjectInstance(0, LwM2mSingleResource.newStringResource(15, "Paris")));
List<TimestampedLwM2mNode> timestampedNodes = new ArrayList<>();
timestampedNodes.add(mostRecentNode);
timestampedNodes.add(new TimestampedLwM2mNode(mostRecentNode.getTimestamp().minusMillis(2),
timestampedNodes.add(new TimestampedLwM2mNode(Instant.ofEpochMilli(System.currentTimeMillis()).minusMillis(2),
new LwM2mObjectInstance(0, LwM2mSingleResource.newStringResource(15, "Londres"))));
timestampedNodes.add(new TimestampedLwM2mNode(Instant.ofEpochMilli(System.currentTimeMillis()).minusMillis(4),
new LwM2mObjectInstance(0, LwM2mSingleResource.newStringResource(15, "Londres"))));
byte[] payload = encoder.encodeTimestampedData(timestampedNodes, contentFormat, new LwM2mPath("/3/0"),
client.getObjectTree().getModel());

TestObserveUtil.sendNotification(
client.getClientConnector(client.getServerIdForRegistrationId(currentRegistration.getId())),
server.getEndpoint(Protocol.COAP).getURI(), payload,
observeResponse.getObservation().getId().getBytes(), 2, contentFormat);
// *** Hack End *** //

// verify result
server.waitForNewObservation(observation);
ObserveResponse response = server.waitForNotificationOf(observation);

assertThat(response).hasContentFormat(contentFormat, givenServerEndpointProvider);
assertThat(response.getContent()).isEqualTo(mostRecentNode.getNode());
assertThat(response.getTimestampedLwM2mNode()).isEqualTo(mostRecentNode);
assertThat(response.getTimestampedLwM2mNodes()).isEqualTo(timestampedNodes);

}

@TestAllCases
public void can_observe_timestamped_instance_with_null(ContentFormat contentFormat,
String givenServerEndpointProvider) throws InterruptedException {
// observe device timezone
ObserveResponse observeResponse = server.send(currentRegistration, new ObserveRequest(contentFormat, 3, 0));
assertThat(observeResponse) //
.hasCode(CONTENT) //
.hasValidUnderlyingResponseFor(givenServerEndpointProvider);

// an observation response should have been sent
SingleObservation observation = observeResponse.getObservation();
assertThat(observation.getPath()).asString().isEqualTo("/3/0");
assertThat(observation.getRegistrationId()).isEqualTo(currentRegistration.getId());
Set<Observation> observations = server.getObservationService().getObservations(currentRegistration);
assertThat(observations).containsExactly(observation);

// *** HACK send time-stamped notification as Leshan client does not support it *** //
// create time-stamped nodes
TimestampedLwM2mNode mostRecentNode = new TimestampedLwM2mNode(null,
new LwM2mObjectInstance(0, LwM2mSingleResource.newStringResource(15, "Paris")));
List<TimestampedLwM2mNode> timestampedNodes = new ArrayList<>();
timestampedNodes.add(mostRecentNode);
Instant anInstant = Instant.ofEpochMilli(System.currentTimeMillis());
timestampedNodes.add(new TimestampedLwM2mNode(anInstant,
new LwM2mObjectInstance(0, LwM2mSingleResource.newStringResource(15, "Londres"))));
timestampedNodes.add(new TimestampedLwM2mNode(anInstant.minusMillis(4),
new LwM2mObjectInstance(0, LwM2mSingleResource.newStringResource(15, "Londres"))));
byte[] payload = encoder.encodeTimestampedData(timestampedNodes, contentFormat, new LwM2mPath("/3/0"),
client.getObjectTree().getModel());
Expand All @@ -194,6 +244,7 @@ public void can_observe_timestamped_instance(ContentFormat contentFormat, String
ObserveResponse response = server.waitForNotificationOf(observation);
assertThat(response).hasContentFormat(contentFormat, givenServerEndpointProvider);
assertThat(response.getContent()).isEqualTo(mostRecentNode.getNode());
assertThat(response.getTimestampedLwM2mNode()).isEqualTo(mostRecentNode);
assertThat(response.getTimestampedLwM2mNodes()).isEqualTo(timestampedNodes);
}

Expand Down Expand Up @@ -235,6 +286,7 @@ public void can_observe_timestamped_object(ContentFormat contentFormat, String g
ObserveResponse response = server.waitForNotificationOf(observation);
assertThat(response).hasContentFormat(contentFormat, givenServerEndpointProvider);
assertThat(response.getContent()).isEqualTo(mostRecentNode.getNode());
assertThat(response.getTimestampedLwM2mNode()).isEqualTo(mostRecentNode);
assertThat(response.getTimestampedLwM2mNodes()).isEqualTo(timestampedNodes);
}
}

0 comments on commit 491017d

Please sign in to comment.