Commit a94810126dfa08057f0d10f41da11dec59e5b250

Authored by nickAS21
1 parent 83bfa14d

Lwm2m: RPC composite read

Showing 25 changed files with 438 additions and 101 deletions
@@ -27,5 +27,6 @@ public class OtherConfiguration { @@ -27,5 +27,6 @@ public class OtherConfiguration {
27 private PowerMode powerMode; 27 private PowerMode powerMode;
28 private String fwUpdateResource; 28 private String fwUpdateResource;
29 private String swUpdateResource; 29 private String swUpdateResource;
  30 + private boolean composite;
30 31
31 } 32 }
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.transport.lwm2m.config;
  17 +
  18 +import lombok.Getter;
  19 +import org.eclipse.leshan.core.LwM2m.Version;
  20 +import org.eclipse.leshan.core.request.ContentFormat;
  21 +
  22 +public enum LwM2mVersion {
  23 + VERSION_1_0(0, Version.V1_0, ContentFormat.TLV),
  24 + VERSION_1_1(1, Version.V1_1, ContentFormat.TEXT);
  25 +
  26 + @Getter
  27 + private final int code;
  28 + @Getter
  29 + private final Version version;
  30 + @Getter
  31 + private final ContentFormat contentFormat;
  32 +
  33 + LwM2mVersion(int code, Version version, ContentFormat contentFormat) {
  34 + this.code = code;
  35 + this.version = version;
  36 + this.contentFormat = contentFormat;
  37 + }
  38 +
  39 + public static LwM2mVersion fromType(Version version) {
  40 + for (LwM2mVersion to : LwM2mVersion.values()) {
  41 + if (to.version.equals(version)) {
  42 + return to;
  43 + }
  44 + }
  45 + throw new IllegalArgumentException(String.format("Unsupported typeLwM2mVersion type : %d", version));
  46 + }
  47 +
  48 + public static ContentFormat fromContentFormat(String versionStr) {
  49 + for (LwM2mVersion to : LwM2mVersion.values()) {
  50 + if (to.version.toString().equals(versionStr)) {
  51 + return to.contentFormat;
  52 + }
  53 + }
  54 + throw new IllegalArgumentException(String.format("Unsupported contentFormatLwM2mVersion version : %d", versionStr));
  55 + }
  56 +
  57 + public static LwM2mVersion fromCode(int code) {
  58 + for (LwM2mVersion to : LwM2mVersion.values()) {
  59 + if (to.code == code) {
  60 + return to;
  61 + }
  62 + }
  63 + throw new IllegalArgumentException(String.format("Unsupported codeLwM2mVersion code : %d", code));
  64 + }
  65 +}
  66 +
@@ -22,37 +22,37 @@ import lombok.Getter; @@ -22,37 +22,37 @@ import lombok.Getter;
22 */ 22 */
23 public enum LwM2mOperationType { 23 public enum LwM2mOperationType {
24 24
25 - READ(0, "Read", true),  
26 - READ_COMPOSITE(1, "ReadComposite", true),  
27 - DISCOVER(2, "Discover", true),  
28 - DISCOVER_ALL(3, "DiscoverAll", false),  
29 - OBSERVE_READ_ALL(4, "ObserveReadAll", false), 25 + READ(0, "Read", 1),
  26 + READ_COMPOSITE(1, "ReadComposite", 2),
  27 + DISCOVER(2, "Discover", 1),
  28 + DISCOVER_ALL(3, "DiscoverAll", 0),
  29 + OBSERVE_READ_ALL(4, "ObserveReadAll", 0),
30 30
31 - OBSERVE(5, "Observe", true),  
32 - OBSERVE_COMPOSITE(6, "ObserveComposite", true),  
33 - OBSERVE_CANCEL(7, "ObserveCancel", true),  
34 - OBSERVE_COMPOSITE_CANCEL(8, "ObserveCompositeCancel", true),  
35 - OBSERVE_CANCEL_ALL(9, "ObserveCancelAll", false),  
36 - EXECUTE(10, "Execute", true), 31 + OBSERVE(5, "Observe", 1),
  32 + OBSERVE_COMPOSITE(6, "ObserveComposite", 2),
  33 + OBSERVE_CANCEL(7, "ObserveCancel", 1),
  34 + OBSERVE_COMPOSITE_CANCEL(8, "ObserveCompositeCancel", 2),
  35 + OBSERVE_CANCEL_ALL(9, "ObserveCancelAll", 0),
  36 + EXECUTE(10, "Execute", 1),
37 /** 37 /**
38 * Replaces the Object Instance or the Resource(s) with the new value provided in the “Write” operation. (see 38 * Replaces the Object Instance or the Resource(s) with the new value provided in the “Write” operation. (see
39 * section 5.3.3 of the LW M2M spec). 39 * section 5.3.3 of the LW M2M spec).
40 * if all resources are to be replaced 40 * if all resources are to be replaced
41 */ 41 */
42 - WRITE_REPLACE(11, "WriteReplace", true), 42 + WRITE_REPLACE(11, "WriteReplace", 1),
43 43
44 /** 44 /**
45 * Adds or updates Resources provided in the new value and leaves other existing Resources unchanged. (see section 45 * Adds or updates Resources provided in the new value and leaves other existing Resources unchanged. (see section
46 * 5.3.3 of the LW M2M spec). 46 * 5.3.3 of the LW M2M spec).
47 * if this is a partial update request 47 * if this is a partial update request
48 */ 48 */
49 - WRITE_UPDATE(12, "WriteUpdate", true),  
50 - WRITE_COMPOSITE(14, "WriteComposite", true),  
51 - WRITE_ATTRIBUTES(15, "WriteAttributes", true),  
52 - DELETE(16, "Delete", true), 49 + WRITE_UPDATE(12, "WriteUpdate", 1),
  50 + WRITE_COMPOSITE(14, "WriteComposite", 2),
  51 + WRITE_ATTRIBUTES(15, "WriteAttributes", 1),
  52 + DELETE(16, "Delete", 1),
53 53
54 // only for RPC 54 // only for RPC
55 - FW_UPDATE(17, "FirmwareUpdate", false); 55 + FW_UPDATE(17, "FirmwareUpdate", 0);
56 56
57 // FW_READ_INFO(18, "FirmwareReadInfo"), 57 // FW_READ_INFO(18, "FirmwareReadInfo"),
58 // SW_READ_INFO(19, "SoftwareReadInfo"), 58 // SW_READ_INFO(19, "SoftwareReadInfo"),
@@ -64,12 +64,12 @@ public enum LwM2mOperationType { @@ -64,12 +64,12 @@ public enum LwM2mOperationType {
64 @Getter 64 @Getter
65 private final String type; 65 private final String type;
66 @Getter 66 @Getter
67 - private final boolean hasObjectId; 67 + private final int hasObjectIdOrComposite;
68 68
69 - LwM2mOperationType(int code, String type, boolean hasObjectId) { 69 + LwM2mOperationType(int code, String type, int hasObjectIdOrComposite) {
70 this.code = code; 70 this.code = code;
71 this.type = type; 71 this.type = type;
72 - this.hasObjectId = hasObjectId; 72 + this.hasObjectIdOrComposite = hasObjectIdOrComposite;
73 } 73 }
74 74
75 public static LwM2mOperationType fromType(String type) { 75 public static LwM2mOperationType fromType(String type) {
@@ -44,6 +44,7 @@ import org.thingsboard.server.common.data.device.data.lwm2m.BootstrapConfigurati @@ -44,6 +44,7 @@ import org.thingsboard.server.common.data.device.data.lwm2m.BootstrapConfigurati
44 import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration; 44 import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration;
45 import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; 45 import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration;
46 import org.thingsboard.server.common.transport.TransportServiceCallback; 46 import org.thingsboard.server.common.transport.TransportServiceCallback;
  47 +import org.thingsboard.server.transport.lwm2m.config.LwM2mVersion;
47 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; 48 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
48 import org.thingsboard.server.transport.lwm2m.server.client.ResourceValue; 49 import org.thingsboard.server.transport.lwm2m.server.client.ResourceValue;
49 import org.thingsboard.server.transport.lwm2m.server.ota.firmware.FirmwareUpdateResult; 50 import org.thingsboard.server.transport.lwm2m.server.ota.firmware.FirmwareUpdateResult;
@@ -85,7 +86,7 @@ import static org.thingsboard.server.transport.lwm2m.server.ota.DefaultLwM2MOtaU @@ -85,7 +86,7 @@ import static org.thingsboard.server.transport.lwm2m.server.ota.DefaultLwM2MOtaU
85 @Slf4j 86 @Slf4j
86 public class LwM2mTransportUtil { 87 public class LwM2mTransportUtil {
87 88
88 - public static final String LWM2M_VERSION_DEFAULT = "1.0"; 89 + public static final String LWM2M_OBJECT_VERSION_DEFAULT = "1.0";
89 90
90 public static final String LOG_LWM2M_TELEMETRY = "logLwm2m"; 91 public static final String LOG_LWM2M_TELEMETRY = "logLwm2m";
91 public static final String LOG_LWM2M_INFO = "info"; 92 public static final String LOG_LWM2M_INFO = "info";
@@ -303,7 +304,7 @@ public class LwM2mTransportUtil { @@ -303,7 +304,7 @@ public class LwM2mTransportUtil {
303 304
304 public static String convertObjectIdToVersionedId(String path, Registration registration) { 305 public static String convertObjectIdToVersionedId(String path, Registration registration) {
305 String ver = registration.getSupportedObject().get(new LwM2mPath(path).getObjectId()); 306 String ver = registration.getSupportedObject().get(new LwM2mPath(path).getObjectId());
306 - ver = ver != null ? ver : LWM2M_VERSION_DEFAULT; 307 + ver = ver != null ? ver : LwM2mVersion.VERSION_1_0.getVersion().toString();
307 try { 308 try {
308 String[] keyArray = path.split(LWM2M_SEPARATOR_PATH); 309 String[] keyArray = path.split(LWM2M_SEPARATOR_PATH);
309 if (keyArray.length > 1) { 310 if (keyArray.length > 1) {
@@ -38,6 +38,7 @@ import org.thingsboard.server.common.data.id.TenantId; @@ -38,6 +38,7 @@ import org.thingsboard.server.common.data.id.TenantId;
38 import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; 38 import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
39 import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; 39 import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto;
40 import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto; 40 import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto;
  41 +import org.thingsboard.server.transport.lwm2m.config.LwM2mVersion;
41 import org.thingsboard.server.transport.lwm2m.server.LwM2mQueuedRequest; 42 import org.thingsboard.server.transport.lwm2m.server.LwM2mQueuedRequest;
42 43
43 import java.util.Collection; 44 import java.util.Collection;
@@ -53,7 +54,7 @@ import java.util.concurrent.locks.ReentrantLock; @@ -53,7 +54,7 @@ import java.util.concurrent.locks.ReentrantLock;
53 import java.util.stream.Collectors; 54 import java.util.stream.Collectors;
54 55
55 import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH; 56 import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH;
56 -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LWM2M_VERSION_DEFAULT; 57 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LWM2M_OBJECT_VERSION_DEFAULT;
57 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertObjectIdToVersionedId; 58 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertObjectIdToVersionedId;
58 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.equalsResourceTypeGetSimpleName; 59 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.equalsResourceTypeGetSimpleName;
59 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.fromVersionedIdToObjectId; 60 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.fromVersionedIdToObjectId;
@@ -243,11 +244,11 @@ public class LwM2mClient implements Cloneable { @@ -243,11 +244,11 @@ public class LwM2mClient implements Cloneable {
243 .getObjectModel(pathIds.getObjectId()) : null; 244 .getObjectModel(pathIds.getObjectId()) : null;
244 } 245 }
245 246
246 - public String objectToString(LwM2mObject lwM2mObject, LwM2mValueConverter converter, String pathIdVer) { 247 + public String objectToString(LwM2mObject lwM2mObject) {
247 StringBuilder builder = new StringBuilder(); 248 StringBuilder builder = new StringBuilder();
248 builder.append("LwM2mObject [id=").append(lwM2mObject.getId()).append(", instances={"); 249 builder.append("LwM2mObject [id=").append(lwM2mObject.getId()).append(", instances={");
249 lwM2mObject.getInstances().forEach((instId, inst) -> { 250 lwM2mObject.getInstances().forEach((instId, inst) -> {
250 - builder.append(instId).append("=").append(this.instanceToString(inst, converter, pathIdVer)).append(", "); 251 + builder.append(instId).append("=").append(this.instanceToString(inst)).append(", ");
251 }); 252 });
252 int startInd = builder.lastIndexOf(", "); 253 int startInd = builder.lastIndexOf(", ");
253 if (startInd > 0) { 254 if (startInd > 0) {
@@ -257,11 +258,11 @@ public class LwM2mClient implements Cloneable { @@ -257,11 +258,11 @@ public class LwM2mClient implements Cloneable {
257 return builder.toString(); 258 return builder.toString();
258 } 259 }
259 260
260 - public String instanceToString(LwM2mObjectInstance objectInstance, LwM2mValueConverter converter, String pathIdVer) { 261 + public String instanceToString(LwM2mObjectInstance objectInstance) {
261 StringBuilder builder = new StringBuilder(); 262 StringBuilder builder = new StringBuilder();
262 builder.append("LwM2mObjectInstance [id=").append(objectInstance.getId()).append(", resources={"); 263 builder.append("LwM2mObjectInstance [id=").append(objectInstance.getId()).append(", resources={");
263 objectInstance.getResources().forEach((resId, res) -> { 264 objectInstance.getResources().forEach((resId, res) -> {
264 - builder.append(resId).append("=").append(this.resourceToString(res, converter, pathIdVer)).append(", "); 265 + builder.append(resId).append("=").append(this.resourceToString(res)).append(", ");
265 }); 266 });
266 int startInd = builder.lastIndexOf(", "); 267 int startInd = builder.lastIndexOf(", ");
267 if (startInd > 0) { 268 if (startInd > 0) {
@@ -271,8 +272,9 @@ public class LwM2mClient implements Cloneable { @@ -271,8 +272,9 @@ public class LwM2mClient implements Cloneable {
271 return builder.toString(); 272 return builder.toString();
272 } 273 }
273 274
274 - public String resourceToString(LwM2mResource lwM2mResource, LwM2mValueConverter converter, String pathIdVer) {  
275 - return lwM2mResource.getValue().toString(); 275 + public String resourceToString(LwM2mResource lwM2mResource) {
  276 +
  277 + return lwM2mResource.isMultiInstances() ? lwM2mResource.getInstances().toString() : lwM2mResource.getValue().toString();
276 } 278 }
277 279
278 public Collection<LwM2mResource> getNewResourceForInstance(String pathRezIdVer, Object params, LwM2mModelProvider modelProvider, 280 public Collection<LwM2mResource> getNewResourceForInstance(String pathRezIdVer, Object params, LwM2mModelProvider modelProvider,
@@ -308,11 +310,14 @@ public class LwM2mClient implements Cloneable { @@ -308,11 +310,14 @@ public class LwM2mClient implements Cloneable {
308 return resources; 310 return resources;
309 } 311 }
310 312
311 - public boolean isValidObjectVersion(String path) { 313 + public void isValidObjectVersion(String path) {
312 LwM2mPath pathIds = new LwM2mPath(fromVersionedIdToObjectId(path)); 314 LwM2mPath pathIds = new LwM2mPath(fromVersionedIdToObjectId(path));
313 String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId()); 315 String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId());
314 String verRez = getVerFromPathIdVerOrId(path); 316 String verRez = getVerFromPathIdVerOrId(path);
315 - return verRez == null ? LWM2M_VERSION_DEFAULT.equals(verSupportedObject) : verRez.equals(verSupportedObject); 317 + if ((verRez != null && !verRez.equals(verSupportedObject)) ||
  318 + (verRez == null && !LWM2M_OBJECT_VERSION_DEFAULT.equals(verSupportedObject))) {
  319 + throw new IllegalArgumentException(String.format("Specified resource id %s is not valid version! Must be version: %s", path, verSupportedObject));
  320 + }
316 } 321 }
317 322
318 /** 323 /**
@@ -357,10 +362,8 @@ public class LwM2mClient implements Cloneable { @@ -357,10 +362,8 @@ public class LwM2mClient implements Cloneable {
357 public ContentFormat getDefaultContentFormat() { 362 public ContentFormat getDefaultContentFormat() {
358 if (registration == null) { 363 if (registration == null) {
359 return ContentFormat.DEFAULT; 364 return ContentFormat.DEFAULT;
360 - } else if (registration.getLwM2mVersion().equals("1.0")) {  
361 - return ContentFormat.TLV;  
362 } else { 365 } else {
363 - return ContentFormat.TEXT; 366 + return LwM2mVersion.fromContentFormat(registration.getLwM2mVersion());
364 } 367 }
365 } 368 }
366 369
@@ -57,6 +57,8 @@ import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; @@ -57,6 +57,8 @@ import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
57 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext; 57 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext;
58 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; 58 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
59 import org.thingsboard.server.transport.lwm2m.server.common.LwM2MExecutorAwareService; 59 import org.thingsboard.server.transport.lwm2m.server.common.LwM2MExecutorAwareService;
  60 +import org.thingsboard.server.transport.lwm2m.server.downlink.composite.TbLwM2MReadCompositeRequest;
  61 +import org.thingsboard.server.transport.lwm2m.server.downlink.composite.TbLwM2MWriteResponseCompositeCallback;
60 import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService; 62 import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
61 import org.thingsboard.server.transport.lwm2m.server.uplink.DefaultLwM2MUplinkMsgHandler; 63 import org.thingsboard.server.transport.lwm2m.server.uplink.DefaultLwM2MUplinkMsgHandler;
62 import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; 64 import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;
@@ -79,6 +81,7 @@ import static org.eclipse.leshan.core.attributes.Attribute.LESSER_THAN; @@ -79,6 +81,7 @@ import static org.eclipse.leshan.core.attributes.Attribute.LESSER_THAN;
79 import static org.eclipse.leshan.core.attributes.Attribute.MAXIMUM_PERIOD; 81 import static org.eclipse.leshan.core.attributes.Attribute.MAXIMUM_PERIOD;
80 import static org.eclipse.leshan.core.attributes.Attribute.MINIMUM_PERIOD; 82 import static org.eclipse.leshan.core.attributes.Attribute.MINIMUM_PERIOD;
81 import static org.eclipse.leshan.core.attributes.Attribute.STEP; 83 import static org.eclipse.leshan.core.attributes.Attribute.STEP;
  84 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.fromVersionedIdToObjectId;
82 85
83 @Slf4j 86 @Slf4j
84 @Service 87 @Service
@@ -121,27 +124,26 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im @@ -121,27 +124,26 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
121 } 124 }
122 125
123 @Override 126 @Override
124 -// public void sendReadCompositeRequest(LwM2mClient client, TbLwM2MReadCompositeRequest request, DownlinkRequestCallback<ReadCompositeRequest, ReadCompositeResponse> callback) {  
125 - public void sendReadCompositeRequest(LwM2mClient client, String [] paths, DefaultLwM2MUplinkMsgHandler lwM2MUplinkMsgHandler) {  
126 -// validateVersionedId(client, request);  
127 - DownlinkRequestCallback<ReadCompositeRequest, ReadCompositeResponse> callback = new TbLwM2MReadCompositeCallback(lwM2MUplinkMsgHandler, logService, client, null); 127 + public void sendReadCompositeRequest(LwM2mClient client, TbLwM2MReadCompositeRequest request, DownlinkRequestCallback<ReadCompositeRequest, ReadCompositeResponse> callback) {
  128 + validateVersionedIds(client, request);
128 ContentFormat requestContentFormat = ContentFormat.SENML_JSON; 129 ContentFormat requestContentFormat = ContentFormat.SENML_JSON;
129 ContentFormat responseContentFormat = ContentFormat.SENML_JSON; 130 ContentFormat responseContentFormat = ContentFormat.SENML_JSON;
130 - ReadCompositeRequest downlink = new ReadCompositeRequest(requestContentFormat, responseContentFormat, paths); 131 +
  132 + ReadCompositeRequest downlink = new ReadCompositeRequest(requestContentFormat, responseContentFormat, request.getObjectIds());
131 sendReadRequestComposite(client, downlink, this.config.getTimeout(), callback); 133 sendReadRequestComposite(client, downlink, this.config.getTimeout(), callback);
132 } 134 }
133 135
134 @Override 136 @Override
135 public void sendWriteCompositeRequest(LwM2mClient client, Map<String, Object> nodes, DefaultLwM2MUplinkMsgHandler handler) { 137 public void sendWriteCompositeRequest(LwM2mClient client, Map<String, Object> nodes, DefaultLwM2MUplinkMsgHandler handler) {
136 // ResourceModel resourceModelWrite = client.getResourceModel(request.getVersionedId(), this.config.getModelProvider()); 138 // ResourceModel resourceModelWrite = client.getResourceModel(request.getVersionedId(), this.config.getModelProvider());
137 - TbLwM2MWriteResponseCompositeCallback callback = new TbLwM2MWriteResponseCompositeCallback (handler, logService, client, null);  
138 - ContentFormat contentFormat = ContentFormat.SENML_JSON;  
139 - try {  
140 - WriteCompositeRequest downlink = new WriteCompositeRequest(contentFormat, nodes);  
141 - sendWriteCompositeRequest(client, downlink, this.config.getTimeout(), callback);  
142 - } catch (Exception e) {  
143 - callback.onError(JacksonUtil.toString(nodes), e);  
144 - } 139 + TbLwM2MWriteResponseCompositeCallback callback = new TbLwM2MWriteResponseCompositeCallback(handler, logService, client, null);
  140 + ContentFormat contentFormat = ContentFormat.SENML_JSON;
  141 + try {
  142 + WriteCompositeRequest downlink = new WriteCompositeRequest(contentFormat, nodes);
  143 + sendWriteCompositeRequest(client, downlink, this.config.getTimeout(), callback);
  144 + } catch (Exception e) {
  145 + callback.onError(JacksonUtil.toString(nodes), e);
  146 + }
145 147
146 } 148 }
147 149
@@ -277,7 +279,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im @@ -277,7 +279,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
277 */ 279 */
278 Collection<LwM2mResource> resources = client.getNewResourcesForInstance(request.getVersionedId(), request.getValue(), this.config.getModelProvider(), this.converter); 280 Collection<LwM2mResource> resources = client.getNewResourcesForInstance(request.getVersionedId(), request.getValue(), this.config.getModelProvider(), this.converter);
279 if (resources.size() > 0) { 281 if (resources.size() > 0) {
280 - ContentFormat contentFormat = request.getObjectContentFormat() != null ? request.getObjectContentFormat() : client.getDefaultContentFormat(); 282 + ContentFormat contentFormat = request.getObjectContentFormat() != null ? request.getObjectContentFormat() : ContentFormat.DEFAULT;
281 WriteRequest downlink = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resources); 283 WriteRequest downlink = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resources);
282 sendRequest(client, downlink, request.getTimeout(), callback); 284 sendRequest(client, downlink, request.getTimeout(), callback);
283 } else { 285 } else {
@@ -407,14 +409,23 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im @@ -407,14 +409,23 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
407 } 409 }
408 410
409 private void validateVersionedId(LwM2mClient client, HasVersionedId request) { 411 private void validateVersionedId(LwM2mClient client, HasVersionedId request) {
410 - if (!client.isValidObjectVersion(request.getVersionedId())) {  
411 - throw new IllegalArgumentException("Specified resource id is not configured in the device profile!");  
412 - } 412 + client.isValidObjectVersion(request.getVersionedId());
413 if (request.getObjectId() == null) { 413 if (request.getObjectId() == null) {
414 throw new IllegalArgumentException("Specified object id is null!"); 414 throw new IllegalArgumentException("Specified object id is null!");
415 } 415 }
416 } 416 }
417 417
  418 + private void validateVersionedIds(LwM2mClient client, HasVersionedIds request) {
  419 + for (String versionedId : request.getVersionedIds()) {
  420 + client.isValidObjectVersion(versionedId);
  421 + }
  422 + for (String objectId : request.getObjectIds()) {
  423 + if (objectId == null) {
  424 + throw new IllegalArgumentException("Specified object id is null!");
  425 + }
  426 + }
  427 + }
  428 +
418 private static <T> void addAttribute(List<Attribute> attributes, String attributeName, T value) { 429 private static <T> void addAttribute(List<Attribute> attributes, String attributeName, T value) {
419 addAttribute(attributes, attributeName, value, null, null); 430 addAttribute(attributes, attributeName, value, null, null);
420 } 431 }
@@ -447,6 +458,15 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im @@ -447,6 +458,15 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
447 } 458 }
448 459
449 private static ContentFormat getRequestContentFormat(LwM2mClient client, HasContentFormat request) { 460 private static ContentFormat getRequestContentFormat(LwM2mClient client, HasContentFormat request) {
450 - return request.getRequestContentFormat() != null ? request.getRequestContentFormat() : client.getDefaultContentFormat(); 461 + if (request.getRequestContentFormat() != null) {
  462 + return request.getRequestContentFormat();
  463 + } else {
  464 + String versionedId = fromVersionedIdToObjectId(((TbLwM2MReadRequest) request).getVersionedId());
  465 + if (versionedId != null && (new LwM2mPath(versionedId).isObject() || new LwM2mPath(versionedId).isObjectInstance())) {
  466 + return ContentFormat.DEFAULT;
  467 + } else {
  468 + return client.getDefaultContentFormat();
  469 + }
  470 + }
451 } 471 }
452 } 472 }
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.transport.lwm2m.server.downlink;
  17 +
  18 +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil;
  19 +
  20 +import java.util.Set;
  21 +import java.util.concurrent.ConcurrentHashMap;
  22 +
  23 +public interface HasVersionedIds {
  24 +
  25 + String[] getVersionedIds();
  26 +
  27 + default String[] getObjectIds() {
  28 + Set objectIds = ConcurrentHashMap.newKeySet();
  29 + for (String versionedId : getVersionedIds()) {
  30 + objectIds.add(LwM2mTransportUtil.fromVersionedIdToObjectId(versionedId));
  31 + }
  32 + return (String[]) objectIds.toArray(String[]::new);
  33 + }
  34 +
  35 +}
@@ -20,6 +20,7 @@ import org.eclipse.leshan.core.request.DeleteRequest; @@ -20,6 +20,7 @@ import org.eclipse.leshan.core.request.DeleteRequest;
20 import org.eclipse.leshan.core.request.DiscoverRequest; 20 import org.eclipse.leshan.core.request.DiscoverRequest;
21 import org.eclipse.leshan.core.request.ExecuteRequest; 21 import org.eclipse.leshan.core.request.ExecuteRequest;
22 import org.eclipse.leshan.core.request.ObserveRequest; 22 import org.eclipse.leshan.core.request.ObserveRequest;
  23 +import org.eclipse.leshan.core.request.ReadCompositeRequest;
23 import org.eclipse.leshan.core.request.ReadRequest; 24 import org.eclipse.leshan.core.request.ReadRequest;
24 import org.eclipse.leshan.core.request.WriteAttributesRequest; 25 import org.eclipse.leshan.core.request.WriteAttributesRequest;
25 import org.eclipse.leshan.core.request.WriteRequest; 26 import org.eclipse.leshan.core.request.WriteRequest;
@@ -27,10 +28,12 @@ import org.eclipse.leshan.core.response.DeleteResponse; @@ -27,10 +28,12 @@ import org.eclipse.leshan.core.response.DeleteResponse;
27 import org.eclipse.leshan.core.response.DiscoverResponse; 28 import org.eclipse.leshan.core.response.DiscoverResponse;
28 import org.eclipse.leshan.core.response.ExecuteResponse; 29 import org.eclipse.leshan.core.response.ExecuteResponse;
29 import org.eclipse.leshan.core.response.ObserveResponse; 30 import org.eclipse.leshan.core.response.ObserveResponse;
  31 +import org.eclipse.leshan.core.response.ReadCompositeResponse;
30 import org.eclipse.leshan.core.response.ReadResponse; 32 import org.eclipse.leshan.core.response.ReadResponse;
31 import org.eclipse.leshan.core.response.WriteAttributesResponse; 33 import org.eclipse.leshan.core.response.WriteAttributesResponse;
32 import org.eclipse.leshan.core.response.WriteResponse; 34 import org.eclipse.leshan.core.response.WriteResponse;
33 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; 35 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
  36 +import org.thingsboard.server.transport.lwm2m.server.downlink.composite.TbLwM2MReadCompositeRequest;
34 import org.thingsboard.server.transport.lwm2m.server.uplink.DefaultLwM2MUplinkMsgHandler; 37 import org.thingsboard.server.transport.lwm2m.server.uplink.DefaultLwM2MUplinkMsgHandler;
35 38
36 import java.util.List; 39 import java.util.List;
@@ -41,8 +44,7 @@ public interface LwM2mDownlinkMsgHandler { @@ -41,8 +44,7 @@ public interface LwM2mDownlinkMsgHandler {
41 44
42 void sendReadRequest(LwM2mClient client, TbLwM2MReadRequest request, DownlinkRequestCallback<ReadRequest, ReadResponse> callback); 45 void sendReadRequest(LwM2mClient client, TbLwM2MReadRequest request, DownlinkRequestCallback<ReadRequest, ReadResponse> callback);
43 46
44 -// void sendReadCompositeRequest(LwM2mClient client, TbLwM2MReadCompositeRequest request, DownlinkRequestCallback<ReadCompositeRequest, ReadCompositeResponse> callback);  
45 - void sendReadCompositeRequest(LwM2mClient client, String [] paths, DefaultLwM2MUplinkMsgHandler lwM2MUplinkMsgHandler); 47 + void sendReadCompositeRequest(LwM2mClient client, TbLwM2MReadCompositeRequest request, DownlinkRequestCallback<ReadCompositeRequest, ReadCompositeResponse> callback);
46 48
47 void sendObserveRequest(LwM2mClient client, TbLwM2MObserveRequest request, DownlinkRequestCallback<ObserveRequest, ObserveResponse> callback); 49 void sendObserveRequest(LwM2mClient client, TbLwM2MObserveRequest request, DownlinkRequestCallback<ObserveRequest, ObserveResponse> callback);
48 50
@@ -25,15 +25,18 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.L @@ -25,15 +25,18 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.L
25 public abstract class TbLwM2MTargetedCallback<R, T> extends AbstractTbLwM2MRequestCallback<R, T> { 25 public abstract class TbLwM2MTargetedCallback<R, T> extends AbstractTbLwM2MRequestCallback<R, T> {
26 26
27 protected final String versionedId; 27 protected final String versionedId;
  28 + protected final String[] versionedIds;
28 29
29 public TbLwM2MTargetedCallback(LwM2MTelemetryLogService logService, LwM2mClient client, String versionedId) { 30 public TbLwM2MTargetedCallback(LwM2MTelemetryLogService logService, LwM2mClient client, String versionedId) {
30 super(logService, client); 31 super(logService, client);
31 this.versionedId = versionedId; 32 this.versionedId = versionedId;
  33 + this.versionedIds = null;
32 } 34 }
33 35
34 - public TbLwM2MTargetedCallback(LwM2MTelemetryLogService logService, LwM2mClient client) { 36 + public TbLwM2MTargetedCallback(LwM2MTelemetryLogService logService, LwM2mClient client, String[] versionedIds) {
35 super(logService, client); 37 super(logService, client);
36 this.versionedId = null; 38 this.versionedId = null;
  39 + this.versionedIds = versionedIds;
37 } 40 }
38 41
39 @Override 42 @Override
@@ -20,8 +20,6 @@ import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; @@ -20,8 +20,6 @@ import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
20 import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService; 20 import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
21 import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler; 21 import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler;
22 22
23 -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LWM2M_INFO;  
24 -  
25 @Slf4j 23 @Slf4j
26 public abstract class TbLwM2MUplinkTargetedCallback<R, T> extends TbLwM2MTargetedCallback<R, T> { 24 public abstract class TbLwM2MUplinkTargetedCallback<R, T> extends TbLwM2MTargetedCallback<R, T> {
27 25
@@ -32,4 +30,9 @@ public abstract class TbLwM2MUplinkTargetedCallback<R, T> extends TbLwM2MTargete @@ -32,4 +30,9 @@ public abstract class TbLwM2MUplinkTargetedCallback<R, T> extends TbLwM2MTargete
32 this.handler = handler; 30 this.handler = handler;
33 } 31 }
34 32
  33 + public TbLwM2MUplinkTargetedCallback(LwM2mUplinkMsgHandler handler, LwM2MTelemetryLogService logService, LwM2mClient client, String[] versionedIds) {
  34 + super(logService, client, versionedIds);
  35 + this.handler = handler;
  36 + }
  37 +
35 } 38 }
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.transport.lwm2m.server.downlink.composite;
  17 +
  18 +import lombok.Getter;
  19 +import org.thingsboard.server.transport.lwm2m.server.downlink.HasVersionedIds;
  20 +import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MDownlinkRequest;
  21 +
  22 +public abstract class AbstractTbLwM2MTargetedDownlinkCompositeRequest<T> implements TbLwM2MDownlinkRequest<T>, HasVersionedIds {
  23 +
  24 + @Getter
  25 + private final String [] versionedIds;
  26 + @Getter
  27 + private final long timeout;
  28 +
  29 + public AbstractTbLwM2MTargetedDownlinkCompositeRequest(String [] versionedIds, long timeout) {
  30 + this.versionedIds = versionedIds;
  31 + this.timeout = timeout;
  32 + }
  33 +
  34 +}
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/composite/TbLwM2MReadCompositeCallback.java renamed from common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MReadCompositeCallback.java
@@ -13,26 +13,27 @@ @@ -13,26 +13,27 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.transport.lwm2m.server.downlink; 16 +package org.thingsboard.server.transport.lwm2m.server.downlink.composite;
17 17
18 import lombok.extern.slf4j.Slf4j; 18 import lombok.extern.slf4j.Slf4j;
19 import org.eclipse.leshan.core.request.ReadCompositeRequest; 19 import org.eclipse.leshan.core.request.ReadCompositeRequest;
20 import org.eclipse.leshan.core.response.ReadCompositeResponse; 20 import org.eclipse.leshan.core.response.ReadCompositeResponse;
21 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; 21 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
  22 +import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MUplinkTargetedCallback;
22 import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService; 23 import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
23 import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler; 24 import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler;
24 25
25 @Slf4j 26 @Slf4j
26 public class TbLwM2MReadCompositeCallback extends TbLwM2MUplinkTargetedCallback<ReadCompositeRequest, ReadCompositeResponse> { 27 public class TbLwM2MReadCompositeCallback extends TbLwM2MUplinkTargetedCallback<ReadCompositeRequest, ReadCompositeResponse> {
27 28
28 - public TbLwM2MReadCompositeCallback(LwM2mUplinkMsgHandler handler, LwM2MTelemetryLogService logService, LwM2mClient client, String targetId) {  
29 - super(handler, logService, client, targetId); 29 + public TbLwM2MReadCompositeCallback(LwM2mUplinkMsgHandler handler, LwM2MTelemetryLogService logService, LwM2mClient client, String[] versionedIds) {
  30 + super(handler, logService, client, versionedIds);
30 } 31 }
31 32
32 @Override 33 @Override
33 public void onSuccess(ReadCompositeRequest request, ReadCompositeResponse response) { 34 public void onSuccess(ReadCompositeRequest request, ReadCompositeResponse response) {
34 super.onSuccess(request, response); 35 super.onSuccess(request, response);
35 - handler.onUpdateValueAfterReadCompositeResponse(client.getRegistration(), versionedId, response); 36 + handler.onUpdateValueAfterReadCompositeResponse(client.getRegistration(), response);
36 } 37 }
37 38
38 } 39 }
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/composite/TbLwM2MReadCompositeRequest.java renamed from common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MReadCompositeRequest.java
@@ -13,15 +13,16 @@ @@ -13,15 +13,16 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.transport.lwm2m.server.downlink; 16 +package org.thingsboard.server.transport.lwm2m.server.downlink.composite;
17 17
18 import lombok.Builder; 18 import lombok.Builder;
19 import lombok.Getter; 19 import lombok.Getter;
20 import org.eclipse.leshan.core.request.ContentFormat; 20 import org.eclipse.leshan.core.request.ContentFormat;
21 import org.eclipse.leshan.core.response.ReadCompositeResponse; 21 import org.eclipse.leshan.core.response.ReadCompositeResponse;
22 import org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType; 22 import org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType;
  23 +import org.thingsboard.server.transport.lwm2m.server.downlink.HasContentFormat;
23 24
24 -public class TbLwM2MReadCompositeRequest extends AbstractTbLwM2MTargetedDownlinkRequest<ReadCompositeResponse> implements HasContentFormat { 25 +public class TbLwM2MReadCompositeRequest extends AbstractTbLwM2MTargetedDownlinkCompositeRequest<ReadCompositeResponse> implements HasContentFormat {
25 26
26 @Getter 27 @Getter
27 private final ContentFormat requestContentFormat; 28 private final ContentFormat requestContentFormat;
@@ -30,8 +31,8 @@ public class TbLwM2MReadCompositeRequest extends AbstractTbLwM2MTargetedDownlink @@ -30,8 +31,8 @@ public class TbLwM2MReadCompositeRequest extends AbstractTbLwM2MTargetedDownlink
30 private final ContentFormat responseContentFormat; 31 private final ContentFormat responseContentFormat;
31 32
32 @Builder 33 @Builder
33 - private TbLwM2MReadCompositeRequest(String versionedId, long timeout, ContentFormat requestContentFormat, ContentFormat responseContentFormat) {  
34 - super(versionedId, timeout); 34 + private TbLwM2MReadCompositeRequest(String [] versionedIds, long timeout, ContentFormat requestContentFormat, ContentFormat responseContentFormat) {
  35 + super(versionedIds, timeout);
35 this.requestContentFormat = requestContentFormat; 36 this.requestContentFormat = requestContentFormat;
36 this.responseContentFormat = responseContentFormat; 37 this.responseContentFormat = responseContentFormat;
37 } 38 }
@@ -40,5 +41,4 @@ public class TbLwM2MReadCompositeRequest extends AbstractTbLwM2MTargetedDownlink @@ -40,5 +41,4 @@ public class TbLwM2MReadCompositeRequest extends AbstractTbLwM2MTargetedDownlink
40 public LwM2mOperationType getType() { 41 public LwM2mOperationType getType() {
41 return LwM2mOperationType.READ_COMPOSITE; 42 return LwM2mOperationType.READ_COMPOSITE;
42 } 43 }
43 -  
44 } 44 }
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/composite/TbLwM2MWriteCompositeRequest.java renamed from common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteCompositeRequest.java
@@ -13,13 +13,14 @@ @@ -13,13 +13,14 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.transport.lwm2m.server.downlink; 16 +package org.thingsboard.server.transport.lwm2m.server.downlink.composite;
17 17
18 import lombok.Builder; 18 import lombok.Builder;
19 import lombok.Getter; 19 import lombok.Getter;
20 import org.eclipse.leshan.core.request.ContentFormat; 20 import org.eclipse.leshan.core.request.ContentFormat;
21 import org.eclipse.leshan.core.response.WriteCompositeResponse; 21 import org.eclipse.leshan.core.response.WriteCompositeResponse;
22 import org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType; 22 import org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType;
  23 +import org.thingsboard.server.transport.lwm2m.server.downlink.AbstractTbLwM2MTargetedDownlinkRequest;
23 24
24 public class TbLwM2MWriteCompositeRequest extends AbstractTbLwM2MTargetedDownlinkRequest<WriteCompositeResponse> { 25 public class TbLwM2MWriteCompositeRequest extends AbstractTbLwM2MTargetedDownlinkRequest<WriteCompositeResponse> {
25 26
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/composite/TbLwM2MWriteResponseCompositeCallback.java renamed from common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/TbLwM2MWriteResponseCompositeCallback.java
@@ -13,11 +13,12 @@ @@ -13,11 +13,12 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.transport.lwm2m.server.downlink; 16 +package org.thingsboard.server.transport.lwm2m.server.downlink.composite;
17 17
18 import org.eclipse.leshan.core.request.WriteCompositeRequest; 18 import org.eclipse.leshan.core.request.WriteCompositeRequest;
19 import org.eclipse.leshan.core.response.WriteCompositeResponse; 19 import org.eclipse.leshan.core.response.WriteCompositeResponse;
20 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; 20 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
  21 +import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MUplinkTargetedCallback;
21 import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService; 22 import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
22 import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler; 23 import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler;
23 24
@@ -50,7 +50,12 @@ import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteAttrib @@ -50,7 +50,12 @@ import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteAttrib
50 import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteReplaceRequest; 50 import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteReplaceRequest;
51 import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteResponseCallback; 51 import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteResponseCallback;
52 import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteUpdateRequest; 52 import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteUpdateRequest;
  53 +import org.thingsboard.server.transport.lwm2m.server.downlink.composite.TbLwM2MReadCompositeCallback;
  54 +import org.thingsboard.server.transport.lwm2m.server.downlink.composite.TbLwM2MReadCompositeRequest;
53 import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService; 55 import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
  56 +import org.thingsboard.server.transport.lwm2m.server.rpc.composite.RpcReadCompositeRequest;
  57 +import org.thingsboard.server.transport.lwm2m.server.rpc.composite.RpcReadResponseCompositeCallback;
  58 +import org.thingsboard.server.transport.lwm2m.server.rpc.composite.RpcWriteCompositeRequest;
54 import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler; 59 import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler;
55 60
56 import java.util.Map; 61 import java.util.Map;
@@ -92,7 +97,7 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler { @@ -92,7 +97,7 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
92 return; 97 return;
93 } 98 }
94 try { 99 try {
95 - if (operationType.isHasObjectId()) { 100 + if (operationType.getHasObjectIdOrComposite() == 1) {
96 String objectId = getIdFromParameters(client, rpcRequst); 101 String objectId = getIdFromParameters(client, rpcRequst);
97 switch (operationType) { 102 switch (operationType) {
98 case READ: 103 case READ:
@@ -125,6 +130,17 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler { @@ -125,6 +130,17 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
125 default: 130 default:
126 throw new IllegalArgumentException("Unsupported operation: " + operationType.name()); 131 throw new IllegalArgumentException("Unsupported operation: " + operationType.name());
127 } 132 }
  133 + } else if (operationType.getHasObjectIdOrComposite() == 2) {
  134 + switch (operationType) {
  135 + case READ_COMPOSITE:
  136 + sendReadCompositeRequest(client, rpcRequst);
  137 + break;
  138 + case WRITE_COMPOSITE:
  139 + sendWriteCompositeRequest(client, rpcRequst);
  140 + break;
  141 + default:
  142 + throw new IllegalArgumentException("Unsupported operation: " + operationType.name());
  143 + }
128 } else { 144 } else {
129 switch (operationType) { 145 switch (operationType) {
130 case OBSERVE_CANCEL_ALL: 146 case OBSERVE_CANCEL_ALL:
@@ -151,14 +167,22 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler { @@ -151,14 +167,22 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
151 private void sendReadRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, String versionedId) { 167 private void sendReadRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, String versionedId) {
152 TbLwM2MReadRequest request = TbLwM2MReadRequest.builder().versionedId(versionedId).timeout(this.config.getTimeout()).build(); 168 TbLwM2MReadRequest request = TbLwM2MReadRequest.builder().versionedId(versionedId).timeout(this.config.getTimeout()).build();
153 var mainCallback = new TbLwM2MReadCallback(uplinkHandler, logService, client, versionedId); 169 var mainCallback = new TbLwM2MReadCallback(uplinkHandler, logService, client, versionedId);
154 - var rpcCallback = new RpcReadResponseCallback<>(transportService, client, requestMsg, versionedId, mainCallback); 170 + var rpcCallback = new RpcReadResponseCallback<>(transportService, client, requestMsg, mainCallback);
155 downlinkHandler.sendReadRequest(client, request, rpcCallback); 171 downlinkHandler.sendReadRequest(client, request, rpcCallback);
156 } 172 }
157 173
  174 + private void sendReadCompositeRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg) {
  175 + String[] versionedIds = getIdsFromParameters(client, requestMsg);
  176 + TbLwM2MReadCompositeRequest request = TbLwM2MReadCompositeRequest.builder().versionedIds(versionedIds).timeout(this.config.getTimeout()).build();
  177 + var mainCallback = new TbLwM2MReadCompositeCallback(uplinkHandler, logService, client, versionedIds);
  178 + var rpcCallback = new RpcReadResponseCompositeCallback(transportService, client, requestMsg, mainCallback);
  179 + downlinkHandler.sendReadCompositeRequest(client, request, rpcCallback);
  180 + }
  181 +
158 private void sendObserveRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, String versionedId) { 182 private void sendObserveRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, String versionedId) {
159 TbLwM2MObserveRequest request = TbLwM2MObserveRequest.builder().versionedId(versionedId).timeout(this.config.getTimeout()).build(); 183 TbLwM2MObserveRequest request = TbLwM2MObserveRequest.builder().versionedId(versionedId).timeout(this.config.getTimeout()).build();
160 var mainCallback = new TbLwM2MObserveCallback(uplinkHandler, logService, client, versionedId); 184 var mainCallback = new TbLwM2MObserveCallback(uplinkHandler, logService, client, versionedId);
161 - var rpcCallback = new RpcReadResponseCallback<>(transportService, client, requestMsg, versionedId, mainCallback); 185 + var rpcCallback = new RpcReadResponseCallback<>(transportService, client, requestMsg, mainCallback);
162 downlinkHandler.sendObserveRequest(client, request, rpcCallback); 186 downlinkHandler.sendObserveRequest(client, request, rpcCallback);
163 } 187 }
164 188
@@ -215,6 +239,16 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler { @@ -215,6 +239,16 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
215 downlinkHandler.sendWriteReplaceRequest(client, request, rpcCallback); 239 downlinkHandler.sendWriteReplaceRequest(client, request, rpcCallback);
216 } 240 }
217 241
  242 + private void sendWriteCompositeRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg) {
  243 + RpcWriteCompositeRequest nodes = JacksonUtil.fromString(requestMsg.getParams(), RpcWriteCompositeRequest.class);
  244 +// TbLwM2MWriteReplaceRequest request = TbLwM2MWriteReplaceRequest.builder().versionedId(versionedId)
  245 +// .value(requestBody.getValue())
  246 +// .timeout(this.config.getTimeout()).build();
  247 +// var mainCallback = new TbLwM2MWriteResponseCallback(uplinkHandler, logService, client, versionedId);
  248 +// var rpcCallback = new RpcEmptyResponseCallback<>(transportService, client, requestMsg, mainCallback);
  249 +// downlinkHandler.sendWriteReplaceRequest(client, request, rpcCallback);
  250 + }
  251 +
218 private void sendCancelObserveRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, String versionedId) { 252 private void sendCancelObserveRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, String versionedId) {
219 TbLwM2MCancelObserveRequest downlink = TbLwM2MCancelObserveRequest.builder().versionedId(versionedId).timeout(this.config.getTimeout()).build(); 253 TbLwM2MCancelObserveRequest downlink = TbLwM2MCancelObserveRequest.builder().versionedId(versionedId).timeout(this.config.getTimeout()).build();
220 var mainCallback = new TbLwM2MCancelObserveCallback(logService, client, versionedId); 254 var mainCallback = new TbLwM2MCancelObserveCallback(logService, client, versionedId);
@@ -249,6 +283,24 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler { @@ -249,6 +283,24 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
249 return targetId; 283 return targetId;
250 } 284 }
251 285
  286 + private String[] getIdsFromParameters(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg rpcRequst) {
  287 + RpcReadCompositeRequest requestParams = JacksonUtil.fromString(rpcRequst.getParams(), RpcReadCompositeRequest.class);
  288 + if (requestParams.getKeys() != null && requestParams.getKeys().length > 0) {
  289 + Set targetIds = ConcurrentHashMap.newKeySet();
  290 + for (String key : requestParams.getKeys()) {
  291 + String targetId = clientContext.getObjectIdByKeyNameFromProfile(client, key);
  292 + if (targetId != null) {
  293 + targetIds.add(targetId);
  294 + }
  295 + }
  296 + return (String[]) targetIds.toArray(String[]::new);
  297 + } else if (requestParams.getIds() != null && requestParams.getIds().length > 0) {
  298 + return requestParams.getIds();
  299 + } else {
  300 + throw new IllegalArgumentException("Can't find 'key' or 'id' in the requestParams parameters!");
  301 + }
  302 + }
  303 +
252 private void sendErrorRpcResponse(TransportProtos.SessionInfoProto sessionInfo, int requestId, String result, String error) { 304 private void sendErrorRpcResponse(TransportProtos.SessionInfoProto sessionInfo, int requestId, String result, String error) {
253 String payload = JacksonUtil.toString(JacksonUtil.newObjectNode().put("result", result).put("error", error)); 305 String payload = JacksonUtil.toString(JacksonUtil.newObjectNode().put("result", result).put("error", error));
254 TransportProtos.ToDeviceRpcResponseMsg msg = TransportProtos.ToDeviceRpcResponseMsg.newBuilder().setRequestId(requestId).setPayload(payload).build(); 306 TransportProtos.ToDeviceRpcResponseMsg msg = TransportProtos.ToDeviceRpcResponseMsg.newBuilder().setRequestId(requestId).setPayload(payload).build();
@@ -24,5 +24,4 @@ public class IdOrKeyRequest { @@ -24,5 +24,4 @@ public class IdOrKeyRequest {
24 24
25 private String key; 25 private String key;
26 private String id; 26 private String id;
27 -  
28 } 27 }
@@ -16,13 +16,11 @@ @@ -16,13 +16,11 @@
16 package org.thingsboard.server.transport.lwm2m.server.rpc; 16 package org.thingsboard.server.transport.lwm2m.server.rpc;
17 17
18 import org.eclipse.leshan.core.ResponseCode; 18 import org.eclipse.leshan.core.ResponseCode;
19 -import org.eclipse.leshan.core.node.codec.LwM2mValueConverter;  
20 import org.thingsboard.common.util.JacksonUtil; 19 import org.thingsboard.common.util.JacksonUtil;
21 import org.thingsboard.server.common.transport.TransportService; 20 import org.thingsboard.server.common.transport.TransportService;
22 import org.thingsboard.server.gen.transport.TransportProtos; 21 import org.thingsboard.server.gen.transport.TransportProtos;
23 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; 22 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
24 import org.thingsboard.server.transport.lwm2m.server.downlink.DownlinkRequestCallback; 23 import org.thingsboard.server.transport.lwm2m.server.downlink.DownlinkRequestCallback;
25 -import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;  
26 24
27 public abstract class RpcDownlinkRequestCallbackProxy<R, T> implements DownlinkRequestCallback<R, T> { 25 public abstract class RpcDownlinkRequestCallbackProxy<R, T> implements DownlinkRequestCallback<R, T> {
28 26
@@ -31,14 +29,12 @@ public abstract class RpcDownlinkRequestCallbackProxy<R, T> implements DownlinkR @@ -31,14 +29,12 @@ public abstract class RpcDownlinkRequestCallbackProxy<R, T> implements DownlinkR
31 private final DownlinkRequestCallback<R, T> callback; 29 private final DownlinkRequestCallback<R, T> callback;
32 30
33 protected final LwM2mClient client; 31 protected final LwM2mClient client;
34 - protected final LwM2mValueConverter converter;  
35 32
36 public RpcDownlinkRequestCallbackProxy(TransportService transportService, LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, DownlinkRequestCallback<R, T> callback) { 33 public RpcDownlinkRequestCallbackProxy(TransportService transportService, LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, DownlinkRequestCallback<R, T> callback) {
37 this.transportService = transportService; 34 this.transportService = transportService;
38 this.client = client; 35 this.client = client;
39 this.request = requestMsg; 36 this.request = requestMsg;
40 this.callback = callback; 37 this.callback = callback;
41 - this.converter = LwM2mValueConverterImpl.getInstance();  
42 } 38 }
43 39
44 @Override 40 @Override
@@ -29,22 +29,19 @@ import java.util.Optional; @@ -29,22 +29,19 @@ import java.util.Optional;
29 29
30 public class RpcReadResponseCallback<R extends LwM2mRequest<T>, T extends ReadResponse> extends RpcLwM2MDownlinkCallback<R, T> { 30 public class RpcReadResponseCallback<R extends LwM2mRequest<T>, T extends ReadResponse> extends RpcLwM2MDownlinkCallback<R, T> {
31 31
32 - private final String versionedId;  
33 -  
34 - public RpcReadResponseCallback(TransportService transportService, LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, String versionedId, DownlinkRequestCallback<R, T> callback) { 32 + public RpcReadResponseCallback(TransportService transportService, LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, DownlinkRequestCallback<R, T> callback) {
35 super(transportService, client, requestMsg, callback); 33 super(transportService, client, requestMsg, callback);
36 - this.versionedId = versionedId;  
37 } 34 }
38 35
39 @Override 36 @Override
40 protected Optional<String> serializeSuccessfulResponse(T response) { 37 protected Optional<String> serializeSuccessfulResponse(T response) {
41 Object value = null; 38 Object value = null;
42 if (response.getContent() instanceof LwM2mObject) { 39 if (response.getContent() instanceof LwM2mObject) {
43 - value = client.objectToString((LwM2mObject) response.getContent(), this.converter, versionedId); 40 + value = client.objectToString((LwM2mObject) response.getContent());
44 } else if (response.getContent() instanceof LwM2mObjectInstance) { 41 } else if (response.getContent() instanceof LwM2mObjectInstance) {
45 - value = client.instanceToString((LwM2mObjectInstance) response.getContent(), this.converter, versionedId); 42 + value = client.instanceToString((LwM2mObjectInstance) response.getContent());
46 } else if (response.getContent() instanceof LwM2mResource) { 43 } else if (response.getContent() instanceof LwM2mResource) {
47 - value = client.resourceToString((LwM2mResource) response.getContent(), this.converter, versionedId); 44 + value = client.resourceToString((LwM2mResource) response.getContent());
48 } 45 }
49 return Optional.of(String.format("%s", value)); 46 return Optional.of(String.format("%s", value));
50 } 47 }
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.transport.lwm2m.server.rpc.composite;
  17 +
  18 +import org.eclipse.leshan.core.request.ReadCompositeRequest;
  19 +import org.eclipse.leshan.core.response.ReadCompositeResponse;
  20 +import org.thingsboard.server.common.data.StringUtils;
  21 +import org.thingsboard.server.common.transport.TransportService;
  22 +import org.thingsboard.server.gen.transport.TransportProtos;
  23 +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
  24 +import org.thingsboard.server.transport.lwm2m.server.downlink.DownlinkRequestCallback;
  25 +import org.thingsboard.server.transport.lwm2m.server.rpc.LwM2MRpcResponseBody;
  26 +import org.thingsboard.server.transport.lwm2m.server.rpc.RpcDownlinkRequestCallbackProxy;
  27 +
  28 +import java.util.Optional;
  29 +
  30 +public abstract class RpcLwM2MDownlinkCompositeCallback<R extends ReadCompositeRequest, T extends ReadCompositeResponse> extends RpcDownlinkRequestCallbackProxy<R, T> {
  31 +
  32 + public RpcLwM2MDownlinkCompositeCallback(TransportService transportService, LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, DownlinkRequestCallback<R, T> callback) {
  33 + super(transportService, client, requestMsg, callback);
  34 + }
  35 +
  36 + @Override
  37 + protected void sendRpcReplyOnSuccess(T response) {
  38 + LwM2MRpcResponseBody.LwM2MRpcResponseBodyBuilder builder = LwM2MRpcResponseBody.builder().result(response.getCode().getName());
  39 + if (response.isSuccess()) {
  40 + Optional<String> responseValue = serializeSuccessfulResponse(response);
  41 + if (responseValue.isPresent() && StringUtils.isNotEmpty(responseValue.get())) {
  42 + builder.value(responseValue.get());
  43 + }
  44 + } else {
  45 + if (StringUtils.isNotEmpty(response.getErrorMessage())) {
  46 + builder.error(response.getErrorMessage());
  47 + }
  48 + }
  49 + reply(builder.build());
  50 + }
  51 +
  52 + protected abstract Optional<String> serializeSuccessfulResponse(T response);
  53 +}
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/rpc/composite/RpcReadCompositeRequest.java renamed from common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/client/LwM2mSoftwareUpdate.java
@@ -13,15 +13,16 @@ @@ -13,15 +13,16 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.transport.lwm2m.client; 16 +package org.thingsboard.server.transport.lwm2m.server.rpc.composite;
17 17
  18 +import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
18 import lombok.Data; 19 import lombok.Data;
19 20
20 -import java.util.UUID;  
21 -  
22 @Data 21 @Data
23 -public class LwM2mSoftwareUpdate {  
24 - private volatile String clientSwVersion;  
25 - private volatile String currentSwVersion;  
26 - private volatile UUID currentSwId;  
27 -}  
  22 +@JsonIgnoreProperties(ignoreUnknown = true)
  23 +public class RpcReadCompositeRequest {
  24 +
  25 + private String [] keys;
  26 + private String [] ids;
  27 +
  28 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.transport.lwm2m.server.rpc.composite;
  17 +
  18 +import org.eclipse.leshan.core.request.ReadCompositeRequest;
  19 +import org.eclipse.leshan.core.response.ReadCompositeResponse;
  20 +import org.thingsboard.server.common.transport.TransportService;
  21 +import org.thingsboard.server.gen.transport.TransportProtos;
  22 +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
  23 +import org.thingsboard.server.transport.lwm2m.server.downlink.DownlinkRequestCallback;
  24 +
  25 +import java.util.Optional;
  26 +
  27 +public class RpcReadResponseCompositeCallback<R extends ReadCompositeRequest, T extends ReadCompositeResponse> extends RpcLwM2MDownlinkCompositeCallback<R, T> {
  28 +
  29 + public RpcReadResponseCompositeCallback(TransportService transportService, LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, DownlinkRequestCallback<R, T> callback) {
  30 + super(transportService, client, requestMsg, callback);
  31 + }
  32 +
  33 + @Override
  34 + protected Optional<String> serializeSuccessfulResponse(T response) {
  35 + return Optional.of(String.format("%s", response.getContent().toString()));
  36 + }
  37 +}
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.transport.lwm2m.server.rpc.composite;
  17 +
  18 +import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
  19 +import lombok.Data;
  20 +
  21 +import java.util.Map;
  22 +
  23 +@Data
  24 +@JsonIgnoreProperties(ignoreUnknown = true)
  25 +public class RpcWriteCompositeRequest {
  26 +
  27 + private Map<String, Object> nodes;
  28 +
  29 +}
@@ -350,17 +350,19 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl @@ -350,17 +350,19 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
350 } 350 }
351 } 351 }
352 352
353 - public void onUpdateValueAfterReadCompositeResponse(Registration registration, String path, ReadCompositeResponse response) { 353 + public void onUpdateValueAfterReadCompositeResponse(Registration registration, ReadCompositeResponse response) {
354 log.warn("201) ReadCompositeResponse: [{}]", response); 354 log.warn("201) ReadCompositeResponse: [{}]", response);
355 if (response.getContent() != null) { 355 if (response.getContent() != null) {
356 LwM2mClient lwM2MClient = clientContext.getClientByEndpoint(registration.getEndpoint()); 356 LwM2mClient lwM2MClient = clientContext.getClientByEndpoint(registration.getEndpoint());
357 response.getContent().forEach((k, v) -> { 357 response.getContent().forEach((k, v) -> {
358 - if (v instanceof LwM2mObject) {  
359 - this.updateObjectResourceValue(lwM2MClient, (LwM2mObject) v, k.toString());  
360 - } else if (v instanceof LwM2mObjectInstance) {  
361 - this.updateObjectInstanceResourceValue(lwM2MClient, (LwM2mObjectInstance) v, k.toString());  
362 - } else if (v instanceof LwM2mResource) {  
363 - this.updateResourcesValue(lwM2MClient, (LwM2mResource) v, k.toString()); 358 + if (v != null) {
  359 + if (v instanceof LwM2mObject) {
  360 + this.updateObjectResourceValue(lwM2MClient, (LwM2mObject) v, k.toString());
  361 + } else if (v instanceof LwM2mObjectInstance) {
  362 + this.updateObjectInstanceResourceValue(lwM2MClient, (LwM2mObjectInstance) v, k.toString());
  363 + } else if (v instanceof LwM2mResource) {
  364 + this.updateResourcesValue(lwM2MClient, (LwM2mResource) v, k.toString());
  365 + }
364 } 366 }
365 }); 367 });
366 } 368 }
@@ -474,12 +476,12 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl @@ -474,12 +476,12 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
474 // String [] paths = new String[] {"/5"}; 476 // String [] paths = new String[] {"/5"};
475 // String [] paths = new String[] {"/"}; 477 // String [] paths = new String[] {"/"};
476 // String [] paths = new String[] {"/9"}; 478 // String [] paths = new String[] {"/9"};
477 - defaultLwM2MDownlinkMsgHandler.sendReadCompositeRequest(lwM2MClient, paths, this); 479 +// defaultLwM2MDownlinkMsgHandler.sendReadCompositeRequest(lwM2MClient, paths, this);
478 Map<String, Object> nodes = new HashMap<>(); 480 Map<String, Object> nodes = new HashMap<>();
479 nodes.put("/3/0/14", "+02"); 481 nodes.put("/3/0/14", "+02");
480 nodes.put("/1/0/2", 100); 482 nodes.put("/1/0/2", 100);
481 nodes.put("/5/0/1", "coap://localhost:5685"); 483 nodes.put("/5/0/1", "coap://localhost:5685");
482 - defaultLwM2MDownlinkMsgHandler.sendWriteCompositeRequest(lwM2MClient, nodes, this); 484 +// defaultLwM2MDownlinkMsgHandler.sendWriteCompositeRequest(lwM2MClient, nodes, this);
483 this.sendObserveRequests(lwM2MClient, profile, supportedObjects); 485 this.sendObserveRequests(lwM2MClient, profile, supportedObjects);
484 this.sendWriteAttributeRequests(lwM2MClient, profile, supportedObjects); 486 this.sendWriteAttributeRequests(lwM2MClient, profile, supportedObjects);
485 // Removed. Used only for debug. 487 // Removed. Used only for debug.
@@ -42,7 +42,7 @@ public interface LwM2mUplinkMsgHandler { @@ -42,7 +42,7 @@ public interface LwM2mUplinkMsgHandler {
42 42
43 void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response); 43 void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response);
44 44
45 - void onUpdateValueAfterReadCompositeResponse(Registration registration, String path, ReadCompositeResponse response); 45 + void onUpdateValueAfterReadCompositeResponse(Registration registration, ReadCompositeResponse response);
46 46
47 void onDeviceProfileUpdate(TransportProtos.SessionInfoProto sessionInfo, DeviceProfile deviceProfile); 47 void onDeviceProfileUpdate(TransportProtos.SessionInfoProto sessionInfo, DeviceProfile deviceProfile);
48 48