From 99238feae030b6f5f340aafb6ce3561d11d94a85 Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Thu, 24 Jun 2021 18:28:27 +0300 Subject: [PATCH] Lwm2m: composite read/write --- .../lwm2m/server/LwM2mOperationType.java | 36 +++--- .../lwm2m/server/LwM2mTransportUtil.java | 1 + .../DefaultLwM2mDownlinkMsgHandler.java | 107 +++++++++++++++++- .../server/downlink/HasContentFormat.java | 6 +- .../downlink/LwM2mDownlinkMsgHandler.java | 7 ++ .../downlink/TbLwM2MObserveRequest.java | 6 +- .../TbLwM2MReadCompositeCallback.java | 38 +++++++ .../downlink/TbLwM2MReadCompositeRequest.java | 44 +++++++ .../server/downlink/TbLwM2MReadRequest.java | 6 +- .../downlink/TbLwM2MTargetedCallback.java | 6 +- .../TbLwM2MWriteCompositeRequest.java | 45 ++++++++ ...TbLwM2MWriteResponseCompositeCallback.java | 36 ++++++ .../uplink/DefaultLwM2MUplinkMsgHandler.java | 41 ++++++- .../server/uplink/LwM2mUplinkMsgHandler.java | 6 + 14 files changed, 354 insertions(+), 31 deletions(-) create mode 100644 common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MReadCompositeCallback.java create mode 100644 common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MReadCompositeRequest.java create mode 100644 common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteCompositeRequest.java create mode 100644 common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteResponseCompositeCallback.java diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mOperationType.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mOperationType.java index f9b3f93854..29a8bd1626 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mOperationType.java +++ b/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; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportUtil.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportUtil.java index bbab28ded5..048d363205 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportUtil.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportUtil.java @@ -450,4 +450,5 @@ public class LwM2mTransportUtil { } return lwm2mResourceValue; } + } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java index 52ef83bf8e..041b7aea41 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java +++ b/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 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 callback) { + public void sendReadCompositeRequest(LwM2mClient client, String [] paths, DefaultLwM2MUplinkMsgHandler lwM2MUplinkMsgHandler) { +// validateVersionedId(client, request); + DownlinkRequestCallback 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 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 callback) { validateVersionedId(client, request); @@ -121,7 +153,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im Set 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 , T extends LwM2mResponse> void sendWriteCompositeRequest(LwM2mClient client, WriteCompositeRequest request, long timeoutInMs, DownlinkRequestCallback 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 , T extends LwM2mResponse> void sendReadRequestComposite(LwM2mClient client, ReadCompositeRequest request, long timeoutInMs, DownlinkRequestCallback 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(); } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/HasContentFormat.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/HasContentFormat.java index 6d2ecc98ed..f2618224e7 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/HasContentFormat.java +++ b/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; + } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/LwM2mDownlinkMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/LwM2mDownlinkMsgHandler.java index adb2e32293..48fe411e16 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/LwM2mDownlinkMsgHandler.java +++ b/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 callback); +// void sendReadCompositeRequest(LwM2mClient client, TbLwM2MReadCompositeRequest request, DownlinkRequestCallback callback); + void sendReadCompositeRequest(LwM2mClient client, String [] paths, DefaultLwM2MUplinkMsgHandler lwM2MUplinkMsgHandler); + void sendObserveRequest(LwM2mClient client, TbLwM2MObserveRequest request, DownlinkRequestCallback callback); void sendObserveAllRequest(LwM2mClient client, TbLwM2MObserveAllRequest request, DownlinkRequestCallback> callback); @@ -59,6 +64,8 @@ public interface LwM2mDownlinkMsgHandler { void sendWriteReplaceRequest(LwM2mClient client, TbLwM2MWriteReplaceRequest request, DownlinkRequestCallback callback); + void sendWriteCompositeRequest(LwM2mClient client, Map nodes, DefaultLwM2MUplinkMsgHandler handler); + void sendWriteUpdateRequest(LwM2mClient client, TbLwM2MWriteUpdateRequest request, DownlinkRequestCallback callback); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MObserveRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MObserveRequest.java index f3348aa2c9..0d13b4a1ff 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MObserveRequest.java +++ b/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 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 diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MReadCompositeCallback.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MReadCompositeCallback.java new file mode 100644 index 0000000000..4dbece6daa --- /dev/null +++ b/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 { + + 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); + } + +} diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MReadCompositeRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MReadCompositeRequest.java new file mode 100644 index 0000000000..1e45427aba --- /dev/null +++ b/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 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; + } + +} diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MReadRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MReadRequest.java index a07e738465..6f388237c2 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MReadRequest.java +++ b/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 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 diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MTargetedCallback.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MTargetedCallback.java index 373c882ec4..a7d0572b38 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MTargetedCallback.java +++ b/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 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("(? { + + @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; + } + + + +} diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteResponseCompositeCallback.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteResponseCompositeCallback.java new file mode 100644 index 0000000000..0d681ed486 --- /dev/null +++ b/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 { + + 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); + } + +} diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2MUplinkMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2MUplinkMsgHandler.java index 1d14de3ba0..ad13254f37 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2MUplinkMsgHandler.java +++ b/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 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 clients, DeviceProfile deviceProfile) { var oldProfile = clientContext.getProfile(deviceProfile.getUuidId()); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/LwM2mUplinkMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/LwM2mUplinkMsgHandler.java index 372daa7052..7926e90907 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/LwM2mUplinkMsgHandler.java +++ b/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 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();