Commit dc7c96c4f03f5e7da6c05b0d13cf1c17e95a6160

Authored by Andrii Shvaika
1 parent 2c31de4a

Refactoring to extract AttributeService

Showing 17 changed files with 382 additions and 691 deletions
... ... @@ -155,7 +155,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore {
155 155 LwM2MServerBootstrap profileLwm2mServer = JacksonUtil.fromString(JacksonUtil.toString(bootstrapObject.getLwm2mServer()), LwM2MServerBootstrap.class);
156 156 UUID sessionUUiD = UUID.randomUUID();
157 157 TransportProtos.SessionInfoProto sessionInfo = helper.getValidateSessionInfo(store.getMsg(), sessionUUiD.getMostSignificantBits(), sessionUUiD.getLeastSignificantBits());
158   - context.getTransportService().registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(null, null, sessionInfo));
  158 + context.getTransportService().registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(null, null, null, sessionInfo));
159 159 if (this.getValidatedSecurityMode(lwM2MBootstrapConfig.bootstrapServer, profileServerBootstrap, lwM2MBootstrapConfig.lwm2mServer, profileLwm2mServer)) {
160 160 lwM2MBootstrapConfig.bootstrapServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.bootstrapServer, profileServerBootstrap);
161 161 lwM2MBootstrapConfig.lwm2mServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.lwm2mServer, profileLwm2mServer);
... ...
... ... @@ -93,8 +93,7 @@ public class LwM2mServerListener {
93 93 @Override
94 94 public void onResponse(Observation observation, Registration registration, ObserveResponse response) {
95 95 if (registration != null) {
96   - service.onUpdateValueAfterReadResponse(registration, convertPathFromObjectIdToIdVer(observation.getPath().toString(),
97   - registration), response, null);
  96 + service.onUpdateValueAfterReadResponse(registration, convertPathFromObjectIdToIdVer(observation.getPath().toString(), registration), response);
98 97 }
99 98 }
100 99
... ...
... ... @@ -31,6 +31,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.SessionCloseNotifica
31 31 import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcRequestMsg;
32 32 import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcResponseMsg;
33 33 import org.thingsboard.server.gen.transport.TransportProtos.ToTransportUpdateCredentialsProto;
  34 +import org.thingsboard.server.transport.lwm2m.server.attributes.LwM2MAttributesService;
34 35 import org.thingsboard.server.transport.lwm2m.server.rpc.LwM2MRpcRequestHandler;
35 36 import org.thingsboard.server.transport.lwm2m.server.uplink.DefaultLwM2MUplinkMsgHandler;
36 37 import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler;
... ... @@ -42,17 +43,18 @@ import java.util.UUID;
42 43 @RequiredArgsConstructor
43 44 public class LwM2mSessionMsgListener implements GenericFutureListener<Future<? super Void>>, SessionMsgListener {
44 45 private final LwM2mUplinkMsgHandler handler;
  46 + private final LwM2MAttributesService attributesService;
45 47 private final LwM2MRpcRequestHandler rpcHandler;
46 48 private final TransportProtos.SessionInfoProto sessionInfo;
47 49
48 50 @Override
49 51 public void onGetAttributesResponse(GetAttributeResponseMsg getAttributesResponse) {
50   - this.handler.onGetAttributesResponse(getAttributesResponse, this.sessionInfo);
  52 + this.attributesService.onGetAttributesResponse(getAttributesResponse, this.sessionInfo);
51 53 }
52 54
53 55 @Override
54 56 public void onAttributeUpdate(AttributeUpdateNotificationMsg attributeUpdateNotification) {
55   - this.handler.onAttributeUpdate(attributeUpdateNotification, this.sessionInfo);
  57 + this.attributesService.onAttributeUpdate(attributeUpdateNotification, this.sessionInfo);
56 58 }
57 59
58 60 @Override
... ...
  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.attributes;
  17 +
  18 +import com.google.common.util.concurrent.ListenableFuture;
  19 +import com.google.common.util.concurrent.SettableFuture;
  20 +import lombok.RequiredArgsConstructor;
  21 +import lombok.extern.slf4j.Slf4j;
  22 +import org.eclipse.leshan.core.model.ResourceModel;
  23 +import org.springframework.stereotype.Service;
  24 +import org.thingsboard.server.common.data.ota.OtaPackageKey;
  25 +import org.thingsboard.server.common.data.ota.OtaPackageType;
  26 +import org.thingsboard.server.common.data.ota.OtaPackageUtil;
  27 +import org.thingsboard.server.common.transport.TransportService;
  28 +import org.thingsboard.server.common.transport.TransportServiceCallback;
  29 +import org.thingsboard.server.gen.transport.TransportProtos;
  30 +import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponseMsg;
  31 +import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
  32 +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
  33 +
  34 +import java.util.Collection;
  35 +import java.util.Collections;
  36 +import java.util.List;
  37 +import java.util.Map;
  38 +import java.util.concurrent.atomic.AtomicInteger;
  39 +
  40 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper.getValueFromKvProto;
  41 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LWM2M_ERROR;
  42 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.isFwSwWords;
  43 +
  44 +@Slf4j
  45 +@Service
  46 +@TbLwM2mTransportComponent
  47 +@RequiredArgsConstructor
  48 +public class DefaultLwM2MAttributesService implements LwM2MAttributesService {
  49 +
  50 + //TODO: add timeout logic
  51 + private final AtomicInteger reqIdSeq = new AtomicInteger();
  52 + private final Map<Integer, SettableFuture<List<TransportProtos.TsKvProto>>> futures;
  53 +
  54 + private final TransportService transportService;
  55 +
  56 + @Override
  57 + public ListenableFuture<List<TransportProtos.TsKvProto>> getSharedAttributes(LwM2mClient client, Collection<String> keys) {
  58 + SettableFuture<List<TransportProtos.TsKvProto>> future = SettableFuture.create();
  59 + int requestId = reqIdSeq.incrementAndGet();
  60 + futures.put(requestId, future);
  61 + transportService.process(client.getSession(), TransportProtos.GetAttributeRequestMsg.newBuilder().setRequestId(requestId).
  62 + addAllSharedAttributeNames(keys).build(), new TransportServiceCallback<Void>() {
  63 + @Override
  64 + public void onSuccess(Void msg) {
  65 +
  66 + }
  67 +
  68 + @Override
  69 + public void onError(Throwable e) {
  70 + SettableFuture<List<TransportProtos.TsKvProto>> callback = futures.remove(requestId);
  71 + if (callback != null) {
  72 + callback.setException(e);
  73 + }
  74 + }
  75 + });
  76 + return future;
  77 + }
  78 +
  79 + @Override
  80 + public void onGetAttributesResponse(GetAttributeResponseMsg getAttributesResponse, TransportProtos.SessionInfoProto sessionInfo) {
  81 + var callback = futures.remove(getAttributesResponse.getRequestId());
  82 + if (callback != null) {
  83 + callback.set(getAttributesResponse.getSharedAttributeListList());
  84 + }
  85 + }
  86 +
  87 + /**
  88 + * Update - send request in change value resources in Client
  89 + * 1. FirmwareUpdate:
  90 + * - If msg.getSharedUpdatedList().forEach(tsKvProto -> {tsKvProto.getKv().getKey().indexOf(FIRMWARE_UPDATE_PREFIX, 0) == 0
  91 + * 2. Shared Other AttributeUpdate
  92 + * -- Path to resources from profile equal keyName or from ModelObject equal name
  93 + * -- Only for resources: isWritable && isPresent as attribute in profile -> LwM2MClientProfile (format: CamelCase)
  94 + * 3. Delete - nothing
  95 + *
  96 + * @param msg -
  97 + */
  98 + @Override
  99 + public void onAttributeUpdate(TransportProtos.AttributeUpdateNotificationMsg msg, TransportProtos.SessionInfoProto sessionInfo) {
  100 +// LwM2mClient lwM2MClient = clientContext.getClientBySessionInfo(sessionInfo);
  101 +// if (msg.getSharedUpdatedCount() > 0 && lwM2MClient != null) {
  102 +// log.warn("2) OnAttributeUpdate, SharedUpdatedList() [{}]", msg.getSharedUpdatedList());
  103 +// msg.getSharedUpdatedList().forEach(tsKvProto -> {
  104 +// String pathName = tsKvProto.getKv().getKey();
  105 +// String pathIdVer = this.getObjectIdByKeyNameFromProfile(sessionInfo, pathName);
  106 +// Object valueNew = getValueFromKvProto(tsKvProto.getKv());
  107 +// if ((OtaPackageUtil.getAttributeKey(OtaPackageType.FIRMWARE, OtaPackageKey.VERSION).equals(pathName)
  108 +// && (!valueNew.equals(lwM2MClient.getFwUpdate().getCurrentVersion())))
  109 +// || (OtaPackageUtil.getAttributeKey(OtaPackageType.FIRMWARE, OtaPackageKey.TITLE).equals(pathName)
  110 +// && (!valueNew.equals(lwM2MClient.getFwUpdate().getCurrentTitle())))) {
  111 +// this.getInfoFirmwareUpdate(lwM2MClient, null);
  112 +// } else if ((OtaPackageUtil.getAttributeKey(OtaPackageType.SOFTWARE, OtaPackageKey.VERSION).equals(pathName)
  113 +// && (!valueNew.equals(lwM2MClient.getSwUpdate().getCurrentVersion())))
  114 +// || (OtaPackageUtil.getAttributeKey(OtaPackageType.SOFTWARE, OtaPackageKey.TITLE).equals(pathName)
  115 +// && (!valueNew.equals(lwM2MClient.getSwUpdate().getCurrentTitle())))) {
  116 +// this.getInfoSoftwareUpdate(lwM2MClient, null);
  117 +// }
  118 +// if (pathIdVer != null) {
  119 +// ResourceModel resourceModel = lwM2MClient.getResourceModel(pathIdVer, this.config
  120 +// .getModelProvider());
  121 +// if (resourceModel != null && resourceModel.operations.isWritable()) {
  122 +// this.updateResourcesValueToClient(lwM2MClient, this.getResourceValueFormatKv(lwM2MClient, pathIdVer), valueNew, pathIdVer);
  123 +// } else {
  124 +// log.error("Resource path - [{}] value - [{}] is not Writable and cannot be updated", pathIdVer, valueNew);
  125 +// String logMsg = String.format("%s: attributeUpdate: Resource path - %s value - %s is not Writable and cannot be updated",
  126 +// LOG_LWM2M_ERROR, pathIdVer, valueNew);
  127 +// this.logToTelemetry(lwM2MClient, logMsg);
  128 +// }
  129 +// } else if (!isFwSwWords(pathName)) {
  130 +// log.error("Resource name name - [{}] value - [{}] is not present as attribute/telemetry in profile and cannot be updated", pathName, valueNew);
  131 +// String logMsg = String.format("%s: attributeUpdate: attribute name - %s value - %s is not present as attribute in profile and cannot be updated",
  132 +// LOG_LWM2M_ERROR, pathName, valueNew);
  133 +// this.logToTelemetry(lwM2MClient, logMsg);
  134 +// }
  135 +//
  136 +// });
  137 +// } else if (msg.getSharedDeletedCount() > 0 && lwM2MClient != null) {
  138 +// msg.getSharedUpdatedList().forEach(tsKvProto -> {
  139 +// String pathName = tsKvProto.getKv().getKey();
  140 +// Object valueNew = getValueFromKvProto(tsKvProto.getKv());
  141 +// if (OtaPackageUtil.getAttributeKey(OtaPackageType.FIRMWARE, OtaPackageKey.VERSION).equals(pathName) && !valueNew.equals(lwM2MClient.getFwUpdate().getCurrentVersion())) {
  142 +// lwM2MClient.getFwUpdate().setCurrentVersion((String) valueNew);
  143 +// }
  144 +// });
  145 +// log.info("[{}] delete [{}] onAttributeUpdate", msg.getSharedDeletedList(), sessionInfo);
  146 +// } else if (lwM2MClient == null) {
  147 +// log.error("OnAttributeUpdate, lwM2MClient is null");
  148 +// }
  149 + }
  150 +}
... ...
  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.attributes;
  17 +
  18 +import com.google.common.util.concurrent.ListenableFuture;
  19 +import org.thingsboard.server.gen.transport.TransportProtos;
  20 +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
  21 +
  22 +import java.util.Collection;
  23 +import java.util.List;
  24 +
  25 +public interface LwM2MAttributesService {
  26 +
  27 + ListenableFuture<List<TransportProtos.TsKvProto>> getSharedAttributes(LwM2mClient client, Collection<String> keys);
  28 +
  29 + void onGetAttributesResponse(TransportProtos.GetAttributeResponseMsg getAttributesResponse, TransportProtos.SessionInfoProto sessionInfo);
  30 +
  31 + void onAttributeUpdate(TransportProtos.AttributeUpdateNotificationMsg attributeUpdateNotification, TransportProtos.SessionInfoProto sessionInfo);
  32 +}
... ...
... ... @@ -75,7 +75,7 @@ public class LwM2mClient implements Cloneable {
75 75 @Getter
76 76 private final Map<String, ResourceValue> resources;
77 77 @Getter
78   - private final Map<String, TsKvProto> delayedRequests;
  78 + private final Map<String, TsKvProto> sharedAttributes;
79 79 @Getter
80 80 private final List<String> pendingReadRequests;
81 81 @Getter
... ... @@ -121,7 +121,7 @@ public class LwM2mClient implements Cloneable {
121 121 this.nodeId = nodeId;
122 122 this.endpoint = endpoint;
123 123 this.lock = new ReentrantLock();
124   - this.delayedRequests = new ConcurrentHashMap<>();
  124 + this.sharedAttributes = new ConcurrentHashMap<>();
125 125 this.pendingReadRequests = new CopyOnWriteArrayList<>();
126 126 this.resources = new ConcurrentHashMap<>();
127 127 this.queuedRequests = new ConcurrentLinkedQueue<>();
... ... @@ -371,7 +371,7 @@ public class LwM2mClient implements Cloneable {
371 371 }
372 372 if (this.pendingReadRequests.size() == 0) {
373 373 this.init = true;
374   - serviceImpl.putDelayedUpdateResourcesThingsboard(this);
  374 + serviceImpl.initAttributes(this);
375 375 }
376 376 }
377 377
... ...
... ... @@ -24,7 +24,6 @@ import org.thingsboard.server.common.data.ota.OtaPackageType;
24 24 import org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus;
25 25 import org.thingsboard.server.gen.transport.TransportProtos;
26 26 import org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType;
27   -import org.thingsboard.server.transport.lwm2m.server.rpc.LwM2mClientRpcRequest;
28 27 import org.thingsboard.server.transport.lwm2m.server.uplink.DefaultLwM2MUplinkMsgHandler;
29 28 import org.thingsboard.server.transport.lwm2m.server.downlink.LwM2mDownlinkMsgHandler;
30 29 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil;
... ... @@ -127,9 +126,6 @@ public class LwM2mFwSwUpdate {
127 126 private final List<String> pendingInfoRequestsStart;
128 127 @Getter
129 128 @Setter
130   - private volatile LwM2mClientRpcRequest rpcRequest;
131   - @Getter
132   - @Setter
133 129 private volatile int updateStrategy;
134 130
135 131 public LwM2mFwSwUpdate(LwM2mUplinkMsgHandler handler, LwM2mClient lwM2MClient, OtaPackageType type, int updateStrategy) {
... ... @@ -214,10 +210,10 @@ public class LwM2mFwSwUpdate {
214 210 } else {
215 211 String msgError = "FirmWareId is null.";
216 212 log.warn("6) [{}]", msgError);
217   - if (this.rpcRequest != null) {
  213 +// if (this.rpcRequest != null) {
218 214 // TODO: refactor.
219 215 // handler.sentRpcResponse(this.rpcRequest, CONTENT.name(), msgError, LOG_LW2M_ERROR);
220   - }
  216 +// }
221 217 log.error(msgError);
222 218 this.sendLogs(handler, WRITE_REPLACE.name(), LOG_LWM2M_ERROR, msgError);
223 219 }
... ...
... ... @@ -26,6 +26,7 @@ import org.eclipse.leshan.core.node.LwM2mResource;
26 26 import org.eclipse.leshan.core.node.ObjectLink;
27 27 import org.eclipse.leshan.core.node.codec.CodecException;
28 28 import org.eclipse.leshan.core.observation.Observation;
  29 +import org.eclipse.leshan.core.request.CancelObservationRequest;
29 30 import org.eclipse.leshan.core.request.ContentFormat;
30 31 import org.eclipse.leshan.core.request.DeleteRequest;
31 32 import org.eclipse.leshan.core.request.DiscoverRequest;
... ... @@ -49,13 +50,10 @@ import org.eclipse.leshan.server.registration.Registration;
49 50 import org.springframework.stereotype.Service;
50 51 import org.thingsboard.common.util.JacksonUtil;
51 52 import org.thingsboard.server.common.data.device.data.lwm2m.ObjectAttributes;
52   -import org.thingsboard.server.common.transport.util.JsonUtils;
53 53 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
54 54 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
55 55 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext;
56 56 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
57   -import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
58   -import org.thingsboard.server.transport.lwm2m.server.rpc.LwM2mClientRpcRequest;
59 57 import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;
60 58
61 59 import javax.annotation.PostConstruct;
... ... @@ -289,200 +287,8 @@ public class DefaultLwM2mDownlinkMsgHandler implements LwM2mDownlinkMsgHandler {
289 287 default:
290 288 throw new IllegalArgumentException("Not supported type:" + type.name());
291 289 }
292   -
293   -// TODO: throw exception and execute callback.
294   -//// if (rpcRequest != null) {
295   -//// String patn = "/" + objectId + "/" + instanceId + "/" + resourceId;
296   -//// String errorMsg = String.format("Bad ResourceModel Operations (E): Resource path - %s ResourceModel type - %s", patn, type);
297   -//// rpcRequest.setErrorMsg(errorMsg);
298   -//// }
299   -// return null;
300   -// } catch (NumberFormatException e) {
301   -// String patn = "/" + objectId + "/" + instanceId + "/" + resourceId;
302   -// String msg = String.format(LOG_LW2M_ERROR + ": NumberFormatException: Resource path - %s type - %s value - %s msg error - %s SendRequest to Client",
303   -// patn, type, value, e.toString());
304   -// handler.sendLogsToThingsboard(client, msg);
305   -// log.error("Path: [{}] type: [{}] value: [{}] errorMsg: [{}]]", patn, type, value, e.toString());
306   -// if (rpcRequest != null) {
307   -// String errorMsg = String.format("NumberFormatException: Resource path - %s type - %s value - %s", patn, type, value);
308   -// handler.sentRpcResponse(rpcRequest, BAD_REQUEST.getName(), errorMsg, LOG_LW2M_ERROR);
309   -// }
310   -// return null;
311   -// }
312   - }
313   -
314   - private void handleResponse(LwM2mClient lwM2mClient, final String path, LwM2mResponse response,
315   - SimpleDownlinkRequest request, LwM2mClientRpcRequest rpcRequest) {
316   - responseRequestExecutor.submit(() -> {
317   - try {
318   - this.sendResponse(lwM2mClient, path, response, request, rpcRequest);
319   - } catch (Exception e) {
320   - log.error("[{}] endpoint [{}] path [{}] Exception Unable to after send response.", lwM2mClient.getRegistration().getEndpoint(), path, e);
321   - }
322   - });
323 290 }
324 291
325   - /**
326   - * processing a response from a client
327   - *
328   - * @param path -
329   - * @param response -
330   - */
331   - private void sendResponse(LwM2mClient lwM2mClient, String path, LwM2mResponse response,
332   - SimpleDownlinkRequest request, LwM2mClientRpcRequest rpcRequest) {
333   -// Registration registration = lwM2mClient.getRegistration();
334   -// String pathIdVer = convertPathFromObjectIdToIdVer(path, registration);
335   -// String msgLog = "";
336   -// if (response instanceof ReadResponse) {
337   -// handler.onUpdateValueAfterReadResponse(registration, pathIdVer, (ReadResponse) response, rpcRequest);
338   -// } else if (response instanceof DeleteResponse) {
339   -// log.warn("11) [{}] Path [{}] DeleteResponse", pathIdVer, response);
340   -// if (rpcRequest != null) {
341   -// rpcRequest.setInfoMsg(null);
342   -// handler.sentRpcResponse(rpcRequest, response.getCode().getName(), null, null);
343   -// }
344   -// } else if (response instanceof DiscoverResponse) {
345   -// String discoverValue = Link.serialize(((DiscoverResponse) response).getObjectLinks());
346   -// msgLog = String.format("%s: type operation: %s path: %s value: %s",
347   -// LOG_LW2M_INFO, DISCOVER.name(), request.getPath().toString(), discoverValue);
348   -// handler.sendLogsToThingsboard(lwM2mClient, msgLog);
349   -// log.warn("DiscoverResponse: [{}]", (DiscoverResponse) response);
350   -// if (rpcRequest != null) {
351   -// handler.sentRpcResponse(rpcRequest, response.getCode().getName(), discoverValue, LOG_LW2M_VALUE);
352   -// }
353   -// } else if (response instanceof ExecuteResponse) {
354   -// msgLog = String.format("%s: type operation: %s path: %s",
355   -// LOG_LW2M_INFO, EXECUTE.name(), request.getPath().toString());
356   -// log.warn("9) [{}] ", msgLog);
357   -// handler.sendLogsToThingsboard(lwM2mClient, msgLog);
358   -// if (rpcRequest != null) {
359   -// msgLog = String.format("Start %s path: %S. Preparation finished: %s", EXECUTE.name(), path, rpcRequest.getInfoMsg());
360   -// rpcRequest.setInfoMsg(msgLog);
361   -// handler.sentRpcResponse(rpcRequest, response.getCode().getName(), path, LOG_LW2M_INFO);
362   -// }
363   -//
364   -// } else if (response instanceof WriteAttributesResponse) {
365   -// msgLog = String.format("%s: type operation: %s path: %s value: %s",
366   -// LOG_LW2M_INFO, WRITE_ATTRIBUTES.name(), request.getPath().toString(), ((WriteAttributesRequest) request).getAttributes().toString());
367   -// handler.sendLogsToThingsboard(lwM2mClient, msgLog);
368   -// log.warn("12) [{}] Path [{}] WriteAttributesResponse", pathIdVer, response);
369   -// if (rpcRequest != null) {
370   -// handler.sentRpcResponse(rpcRequest, response.getCode().getName(), response.toString(), LOG_LW2M_VALUE);
371   -// }
372   -// } else if (response instanceof WriteResponse) {
373   -// msgLog = String.format("Type operation: Write path: %s", pathIdVer);
374   -// log.warn("10) [{}] response: [{}]", msgLog, response);
375   -// this.infoWriteResponse(lwM2mClient, response, request, rpcRequest);
376   -// handler.onWriteResponseOk(registration, pathIdVer, (WriteRequest) request);
377   -// }
378   - }
379   -
380   -// private void infoWriteResponse(LwM2mClient lwM2mClient, LwM2mResponse response, SimpleDownlinkRequest
381   -// request, LwM2mClientRpcRequest rpcRequest) {
382   -// try {
383   -// Registration registration = lwM2mClient.getRegistration();
384   -// LwM2mNode node = ((WriteRequest) request).getNode();
385   -// String msg = null;
386   -// Object value;
387   -// if (node instanceof LwM2mObject) {
388   -// msg = String.format("%s: Update finished successfully: Lwm2m code - %d Source path: %s value: %s",
389   -// LOG_LW2M_INFO, response.getCode().getCode(), request.getPath().toString(), ((LwM2mObject) node).toString());
390   -// } else if (node instanceof LwM2mObjectInstance) {
391   -// msg = String.format("%s: Update finished successfully: Lwm2m code - %d Source path: %s value: %s",
392   -// LOG_LW2M_INFO, response.getCode().getCode(), request.getPath().toString(), ((LwM2mObjectInstance) node).prettyPrint());
393   -// } else if (node instanceof LwM2mSingleResource) {
394   -// LwM2mSingleResource singleResource = (LwM2mSingleResource) node;
395   -// if (singleResource.getType() == ResourceModel.Type.STRING || singleResource.getType() == ResourceModel.Type.OPAQUE) {
396   -// int valueLength;
397   -// if (singleResource.getType() == ResourceModel.Type.STRING) {
398   -// valueLength = ((String) singleResource.getValue()).length();
399   -// value = ((String) singleResource.getValue())
400   -// .substring(Math.min(valueLength, config.getLogMaxLength())).trim();
401   -//
402   -// } else {
403   -// valueLength = ((byte[]) singleResource.getValue()).length;
404   -// value = new String(Arrays.copyOf(((byte[]) singleResource.getValue()),
405   -// Math.min(valueLength, config.getLogMaxLength()))).trim();
406   -// }
407   -// value = valueLength > config.getLogMaxLength() ? value + "..." : value;
408   -// msg = String.format("%s: Update finished successfully: Lwm2m code - %d Resource path: %s length: %s value: %s",
409   -// LOG_LW2M_INFO, response.getCode().getCode(), request.getPath().toString(), valueLength, value);
410   -// } else {
411   -// value = this.converter.convertValue(singleResource.getValue(),
412   -// singleResource.getType(), ResourceModel.Type.STRING, request.getPath());
413   -// msg = String.format("%s: Update finished successfully. Lwm2m code: %d Resource path: %s value: %s",
414   -// LOG_LW2M_INFO, response.getCode().getCode(), request.getPath().toString(), value);
415   -// }
416   -// }
417   -// if (msg != null) {
418   -// handler.sendLogsToThingsboard(lwM2mClient, msg);
419   -// if (request.getPath().toString().equals(FW_PACKAGE_5_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) {
420   -// this.afterWriteSuccessFwSwUpdate(registration, request);
421   -// if (rpcRequest != null) {
422   -// rpcRequest.setInfoMsg(msg);
423   -// }
424   -// } else if (rpcRequest != null) {
425   -// handler.sentRpcResponse(rpcRequest, response.getCode().getName(), msg, LOG_LW2M_INFO);
426   -// }
427   -// }
428   -// } catch (Exception e) {
429   -// log.trace("Fail convert value from request to string. ", e);
430   -// }
431   -// }
432   -
433   - /**
434   - * After finish operation FwSwUpdate Write (success):
435   - * fw_state/sw_state = DOWNLOADED
436   - * send operation Execute
437   - */
438   -// private void afterWriteSuccessFwSwUpdate(Registration registration, SimpleDownlinkRequest request) {
439   -// LwM2mClient client = this.lwM2mClientContext.getClientByRegistrationId(registration.getId());
440   -// if (request.getPath().toString().equals(FW_PACKAGE_5_ID) && client.getFwUpdate() != null) {
441   -// client.getFwUpdate().setStateUpdate(DOWNLOADED.name());
442   -// client.getFwUpdate().sendLogs(this.handler, WRITE_REPLACE.name(), LOG_LW2M_INFO, null);
443   -// }
444   -// if (request.getPath().toString().equals(SW_PACKAGE_ID) && client.getSwUpdate() != null) {
445   -// client.getSwUpdate().setStateUpdate(DOWNLOADED.name());
446   -// client.getSwUpdate().sendLogs(this.handler, WRITE_REPLACE.name(), LOG_LW2M_INFO, null);
447   -// }
448   -// }
449   -
450   - /**
451   - * After finish operation FwSwUpdate Write (error): fw_state = FAILED
452   - */
453   -// private void afterWriteFwSWUpdateError(Registration registration, SimpleDownlinkRequest request, String
454   -// msgError) {
455   -// LwM2mClient client = this.lwM2mClientContext.getClientByRegistrationId(registration.getId());
456   -// if (request.getPath().toString().equals(FW_PACKAGE_5_ID) && client.getFwUpdate() != null) {
457   -// client.getFwUpdate().setStateUpdate(FAILED.name());
458   -// client.getFwUpdate().sendLogs(this.handler, WRITE_REPLACE.name(), LOG_LW2M_ERROR, msgError);
459   -// }
460   -// if (request.getPath().toString().equals(SW_PACKAGE_ID) && client.getSwUpdate() != null) {
461   -// client.getSwUpdate().setStateUpdate(FAILED.name());
462   -// client.getSwUpdate().sendLogs(this.handler, WRITE_REPLACE.name(), LOG_LW2M_ERROR, msgError);
463   -// }
464   -// }
465   -
466   -// private void afterExecuteFwSwUpdateError(Registration registration, SimpleDownlinkRequest request, String
467   -// msgError) {
468   -// LwM2mClient client = this.lwM2mClientContext.getClientByRegistrationId(registration.getId());
469   -// if (request.getPath().toString().equals(FW_UPDATE_ID) && client.getFwUpdate() != null) {
470   -// client.getFwUpdate().sendLogs(this.handler, EXECUTE.name(), LOG_LW2M_ERROR, msgError);
471   -// }
472   -// if (request.getPath().toString().equals(SW_INSTALL_ID) && client.getSwUpdate() != null) {
473   -// client.getSwUpdate().sendLogs(this.handler, EXECUTE.name(), LOG_LW2M_ERROR, msgError);
474   -// }
475   -// }
476   -
477   -// private void afterObserveCancel(LwM2mClient lwM2mClient, int observeCancelCnt, String
478   -// observeCancelMsg, LwM2mClientRpcRequest rpcRequest) {
479   -// handler.sendLogsToThingsboard(lwM2mClient, observeCancelMsg);
480   -// log.warn("[{}]", observeCancelMsg);
481   -// if (rpcRequest != null) {
482   -// rpcRequest.setInfoMsg(String.format("Count: %d", observeCancelCnt));
483   -// handler.sentRpcResponse(rpcRequest, CONTENT.name(), null, LOG_LW2M_INFO);
484   -// }
485   -// }
486 292 private void validateVersionedId(LwM2mClient client, HasVersionedId request) {
487 293 if (!client.isValidObjectVersion(request.getVersionedId())) {
488 294 throw new IllegalArgumentException("Specified resource id is not configured in the device profile!");
... ...
... ... @@ -31,6 +31,6 @@ public class TbLwM2MObserveCallback extends TbLwM2MTargetedCallback<ObserveReque
31 31 @Override
32 32 public void onSuccess(ObserveRequest request, ObserveResponse response) {
33 33 super.onSuccess(request, response);
34   - handler.onUpdateValueAfterReadResponse(client.getRegistration(), versionedId, response, null);
  34 + handler.onUpdateValueAfterReadResponse(client.getRegistration(), versionedId, response);
35 35 }
36 36 }
... ...
... ... @@ -31,7 +31,7 @@ public class TbLwM2MReadCallback extends TbLwM2MTargetedCallback<ReadRequest, Re
31 31 @Override
32 32 public void onSuccess(ReadRequest request, ReadResponse response) {
33 33 super.onSuccess(request, response);
34   - handler.onUpdateValueAfterReadResponse(client.getRegistration(), versionedId, response, null);
  34 + handler.onUpdateValueAfterReadResponse(client.getRegistration(), versionedId, response);
35 35 }
36 36
37 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.ota;
  17 +
  18 +import lombok.RequiredArgsConstructor;
  19 +import lombok.extern.slf4j.Slf4j;
  20 +import org.springframework.stereotype.Service;
  21 +import org.thingsboard.server.common.data.ota.OtaPackageKey;
  22 +import org.thingsboard.server.common.data.ota.OtaPackageType;
  23 +import org.thingsboard.server.common.transport.TransportService;
  24 +import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
  25 +import org.thingsboard.server.transport.lwm2m.server.attributes.LwM2MAttributesService;
  26 +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
  27 +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
  28 +
  29 +import java.util.ArrayList;
  30 +import java.util.List;
  31 +import java.util.Map;
  32 +import java.util.concurrent.ConcurrentHashMap;
  33 +
  34 +import static org.thingsboard.server.common.data.ota.OtaPackageUtil.getAttributeKey;
  35 +
  36 +@Slf4j
  37 +@Service
  38 +@TbLwM2mTransportComponent
  39 +@RequiredArgsConstructor
  40 +public class DefaultLwM2MOtaUpdateService implements LwM2MOtaUpdateService {
  41 +
  42 + private static final String FW_NAME_ID = "/5/0/6";
  43 + private static final String FW_VER_ID = "/5/0/7";
  44 + private static final String SW_NAME_ID = "/9/0/0";
  45 + private static final String SW_VER_ID = "/9/0/1";
  46 +
  47 + private final Map<String, LwM2MClientOtaState> fwStates = new ConcurrentHashMap<>();
  48 + private final Map<String, LwM2MClientOtaState> swStates = new ConcurrentHashMap<>();
  49 +
  50 + private final LwM2MAttributesService attributesService;
  51 + private final TransportService transportService;
  52 + private final LwM2mClientContext clientContext;
  53 +
  54 + @Override
  55 + public void init(LwM2mClient client) {
  56 + //TODO: check that the client supports FW and SW by checking the supported objects in the model.
  57 + List<String> attributesToFetch = new ArrayList<>();
  58 + if (client.isValidObjectVersion(FW_NAME_ID) || client.isValidObjectVersion(FW_VER_ID)) {
  59 + LwM2MClientOtaState fwState = getOrInitFwSate(client);
  60 + attributesToFetch.add(getAttributeKey(OtaPackageType.FIRMWARE, OtaPackageKey.TITLE));
  61 + attributesToFetch.add(getAttributeKey(OtaPackageType.FIRMWARE, OtaPackageKey.VERSION));
  62 + }
  63 +
  64 + if (client.isValidObjectVersion(SW_NAME_ID) || client.isValidObjectVersion(SW_VER_ID)) {
  65 + LwM2MClientOtaState swState = getOrInitSwSate(client);
  66 + attributesToFetch.add(getAttributeKey(OtaPackageType.SOFTWARE, OtaPackageKey.TITLE));
  67 + attributesToFetch.add(getAttributeKey(OtaPackageType.SOFTWARE, OtaPackageKey.VERSION));
  68 + }
  69 +
  70 + var future = attributesService.getSharedAttributes(client, attributesToFetch);
  71 + }
  72 +
  73 + private LwM2MClientOtaState getOrInitFwSate(LwM2mClient client) {
  74 + //TODO: fetch state from the cache.
  75 + return fwStates.computeIfAbsent(client.getEndpoint(), endpoint -> new LwM2MClientOtaState());
  76 + }
  77 +
  78 + private LwM2MClientOtaState getOrInitSwSate(LwM2mClient client) {
  79 + //TODO: fetch state from the cache.
  80 + return swStates.computeIfAbsent(client.getEndpoint(), endpoint -> new LwM2MClientOtaState());
  81 + }
  82 +
  83 +}
... ...
  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.ota;
  17 +
  18 +public class LwM2MClientOtaState {
  19 +}
... ...
  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.ota;
  17 +
  18 +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
  19 +
  20 +public interface LwM2MOtaUpdateService {
  21 +
  22 + void init(LwM2mClient client);
  23 +
  24 +}
... ...
... ... @@ -58,11 +58,6 @@ import java.util.UUID;
58 58 import java.util.concurrent.ConcurrentHashMap;
59 59 import java.util.stream.Collectors;
60 60
61   -import static org.eclipse.californium.core.coap.CoAP.ResponseCode.BAD_REQUEST;
62   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LWM2M_ERROR;
63   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LWM2M_INFO;
64   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LWM2M_VALUE;
65   -
66 61 @Slf4j
67 62 @Service
68 63 @TbLwM2mTransportComponent
... ... @@ -258,17 +253,6 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
258 253 transportService.process(sessionInfo, msg, null);
259 254 }
260 255
261   - private void sendErrorRpcResponse(LwM2mClientRpcRequest lwm2mClientRpcRequest, String msgError, TransportProtos.SessionInfoProto sessionInfo) {
262   - if (lwm2mClientRpcRequest == null) {
263   - lwm2mClientRpcRequest = new LwM2mClientRpcRequest();
264   - }
265   - lwm2mClientRpcRequest.setResponseCode(BAD_REQUEST.name());
266   - if (lwm2mClientRpcRequest.getErrorMsg() == null) {
267   - lwm2mClientRpcRequest.setErrorMsg(msgError);
268   - }
269   - this.onToDeviceRpcResponse(lwm2mClientRpcRequest.getDeviceRpcResponseResultMsg(), sessionInfo);
270   - }
271   -
272 256 private void cleanupOldSessions() {
273 257 log.warn("4.1) before rpcSubscriptions.size(): [{}]", rpcSubscriptions.size());
274 258 if (rpcSubscriptions.size() > 0) {
... ... @@ -281,27 +265,6 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
281 265 log.warn("4.4) after rpcSubscriptions.size(): [{}]", rpcSubscriptions.size());
282 266 }
283 267
284   - public void sentRpcResponse(LwM2mClientRpcRequest rpcRequest, String requestCode, String msg, String typeMsg) {
285   - rpcRequest.setResponseCode(requestCode);
286   - if (LOG_LWM2M_ERROR.equals(typeMsg)) {
287   - rpcRequest.setInfoMsg(null);
288   - rpcRequest.setValueMsg(null);
289   - if (rpcRequest.getErrorMsg() == null) {
290   - msg = msg.isEmpty() ? null : msg;
291   - rpcRequest.setErrorMsg(msg);
292   - }
293   - } else if (LOG_LWM2M_INFO.equals(typeMsg)) {
294   - if (rpcRequest.getInfoMsg() == null) {
295   - rpcRequest.setInfoMsg(msg);
296   - }
297   - } else if (LOG_LWM2M_VALUE.equals(typeMsg)) {
298   - if (rpcRequest.getValueMsg() == null) {
299   - rpcRequest.setValueMsg(msg);
300   - }
301   - }
302   - this.onToDeviceRpcResponse(rpcRequest.getDeviceRpcResponseResultMsg(), rpcRequest.getSessionInfo());
303   - }
304   -
305 268 @Override
306 269 public void onToDeviceRpcResponse(TransportProtos.ToDeviceRpcResponseMsg toDeviceResponse, TransportProtos.SessionInfoProto sessionInfo) {
307 270 log.warn("5) onToDeviceRpcResponse: [{}], sessionUUID: [{}]", toDeviceResponse, new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()));
... ...
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;
17   -
18   -import com.google.gson.Gson;
19   -import com.google.gson.JsonObject;
20   -import com.google.gson.reflect.TypeToken;
21   -import lombok.Data;
22   -import lombok.extern.slf4j.Slf4j;
23   -import org.apache.commons.lang3.StringUtils;
24   -import org.eclipse.leshan.core.node.LwM2mPath;
25   -import org.eclipse.leshan.server.registration.Registration;
26   -import org.thingsboard.server.gen.transport.TransportProtos;
27   -import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler;
28   -
29   -import java.util.Map;
30   -import java.util.Objects;
31   -import java.util.concurrent.ConcurrentHashMap;
32   -import java.util.concurrent.TimeoutException;
33   -
34   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.ERROR_KEY;
35   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FINISH_JSON_KEY;
36   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FINISH_VALUE_KEY;
37   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.INFO_KEY;
38   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.KEY_NAME_KEY;
39   -
40   -import org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType;
41   -
42   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType.DISCOVER_ALL;
43   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType.EXECUTE;
44   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType.FW_UPDATE;
45   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType.OBSERVE_CANCEL;
46   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType.OBSERVE_READ_ALL;
47   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType.WRITE_ATTRIBUTES;
48   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType.WRITE_REPLACE;
49   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mOperationType.WRITE_UPDATE;
50   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.METHOD_KEY;
51   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.PARAMS_KEY;
52   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.RESULT_KEY;
53   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SEPARATOR_KEY;
54   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.START_JSON_KEY;
55   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.TARGET_ID_VER_KEY;
56   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.VALUE_KEY;
57   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.fromVersionedIdToObjectId;
58   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.validPathIdVer;
59   -
60   -@Slf4j
61   -@Data
62   -public class LwM2mClientRpcRequest {
63   -
64   - private Registration registration;
65   - private TransportProtos.SessionInfoProto sessionInfo;
66   - private String bodyParams;
67   - private int requestId;
68   -
69   - private LwM2mOperationType typeOper;
70   - private String key;
71   - private String targetIdVer;
72   - private Object value;
73   - private Map<String, Object> params;
74   -
75   - private String errorMsg;
76   - private String valueMsg;
77   - private String infoMsg;
78   - private String responseCode;
79   -
80   - public LwM2mClientRpcRequest() {
81   - }
82   -
83   - public LwM2mClientRpcRequest(LwM2mOperationType lwM2mTypeOper, String bodyParams, int requestId,
84   - TransportProtos.SessionInfoProto sessionInfo, Registration registration, LwM2mUplinkMsgHandler handler) {
85   - this.registration = registration;
86   - this.sessionInfo = sessionInfo;
87   - this.requestId = requestId;
88   - if (lwM2mTypeOper != null) {
89   - this.typeOper = lwM2mTypeOper;
90   - } else {
91   - this.errorMsg = METHOD_KEY + " - " + typeOper + " is not valid.";
92   - }
93   - if (this.errorMsg == null && !bodyParams.equals("null")) {
94   - this.bodyParams = bodyParams;
95   - this.init(handler);
96   - }
97   - }
98   -
99   - public TransportProtos.ToDeviceRpcResponseMsg getDeviceRpcResponseResultMsg() {
100   - JsonObject payloadResp = new JsonObject();
101   - payloadResp.addProperty(RESULT_KEY, this.responseCode);
102   - if (this.errorMsg != null) {
103   - payloadResp.addProperty(ERROR_KEY, this.errorMsg);
104   - } else if (this.valueMsg != null) {
105   - payloadResp.addProperty(VALUE_KEY, this.valueMsg);
106   - } else if (this.infoMsg != null) {
107   - payloadResp.addProperty(INFO_KEY, this.infoMsg);
108   - }
109   - return TransportProtos.ToDeviceRpcResponseMsg.newBuilder()
110   - .setPayload(payloadResp.getAsJsonObject().toString())
111   - .setRequestId(this.requestId)
112   - .build();
113   - }
114   -
115   - private void init(LwM2mUplinkMsgHandler handler) {
116   - try {
117   - // #1
118   - if (this.bodyParams.contains(KEY_NAME_KEY)) {
119   - String targetIdVerStr = this.getValueKeyFromBody(KEY_NAME_KEY);
120   - if (targetIdVerStr != null) {
121   - String targetIdVer = handler.getObjectIdByKeyNameFromProfile(sessionInfo, targetIdVerStr);
122   - if (targetIdVer != null) {
123   - this.targetIdVer = targetIdVer;
124   - this.setInfoMsg(String.format("Changed by: key - %s, pathIdVer - %s",
125   - targetIdVerStr, targetIdVer));
126   - }
127   - }
128   - }
129   - if (this.getTargetIdVer() == null && this.bodyParams.contains(TARGET_ID_VER_KEY)) {
130   - this.setValidTargetIdVerKey();
131   - }
132   - if (this.bodyParams.contains(VALUE_KEY)) {
133   - this.value = this.getValueKeyFromBody(VALUE_KEY);
134   - }
135   - try {
136   - if (this.bodyParams.contains(PARAMS_KEY)) {
137   - this.setValidParamsKey(handler);
138   - }
139   - } catch (Exception e) {
140   - this.setErrorMsg(String.format("Params of request is bad Json format. %s", e.getMessage()));
141   - }
142   -
143   - if (this.getTargetIdVer() == null
144   - && !(OBSERVE_READ_ALL == this.getTypeOper()
145   - || DISCOVER_ALL == this.getTypeOper()
146   - || OBSERVE_CANCEL == this.getTypeOper()
147   - || FW_UPDATE == this.getTypeOper())) {
148   - this.setErrorMsg(TARGET_ID_VER_KEY + " and " +
149   - KEY_NAME_KEY + " is null or bad format");
150   - }
151   - /**
152   - * EXECUTE && WRITE_REPLACE - only for Resource or ResourceInstance
153   - */
154   - else if (this.getTargetIdVer() != null
155   - && (EXECUTE == this.getTypeOper()
156   - || WRITE_REPLACE == this.getTypeOper())
157   - && !(new LwM2mPath(Objects.requireNonNull(fromVersionedIdToObjectId(this.getTargetIdVer()))).isResource()
158   - || new LwM2mPath(Objects.requireNonNull(fromVersionedIdToObjectId(this.getTargetIdVer()))).isResourceInstance())) {
159   - this.setErrorMsg("Invalid parameter " + TARGET_ID_VER_KEY
160   - + ". Only Resource or ResourceInstance can be this operation");
161   - }
162   - } catch (Exception e) {
163   - this.setErrorMsg(String.format("Bad format request. %s", e.getMessage()));
164   - }
165   -
166   - }
167   -
168   - private void setValidTargetIdVerKey() {
169   - String targetIdVerStr = this.getValueKeyFromBody(TARGET_ID_VER_KEY);
170   - // targetIdVer without ver - ok
171   - try {
172   - // targetIdVer with/without ver - ok
173   - this.targetIdVer = validPathIdVer(targetIdVerStr, this.registration);
174   - if (this.targetIdVer != null) {
175   - this.infoMsg = String.format("Changed by: pathIdVer - %s", this.targetIdVer);
176   - }
177   - } catch (Exception e) {
178   - if (this.targetIdVer == null) {
179   - this.errorMsg = TARGET_ID_VER_KEY + " - " + targetIdVerStr + " is not valid.";
180   - }
181   - }
182   - }
183   -
184   - private void setValidParamsKey(LwM2mUplinkMsgHandler handler) {
185   - String paramsStr = this.getValueKeyFromBody(PARAMS_KEY);
186   - if (paramsStr != null) {
187   - String params2Json =
188   - START_JSON_KEY
189   - + "\""
190   - + paramsStr
191   - .replaceAll(SEPARATOR_KEY, "\"" + SEPARATOR_KEY + "\"")
192   - .replaceAll(FINISH_VALUE_KEY, "\"" + FINISH_VALUE_KEY + "\"")
193   - + "\""
194   - + FINISH_JSON_KEY;
195   - // jsonObject
196   - Map<String, Object> params = new Gson().fromJson(params2Json, new TypeToken<ConcurrentHashMap<String, Object>>() {
197   - }.getType());
198   - if (WRITE_UPDATE == this.getTypeOper()) {
199   - if (this.targetIdVer != null) {
200   - Map<String, Object> paramsResourceId = this.convertParamsToResourceId((ConcurrentHashMap<String, Object>) params, handler);
201   - if (paramsResourceId.size() > 0) {
202   - this.setParams(paramsResourceId);
203   - }
204   - }
205   - } else if (WRITE_ATTRIBUTES == this.getTypeOper()) {
206   - this.setParams(params);
207   - }
208   - }
209   - }
210   -
211   - private String getValueKeyFromBody(String key) {
212   - String valueKey = null;
213   - int startInd = -1;
214   - int finishInd = -1;
215   - try {
216   - switch (key) {
217   - case KEY_NAME_KEY:
218   - case TARGET_ID_VER_KEY:
219   - case VALUE_KEY:
220   - startInd = this.bodyParams.indexOf(SEPARATOR_KEY, this.bodyParams.indexOf(key));
221   - finishInd = this.bodyParams.indexOf(FINISH_VALUE_KEY, this.bodyParams.indexOf(key));
222   - if (startInd >= 0 && finishInd < 0) {
223   - finishInd = this.bodyParams.indexOf(FINISH_JSON_KEY, this.bodyParams.indexOf(key));
224   - }
225   - break;
226   - case PARAMS_KEY:
227   - startInd = this.bodyParams.indexOf(START_JSON_KEY, this.bodyParams.indexOf(key));
228   - finishInd = this.bodyParams.indexOf(FINISH_JSON_KEY, this.bodyParams.indexOf(key));
229   - }
230   - if (startInd >= 0 && finishInd > 0) {
231   - valueKey = this.bodyParams.substring(startInd + 1, finishInd);
232   - }
233   - } catch (Exception e) {
234   - log.error("", new TimeoutException());
235   - }
236   - /**
237   - * ReplaceAll "\""
238   - */
239   - if (StringUtils.trimToNull(valueKey) != null) {
240   - char[] chars = valueKey.toCharArray();
241   - for (int i = 0; i < chars.length; i++) {
242   - if (chars[i] == 92 || chars[i] == 34) chars[i] = 32;
243   - }
244   - return key.equals(PARAMS_KEY) ? String.valueOf(chars) : String.valueOf(chars).replaceAll(" ", "");
245   - }
246   - return null;
247   - }
248   -
249   - private ConcurrentHashMap<String, Object> convertParamsToResourceId(ConcurrentHashMap<String, Object> params,
250   - LwM2mUplinkMsgHandler serviceImpl) {
251   - Map<String, Object> paramsIdVer = new ConcurrentHashMap<>();
252   - LwM2mPath targetId = new LwM2mPath(Objects.requireNonNull(fromVersionedIdToObjectId(this.targetIdVer)));
253   - if (targetId.isObjectInstance()) {
254   - params.forEach((k, v) -> {
255   - try {
256   - int id = Integer.parseInt(k);
257   - paramsIdVer.put(String.valueOf(id), v);
258   - } catch (NumberFormatException e) {
259   - String targetIdVer = serviceImpl.getObjectIdByKeyNameFromProfile(sessionInfo, k);
260   - if (targetIdVer != null) {
261   - LwM2mPath lwM2mPath = new LwM2mPath(Objects.requireNonNull(fromVersionedIdToObjectId(targetIdVer)));
262   - paramsIdVer.put(String.valueOf(lwM2mPath.getResourceId()), v);
263   - }
264   - /** WRITE_UPDATE*/
265   - else {
266   - String rezId = this.getRezIdByResourceNameAndObjectInstanceId(k, serviceImpl);
267   - if (rezId != null) {
268   - paramsIdVer.put(rezId, v);
269   - }
270   - }
271   - }
272   - });
273   - }
274   - return (ConcurrentHashMap<String, Object>) paramsIdVer;
275   - }
276   -
277   - private String getRezIdByResourceNameAndObjectInstanceId(String resourceName, LwM2mUplinkMsgHandler handler) {
278   -// LwM2mClient lwM2mClient = handler.clientContext.getClientBySessionInfo(this.sessionInfo);
279   -// return lwM2mClient != null ?
280   -// lwM2mClient.getRezIdByResourceNameAndObjectInstanceId(resourceName, this.targetIdVer, handler.config.getModelProvider()) :
281   -// null;
282   - return null;
283   - }
284   -}
... ... @@ -33,6 +33,7 @@ import org.eclipse.leshan.core.response.ReadResponse;
33 33 import org.eclipse.leshan.server.registration.Registration;
34 34 import org.springframework.context.annotation.Lazy;
35 35 import org.springframework.stereotype.Service;
  36 +import org.thingsboard.common.util.DonAsynchron;
36 37 import org.thingsboard.common.util.ThingsBoardExecutors;
37 38 import org.thingsboard.server.cache.ota.OtaPackageDataCache;
38 39 import org.thingsboard.server.common.data.Device;
... ... @@ -41,15 +42,12 @@ import org.thingsboard.server.common.data.device.data.lwm2m.ObjectAttributes;
41 42 import org.thingsboard.server.common.data.device.data.lwm2m.TelemetryMappingConfiguration;
42 43 import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration;
43 44 import org.thingsboard.server.common.data.id.OtaPackageId;
44   -import org.thingsboard.server.common.data.ota.OtaPackageKey;
45 45 import org.thingsboard.server.common.data.ota.OtaPackageType;
46 46 import org.thingsboard.server.common.data.ota.OtaPackageUtil;
47 47 import org.thingsboard.server.common.transport.TransportService;
48 48 import org.thingsboard.server.common.transport.TransportServiceCallback;
49   -import org.thingsboard.server.common.transport.adaptor.AdaptorException;
50 49 import org.thingsboard.server.common.transport.service.DefaultTransportService;
51 50 import org.thingsboard.server.gen.transport.TransportProtos;
52   -import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg;
53 51 import org.thingsboard.server.gen.transport.TransportProtos.SessionEvent;
54 52 import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto;
55 53 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
... ... @@ -61,6 +59,7 @@ import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext;
61 59 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper;
62 60 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil;
63 61 import org.thingsboard.server.transport.lwm2m.server.adaptors.LwM2MJsonAdaptor;
  62 +import org.thingsboard.server.transport.lwm2m.server.attributes.LwM2MAttributesService;
64 63 import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClientState;
65 64 import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClientStateException;
66 65 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
... ... @@ -83,7 +82,6 @@ import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteAttrib
83 82 import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteResponseCallback;
84 83 import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteReplaceRequest;
85 84 import org.thingsboard.server.transport.lwm2m.server.rpc.LwM2MRpcRequestHandler;
86   -import org.thingsboard.server.transport.lwm2m.server.rpc.LwM2mClientRpcRequest;
87 85 import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MDtlsSessionStore;
88 86 import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;
89 87
... ... @@ -107,7 +105,6 @@ import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPA
107 105 import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.FAILED;
108 106 import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.INITIATED;
109 107 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper.getValueFromKvProto;
110   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.DEVICE_ATTRIBUTES_REQUEST;
111 108 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_5_ID;
112 109 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_RESULT_ID;
113 110 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_STATE_ID;
... ... @@ -119,8 +116,6 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.S
119 116 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertOtaUpdateValueToString;
120 117 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer;
121 118 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.fromVersionedIdToObjectId;
122   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.getAckCallback;
123   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.isFwSwWords;
124 119 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.validateObjectVerFromKey;
125 120
126 121
... ... @@ -136,6 +131,7 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
136 131
137 132 private final TransportService transportService;
138 133 private final LwM2mTransportContext context;
  134 + private final LwM2MAttributesService attributesService;
139 135 public final LwM2MTransportServerConfig config;
140 136 public final OtaPackageDataCache otaPackageDataCache;
141 137 public final LwM2mTransportServerHelper helper;
... ... @@ -147,13 +143,14 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
147 143
148 144 public final Map<String, Integer> firmwareUpdateState;
149 145
150   - public DefaultLwM2MUplinkMsgHandler(TransportService transportService, LwM2MTransportServerConfig config, LwM2mTransportServerHelper helper,
  146 + public DefaultLwM2MUplinkMsgHandler(TransportService transportService, LwM2MAttributesService attributesService, LwM2MTransportServerConfig config, LwM2mTransportServerHelper helper,
151 147 LwM2mClientContext clientContext,
152 148 @Lazy LwM2MRpcRequestHandler rpcHandler,
153 149 @Lazy LwM2mDownlinkMsgHandler defaultLwM2MDownlinkMsgHandler,
154 150 OtaPackageDataCache otaPackageDataCache,
155 151 LwM2mTransportContext context, LwM2MJsonAdaptor adaptor, TbLwM2MDtlsSessionStore sessionStore) {
156 152 this.transportService = transportService;
  153 + this.attributesService = attributesService;
157 154 this.config = config;
158 155 this.helper = helper;
159 156 this.clientContext = clientContext;
... ... @@ -167,7 +164,7 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
167 164 }
168 165
169 166 @PostConstruct
170   - public void init() {
  167 + public void initAttributes() {
171 168 this.context.getScheduler().scheduleAtFixedRate(this::reportActivity, new Random().nextInt((int) config.getSessionReportTimeout()), config.getSessionReportTimeout(), TimeUnit.MILLISECONDS);
172 169 this.registrationExecutor = ThingsBoardExecutors.newWorkStealingPool(this.config.getRegisteredPoolSize(), "LwM2M registration");
173 170 this.updateRegistrationExecutor = ThingsBoardExecutors.newWorkStealingPool(this.config.getUpdateRegisteredPoolSize(), "LwM2M update registration");
... ... @@ -202,7 +199,7 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
202 199 }
203 200 this.logToTelemetry(lwM2MClient, LOG_LWM2M_INFO + ": Client registered with registration id: " + registration.getId());
204 201 SessionInfoProto sessionInfo = lwM2MClient.getSession();
205   - transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(this, rpcHandler, sessionInfo));
  202 + transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(this, attributesService, rpcHandler, sessionInfo));
206 203 log.warn("40) sessionId [{}] Registering rpc subscription after Registration client", new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()));
207 204 TransportProtos.TransportToDeviceActorMsg msg = TransportProtos.TransportToDeviceActorMsg.newBuilder()
208 205 .setSessionInfo(sessionInfo)
... ... @@ -211,9 +208,10 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
211 208 .setSubscribeToRPC(TransportProtos.SubscribeToRPCMsg.newBuilder().setSessionType(TransportProtos.SessionType.ASYNC).build())
212 209 .build();
213 210 transportService.process(msg, null);
214   - this.getInfoFirmwareUpdate(lwM2MClient, null);
215   - this.getInfoSoftwareUpdate(lwM2MClient, null);
  211 + this.getInfoFirmwareUpdate(lwM2MClient);
  212 + this.getInfoSoftwareUpdate(lwM2MClient);
216 213 this.initClientTelemetry(lwM2MClient);
  214 + this.initAttributes(lwM2MClient);
217 215 } else {
218 216 log.error("Client: [{}] onRegistered [{}] name [{}] lwM2MClient ", registration.getId(), registration.getEndpoint(), null);
219 217 }
... ... @@ -324,7 +322,7 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
324 322 * @param response - observe
325 323 */
326 324 @Override
327   - public void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response, LwM2mClientRpcRequest rpcRequest) {
  325 + public void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response) {
328 326 if (response.getContent() != null) {
329 327 LwM2mClient lwM2MClient = clientContext.getClientByEndpoint(registration.getEndpoint());
330 328 ObjectModel objectModelVersion = lwM2MClient.getObjectModel(path, this.config.getModelProvider());
... ... @@ -344,70 +342,6 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
344 342 }
345 343
346 344 /**
347   - * Update - send request in change value resources in Client
348   - * 1. FirmwareUpdate:
349   - * - If msg.getSharedUpdatedList().forEach(tsKvProto -> {tsKvProto.getKv().getKey().indexOf(FIRMWARE_UPDATE_PREFIX, 0) == 0
350   - * 2. Shared Other AttributeUpdate
351   - * -- Path to resources from profile equal keyName or from ModelObject equal name
352   - * -- Only for resources: isWritable && isPresent as attribute in profile -> LwM2MClientProfile (format: CamelCase)
353   - * 3. Delete - nothing
354   - *
355   - * @param msg -
356   - */
357   - @Override
358   - public void onAttributeUpdate(AttributeUpdateNotificationMsg msg, TransportProtos.SessionInfoProto sessionInfo) {
359   - LwM2mClient lwM2MClient = clientContext.getClientBySessionInfo(sessionInfo);
360   - if (msg.getSharedUpdatedCount() > 0 && lwM2MClient != null) {
361   - log.warn("2) OnAttributeUpdate, SharedUpdatedList() [{}]", msg.getSharedUpdatedList());
362   - msg.getSharedUpdatedList().forEach(tsKvProto -> {
363   - String pathName = tsKvProto.getKv().getKey();
364   - String pathIdVer = this.getObjectIdByKeyNameFromProfile(sessionInfo, pathName);
365   - Object valueNew = getValueFromKvProto(tsKvProto.getKv());
366   - if ((OtaPackageUtil.getAttributeKey(OtaPackageType.FIRMWARE, OtaPackageKey.VERSION).equals(pathName)
367   - && (!valueNew.equals(lwM2MClient.getFwUpdate().getCurrentVersion())))
368   - || (OtaPackageUtil.getAttributeKey(OtaPackageType.FIRMWARE, OtaPackageKey.TITLE).equals(pathName)
369   - && (!valueNew.equals(lwM2MClient.getFwUpdate().getCurrentTitle())))) {
370   - this.getInfoFirmwareUpdate(lwM2MClient, null);
371   - } else if ((OtaPackageUtil.getAttributeKey(OtaPackageType.SOFTWARE, OtaPackageKey.VERSION).equals(pathName)
372   - && (!valueNew.equals(lwM2MClient.getSwUpdate().getCurrentVersion())))
373   - || (OtaPackageUtil.getAttributeKey(OtaPackageType.SOFTWARE, OtaPackageKey.TITLE).equals(pathName)
374   - && (!valueNew.equals(lwM2MClient.getSwUpdate().getCurrentTitle())))) {
375   - this.getInfoSoftwareUpdate(lwM2MClient, null);
376   - }
377   - if (pathIdVer != null) {
378   - ResourceModel resourceModel = lwM2MClient.getResourceModel(pathIdVer, this.config
379   - .getModelProvider());
380   - if (resourceModel != null && resourceModel.operations.isWritable()) {
381   - this.updateResourcesValueToClient(lwM2MClient, this.getResourceValueFormatKv(lwM2MClient, pathIdVer), valueNew, pathIdVer);
382   - } else {
383   - log.error("Resource path - [{}] value - [{}] is not Writable and cannot be updated", pathIdVer, valueNew);
384   - String logMsg = String.format("%s: attributeUpdate: Resource path - %s value - %s is not Writable and cannot be updated",
385   - LOG_LWM2M_ERROR, pathIdVer, valueNew);
386   - this.logToTelemetry(lwM2MClient, logMsg);
387   - }
388   - } else if (!isFwSwWords(pathName)) {
389   - log.error("Resource name name - [{}] value - [{}] is not present as attribute/telemetry in profile and cannot be updated", pathName, valueNew);
390   - String logMsg = String.format("%s: attributeUpdate: attribute name - %s value - %s is not present as attribute in profile and cannot be updated",
391   - LOG_LWM2M_ERROR, pathName, valueNew);
392   - this.logToTelemetry(lwM2MClient, logMsg);
393   - }
394   -
395   - });
396   - } else if (msg.getSharedDeletedCount() > 0 && lwM2MClient != null) {
397   - msg.getSharedUpdatedList().forEach(tsKvProto -> {
398   - String pathName = tsKvProto.getKv().getKey();
399   - Object valueNew = getValueFromKvProto(tsKvProto.getKv());
400   - if (OtaPackageUtil.getAttributeKey(OtaPackageType.FIRMWARE, OtaPackageKey.VERSION).equals(pathName) && !valueNew.equals(lwM2MClient.getFwUpdate().getCurrentVersion())) {
401   - lwM2MClient.getFwUpdate().setCurrentVersion((String) valueNew);
402   - }
403   - });
404   - log.info("[{}] delete [{}] onAttributeUpdate", msg.getSharedDeletedList(), sessionInfo);
405   - } else if (lwM2MClient == null) {
406   - log.error("OnAttributeUpdate, lwM2MClient is null");
407   - }
408   - }
409   -
410   - /**
411 345 * @param sessionInfo -
412 346 * @param deviceProfile -
413 347 */
... ... @@ -929,7 +863,7 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
929 863 }
930 864 }
931 865
932   - private void updateResourcesValueToClient(LwM2mClient lwM2MClient, Object valueOld, Object newValue, String versionedId) {
  866 + private void pushUpdateToClientIfNeeded(LwM2mClient lwM2MClient, Object valueOld, Object newValue, String versionedId) {
933 867 if (newValue != null && (valueOld == null || !newValue.toString().equals(valueOld.toString()))) {
934 868 TbLwM2MWriteReplaceRequest request = TbLwM2MWriteReplaceRequest.builder().versionedId(versionedId).value(newValue).timeout(this.config.getTimeout()).build();
935 869 defaultLwM2MDownlinkMsgHandler.sendWriteReplaceRequest(lwM2MClient, request, new TbLwM2MWriteResponseCallback(this, lwM2MClient, versionedId));
... ... @@ -974,25 +908,6 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
974 908 }
975 909
976 910 /**
977   - * 1. FirmwareUpdate:
978   - * - msg.getSharedUpdatedList().forEach(tsKvProto -> {tsKvProto.getKv().getKey().indexOf(FIRMWARE_UPDATE_PREFIX, 0) == 0
979   - * 2. Update resource value on client: if there is a difference in values between the current resource values and the shared attribute values
980   - * - Get path resource by result attributesResponse
981   - *
982   - * @param attributesResponse -
983   - * @param sessionInfo -
984   - */
985   - @Override
986   - public void onGetAttributesResponse(TransportProtos.GetAttributeResponseMsg attributesResponse, TransportProtos.SessionInfoProto sessionInfo) {
987   - try {
988   - List<TransportProtos.TsKvProto> tsKvProtos = attributesResponse.getSharedAttributeListList();
989   - this.updateAttributeFromThingsboard(tsKvProtos, sessionInfo);
990   - } catch (Exception e) {
991   - log.error("", e);
992   - }
993   - }
994   -
995   - /**
996 911 * #1.1 If two names have equal path => last time attribute
997 912 * #2.1 if there is a difference in values between the current resource values and the shared attribute values
998 913 * => send to client Request Update of value (new value from shared attribute)
... ... @@ -1000,31 +915,27 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
1000 915 * #2.1 if there is not a difference in values between the current resource values and the shared attribute values
1001 916 *
1002 917 * @param tsKvProtos
1003   - * @param sessionInfo
1004 918 */
1005   - public void updateAttributeFromThingsboard(List<TransportProtos.TsKvProto> tsKvProtos, TransportProtos.SessionInfoProto sessionInfo) {
1006   - LwM2mClient lwM2MClient = clientContext.getClientBySessionInfo(sessionInfo);
1007   - if (lwM2MClient != null) {
1008   - log.warn("1) UpdateAttributeFromThingsboard, tsKvProtos [{}]", tsKvProtos);
1009   - tsKvProtos.forEach(tsKvProto -> {
1010   - String pathIdVer = this.getObjectIdByKeyNameFromProfile(sessionInfo, tsKvProto.getKv().getKey());
1011   - if (pathIdVer != null) {
1012   - // #1.1
1013   - if (lwM2MClient.getDelayedRequests().containsKey(pathIdVer) && tsKvProto.getTs() > lwM2MClient.getDelayedRequests().get(pathIdVer).getTs()) {
1014   - lwM2MClient.getDelayedRequests().put(pathIdVer, tsKvProto);
1015   - } else if (!lwM2MClient.getDelayedRequests().containsKey(pathIdVer)) {
1016   - lwM2MClient.getDelayedRequests().put(pathIdVer, tsKvProto);
  919 + public void onAttributesUpdate(LwM2mClient lwM2MClient, List<TransportProtos.TsKvProto> tsKvProtos) {
  920 + log.trace("[{}] onAttributesUpdate [{}]", lwM2MClient.getEndpoint(), tsKvProtos);
  921 + tsKvProtos.forEach(tsKvProto -> {
  922 + String pathIdVer = this.getObjectIdByKeyNameFromProfile(lwM2MClient, tsKvProto.getKv().getKey());
  923 + if (pathIdVer != null) {
  924 + // #1.1
  925 + if (lwM2MClient.getSharedAttributes().containsKey(pathIdVer)) {
  926 + if (tsKvProto.getTs() > lwM2MClient.getSharedAttributes().get(pathIdVer).getTs()) {
  927 + lwM2MClient.getSharedAttributes().put(pathIdVer, tsKvProto);
1017 928 }
  929 + } else {
  930 + lwM2MClient.getSharedAttributes().put(pathIdVer, tsKvProto);
1018 931 }
1019   - });
1020   - // #2.1
1021   - lwM2MClient.getDelayedRequests().forEach((pathIdVer, tsKvProto) -> {
1022   - this.updateResourcesValueToClient(lwM2MClient, this.getResourceValueFormatKv(lwM2MClient, pathIdVer),
1023   - getValueFromKvProto(tsKvProto.getKv()), pathIdVer);
1024   - });
1025   - } else {
1026   - log.error("UpdateAttributeFromThingsboard, lwM2MClient is null");
1027   - }
  932 + }
  933 + });
  934 + // #2.1
  935 + lwM2MClient.getSharedAttributes().forEach((pathIdVer, tsKvProto) -> {
  936 + this.pushUpdateToClientIfNeeded(lwM2MClient, this.getResourceValueFormatKv(lwM2MClient, pathIdVer),
  937 + getValueFromKvProto(tsKvProto.getKv()), pathIdVer);
  938 + });
1028 939 }
1029 940
1030 941 /**
... ... @@ -1053,7 +964,7 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
1053 964 */
1054 965 private void reportActivityAndRegister(SessionInfoProto sessionInfo) {
1055 966 if (sessionInfo != null && transportService.reportActivity(sessionInfo) == null) {
1056   - transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(this, rpcHandler, sessionInfo));
  967 + transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(this, attributesService, rpcHandler, sessionInfo));
1057 968 this.reportActivitySubscription(sessionInfo);
1058 969 }
1059 970 }
... ... @@ -1072,25 +983,20 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
1072 983 *
1073 984 * @param lwM2MClient - LwM2M Client
1074 985 */
1075   - public void putDelayedUpdateResourcesThingsboard(LwM2mClient lwM2MClient) {
1076   - SessionInfoProto sessionInfo = this.getSessionInfo(lwM2MClient);
1077   - if (sessionInfo != null) {
1078   - //#1.1
1079   - Map<String, String> keyNamesMap = this.getNamesFromProfileForSharedAttributes(lwM2MClient);
1080   - if (keyNamesMap.values().size() > 0) {
1081   - try {
1082   - //#1.2
1083   - TransportProtos.GetAttributeRequestMsg getAttributeMsg = adaptor.convertToGetAttributes(null, keyNamesMap.values());
1084   - transportService.process(sessionInfo, getAttributeMsg, getAckCallback(lwM2MClient, getAttributeMsg.getRequestId(), DEVICE_ATTRIBUTES_REQUEST));
1085   - } catch (AdaptorException e) {
1086   - log.trace("Failed to decode get attributes request", e);
1087   - }
1088   - }
1089   -
  986 + public void initAttributes(LwM2mClient lwM2MClient) {
  987 + Map<String, String> keyNamesMap = this.getNamesFromProfileForSharedAttributes(lwM2MClient);
  988 + if (!keyNamesMap.isEmpty()) {
  989 + Set<String> keysToFetch = new HashSet<>(keyNamesMap.values());
  990 + keysToFetch.removeAll(OtaPackageUtil.ALL_FW_ATTRIBUTE_KEYS);
  991 + keysToFetch.removeAll(OtaPackageUtil.ALL_SW_ATTRIBUTE_KEYS);
  992 + DonAsynchron.withCallback(attributesService.getSharedAttributes(lwM2MClient, keysToFetch),
  993 + v -> onAttributesUpdate(lwM2MClient, v),
  994 + t -> log.error("[{}] Failed to get attributes", lwM2MClient.getEndpoint(), t),
  995 + registrationExecutor);
1090 996 }
1091 997 }
1092 998
1093   - public void getInfoFirmwareUpdate(LwM2mClient lwM2MClient, LwM2mClientRpcRequest rpcRequest) {
  999 + public void getInfoFirmwareUpdate(LwM2mClient lwM2MClient) {
1094 1000 if (lwM2MClient.getRegistration().getSupportedVersion(FW_5_ID) != null) {
1095 1001 SessionInfoProto sessionInfo = this.getSessionInfo(lwM2MClient);
1096 1002 if (sessionInfo != null) {
... ... @@ -1102,20 +1008,20 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
1102 1008 if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus())
1103 1009 && response.getType().equals(OtaPackageType.FIRMWARE.name())) {
1104 1010 LwM2mFwSwUpdate fwUpdate = lwM2MClient.getFwUpdate(DefaultLwM2MUplinkMsgHandler.this, clientContext);
1105   - if (rpcRequest != null) {
1106   - fwUpdate.setStateUpdate(INITIATED.name());
1107   - }
  1011 +// if (rpcRequest != null) {
  1012 +// fwUpdate.setStateUpdate(INITIATED.name());
  1013 +// }
1108 1014 if (!FAILED.name().equals(fwUpdate.getStateUpdate())) {
1109 1015 log.warn("7) firmware start with ver: [{}]", response.getVersion());
1110   - fwUpdate.setRpcRequest(rpcRequest);
  1016 +// fwUpdate.setRpcRequest(rpcRequest);
1111 1017 fwUpdate.setCurrentVersion(response.getVersion());
1112 1018 fwUpdate.setCurrentTitle(response.getTitle());
1113 1019 fwUpdate.setCurrentId(new UUID(response.getOtaPackageIdMSB(), response.getOtaPackageIdLSB()));
1114   - if (rpcRequest == null) {
  1020 +// if (rpcRequest == null) {
1115 1021 fwUpdate.sendReadObserveInfo(defaultLwM2MDownlinkMsgHandler);
1116   - } else {
1117   - fwUpdate.writeFwSwWare(handler, defaultLwM2MDownlinkMsgHandler);
1118   - }
  1022 +// } else {
  1023 +// fwUpdate.writeFwSwWare(handler, defaultLwM2MDownlinkMsgHandler);
  1024 +// }
1119 1025 } else {
1120 1026 String msgError = String.format("OtaPackage device: %s, version: %s, stateUpdate: %s",
1121 1027 lwM2MClient.getDeviceName(), response.getVersion(), fwUpdate.getStateUpdate());
... ... @@ -1125,10 +1031,10 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
1125 1031 String msgError = String.format("OtaPackage device: %s, responseStatus: %s",
1126 1032 lwM2MClient.getDeviceName(), response.getResponseStatus().toString());
1127 1033 log.trace(msgError);
1128   - if (rpcRequest != null) {
  1034 +// if (rpcRequest != null) {
1129 1035 //TODO: refactor
1130 1036 // sendErrorRpcResponse(rpcRequest, msgError, sessionInfo);
1131   - }
  1037 +// }
1132 1038 }
1133 1039 }
1134 1040
... ... @@ -1141,7 +1047,7 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
1141 1047 }
1142 1048 }
1143 1049
1144   - public void getInfoSoftwareUpdate(LwM2mClient lwM2MClient, LwM2mClientRpcRequest rpcRequest) {
  1050 + public void getInfoSoftwareUpdate(LwM2mClient lwM2MClient) {
1145 1051 if (lwM2MClient.getRegistration().getSupportedVersion(SW_ID) != null) {
1146 1052 SessionInfoProto sessionInfo = this.getSessionInfo(lwM2MClient);
1147 1053 if (sessionInfo != null) {
... ... @@ -1152,16 +1058,16 @@ public class DefaultLwM2MUplinkMsgHandler implements LwM2mUplinkMsgHandler {
1152 1058 public void onSuccess(TransportProtos.GetOtaPackageResponseMsg response) {
1153 1059 if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus())
1154 1060 && response.getType().equals(OtaPackageType.SOFTWARE.name())) {
1155   - lwM2MClient.getSwUpdate().setRpcRequest(rpcRequest);
  1061 +// lwM2MClient.getSwUpdate().setRpcRequest(rpcRequest);
1156 1062 lwM2MClient.getSwUpdate().setCurrentVersion(response.getVersion());
1157 1063 lwM2MClient.getSwUpdate().setCurrentTitle(response.getTitle());
1158 1064 lwM2MClient.getSwUpdate().setCurrentId(new OtaPackageId(new UUID(response.getOtaPackageIdMSB(), response.getOtaPackageIdLSB())).getId());
1159 1065 lwM2MClient.getSwUpdate().sendReadObserveInfo(defaultLwM2MDownlinkMsgHandler);
1160   - if (rpcRequest == null) {
  1066 +// if (rpcRequest == null) {
1161 1067 lwM2MClient.getSwUpdate().sendReadObserveInfo(defaultLwM2MDownlinkMsgHandler);
1162   - } else {
1163   - lwM2MClient.getSwUpdate().writeFwSwWare(handler, defaultLwM2MDownlinkMsgHandler);
1164   - }
  1068 +// } else {
  1069 +// lwM2MClient.getSwUpdate().writeFwSwWare(handler, defaultLwM2MDownlinkMsgHandler);
  1070 +// }
1165 1071 } else {
1166 1072 log.trace("Software [{}] [{}]", lwM2MClient.getDeviceName(), response.getResponseStatus().toString());
1167 1073 }
... ...
... ... @@ -24,7 +24,6 @@ import org.thingsboard.server.common.data.DeviceProfile;
24 24 import org.thingsboard.server.gen.transport.TransportProtos;
25 25 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
26 26 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
27   -import org.thingsboard.server.transport.lwm2m.server.rpc.LwM2mClientRpcRequest;
28 27
29 28 import java.util.Collection;
30 29 import java.util.Optional;
... ... @@ -39,15 +38,13 @@ public interface LwM2mUplinkMsgHandler {
39 38
40 39 void onSleepingDev(Registration registration);
41 40
42   - void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response, LwM2mClientRpcRequest rpcRequest);
43   -
44   - void onAttributeUpdate(TransportProtos.AttributeUpdateNotificationMsg msg, TransportProtos.SessionInfoProto sessionInfo);
  41 + void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response);
45 42
46 43 void onDeviceProfileUpdate(TransportProtos.SessionInfoProto sessionInfo, DeviceProfile deviceProfile);
47 44
48 45 void onDeviceUpdate(TransportProtos.SessionInfoProto sessionInfo, Device device, Optional<DeviceProfile> deviceProfileOpt);
49 46
50   - void onResourceUpdate (Optional<TransportProtos.ResourceUpdateMsg> resourceUpdateMsgOpt);
  47 + void onResourceUpdate(Optional<TransportProtos.ResourceUpdateMsg> resourceUpdateMsgOpt);
51 48
52 49 void onResourceDelete(Optional<TransportProtos.ResourceDeleteMsg> resourceDeleteMsgOpt);
53 50
... ... @@ -67,7 +64,5 @@ public interface LwM2mUplinkMsgHandler {
67 64
68 65 String getObjectIdByKeyNameFromProfile(LwM2mClient lwM2mClient, String keyName);
69 66
70   - void onGetAttributesResponse(TransportProtos.GetAttributeResponseMsg attributesResponse, TransportProtos.SessionInfoProto sessionInfo);
71   -
72 67 LwM2MTransportServerConfig getConfig();
73 68 }
... ...