Browse Source

Lwm2m: composite read/write

pull/4791/head
nickAS21 5 years ago
parent
commit
99238feae0
  1. 36
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mOperationType.java
  2. 1
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportUtil.java
  3. 107
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java
  4. 6
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/HasContentFormat.java
  5. 7
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/LwM2mDownlinkMsgHandler.java
  6. 6
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MObserveRequest.java
  7. 38
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MReadCompositeCallback.java
  8. 44
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MReadCompositeRequest.java
  9. 6
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MReadRequest.java
  10. 6
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MTargetedCallback.java
  11. 45
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteCompositeRequest.java
  12. 36
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteResponseCompositeCallback.java
  13. 41
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2MUplinkMsgHandler.java
  14. 6
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/LwM2mUplinkMsgHandler.java

36
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mOperationType.java

@ -23,37 +23,41 @@ import lombok.Getter;
public enum LwM2mOperationType {
READ(0, "Read", true),
DISCOVER(1, "Discover", true),
DISCOVER_ALL(2, "DiscoverAll", false),
OBSERVE_READ_ALL(3, "ObserveReadAll", false),
READ_COMPOSITE(1, "ReadComposite", true),
DISCOVER(2, "Discover", true),
DISCOVER_ALL(3, "DiscoverAll", false),
OBSERVE_READ_ALL(4, "ObserveReadAll", false),
OBSERVE(4, "Observe", true),
OBSERVE_CANCEL(5, "ObserveCancel", true),
OBSERVE_CANCEL_ALL(6, "ObserveCancelAll", false),
EXECUTE(7, "Execute", true),
OBSERVE(5, "Observe", true),
OBSERVE_COMPOSITE(6, "ObserveComposite", true),
OBSERVE_CANCEL(7, "ObserveCancel", true),
OBSERVE_COMPOSITE_CANCEL(8, "ObserveCompositeCancel", true),
OBSERVE_CANCEL_ALL(9, "ObserveCancelAll", false),
EXECUTE(10, "Execute", true),
/**
* Replaces the Object Instance or the Resource(s) with the new value provided in the “Write” operation. (see
* section 5.3.3 of the LW M2M spec).
* if all resources are to be replaced
*/
WRITE_REPLACE(8, "WriteReplace", true),
WRITE_REPLACE(11, "WriteReplace", true),
/**
* Adds or updates Resources provided in the new value and leaves other existing Resources unchanged. (see section
* 5.3.3 of the LW M2M spec).
* if this is a partial update request
*/
WRITE_UPDATE(9, "WriteUpdate", true),
WRITE_ATTRIBUTES(10, "WriteAttributes", true),
DELETE(11, "Delete", true),
WRITE_UPDATE(12, "WriteUpdate", true),
WRITE_COMPOSITE(14, "WriteComposite", true),
WRITE_ATTRIBUTES(15, "WriteAttributes", true),
DELETE(16, "Delete", true),
// only for RPC
FW_UPDATE(12, "FirmwareUpdate", false);
FW_UPDATE(17, "FirmwareUpdate", false);
// FW_READ_INFO(12, "FirmwareReadInfo"),
// SW_READ_INFO(15, "SoftwareReadInfo"),
// SW_UPDATE(16, "SoftwareUpdate"),
// SW_UNINSTALL(18, "SoftwareUninstall");
// FW_READ_INFO(18, "FirmwareReadInfo"),
// SW_READ_INFO(19, "SoftwareReadInfo"),
// SW_UPDATE(20, "SoftwareUpdate"),
// SW_UNINSTALL(21, "SoftwareUninstall");
@Getter
private final int code;

1
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportUtil.java

@ -450,4 +450,5 @@ public class LwM2mTransportUtil {
}
return lwm2mResourceValue;
}
}

107
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java

@ -31,17 +31,21 @@ import org.eclipse.leshan.core.request.DeleteRequest;
import org.eclipse.leshan.core.request.DiscoverRequest;
import org.eclipse.leshan.core.request.ExecuteRequest;
import org.eclipse.leshan.core.request.ObserveRequest;
import org.eclipse.leshan.core.request.ReadCompositeRequest;
import org.eclipse.leshan.core.request.ReadRequest;
import org.eclipse.leshan.core.request.SimpleDownlinkRequest;
import org.eclipse.leshan.core.request.WriteAttributesRequest;
import org.eclipse.leshan.core.request.WriteCompositeRequest;
import org.eclipse.leshan.core.request.WriteRequest;
import org.eclipse.leshan.core.response.DeleteResponse;
import org.eclipse.leshan.core.response.DiscoverResponse;
import org.eclipse.leshan.core.response.ExecuteResponse;
import org.eclipse.leshan.core.response.LwM2mResponse;
import org.eclipse.leshan.core.response.ObserveResponse;
import org.eclipse.leshan.core.response.ReadCompositeResponse;
import org.eclipse.leshan.core.response.ReadResponse;
import org.eclipse.leshan.core.response.WriteAttributesResponse;
import org.eclipse.leshan.core.response.WriteCompositeResponse;
import org.eclipse.leshan.core.response.WriteResponse;
import org.eclipse.leshan.core.util.Hex;
import org.eclipse.leshan.server.registration.Registration;
@ -54,6 +58,7 @@ import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
import org.thingsboard.server.transport.lwm2m.server.common.LwM2MExecutorAwareService;
import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
import org.thingsboard.server.transport.lwm2m.server.uplink.DefaultLwM2MUplinkMsgHandler;
import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;
import javax.annotation.PostConstruct;
@ -63,6 +68,7 @@ import java.util.Collection;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
@ -110,10 +116,36 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
@Override
public void sendReadRequest(LwM2mClient client, TbLwM2MReadRequest request, DownlinkRequestCallback<ReadRequest, ReadResponse> callback) {
validateVersionedId(client, request);
ReadRequest downlink = new ReadRequest(getContentFormat(client, request), request.getObjectId());
ReadRequest downlink = new ReadRequest(getRequestContentFormat(client, request), request.getObjectId());
sendRequest(client, downlink, request.getTimeout(), callback);
}
@Override
// public void sendReadCompositeRequest(LwM2mClient client, TbLwM2MReadCompositeRequest request, DownlinkRequestCallback<ReadCompositeRequest, ReadCompositeResponse> callback) {
public void sendReadCompositeRequest(LwM2mClient client, String [] paths, DefaultLwM2MUplinkMsgHandler lwM2MUplinkMsgHandler) {
// validateVersionedId(client, request);
DownlinkRequestCallback<ReadCompositeRequest, ReadCompositeResponse> callback = new TbLwM2MReadCompositeCallback(lwM2MUplinkMsgHandler, logService, client, null);
ContentFormat requestContentFormat = ContentFormat.SENML_JSON;
ContentFormat responseContentFormat = ContentFormat.SENML_JSON;
ReadCompositeRequest downlink = new ReadCompositeRequest(requestContentFormat, responseContentFormat, paths);
sendReadRequestComposite(client, downlink, this.config.getTimeout(), callback);
}
@Override
public void sendWriteCompositeRequest(LwM2mClient client, Map<String, Object> nodes, DefaultLwM2MUplinkMsgHandler handler) {
// ResourceModel resourceModelWrite = client.getResourceModel(request.getVersionedId(), this.config.getModelProvider());
TbLwM2MWriteResponseCompositeCallback callback = new TbLwM2MWriteResponseCompositeCallback (handler, logService, client, null);
ContentFormat contentFormat = ContentFormat.SENML_JSON;
try {
WriteCompositeRequest downlink = new WriteCompositeRequest(contentFormat, nodes);
sendWriteCompositeRequest(client, downlink, this.config.getTimeout(), callback);
} catch (Exception e) {
callback.onError(JacksonUtil.toString(nodes), e);
}
}
@Override
public void sendObserveRequest(LwM2mClient client, TbLwM2MObserveRequest request, DownlinkRequestCallback<ObserveRequest, ObserveResponse> callback) {
validateVersionedId(client, request);
@ -121,7 +153,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
Set<Observation> observations = context.getServer().getObservationService().getObservations(client.getRegistration());
if (observations.stream().noneMatch(observation -> observation.getPath().equals(resultIds))) {
ObserveRequest downlink;
ContentFormat contentFormat = getContentFormat(client, request);
ContentFormat contentFormat = getRequestContentFormat(client, request);
if (resultIds.isResource()) {
downlink = new ObserveRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId());
} else if (resultIds.isObjectInstance()) {
@ -278,6 +310,73 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
}
}
private <R extends SimpleDownlinkRequest<T>, T extends LwM2mResponse> void sendWriteCompositeRequest(LwM2mClient client, WriteCompositeRequest request, long timeoutInMs, DownlinkRequestCallback<WriteCompositeRequest, WriteCompositeResponse> callback) {
Registration registration = client.getRegistration();
try {
logService.log(client, String.format("[%s][%s] Sending request: %s to %s", registration.getId(), registration.getSocketAddress(), request.getClass().getSimpleName(), request.getPaths()));
context.getServer().send(registration, request, timeoutInMs, response -> {
executor.submit(() -> {
try {
callback.onSuccess(request, response);
} catch (Exception e) {
log.error("[{}] failed to process successful response [{}] ", registration.getEndpoint(), response, e);
}
});
}, e -> {
executor.submit(() -> {
callback.onError(JacksonUtil.toString(request), e);
});
});
} catch (Exception e) {
callback.onError(JacksonUtil.toString(request), e);
}
}
private <R extends SimpleDownlinkRequest<T>, T extends LwM2mResponse> void sendReadRequestComposite(LwM2mClient client, ReadCompositeRequest request, long timeoutInMs, DownlinkRequestCallback<ReadCompositeRequest, ReadCompositeResponse> callback) {
Registration registration = client.getRegistration();
try {
logService.log(client, String.format("[%s][%s] Sending request: %s to %s", registration.getId(), registration.getSocketAddress(), request.getClass().getSimpleName(), request.getPaths()));
context.getServer().send(registration, request, timeoutInMs, response -> {
executor.submit(() -> {
try {
/**
* [{"bn":"/3/0/","n":"0","vs":"Thingsboard Test Device"},
* {"n":"1","vs":"Model 500"},
* {"n":"2","vs":"TH-500-000-0001"},
* {"n":"3","vs":"TestThingsboard@TestMore1024_2.04"},
* {"n":"6","v":1},{"n":"7","v":56},
* {"n":"8","v":42},{"n":"9","v":16},
* {"n":"10","v":127619},{"n":"13","v":1624520988},
* {"n":"14","vs":"+03"},{"n":"15","vs":"Europe/Kiev"},
* {"n":"16","vs":"U"},{"n":"17","vs":"smart meters"},
* {"n":"18","vs":"1.01"},{"n":"19","vs":"1.02"},
* {"n":"20","v":3},{"n":"21","v":256000},
* {"bn":"/5/0/","n":"1","vs":""},
* {"n":"3","v":0},{"n":"5","v":0},
* {"n":"6","vs":""},{"n":"7","vs":""},
* {"n":"8/0","v":0},{"n":"8/1","v":1},
* {"n":"9","v":2},
* {"bn":"/1/0/","n":"0","v":123},
* {"n":"1","v":300},
* {"n":"6","vb":false},
* {"n":"22","vs":"U"},
* {"n":"7","vs":"U"}]
*/
callback.onSuccess(request, response);
} catch (Exception e) {
log.error("[{}] failed to process successful response [{}] ", registration.getEndpoint(), response, e);
}
});
}, e -> {
executor.submit(() -> {
callback.onError(JacksonUtil.toString(request), e);
});
});
} catch (Exception e) {
callback.onError(JacksonUtil.toString(request), e);
}
}
private WriteRequest getWriteRequestSingleResource(ResourceModel.Type type, ContentFormat contentFormat, int objectId, int instanceId, int resourceId, Object value) {
switch (type) {
case STRING: // String
@ -347,7 +446,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
throw new CodecException("Invalid ResourceModel_Type for %s ContentFormat.", type);
}
private static ContentFormat getContentFormat(LwM2mClient client, HasContentFormat request) {
return request.getContentFormat() != null ? request.getContentFormat() : client.getDefaultContentFormat();
private static ContentFormat getRequestContentFormat(LwM2mClient client, HasContentFormat request) {
return request.getRequestContentFormat() != null ? request.getRequestContentFormat() : client.getDefaultContentFormat();
}
}

6
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/HasContentFormat.java

@ -19,5 +19,9 @@ import org.eclipse.leshan.core.request.ContentFormat;
public interface HasContentFormat {
ContentFormat getContentFormat();
ContentFormat getRequestContentFormat();
default ContentFormat getResponseContentFormat() {
return null;
}
}

7
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/LwM2mDownlinkMsgHandler.java

@ -31,14 +31,19 @@ import org.eclipse.leshan.core.response.ReadResponse;
import org.eclipse.leshan.core.response.WriteAttributesResponse;
import org.eclipse.leshan.core.response.WriteResponse;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
import org.thingsboard.server.transport.lwm2m.server.uplink.DefaultLwM2MUplinkMsgHandler;
import java.util.List;
import java.util.Map;
import java.util.Set;
public interface LwM2mDownlinkMsgHandler {
void sendReadRequest(LwM2mClient client, TbLwM2MReadRequest request, DownlinkRequestCallback<ReadRequest, ReadResponse> callback);
// void sendReadCompositeRequest(LwM2mClient client, TbLwM2MReadCompositeRequest request, DownlinkRequestCallback<ReadCompositeRequest, ReadCompositeResponse> callback);
void sendReadCompositeRequest(LwM2mClient client, String [] paths, DefaultLwM2MUplinkMsgHandler lwM2MUplinkMsgHandler);
void sendObserveRequest(LwM2mClient client, TbLwM2MObserveRequest request, DownlinkRequestCallback<ObserveRequest, ObserveResponse> callback);
void sendObserveAllRequest(LwM2mClient client, TbLwM2MObserveAllRequest request, DownlinkRequestCallback<TbLwM2MObserveAllRequest, Set<String>> callback);
@ -59,6 +64,8 @@ public interface LwM2mDownlinkMsgHandler {
void sendWriteReplaceRequest(LwM2mClient client, TbLwM2MWriteReplaceRequest request, DownlinkRequestCallback<WriteRequest, WriteResponse> callback);
void sendWriteCompositeRequest(LwM2mClient client, Map<String, Object> nodes, DefaultLwM2MUplinkMsgHandler handler);
void sendWriteUpdateRequest(LwM2mClient client, TbLwM2MWriteUpdateRequest request, DownlinkRequestCallback<WriteRequest, WriteResponse> callback);

6
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MObserveRequest.java

@ -24,12 +24,12 @@ import org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType;
public class TbLwM2MObserveRequest extends AbstractTbLwM2MTargetedDownlinkRequest<ObserveResponse> implements HasContentFormat {
@Getter
private final ContentFormat contentFormat;
private final ContentFormat requestContentFormat;
@Builder
private TbLwM2MObserveRequest(String versionedId, long timeout, ContentFormat contentFormat) {
private TbLwM2MObserveRequest(String versionedId, long timeout, ContentFormat requestContentFormat) {
super(versionedId, timeout);
this.contentFormat = contentFormat;
this.requestContentFormat = requestContentFormat;
}
@Override

38
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MReadCompositeCallback.java

@ -0,0 +1,38 @@
/**
* Copyright © 2016-2021 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.transport.lwm2m.server.downlink;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.leshan.core.request.ReadCompositeRequest;
import org.eclipse.leshan.core.response.ReadCompositeResponse;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler;
@Slf4j
public class TbLwM2MReadCompositeCallback extends TbLwM2MUplinkTargetedCallback<ReadCompositeRequest, ReadCompositeResponse> {
public TbLwM2MReadCompositeCallback(LwM2mUplinkMsgHandler handler, LwM2MTelemetryLogService logService, LwM2mClient client, String targetId) {
super(handler, logService, client, targetId);
}
@Override
public void onSuccess(ReadCompositeRequest request, ReadCompositeResponse response) {
super.onSuccess(request, response);
handler.onUpdateValueAfterReadCompositeResponse(client.getRegistration(), versionedId, response);
}
}

44
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MReadCompositeRequest.java

@ -0,0 +1,44 @@
/**
* Copyright © 2016-2021 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.transport.lwm2m.server.downlink;
import lombok.Builder;
import lombok.Getter;
import org.eclipse.leshan.core.request.ContentFormat;
import org.eclipse.leshan.core.response.ReadCompositeResponse;
import org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType;
public class TbLwM2MReadCompositeRequest extends AbstractTbLwM2MTargetedDownlinkRequest<ReadCompositeResponse> implements HasContentFormat {
@Getter
private final ContentFormat requestContentFormat;
@Getter
private final ContentFormat responseContentFormat;
@Builder
private TbLwM2MReadCompositeRequest(String versionedId, long timeout, ContentFormat requestContentFormat, ContentFormat responseContentFormat) {
super(versionedId, timeout);
this.requestContentFormat = requestContentFormat;
this.responseContentFormat = responseContentFormat;
}
@Override
public LwM2mOperationType getType() {
return LwM2mOperationType.READ_COMPOSITE;
}
}

6
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MReadRequest.java

@ -24,12 +24,12 @@ import org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType;
public class TbLwM2MReadRequest extends AbstractTbLwM2MTargetedDownlinkRequest<ReadResponse> implements HasContentFormat {
@Getter
private final ContentFormat contentFormat;
private final ContentFormat requestContentFormat;
@Builder
private TbLwM2MReadRequest(String versionedId, long timeout, ContentFormat contentFormat) {
private TbLwM2MReadRequest(String versionedId, long timeout, ContentFormat requestContentFormat) {
super(versionedId, timeout);
this.contentFormat = contentFormat;
this.requestContentFormat = requestContentFormat;
}
@Override

6
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MTargetedCallback.java

@ -18,7 +18,6 @@ package org.thingsboard.server.transport.lwm2m.server.downlink;
import lombok.extern.slf4j.Slf4j;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler;
import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LWM2M_INFO;
@ -32,6 +31,11 @@ public abstract class TbLwM2MTargetedCallback<R, T> extends AbstractTbLwM2MReque
this.versionedId = versionedId;
}
public TbLwM2MTargetedCallback(LwM2MTelemetryLogService logService, LwM2mClient client) {
super(logService, client);
this.versionedId = null;
}
@Override
public void onSuccess(R request, T response) {
//TODO convert camelCase to "camel case" using .split("(?<!(^|[A-Z]))(?=[A-Z])|(?<!^)(?=[A-Z][a-z])")

45
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteCompositeRequest.java

@ -0,0 +1,45 @@
/**
* Copyright © 2016-2021 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.transport.lwm2m.server.downlink;
import lombok.Builder;
import lombok.Getter;
import org.eclipse.leshan.core.request.ContentFormat;
import org.eclipse.leshan.core.response.WriteCompositeResponse;
import org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType;
public class TbLwM2MWriteCompositeRequest extends AbstractTbLwM2MTargetedDownlinkRequest<WriteCompositeResponse> {
@Getter
private final ContentFormat contentFormat;
@Getter
private final Object value;
@Builder
private TbLwM2MWriteCompositeRequest(String versionedId, long timeout, ContentFormat contentFormat, Object value) {
super(versionedId, timeout);
this.contentFormat = contentFormat;
this.value = value;
}
@Override
public LwM2mOperationType getType() {
return LwM2mOperationType.WRITE_REPLACE;
}
}

36
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteResponseCompositeCallback.java

@ -0,0 +1,36 @@
/**
* Copyright © 2016-2021 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.transport.lwm2m.server.downlink;
import org.eclipse.leshan.core.request.WriteCompositeRequest;
import org.eclipse.leshan.core.response.WriteCompositeResponse;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler;
public class TbLwM2MWriteResponseCompositeCallback extends TbLwM2MUplinkTargetedCallback<WriteCompositeRequest, WriteCompositeResponse> {
public TbLwM2MWriteResponseCompositeCallback(LwM2mUplinkMsgHandler handler, LwM2MTelemetryLogService logService, LwM2mClient client, String targetId) {
super(handler, logService, client, targetId);
}
@Override
public void onSuccess(WriteCompositeRequest request, WriteCompositeResponse response) {
super.onSuccess(request, response);
handler.onWriteCompositeResponseOk(client, request);
}
}

41
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2MUplinkMsgHandler.java

@ -30,14 +30,15 @@ import org.eclipse.leshan.core.node.LwM2mResource;
import org.eclipse.leshan.core.observation.Observation;
import org.eclipse.leshan.core.request.ObserveRequest;
import org.eclipse.leshan.core.request.ReadRequest;
import org.eclipse.leshan.core.request.WriteCompositeRequest;
import org.eclipse.leshan.core.request.WriteRequest;
import org.eclipse.leshan.core.response.ObserveResponse;
import org.eclipse.leshan.core.response.ReadCompositeResponse;
import org.eclipse.leshan.core.response.ReadResponse;
import org.eclipse.leshan.server.registration.Registration;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.thingsboard.common.util.DonAsynchron;
import org.thingsboard.server.cache.ota.OtaPackageDataCache;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.StringUtils;
@ -83,8 +84,6 @@ import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteAttrib
import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteAttributesRequest;
import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
import org.thingsboard.server.transport.lwm2m.server.ota.LwM2MOtaUpdateService;
import org.thingsboard.server.transport.lwm2m.server.ota.firmware.LwM2MFirmwareUpdateStrategy;
import org.thingsboard.server.transport.lwm2m.server.ota.software.LwM2MSoftwareUpdateStrategy;
import org.thingsboard.server.transport.lwm2m.server.rpc.LwM2MRpcRequestHandler;
import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MDtlsSessionStore;
import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;
@ -94,6 +93,7 @@ import javax.annotation.PreDestroy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@ -354,6 +354,22 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
}
}
public void onUpdateValueAfterReadCompositeResponse(Registration registration, String path, ReadCompositeResponse response) {
log.warn("201) ReadCompositeResponse: [{}]", response);
if (response.getContent() != null) {
LwM2mClient lwM2MClient = clientContext.getClientByEndpoint(registration.getEndpoint());
response.getContent().forEach((k, v) -> {
if (v instanceof LwM2mObject) {
this.updateObjectResourceValue(lwM2MClient, (LwM2mObject) v, k.toString());
} else if (v instanceof LwM2mObjectInstance) {
this.updateObjectInstanceResourceValue(lwM2MClient, (LwM2mObjectInstance) v, k.toString());
} else if (v instanceof LwM2mResource) {
this.updateResourcesValue(lwM2MClient, (LwM2mResource) v, k.toString());
}
});
}
}
/**
* @param sessionInfo -
* @param deviceProfile -
@ -429,6 +445,17 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
if (supportedObjects != null && supportedObjects.size() > 0) {
// #1
this.sendReadRequests(lwM2MClient, profile, supportedObjects);
// test composite
String[] paths = new String[]{"/3/0", "/1/0", "/5/0"};
// String [] paths = new String[] {"/5"};
// String [] paths = new String[] {"/"};
// String [] paths = new String[] {"/9"};
defaultLwM2MDownlinkMsgHandler.sendReadCompositeRequest(lwM2MClient, paths, this);
Map<String, Object> nodes = new HashMap<>();
nodes.put("/3/0/14", "+02");
nodes.put("/1/0/2", 100);
nodes.put("/5/0/1", "coap://localhost:5685");
defaultLwM2MDownlinkMsgHandler.sendWriteCompositeRequest(lwM2MClient, nodes, this);
this.sendObserveRequests(lwM2MClient, profile, supportedObjects);
this.sendWriteAttributeRequests(lwM2MClient, profile, supportedObjects);
// Removed. Used only for debug.
@ -712,6 +739,14 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
}
@Override
public void onWriteCompositeResponseOk(LwM2mClient client, WriteCompositeRequest request) {
log.warn("202) ReadCompositeResponse: [{}]", request.getNodes());
request.getNodes().forEach((k, v) -> {
this.updateResourcesValue(client, (LwM2mResource) v, k.toString());
});
}
//TODO: review and optimize the logic to minimize number of the requests to device.
private void onDeviceProfileUpdate(List<LwM2mClient> clients, DeviceProfile deviceProfile) {
var oldProfile = clientContext.getProfile(deviceProfile.getUuidId());

6
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/LwM2mUplinkMsgHandler.java

@ -16,7 +16,9 @@
package org.thingsboard.server.transport.lwm2m.server.uplink;
import org.eclipse.leshan.core.observation.Observation;
import org.eclipse.leshan.core.request.WriteCompositeRequest;
import org.eclipse.leshan.core.request.WriteRequest;
import org.eclipse.leshan.core.response.ReadCompositeResponse;
import org.eclipse.leshan.core.response.ReadResponse;
import org.eclipse.leshan.server.registration.Registration;
import org.thingsboard.server.common.data.Device;
@ -40,6 +42,8 @@ public interface LwM2mUplinkMsgHandler {
void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response);
void onUpdateValueAfterReadCompositeResponse(Registration registration, String path, ReadCompositeResponse response);
void onDeviceProfileUpdate(TransportProtos.SessionInfoProto sessionInfo, DeviceProfile deviceProfile);
void onDeviceUpdate(TransportProtos.SessionInfoProto sessionInfo, Device device, Optional<DeviceProfile> deviceProfileOpt);
@ -54,6 +58,8 @@ public interface LwM2mUplinkMsgHandler {
void onWriteResponseOk(LwM2mClient client, String path, WriteRequest request);
void onWriteCompositeResponseOk(LwM2mClient client, WriteCompositeRequest request);
void onToTransportUpdateCredentials(TransportProtos.ToTransportUpdateCredentialsProto updateCredentials);
LwM2MTransportServerConfig getConfig();

Loading…
Cancel
Save