Showing
25 changed files
with
438 additions
and
101 deletions
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2mVersion.java
0 → 100644
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 | 22 | */ |
23 | 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 | 38 | * Replaces the Object Instance or the Resource(s) with the new value provided in the “Write” operation. (see |
39 | 39 | * section 5.3.3 of the LW M2M spec). |
40 | 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 | 45 | * Adds or updates Resources provided in the new value and leaves other existing Resources unchanged. (see section |
46 | 46 | * 5.3.3 of the LW M2M spec). |
47 | 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 | 54 | // only for RPC |
55 | - FW_UPDATE(17, "FirmwareUpdate", false); | |
55 | + FW_UPDATE(17, "FirmwareUpdate", 0); | |
56 | 56 | |
57 | 57 | // FW_READ_INFO(18, "FirmwareReadInfo"), |
58 | 58 | // SW_READ_INFO(19, "SoftwareReadInfo"), |
... | ... | @@ -64,12 +64,12 @@ public enum LwM2mOperationType { |
64 | 64 | @Getter |
65 | 65 | private final String type; |
66 | 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 | 70 | this.code = code; |
71 | 71 | this.type = type; |
72 | - this.hasObjectId = hasObjectId; | |
72 | + this.hasObjectIdOrComposite = hasObjectIdOrComposite; | |
73 | 73 | } |
74 | 74 | |
75 | 75 | public static LwM2mOperationType fromType(String type) { | ... | ... |
... | ... | @@ -44,6 +44,7 @@ import org.thingsboard.server.common.data.device.data.lwm2m.BootstrapConfigurati |
44 | 44 | import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration; |
45 | 45 | import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; |
46 | 46 | import org.thingsboard.server.common.transport.TransportServiceCallback; |
47 | +import org.thingsboard.server.transport.lwm2m.config.LwM2mVersion; | |
47 | 48 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; |
48 | 49 | import org.thingsboard.server.transport.lwm2m.server.client.ResourceValue; |
49 | 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 | 86 | @Slf4j |
86 | 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 | 91 | public static final String LOG_LWM2M_TELEMETRY = "logLwm2m"; |
91 | 92 | public static final String LOG_LWM2M_INFO = "info"; |
... | ... | @@ -303,7 +304,7 @@ public class LwM2mTransportUtil { |
303 | 304 | |
304 | 305 | public static String convertObjectIdToVersionedId(String path, Registration registration) { |
305 | 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 | 308 | try { |
308 | 309 | String[] keyArray = path.split(LWM2M_SEPARATOR_PATH); |
309 | 310 | if (keyArray.length > 1) { | ... | ... |
... | ... | @@ -38,6 +38,7 @@ import org.thingsboard.server.common.data.id.TenantId; |
38 | 38 | import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; |
39 | 39 | import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; |
40 | 40 | import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto; |
41 | +import org.thingsboard.server.transport.lwm2m.config.LwM2mVersion; | |
41 | 42 | import org.thingsboard.server.transport.lwm2m.server.LwM2mQueuedRequest; |
42 | 43 | |
43 | 44 | import java.util.Collection; |
... | ... | @@ -53,7 +54,7 @@ import java.util.concurrent.locks.ReentrantLock; |
53 | 54 | import java.util.stream.Collectors; |
54 | 55 | |
55 | 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 | 58 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertObjectIdToVersionedId; |
58 | 59 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.equalsResourceTypeGetSimpleName; |
59 | 60 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.fromVersionedIdToObjectId; |
... | ... | @@ -243,11 +244,11 @@ public class LwM2mClient implements Cloneable { |
243 | 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 | 248 | StringBuilder builder = new StringBuilder(); |
248 | 249 | builder.append("LwM2mObject [id=").append(lwM2mObject.getId()).append(", instances={"); |
249 | 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 | 253 | int startInd = builder.lastIndexOf(", "); |
253 | 254 | if (startInd > 0) { |
... | ... | @@ -257,11 +258,11 @@ public class LwM2mClient implements Cloneable { |
257 | 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 | 262 | StringBuilder builder = new StringBuilder(); |
262 | 263 | builder.append("LwM2mObjectInstance [id=").append(objectInstance.getId()).append(", resources={"); |
263 | 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 | 267 | int startInd = builder.lastIndexOf(", "); |
267 | 268 | if (startInd > 0) { |
... | ... | @@ -271,8 +272,9 @@ public class LwM2mClient implements Cloneable { |
271 | 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 | 280 | public Collection<LwM2mResource> getNewResourceForInstance(String pathRezIdVer, Object params, LwM2mModelProvider modelProvider, |
... | ... | @@ -308,11 +310,14 @@ public class LwM2mClient implements Cloneable { |
308 | 310 | return resources; |
309 | 311 | } |
310 | 312 | |
311 | - public boolean isValidObjectVersion(String path) { | |
313 | + public void isValidObjectVersion(String path) { | |
312 | 314 | LwM2mPath pathIds = new LwM2mPath(fromVersionedIdToObjectId(path)); |
313 | 315 | String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId()); |
314 | 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 | 362 | public ContentFormat getDefaultContentFormat() { |
358 | 363 | if (registration == null) { |
359 | 364 | return ContentFormat.DEFAULT; |
360 | - } else if (registration.getLwM2mVersion().equals("1.0")) { | |
361 | - return ContentFormat.TLV; | |
362 | 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 | 57 | import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext; |
58 | 58 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; |
59 | 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 | 62 | import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService; |
61 | 63 | import org.thingsboard.server.transport.lwm2m.server.uplink.DefaultLwM2MUplinkMsgHandler; |
62 | 64 | import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; |
... | ... | @@ -79,6 +81,7 @@ import static org.eclipse.leshan.core.attributes.Attribute.LESSER_THAN; |
79 | 81 | import static org.eclipse.leshan.core.attributes.Attribute.MAXIMUM_PERIOD; |
80 | 82 | import static org.eclipse.leshan.core.attributes.Attribute.MINIMUM_PERIOD; |
81 | 83 | import static org.eclipse.leshan.core.attributes.Attribute.STEP; |
84 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.fromVersionedIdToObjectId; | |
82 | 85 | |
83 | 86 | @Slf4j |
84 | 87 | @Service |
... | ... | @@ -121,27 +124,26 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im |
121 | 124 | } |
122 | 125 | |
123 | 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 | 129 | ContentFormat requestContentFormat = ContentFormat.SENML_JSON; |
129 | 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 | 133 | sendReadRequestComposite(client, downlink, this.config.getTimeout(), callback); |
132 | 134 | } |
133 | 135 | |
134 | 136 | @Override |
135 | 137 | public void sendWriteCompositeRequest(LwM2mClient client, Map<String, Object> nodes, DefaultLwM2MUplinkMsgHandler handler) { |
136 | 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 | 279 | */ |
278 | 280 | Collection<LwM2mResource> resources = client.getNewResourcesForInstance(request.getVersionedId(), request.getValue(), this.config.getModelProvider(), this.converter); |
279 | 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 | 283 | WriteRequest downlink = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resources); |
282 | 284 | sendRequest(client, downlink, request.getTimeout(), callback); |
283 | 285 | } else { |
... | ... | @@ -407,14 +409,23 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im |
407 | 409 | } |
408 | 410 | |
409 | 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 | 413 | if (request.getObjectId() == null) { |
414 | 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 | 429 | private static <T> void addAttribute(List<Attribute> attributes, String attributeName, T value) { |
419 | 430 | addAttribute(attributes, attributeName, value, null, null); |
420 | 431 | } |
... | ... | @@ -447,6 +458,15 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im |
447 | 458 | } |
448 | 459 | |
449 | 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 | 20 | import org.eclipse.leshan.core.request.DiscoverRequest; |
21 | 21 | import org.eclipse.leshan.core.request.ExecuteRequest; |
22 | 22 | import org.eclipse.leshan.core.request.ObserveRequest; |
23 | +import org.eclipse.leshan.core.request.ReadCompositeRequest; | |
23 | 24 | import org.eclipse.leshan.core.request.ReadRequest; |
24 | 25 | import org.eclipse.leshan.core.request.WriteAttributesRequest; |
25 | 26 | import org.eclipse.leshan.core.request.WriteRequest; |
... | ... | @@ -27,10 +28,12 @@ import org.eclipse.leshan.core.response.DeleteResponse; |
27 | 28 | import org.eclipse.leshan.core.response.DiscoverResponse; |
28 | 29 | import org.eclipse.leshan.core.response.ExecuteResponse; |
29 | 30 | import org.eclipse.leshan.core.response.ObserveResponse; |
31 | +import org.eclipse.leshan.core.response.ReadCompositeResponse; | |
30 | 32 | import org.eclipse.leshan.core.response.ReadResponse; |
31 | 33 | import org.eclipse.leshan.core.response.WriteAttributesResponse; |
32 | 34 | import org.eclipse.leshan.core.response.WriteResponse; |
33 | 35 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; |
36 | +import org.thingsboard.server.transport.lwm2m.server.downlink.composite.TbLwM2MReadCompositeRequest; | |
34 | 37 | import org.thingsboard.server.transport.lwm2m.server.uplink.DefaultLwM2MUplinkMsgHandler; |
35 | 38 | |
36 | 39 | import java.util.List; |
... | ... | @@ -41,8 +44,7 @@ public interface LwM2mDownlinkMsgHandler { |
41 | 44 | |
42 | 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 | 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 | 25 | public abstract class TbLwM2MTargetedCallback<R, T> extends AbstractTbLwM2MRequestCallback<R, T> { |
26 | 26 | |
27 | 27 | protected final String versionedId; |
28 | + protected final String[] versionedIds; | |
28 | 29 | |
29 | 30 | public TbLwM2MTargetedCallback(LwM2MTelemetryLogService logService, LwM2mClient client, String versionedId) { |
30 | 31 | super(logService, client); |
31 | 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 | 37 | super(logService, client); |
36 | 38 | this.versionedId = null; |
39 | + this.versionedIds = versionedIds; | |
37 | 40 | } |
38 | 41 | |
39 | 42 | @Override | ... | ... |
... | ... | @@ -20,8 +20,6 @@ import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; |
20 | 20 | import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService; |
21 | 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 | 23 | @Slf4j |
26 | 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 | 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 | 13 | * See the License for the specific language governing permissions and |
14 | 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 | 18 | import lombok.extern.slf4j.Slf4j; |
19 | 19 | import org.eclipse.leshan.core.request.ReadCompositeRequest; |
20 | 20 | import org.eclipse.leshan.core.response.ReadCompositeResponse; |
21 | 21 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; |
22 | +import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MUplinkTargetedCallback; | |
22 | 23 | import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService; |
23 | 24 | import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler; |
24 | 25 | |
25 | 26 | @Slf4j |
26 | 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 | 33 | @Override |
33 | 34 | public void onSuccess(ReadCompositeRequest request, ReadCompositeResponse response) { |
34 | 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 | 13 | * See the License for the specific language governing permissions and |
14 | 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 | 18 | import lombok.Builder; |
19 | 19 | import lombok.Getter; |
20 | 20 | import org.eclipse.leshan.core.request.ContentFormat; |
21 | 21 | import org.eclipse.leshan.core.response.ReadCompositeResponse; |
22 | 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 | 27 | @Getter |
27 | 28 | private final ContentFormat requestContentFormat; |
... | ... | @@ -30,8 +31,8 @@ public class TbLwM2MReadCompositeRequest extends AbstractTbLwM2MTargetedDownlink |
30 | 31 | private final ContentFormat responseContentFormat; |
31 | 32 | |
32 | 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 | 36 | this.requestContentFormat = requestContentFormat; |
36 | 37 | this.responseContentFormat = responseContentFormat; |
37 | 38 | } |
... | ... | @@ -40,5 +41,4 @@ public class TbLwM2MReadCompositeRequest extends AbstractTbLwM2MTargetedDownlink |
40 | 41 | public LwM2mOperationType getType() { |
41 | 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 | * See the License for the specific language governing permissions and |
14 | 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 | 18 | import lombok.Builder; |
19 | 19 | import lombok.Getter; |
20 | 20 | import org.eclipse.leshan.core.request.ContentFormat; |
21 | 21 | import org.eclipse.leshan.core.response.WriteCompositeResponse; |
22 | 22 | import org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType; |
23 | +import org.thingsboard.server.transport.lwm2m.server.downlink.AbstractTbLwM2MTargetedDownlinkRequest; | |
23 | 24 | |
24 | 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 | 13 | * See the License for the specific language governing permissions and |
14 | 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 | 18 | import org.eclipse.leshan.core.request.WriteCompositeRequest; |
19 | 19 | import org.eclipse.leshan.core.response.WriteCompositeResponse; |
20 | 20 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; |
21 | +import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MUplinkTargetedCallback; | |
21 | 22 | import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService; |
22 | 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 | 50 | import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteReplaceRequest; |
51 | 51 | import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteResponseCallback; |
52 | 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 | 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 | 59 | import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler; |
55 | 60 | |
56 | 61 | import java.util.Map; |
... | ... | @@ -92,7 +97,7 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler { |
92 | 97 | return; |
93 | 98 | } |
94 | 99 | try { |
95 | - if (operationType.isHasObjectId()) { | |
100 | + if (operationType.getHasObjectIdOrComposite() == 1) { | |
96 | 101 | String objectId = getIdFromParameters(client, rpcRequst); |
97 | 102 | switch (operationType) { |
98 | 103 | case READ: |
... | ... | @@ -125,6 +130,17 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler { |
125 | 130 | default: |
126 | 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 | 144 | } else { |
129 | 145 | switch (operationType) { |
130 | 146 | case OBSERVE_CANCEL_ALL: |
... | ... | @@ -151,14 +167,22 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler { |
151 | 167 | private void sendReadRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, String versionedId) { |
152 | 168 | TbLwM2MReadRequest request = TbLwM2MReadRequest.builder().versionedId(versionedId).timeout(this.config.getTimeout()).build(); |
153 | 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 | 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 | 182 | private void sendObserveRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, String versionedId) { |
159 | 183 | TbLwM2MObserveRequest request = TbLwM2MObserveRequest.builder().versionedId(versionedId).timeout(this.config.getTimeout()).build(); |
160 | 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 | 186 | downlinkHandler.sendObserveRequest(client, request, rpcCallback); |
163 | 187 | } |
164 | 188 | |
... | ... | @@ -215,6 +239,16 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler { |
215 | 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 | 252 | private void sendCancelObserveRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, String versionedId) { |
219 | 253 | TbLwM2MCancelObserveRequest downlink = TbLwM2MCancelObserveRequest.builder().versionedId(versionedId).timeout(this.config.getTimeout()).build(); |
220 | 254 | var mainCallback = new TbLwM2MCancelObserveCallback(logService, client, versionedId); |
... | ... | @@ -249,6 +283,24 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler { |
249 | 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 | 304 | private void sendErrorRpcResponse(TransportProtos.SessionInfoProto sessionInfo, int requestId, String result, String error) { |
253 | 305 | String payload = JacksonUtil.toString(JacksonUtil.newObjectNode().put("result", result).put("error", error)); |
254 | 306 | TransportProtos.ToDeviceRpcResponseMsg msg = TransportProtos.ToDeviceRpcResponseMsg.newBuilder().setRequestId(requestId).setPayload(payload).build(); | ... | ... |
... | ... | @@ -16,13 +16,11 @@ |
16 | 16 | package org.thingsboard.server.transport.lwm2m.server.rpc; |
17 | 17 | |
18 | 18 | import org.eclipse.leshan.core.ResponseCode; |
19 | -import org.eclipse.leshan.core.node.codec.LwM2mValueConverter; | |
20 | 19 | import org.thingsboard.common.util.JacksonUtil; |
21 | 20 | import org.thingsboard.server.common.transport.TransportService; |
22 | 21 | import org.thingsboard.server.gen.transport.TransportProtos; |
23 | 22 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; |
24 | 23 | import org.thingsboard.server.transport.lwm2m.server.downlink.DownlinkRequestCallback; |
25 | -import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; | |
26 | 24 | |
27 | 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 | 29 | private final DownlinkRequestCallback<R, T> callback; |
32 | 30 | |
33 | 31 | protected final LwM2mClient client; |
34 | - protected final LwM2mValueConverter converter; | |
35 | 32 | |
36 | 33 | public RpcDownlinkRequestCallbackProxy(TransportService transportService, LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, DownlinkRequestCallback<R, T> callback) { |
37 | 34 | this.transportService = transportService; |
38 | 35 | this.client = client; |
39 | 36 | this.request = requestMsg; |
40 | 37 | this.callback = callback; |
41 | - this.converter = LwM2mValueConverterImpl.getInstance(); | |
42 | 38 | } |
43 | 39 | |
44 | 40 | @Override | ... | ... |
... | ... | @@ -29,22 +29,19 @@ import java.util.Optional; |
29 | 29 | |
30 | 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 | 33 | super(transportService, client, requestMsg, callback); |
36 | - this.versionedId = versionedId; | |
37 | 34 | } |
38 | 35 | |
39 | 36 | @Override |
40 | 37 | protected Optional<String> serializeSuccessfulResponse(T response) { |
41 | 38 | Object value = null; |
42 | 39 | if (response.getContent() instanceof LwM2mObject) { |
43 | - value = client.objectToString((LwM2mObject) response.getContent(), this.converter, versionedId); | |
40 | + value = client.objectToString((LwM2mObject) response.getContent()); | |
44 | 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 | 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 | 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 | 13 | * See the License for the specific language governing permissions and |
14 | 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 | 19 | import lombok.Data; |
19 | 20 | |
20 | -import java.util.UUID; | |
21 | - | |
22 | 21 | @Data |
23 | -public class LwM2mSoftwareUpdate { | |
24 | - private volatile String clientSwVersion; | |
25 | - private volatile String currentSwVersion; | |
26 | - private volatile UUID currentSwId; | |
27 | -} | |
\ No newline at end of file | ||
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 | 350 | } |
351 | 351 | } |
352 | 352 | |
353 | - public void onUpdateValueAfterReadCompositeResponse(Registration registration, String path, ReadCompositeResponse response) { | |
353 | + public void onUpdateValueAfterReadCompositeResponse(Registration registration, ReadCompositeResponse response) { | |
354 | 354 | log.warn("201) ReadCompositeResponse: [{}]", response); |
355 | 355 | if (response.getContent() != null) { |
356 | 356 | LwM2mClient lwM2MClient = clientContext.getClientByEndpoint(registration.getEndpoint()); |
357 | 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 | 476 | // String [] paths = new String[] {"/5"}; |
475 | 477 | // String [] paths = new String[] {"/"}; |
476 | 478 | // String [] paths = new String[] {"/9"}; |
477 | - defaultLwM2MDownlinkMsgHandler.sendReadCompositeRequest(lwM2MClient, paths, this); | |
479 | +// defaultLwM2MDownlinkMsgHandler.sendReadCompositeRequest(lwM2MClient, paths, this); | |
478 | 480 | Map<String, Object> nodes = new HashMap<>(); |
479 | 481 | nodes.put("/3/0/14", "+02"); |
480 | 482 | nodes.put("/1/0/2", 100); |
481 | 483 | nodes.put("/5/0/1", "coap://localhost:5685"); |
482 | - defaultLwM2MDownlinkMsgHandler.sendWriteCompositeRequest(lwM2MClient, nodes, this); | |
484 | +// defaultLwM2MDownlinkMsgHandler.sendWriteCompositeRequest(lwM2MClient, nodes, this); | |
483 | 485 | this.sendObserveRequests(lwM2MClient, profile, supportedObjects); |
484 | 486 | this.sendWriteAttributeRequests(lwM2MClient, profile, supportedObjects); |
485 | 487 | // Removed. Used only for debug. | ... | ... |
... | ... | @@ -42,7 +42,7 @@ public interface LwM2mUplinkMsgHandler { |
42 | 42 | |
43 | 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 | 47 | void onDeviceProfileUpdate(TransportProtos.SessionInfoProto sessionInfo, DeviceProfile deviceProfile); |
48 | 48 | ... | ... |