Commit 8d3e30e8a345b0136edce6f927abdfccfed906e0

Authored by nickAS21
Committed by GitHub
1 parent c768fcba

Lwm2m: Fw/Sw updare with test successful/error (#4566)

* Lwm2m: start Sw

* Lwm2m: FwUpdate - new

* Lwm2m: SwUpdate - error

* Lwm2m: SwUpdate - successful/error -test ok

* Lwm2m: SwUpdate - change

* Lwm2m: add executor to observe

* Lwm2m: add operation observe_cancel_All

* Lwm2m: fix bug add software to profile

* Lwm2m: add for logs object to string

* Lwm2m: fix bug swUpdate

* Lwm2m: add new commands only for rpc
Showing 16 changed files with 598 additions and 363 deletions
... ... @@ -47,6 +47,7 @@ import java.util.UUID;
47 47 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.BOOTSTRAP_SERVER;
48 48 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_ERROR;
49 49 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_INFO;
  50 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_TELEMETRY;
50 51 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LWM2M_SERVER;
51 52 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SERVERS;
52 53 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.getBootstrapParametersFromThingsboard;
... ... @@ -167,13 +168,13 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore {
167 168 lwM2MBootstrapConfig.bootstrapServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.bootstrapServer, profileServerBootstrap);
168 169 lwM2MBootstrapConfig.lwm2mServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.lwm2mServer, profileLwm2mServer);
169 170 String logMsg = String.format("%s: getParametersBootstrap: %s Access connect client with bootstrap server.", LOG_LW2M_INFO, store.getEndPoint());
170   - helper.sendParametersOnThingsboardTelemetry(helper.getKvLogyToThingsboard(logMsg), sessionInfo);
  171 + helper.sendParametersOnThingsboardTelemetry(helper.getKvStringtoThingsboard(LOG_LW2M_TELEMETRY, logMsg), sessionInfo);
171 172 return lwM2MBootstrapConfig;
172 173 } else {
173 174 log.error(" [{}] Different values SecurityMode between of client and profile.", store.getEndPoint());
174 175 log.error("{} getParametersBootstrap: [{}] Different values SecurityMode between of client and profile.", LOG_LW2M_ERROR, store.getEndPoint());
175 176 String logMsg = String.format("%s: getParametersBootstrap: %s Different values SecurityMode between of client and profile.", LOG_LW2M_ERROR, store.getEndPoint());
176   - helper.sendParametersOnThingsboardTelemetry(helper.getKvLogyToThingsboard(logMsg), sessionInfo);
  177 + helper.sendParametersOnThingsboardTelemetry(helper.getKvStringtoThingsboard(LOG_LW2M_TELEMETRY, logMsg), sessionInfo);
177 178 return null;
178 179 }
179 180 }
... ...
... ... @@ -156,9 +156,7 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig {
156 156 keyStoreValue = KeyStore.getInstance(keyStoreType);
157 157 keyStoreValue.load(inKeyStore, keyStorePassword == null ? null : keyStorePassword.toCharArray());
158 158 } catch (Exception e) {
159   - log.warn("Unable to lookup LwM2M keystore. Reason: {}, {}" , uri, e.getMessage());
160   -// Absence of the key store should not block user from using plain LwM2M
161   -// throw new RuntimeException("Failed to lookup LwM2M keystore: " + (uri != null ? uri.toString() : ""), e);
  159 + log.trace("Unable to lookup LwM2M keystore. Reason: {}, {}" , uri, e.getMessage());
162 160 }
163 161 }
164 162 }
... ...
... ... @@ -23,13 +23,12 @@ import com.google.gson.JsonElement;
23 23 import com.google.gson.JsonObject;
24 24 import com.google.gson.reflect.TypeToken;
25 25 import lombok.extern.slf4j.Slf4j;
  26 +import org.eclipse.leshan.core.model.ObjectModel;
26 27 import org.eclipse.leshan.core.model.ResourceModel;
27   -import org.eclipse.leshan.core.node.LwM2mMultipleResource;
28 28 import org.eclipse.leshan.core.node.LwM2mObject;
29 29 import org.eclipse.leshan.core.node.LwM2mObjectInstance;
30 30 import org.eclipse.leshan.core.node.LwM2mPath;
31 31 import org.eclipse.leshan.core.node.LwM2mResource;
32   -import org.eclipse.leshan.core.node.LwM2mSingleResource;
33 32 import org.eclipse.leshan.core.observation.Observation;
34 33 import org.eclipse.leshan.core.request.ContentFormat;
35 34 import org.eclipse.leshan.core.request.WriteRequest;
... ... @@ -44,7 +43,6 @@ import org.thingsboard.server.common.data.Device;
44 43 import org.thingsboard.server.common.data.DeviceProfile;
45 44 import org.thingsboard.server.common.data.firmware.FirmwareKey;
46 45 import org.thingsboard.server.common.data.firmware.FirmwareType;
47   -import org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus;
48 46 import org.thingsboard.server.common.data.firmware.FirmwareUtil;
49 47 import org.thingsboard.server.common.data.id.FirmwareId;
50 48 import org.thingsboard.server.common.transport.TransportService;
... ... @@ -57,6 +55,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.SessionEvent;
57 55 import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto;
58 56 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
59 57 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
  58 +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper;
60 59 import org.thingsboard.server.transport.lwm2m.server.adaptors.LwM2MJsonAdaptor;
61 60 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
62 61 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
... ... @@ -85,19 +84,19 @@ import java.util.stream.Collectors;
85 84
86 85 import static org.eclipse.californium.core.coap.CoAP.ResponseCode.BAD_REQUEST;
87 86 import static org.eclipse.leshan.core.attributes.Attribute.OBJECT_VERSION;
  87 +import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.DOWNLOADED;
  88 +import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.UPDATING;
88 89 import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH;
89 90 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper.getValueFromKvProto;
90 91 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.CLIENT_NOT_AUTHORIZED;
91 92 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.DEVICE_ATTRIBUTES_REQUEST;
92   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.EqualsFwSateToFirmwareUpdateStatus;
93 93 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_ID;
94 94 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_RESULT_ID;
95   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_STATE_ID;
96 95 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_ERROR;
97 96 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_INFO;
  97 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_TELEMETRY;
98 98 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_VALUE;
99 99 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LWM2M_STRATEGY_2;
100   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper;
101 100 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER;
102 101 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER_All;
103 102 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.EXECUTE;
... ... @@ -109,6 +108,7 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.L
109 108 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_REPLACE;
110 109 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_UPDATE;
111 110 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_ID;
  111 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_RESULT_ID;
112 112 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertJsonArrayToSet;
113 113 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromIdVerToObjectId;
114 114 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer;
... ... @@ -123,7 +123,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
123 123
124 124 private ExecutorService registrationExecutor;
125 125 private ExecutorService updateRegistrationExecutor;
126   - private ExecutorService unregistrationExecutor;
  126 + private ExecutorService unRegistrationExecutor;
127 127 private LwM2mValueConverterImpl converter;
128 128
129 129 private final TransportService transportService;
... ... @@ -155,7 +155,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
155 155 this.context.getScheduler().scheduleAtFixedRate(this::reportActivity, new Random().nextInt((int) config.getSessionReportTimeout()), config.getSessionReportTimeout(), TimeUnit.MILLISECONDS);
156 156 this.registrationExecutor = ThingsBoardExecutors.newWorkStealingPool(this.config.getRegisteredPoolSize(), "LwM2M registration");
157 157 this.updateRegistrationExecutor = ThingsBoardExecutors.newWorkStealingPool(this.config.getUpdateRegisteredPoolSize(), "LwM2M update registration");
158   - this.unregistrationExecutor = ThingsBoardExecutors.newWorkStealingPool(this.config.getUnRegisteredPoolSize(), "LwM2M unregistration");
  158 + this.unRegistrationExecutor = ThingsBoardExecutors.newWorkStealingPool(this.config.getUnRegisteredPoolSize(), "LwM2M unRegistration");
159 159 this.converter = LwM2mValueConverterImpl.getInstance();
160 160 }
161 161
... ... @@ -219,11 +219,14 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
219 219 request.send();
220 220 }
221 221 }
  222 + this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client update Registration", registration.getId());
222 223 } else {
223 224 log.error("Client: [{}] updatedReg [{}] name [{}] sessionInfo ", registration.getId(), registration.getEndpoint(), null);
  225 + this.sendLogsToThingsboard(LOG_LW2M_ERROR + ": Client update Registration", registration.getId());
224 226 }
225 227 } catch (Throwable t) {
226 228 log.error("[{}] endpoint [{}] error Unable update registration.", registration.getEndpoint(), t);
  229 + this.sendLogsToThingsboard(LOG_LW2M_ERROR + String.format(": Client update Registration, %s", t.getMessage()), registration.getId());
227 230 }
228 231 });
229 232 }
... ... @@ -234,13 +237,14 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
234 237 * !!! Warn: if have not finishing unReg, then this operation will be finished on next Client`s connect
235 238 */
236 239 public void unReg(Registration registration, Collection<Observation> observations) {
237   - unregistrationExecutor.submit(() -> {
  240 + unRegistrationExecutor.submit(() -> {
238 241 try {
239   - this.setCancelObservations(registration);
  242 + this.setCancelObservationsAll(registration);
240 243 this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client unRegistration", registration.getId());
241   - this.closeClientSession(registration);
  244 + this.closeClientSession(registration); ;
242 245 } catch (Throwable t) {
243 246 log.error("[{}] endpoint [{}] error Unable un registration.", registration.getEndpoint(), t);
  247 + this.sendLogsToThingsboard(LOG_LW2M_ERROR + String.format(": Client Unable un Registration, %s", t.getMessage()), registration.getId());
244 248 }
245 249 });
246 250 }
... ... @@ -265,13 +269,18 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
265 269 //TODO: associate endpointId with device information.
266 270 }
267 271
  272 + /**
  273 + * Cancel observation for All objects for this registration
  274 + */
268 275 @Override
269   - public void setCancelObservations(Registration registration) {
  276 + public void setCancelObservationsAll(Registration registration) {
270 277 if (registration != null) {
271   - Set<Observation> observations = context.getServer().getObservationService().getObservations(registration);
272   - observations.forEach(observation -> lwM2mTransportRequest.sendAllRequest(registration,
273   - convertPathFromObjectIdToIdVer(observation.getPath().toString(), registration), OBSERVE_CANCEL,
274   - null, null, this.config.getTimeout(), null));
  278 + lwM2mTransportRequest.sendAllRequest(registration, null, OBSERVE_CANCEL,
  279 + null, null, this.config.getTimeout(), null);
  280 +// Set<Observation> observations = context.getServer().getObservationService().getObservations(registration);
  281 +// observations.forEach(observation -> lwM2mTransportRequest.sendAllRequest(registration,
  282 +// convertPathFromObjectIdToIdVer(observation.getPath().toString(), registration), OBSERVE_CANCEL,
  283 +// null, null, this.config.getTimeout(), null));
275 284 }
276 285 }
277 286
... ... @@ -285,34 +294,43 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
285 294 @Override
286 295 public void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response, Lwm2mClientRpcRequest rpcRequest) {
287 296 if (response.getContent() != null) {
288   - Object value = null;
289   - if (response.getContent() instanceof LwM2mObject) {
290   - LwM2mObject lwM2mObject = (LwM2mObject) response.getContent();
291   - if (rpcRequest != null) {
292   - value = lwM2mObject.toString();
293   - }
294   - this.updateObjectResourceValue(registration, lwM2mObject, path);
295   - } else if (response.getContent() instanceof LwM2mObjectInstance) {
296   - LwM2mObjectInstance lwM2mObjectInstance = (LwM2mObjectInstance) response.getContent();
297   - if (rpcRequest != null) {
298   - value = lwM2mObjectInstance.toString();
  297 + LwM2mClient lwM2MClient = clientContext.getOrRegister(registration);
  298 + ObjectModel objectModelVersion = lwM2MClient.getObjectModel(path, this.config.getModelProvider());
  299 + if (objectModelVersion != null) {
  300 + if (response.getContent() instanceof LwM2mObject) {
  301 + LwM2mObject lwM2mObject = (LwM2mObject) response.getContent();
  302 + this.updateObjectResourceValue(registration, lwM2mObject, path);
  303 + } else if (response.getContent() instanceof LwM2mObjectInstance) {
  304 + LwM2mObjectInstance lwM2mObjectInstance = (LwM2mObjectInstance) response.getContent();
  305 + this.updateObjectInstanceResourceValue(registration, lwM2mObjectInstance, path);
  306 + } else if (response.getContent() instanceof LwM2mResource) {
  307 + LwM2mResource lwM2mResource = (LwM2mResource) response.getContent();
  308 + this.updateResourcesValue(registration, lwM2mResource, path);
299 309 }
300   - this.updateObjectInstanceResourceValue(registration, lwM2mObjectInstance, path);
301   - } else if (response.getContent() instanceof LwM2mResource) {
302   - LwM2mResource lwM2mResource = (LwM2mResource) response.getContent();
303   - if (rpcRequest != null) {
304   - value = lwM2mResource.isMultiInstances() ? ((LwM2mMultipleResource) lwM2mResource).toString() :
305   - ((LwM2mSingleResource) lwM2mResource).toString();
306   - }
307   - this.updateResourcesValue(registration, lwM2mResource, path);
308 310 }
309 311 if (rpcRequest != null) {
310   - rpcRequest.setValueMsg(String.format("%s", value));
311   - this.sentRpcRequest(rpcRequest, response.getCode().getName(), (String) value, LOG_LW2M_VALUE);
  312 + this.sendRpcRequestAfterReadResponse(registration, lwM2MClient, path, response, rpcRequest);
312 313 }
313 314 }
314 315 }
315 316
  317 + private void sendRpcRequestAfterReadResponse(Registration registration, LwM2mClient lwM2MClient, String pathIdVer, ReadResponse response,
  318 + Lwm2mClientRpcRequest rpcRequest) {
  319 + Object value = null;
  320 + if (response.getContent() instanceof LwM2mObject) {
  321 + value = lwM2MClient.objectToString((LwM2mObject) response.getContent(), this.converter, pathIdVer);
  322 + } else if (response.getContent() instanceof LwM2mObjectInstance) {
  323 + value = lwM2MClient.instanceToString((LwM2mObjectInstance) response.getContent(), this.converter, pathIdVer);
  324 + } else if (response.getContent() instanceof LwM2mResource) {
  325 + value = lwM2MClient.resourceToString ((LwM2mResource) response.getContent(), this.converter, pathIdVer);
  326 + }
  327 + String msg = String.format("%s: type operation %s path - %s value - %s", LOG_LW2M_INFO,
  328 + READ, pathIdVer, value);
  329 + this.sendLogsToThingsboard(msg, registration.getId());
  330 + rpcRequest.setValueMsg(String.format("%s", value));
  331 + this.sentRpcRequest(rpcRequest, response.getCode().getName(), (String) value, LOG_LW2M_VALUE);
  332 + }
  333 +
316 334 /**
317 335 * Update - send request in change value resources in Client
318 336 * 1. FirmwareUpdate:
... ... @@ -411,12 +429,12 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
411 429 }
412 430
413 431 @Override
414   - public void onToDeviceRpcRequest(TransportProtos.ToDeviceRpcRequestMsg toDeviceRequest, SessionInfoProto sessionInfo) {
  432 + public void onToDeviceRpcRequest(TransportProtos.ToDeviceRpcRequestMsg toDeviceRpcRequestMsg, SessionInfoProto sessionInfo) {
  433 + log.warn("4) RPC-OK finish to [{}]", toDeviceRpcRequestMsg);
415 434 Lwm2mClientRpcRequest lwm2mClientRpcRequest = null;
416 435 try {
417   - log.info("[{}] toDeviceRpcRequest", toDeviceRequest);
418 436 Registration registration = clientContext.getClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())).getRegistration();
419   - lwm2mClientRpcRequest = this.getDeviceRpcRequest(toDeviceRequest, sessionInfo, registration);
  437 + lwm2mClientRpcRequest = this.getDeviceRpcRequest(toDeviceRpcRequestMsg, sessionInfo, registration);
420 438 if (lwm2mClientRpcRequest.getErrorMsg() != null) {
421 439 lwm2mClientRpcRequest.setResponseCode(BAD_REQUEST.name());
422 440 this.onToDeviceRpcResponse(lwm2mClientRpcRequest.getDeviceRpcResponseResultMsg(), sessionInfo);
... ... @@ -486,7 +504,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
486 504 }
487 505 lwm2mClientRpcRequest.setSessionInfo(sessionInfo);
488 506 if (!(OBSERVE_READ_ALL == lwm2mClientRpcRequest.getTypeOper()
489   - || DISCOVER_All == lwm2mClientRpcRequest.getTypeOper())
  507 + || DISCOVER_All == lwm2mClientRpcRequest.getTypeOper()
  508 + || OBSERVE_CANCEL == lwm2mClientRpcRequest.getTypeOper())
490 509 && lwm2mClientRpcRequest.getTargetIdVer() == null) {
491 510 lwm2mClientRpcRequest.setErrorMsg(lwm2mClientRpcRequest.targetIdVerKey + " and " +
492 511 lwm2mClientRpcRequest.keyNameKey + " is null or bad format");
... ... @@ -599,7 +618,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
599 618 */
600 619 @Override
601 620 public void onAwakeDev(Registration registration) {
602   - log.info("[{}] [{}] Received endpoint Awake version event", registration.getId(), registration.getEndpoint());
  621 + log.trace("[{}] [{}] Received endpoint Awake version event", registration.getId(), registration.getEndpoint());
603 622 this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client is awake!", registration.getId());
604 623 //TODO: associate endpointId with device information.
605 624 }
... ... @@ -615,7 +634,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
615 634 if (logMsg.length() > 1024) {
616 635 logMsg = logMsg.substring(0, 1024);
617 636 }
618   - this.helper.sendParametersOnThingsboardTelemetry(this.helper.getKvLogyToThingsboard(logMsg), sessionInfo);
  637 + this.helper.sendParametersOnThingsboardTelemetry(this.helper.getKvStringtoThingsboard(LOG_LW2M_TELEMETRY, logMsg), sessionInfo);
619 638 }
620 639 }
621 640
... ... @@ -699,22 +718,54 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
699 718 if (lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) {
700 719 lwM2MClient.getSwUpdate().initReadValue(this, path);
701 720 }
702   - if (lwM2MClient.getFwUpdate().getStateUpdate() != null
703   - && !FirmwareUpdateStatus.DOWNLOADING.name().equals(lwM2MClient.getFwUpdate().getStateUpdate())
704   - && (convertPathFromObjectIdToIdVer(FW_STATE_ID, registration).equals(path)
705   - || convertPathFromObjectIdToIdVer(FW_RESULT_ID, registration).equals(path))) {
706   - Long stateFw = (Long) lwM2MClient.getResourceValue(null, FW_STATE_ID);
707   - Long updateResultFw = (Long) lwM2MClient.getResourceValue(null, FW_RESULT_ID);
708   - FirmwareUpdateStatus state = EqualsFwSateToFirmwareUpdateStatus(LwM2mTransportUtil.StateFw.fromStateFwByCode(stateFw.intValue()),
709   - LwM2mTransportUtil.UpdateResultFw.fromUpdateResultFwByCode(updateResultFw.intValue()));
710   - if (state != FirmwareUpdateStatus.DOWNLOADING && state != FirmwareUpdateStatus.DOWNLOADED) {
711   - lwM2MClient.getFwUpdate().setStateUpdate(state.name());
712   - lwM2MClient.getFwUpdate().sendLogs(OBSERVE.name());
  721 +
  722 + /**
  723 + * Before operation Execute (FwUpdate) inspection Update Result :
  724 + * - after finished operation Write result: success (FwUpdate): fw_state = DOWNLOADED
  725 + * - before start operation Execute (FwUpdate) Update Result = 0 - Initial value
  726 + * - start Execute (FwUpdate)
  727 + * After finished operation Execute (FwUpdate) inspection Update Result :
  728 + * - after start operation Execute (FwUpdate): fw_state = UPDATING
  729 + * - after success finished operation Execute (FwUpdate) Update Result == 1 ("Firmware updated successfully")
  730 + * - finished operation Execute (FwUpdate)
  731 + */
  732 + if (lwM2MClient.getFwUpdate() != null
  733 + && (convertPathFromObjectIdToIdVer(FW_RESULT_ID, registration).equals(path))) {
  734 + if (DOWNLOADED.name().equals(lwM2MClient.getFwUpdate().getStateUpdate())
  735 + && lwM2MClient.getFwUpdate().conditionalFwExecuteStart()) {
  736 + lwM2MClient.getFwUpdate().executeFwSwWare();
  737 + } else if (UPDATING.name().equals(lwM2MClient.getFwUpdate().getStateUpdate())
  738 + && lwM2MClient.getFwUpdate().conditionalFwExecuteAfterSuccess()) {
  739 + lwM2MClient.getFwUpdate().finishFwSwUpdate(true);
  740 + } else if (UPDATING.name().equals(lwM2MClient.getFwUpdate().getStateUpdate())
  741 + && lwM2MClient.getFwUpdate().conditionalFwExecuteAfterError()) {
  742 + lwM2MClient.getFwUpdate().finishFwSwUpdate(false);
713 743 }
714   - log.warn ("update Resource [{}]", lwM2mResource);
715 744 }
716   - if (FirmwareUpdateStatus.DOWNLOADED.name().equals(lwM2MClient.getSwUpdate().getStateUpdate())) {
717 745
  746 + /**
  747 + * Before operation Execute (SwUpdate) inspection Update Result :
  748 + * - after finished operation Write result: success (SwUpdate): fw_state = DOWNLOADED
  749 + * - before operation Execute (SwUpdate) Update Result = 3 - Successfully Downloaded and package integrity verified
  750 + * - start Execute (SwUpdate)
  751 + * After finished operation Execute (SwUpdate) inspection Update Result :
  752 + * - after start operation Execute (SwUpdate): fw_state = UPDATING
  753 + * - after success finished operation Execute (SwUpdate) Update Result == 2 "Software successfully installed.""
  754 + * - after success finished operation Execute (SwUpdate) Update Result == 2 "Software successfully installed.""
  755 + * - finished operation Execute (SwUpdate)
  756 + */
  757 + if (lwM2MClient.getSwUpdate() != null
  758 + && (convertPathFromObjectIdToIdVer(SW_RESULT_ID, registration).equals(path))) {
  759 + if (DOWNLOADED.name().equals(lwM2MClient.getSwUpdate().getStateUpdate())
  760 + && lwM2MClient.getSwUpdate().conditionalSwUpdateExecute()) {
  761 + lwM2MClient.getSwUpdate().executeFwSwWare();
  762 + } else if (UPDATING.name().equals(lwM2MClient.getSwUpdate().getStateUpdate())
  763 + && lwM2MClient.getSwUpdate().conditionalSwExecuteAfterSuccess()) {
  764 + lwM2MClient.getSwUpdate().finishFwSwUpdate(true);
  765 + } else if (UPDATING.name().equals(lwM2MClient.getSwUpdate().getStateUpdate())
  766 + && lwM2MClient.getSwUpdate().conditionalSwExecuteAfterError()) {
  767 + lwM2MClient.getSwUpdate().finishFwSwUpdate(false);
  768 + }
718 769 }
719 770 Set<String> paths = new HashSet<>();
720 771 paths.add(path);
... ... @@ -736,7 +787,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
736 787 */
737 788 private void updateAttrTelemetry(Registration registration, Set<String> paths) {
738 789 try {
739   - ResultsAddKeyValueProto results = getParametersFromProfile(registration, paths);
  790 + ResultsAddKeyValueProto results = this.getParametersFromProfile(registration, paths);
740 791 SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(registration);
741 792 if (results != null && sessionInfo != null) {
742 793 if (results.getResultAttributes().size() > 0) {
... ... @@ -1020,8 +1071,6 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1020 1071 registrationIds.forEach(registrationId -> {
1021 1072 Registration registration = clientContext.getRegistration(registrationId);
1022 1073 this.readObserveFromProfile(registration, sendAttrToThingsboard.getPathPostParametersAdd(), READ);
1023   - // send attr/telemetry to tingsboard for new path
1024   -// this.updateAttrTelemetry(registration, sendAttrToThingsboard.getPathPostParametersAdd());
1025 1074 });
1026 1075 }
1027 1076 // #4.2 del
... ... @@ -1348,7 +1397,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1348 1397 TransportProtos.GetAttributeRequestMsg getAttributeMsg = adaptor.convertToGetAttributes(null, keyNamesMap.values());
1349 1398 transportService.process(sessionInfo, getAttributeMsg, getAckCallback(lwM2MClient, getAttributeMsg.getRequestId(), DEVICE_ATTRIBUTES_REQUEST));
1350 1399 } catch (AdaptorException e) {
1351   - log.warn("Failed to decode get attributes request", e);
  1400 + log.trace("Failed to decode get attributes request", e);
1352 1401 }
1353 1402 }
1354 1403
... ... @@ -1369,7 +1418,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1369 1418 lwM2MClient.getFwUpdate().setCurrentVersion(response.getVersion());
1370 1419 lwM2MClient.getFwUpdate().setCurrentTitle(response.getTitle());
1371 1420 lwM2MClient.getFwUpdate().setCurrentId(new FirmwareId(new UUID(response.getFirmwareIdMSB(), response.getFirmwareIdLSB())).getId());
1372   - lwM2MClient.getFwUpdate().sendReadInfo(serviceImpl);
  1421 + lwM2MClient.getFwUpdate().sendReadObserveInfo(serviceImpl);
1373 1422 } else {
1374 1423 log.trace("Firmware [{}] [{}]", lwM2MClient.getDeviceName(), response.getResponseStatus().toString());
1375 1424 }
... ... @@ -1377,7 +1426,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1377 1426
1378 1427 @Override
1379 1428 public void onError(Throwable e) {
1380   - log.warn("Failed to process firmwareUpdate ", e);
  1429 + log.trace("Failed to process firmwareUpdate ", e);
1381 1430 }
1382 1431 });
1383 1432 }
... ... @@ -1398,7 +1447,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1398 1447 lwM2MClient.getSwUpdate().setCurrentVersion(response.getVersion());
1399 1448 lwM2MClient.getSwUpdate().setCurrentTitle(response.getTitle());
1400 1449 lwM2MClient.getSwUpdate().setCurrentId(new FirmwareId(new UUID(response.getFirmwareIdMSB(), response.getFirmwareIdLSB())).getId());
1401   - lwM2MClient.getSwUpdate().sendReadInfo(serviceImpl);
  1450 + lwM2MClient.getSwUpdate().sendReadObserveInfo(serviceImpl);
1402 1451 } else {
1403 1452 log.trace("Software [{}] [{}]", lwM2MClient.getDeviceName(), response.getResponseStatus().toString());
1404 1453 }
... ... @@ -1448,4 +1497,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1448 1497 objectId != null && objectVer != null && objectVer.equals(lwM2mClient.getRegistration().getSupportedVersion(objectId)));
1449 1498 }
1450 1499
  1500 + public LwM2MTransportServerConfig getConfig() {
  1501 + return this.config;
  1502 + }
  1503 +
1451 1504 }
... ...
... ... @@ -117,7 +117,6 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
117 117 }
118 118
119 119 private LeshanServer getLhServer() {
120   -// this.registrationStoreExecutor = (ScheduledExecutorService) ThingsBoardExecutors.newWorkStealingPool(this.config.getRegistrationStorePoolSize(), "LwM2M registrationStore");
121 120 this.registrationStoreExecutor = Executors.newScheduledThreadPool(this.config.getRegistrationStorePoolSize(), ThingsBoardThreadFactory.forName("LwM2M registrationStore"));
122 121
123 122 LeshanServerBuilder builder = new LeshanServerBuilder();
... ...
... ... @@ -86,7 +86,7 @@ public class LwM2mServerListener {
86 86
87 87 @Override
88 88 public void cancelled(Observation observation) {
89   - String msg = String.format("%s: Cancel Observation %s.", LOG_LW2M_INFO, observation.getPath());
  89 + String msg = String.format("%s: Canceled Observation %s.", LOG_LW2M_INFO, observation.getPath());
90 90 service.sendLogsToThingsboard(msg, observation.getRegistrationId());
91 91 log.warn(msg);
92 92 }
... ... @@ -94,13 +94,14 @@ public class LwM2mServerListener {
94 94 @Override
95 95 public void onResponse(Observation observation, Registration registration, ObserveResponse response) {
96 96 if (registration != null) {
97   - try {
98   - service.onUpdateValueAfterReadResponse(registration, convertPathFromObjectIdToIdVer(observation.getPath().toString(),
99   - registration), response, null);
100   - } catch (Exception e) {
101   - log.error("Observation/Read onResponse", e);
102   -
103   - }
  97 +// if (observation.getPath().isResource() || observation.getPath().isResourceInstance()) {
  98 +// String msg = String.format("%s: Successful Observation %s.", LOG_LW2M_INFO,
  99 +// observation.getPath());
  100 +// log.warn(msg);
  101 +// service.sendLogsToThingsboard(msg, registration.getId());
  102 +// }
  103 + service.onUpdateValueAfterReadResponse(registration, convertPathFromObjectIdToIdVer(observation.getPath().toString(),
  104 + registration), response, null);
104 105 }
105 106 }
106 107
... ... @@ -113,9 +114,8 @@ public class LwM2mServerListener {
113 114 public void newObservation(Observation observation, Registration registration) {
114 115 String msg = String.format("%s: Successful start newObservation %s.", LOG_LW2M_INFO,
115 116 observation.getPath());
  117 + log.warn(msg);
116 118 service.sendLogsToThingsboard(msg, registration.getId());
117   - log.trace(msg);
118 119 }
119 120 };
120   -
121 121 }
... ...
... ... @@ -21,6 +21,7 @@ import org.eclipse.leshan.server.registration.Registration;
21 21 import org.thingsboard.server.common.data.Device;
22 22 import org.thingsboard.server.common.data.DeviceProfile;
23 23 import org.thingsboard.server.gen.transport.TransportProtos;
  24 +import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
24 25 import org.thingsboard.server.transport.lwm2m.server.client.Lwm2mClientRpcRequest;
25 26
26 27 import java.util.Collection;
... ... @@ -36,7 +37,7 @@ public interface LwM2mTransportMsgHandler {
36 37
37 38 void onSleepingDev(Registration registration);
38 39
39   - void setCancelObservations(Registration registration);
  40 + void setCancelObservationsAll(Registration registration);
40 41
41 42 void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response, Lwm2mClientRpcRequest rpcRequest);
42 43
... ... @@ -63,4 +64,6 @@ public interface LwM2mTransportMsgHandler {
63 64 void onAwakeDev(Registration registration);
64 65
65 66 void sendLogsToThingsboard(String msg, String registrationId);
  67 +
  68 + LwM2MTransportServerConfig getConfig();
66 69 }
... ...
... ... @@ -36,7 +36,6 @@ import org.eclipse.leshan.core.request.ObserveRequest;
36 36 import org.eclipse.leshan.core.request.ReadRequest;
37 37 import org.eclipse.leshan.core.request.WriteRequest;
38 38 import org.eclipse.leshan.core.request.exception.ClientSleepingException;
39   -import org.eclipse.leshan.core.response.CancelObservationResponse;
40 39 import org.eclipse.leshan.core.response.DeleteResponse;
41 40 import org.eclipse.leshan.core.response.DiscoverResponse;
42 41 import org.eclipse.leshan.core.response.ExecuteResponse;
... ... @@ -49,7 +48,6 @@ import org.eclipse.leshan.core.util.Hex;
49 48 import org.eclipse.leshan.core.util.NamedThreadFactory;
50 49 import org.eclipse.leshan.server.registration.Registration;
51 50 import org.springframework.stereotype.Service;
52   -import org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus;
53 51 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
54 52 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
55 53 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
... ... @@ -70,16 +68,25 @@ import java.util.stream.Collectors;
70 68 import static org.eclipse.californium.core.coap.CoAP.ResponseCode.CONTENT;
71 69 import static org.eclipse.leshan.core.ResponseCode.BAD_REQUEST;
72 70 import static org.eclipse.leshan.core.ResponseCode.NOT_FOUND;
  71 +import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.DOWNLOADED;
  72 +import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.FAILED;
  73 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper.getContentFormatByResourceModelType;
73 74 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.DEFAULT_TIMEOUT;
74 75 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_ID;
  76 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_UPDATE_ID;
75 77 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_ERROR;
76 78 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_INFO;
77 79 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_VALUE;
78 80 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper;
  81 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER;
79 82 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER_All;
  83 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.EXECUTE;
80 84 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_CANCEL;
81 85 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_READ_ALL;
82   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.RESPONSE_CHANNEL;
  86 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_REPLACE;
  87 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_UPDATE;
  88 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.RESPONSE_REQUEST_CHANNEL;
  89 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_INSTALL_ID;
83 90 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_PACKAGE_ID;
84 91 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromIdVerToObjectId;
85 92 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer;
... ... @@ -90,7 +97,7 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.c
90 97 @TbLwM2mTransportComponent
91 98 @RequiredArgsConstructor
92 99 public class LwM2mTransportRequest {
93   - private ExecutorService executorResponse;
  100 + private ExecutorService responseRequestExecutor;
94 101
95 102 public LwM2mValueConverterImpl converter;
96 103
... ... @@ -102,8 +109,8 @@ public class LwM2mTransportRequest {
102 109 @PostConstruct
103 110 public void init() {
104 111 this.converter = LwM2mValueConverterImpl.getInstance();
105   - executorResponse = Executors.newFixedThreadPool(this.config.getResponsePoolSize(),
106   - new NamedThreadFactory(String.format("LwM2M %s channel response", RESPONSE_CHANNEL)));
  112 + responseRequestExecutor = Executors.newFixedThreadPool(this.config.getResponsePoolSize(),
  113 + new NamedThreadFactory(String.format("LwM2M %s channel response after request", RESPONSE_REQUEST_CHANNEL)));
107 114 }
108 115
109 116 /**
... ... @@ -119,118 +126,14 @@ public class LwM2mTransportRequest {
119 126 String contentFormatName, Object params, long timeoutInMs, Lwm2mClientRpcRequest rpcRequest) {
120 127 try {
121 128 String target = convertPathFromIdVerToObjectId(targetIdVer);
122   - DownlinkRequest request = null;
123 129 ContentFormat contentFormat = contentFormatName != null ? ContentFormat.fromName(contentFormatName.toUpperCase()) : ContentFormat.DEFAULT;
124 130 LwM2mClient lwM2MClient = this.lwM2mClientContext.getOrRegister(registration);
125 131 LwM2mPath resultIds = target != null ? new LwM2mPath(target) : null;
126 132 if (!OBSERVE_READ_ALL.name().equals(typeOper.name()) && resultIds != null && registration != null && resultIds.getObjectId() >= 0 && lwM2MClient != null) {
127 133 if (lwM2MClient.isValidObjectVersion(targetIdVer)) {
128 134 timeoutInMs = timeoutInMs > 0 ? timeoutInMs : DEFAULT_TIMEOUT;
129   - ResourceModel resourceModel = null;
130   - switch (typeOper) {
131   - case READ:
132   - request = new ReadRequest(contentFormat, target);
133   - break;
134   - case DISCOVER:
135   - request = new DiscoverRequest(target);
136   - break;
137   - case OBSERVE:
138   - if (resultIds.isResource()) {
139   - Set<Observation> observations = context.getServer().getObservationService().getObservations(registration);
140   - Set<Observation> paths = observations.stream().filter(observation -> observation.getPath().equals(resultIds)).collect(Collectors.toSet());
141   - if (paths.size() == 0) {
142   - request = new ObserveRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId());
143   - } else {
144   - request = new ReadRequest(contentFormat, target);
145   - }
146   - } else if (resultIds.isObjectInstance()) {
147   - request = new ObserveRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId());
148   - } else if (resultIds.getObjectId() >= 0) {
149   - request = new ObserveRequest(contentFormat, resultIds.getObjectId());
150   - }
151   - break;
152   - case OBSERVE_CANCEL:
153   - /*
154   - lwM2MTransportRequest.sendAllRequest(lwServer, registration, path, POST_TYPE_OPER_OBSERVE_CANCEL, null, null, null, null, context.getTimeout());
155   - At server side this will not remove the observation from the observation store, to do it you need to use
156   - {@code ObservationService#cancelObservation()}
157   - */
158   - context.getServer().getObservationService().cancelObservations(registration, target);
159   - break;
160   - case EXECUTE:
161   - resourceModel = lwM2MClient.getResourceModel(targetIdVer, this.config
162   - .getModelProvider());
163   - if (params != null && !resourceModel.multiple) {
164   - request = new ExecuteRequest(target, (String) this.converter.convertValue(params, resourceModel.type, ResourceModel.Type.STRING, resultIds));
165   - } else {
166   - request = new ExecuteRequest(target);
167   - }
168   - break;
169   - case WRITE_REPLACE:
170   - // Request to write a <b>String Single-Instance Resource</b> using the TLV content format.
171   - resourceModel = lwM2MClient.getResourceModel(targetIdVer, this.config.getModelProvider());
172   - if (contentFormat.equals(ContentFormat.TLV)) {
173   - request = this.getWriteRequestSingleResource(null, resultIds.getObjectId(),
174   - resultIds.getObjectInstanceId(), resultIds.getResourceId(), params, resourceModel.type,
175   - registration, rpcRequest);
176   - }
177   - // Mode.REPLACE && Request to write a <b>String Single-Instance Resource</b> using the given content format (TEXT, TLV, JSON)
178   - else if (!contentFormat.equals(ContentFormat.TLV)) {
179   - request = this.getWriteRequestSingleResource(contentFormat, resultIds.getObjectId(),
180   - resultIds.getObjectInstanceId(), resultIds.getResourceId(), params, resourceModel.type,
181   - registration, rpcRequest);
182   - }
183   - break;
184   - case WRITE_UPDATE:
185   - if (resultIds.isResource()) {
186   - /**
187   - * send request: path = '/3/0' node == wM2mObjectInstance
188   - * with params == "\"resources\": {15: resource:{id:15. value:'+01'...}}
189   - **/
190   - Collection<LwM2mResource> resources = lwM2MClient.getNewOneResourceForInstance(
191   - targetIdVer, params,
192   - this.config.getModelProvider(),
193   - this.converter);
194   - request = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(),
195   - resultIds.getObjectInstanceId(), resources);
196   - }
197   -
198   - /**
199   - * params = "{\"id\":0,\"resources\":[{\"id\":14,\"value\":\"+5\"},{\"id\":15,\"value\":\"+9\"}]}"
200   - *
201   - * int rscId = resultIds.getObjectInstanceId();
202   - */
203   -
204   - else if (resultIds.isObjectInstance()) {
205   - if (((ConcurrentHashMap) params).size() > 0) {
206   - Collection<LwM2mResource> resources = lwM2MClient.getNewManyResourcesForInstance(
207   - targetIdVer, params,
208   - this.config.getModelProvider(),
209   - this.converter);
210   - if (resources.size() > 0) {
211   - request = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(),
212   - resultIds.getObjectInstanceId(), resources);
213   - } else {
214   - Lwm2mClientRpcRequest rpcRequestClone = (Lwm2mClientRpcRequest) rpcRequest.clone();
215   - if (rpcRequestClone != null) {
216   - String errorMsg = String.format("Path %s params is not valid", targetIdVer);
217   - serviceImpl.sentRpcRequest(rpcRequestClone, BAD_REQUEST.getName(), errorMsg, LOG_LW2M_ERROR);
218   - rpcRequest = null;
219   - }
220   - }
221   - }
222   - } else if (resultIds.getObjectId() >= 0) {
223   - request = new ObserveRequest(resultIds.getObjectId());
224   - }
225   - break;
226   - case WRITE_ATTRIBUTES:
227   - request = createWriteAttributeRequest(target, params);
228   - break;
229   - case DELETE:
230   - request = new DeleteRequest(target);
231   - break;
232   - }
233   -
  135 + DownlinkRequest request = createRequest (registration, lwM2MClient, typeOper, contentFormat, target,
  136 + targetIdVer, resultIds, params, rpcRequest);
234 137 if (request != null) {
235 138 try {
236 139 this.sendRequest(registration, lwM2MClient, request, timeoutInMs, rpcRequest);
... ... @@ -242,15 +145,19 @@ public class LwM2mTransportRequest {
242 145 } catch (Exception e) {
243 146 log.error("[{}] [{}] [{}] Failed to send downlink.", registration.getEndpoint(), targetIdVer, typeOper.name(), e);
244 147 }
245   - } else if (OBSERVE_CANCEL == typeOper) {
246   - log.trace("[{}], [{}] - [{}] SendRequest", registration.getEndpoint(), typeOper.name(), targetIdVer);
247   - if (rpcRequest != null) {
248   - rpcRequest.setInfoMsg(null);
249   - serviceImpl.sentRpcRequest(rpcRequest, CONTENT.name(), null, null);
  148 + }
  149 + else if (WRITE_UPDATE.name().equals(typeOper.name())) {
  150 + Lwm2mClientRpcRequest rpcRequestClone = (Lwm2mClientRpcRequest) rpcRequest.clone();
  151 + if (rpcRequestClone != null) {
  152 + String errorMsg = String.format("Path %s params is not valid", targetIdVer);
  153 + serviceImpl.sentRpcRequest(rpcRequestClone, BAD_REQUEST.getName(), errorMsg, LOG_LW2M_ERROR);
  154 + rpcRequest = null;
250 155 }
251   - } else {
  156 + }
  157 + else if (!OBSERVE_CANCEL.name().equals(typeOper.name())) {
252 158 log.error("[{}], [{}] - [{}] error SendRequest", registration.getEndpoint(), typeOper.name(), targetIdVer);
253 159 if (rpcRequest != null) {
  160 + ResourceModel resourceModel = lwM2MClient.getResourceModel(targetIdVer, this.config.getModelProvider());
254 161 String errorMsg = resourceModel == null ? String.format("Path %s not found in object version", targetIdVer) : "SendRequest - null";
255 162 serviceImpl.sentRpcRequest(rpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
256 163 }
... ... @@ -265,30 +172,140 @@ public class LwM2mTransportRequest {
265 172 Set<Observation> observations = context.getServer().getObservationService().getObservations(registration);
266 173 paths = observations.stream().map(observation -> observation.getPath().toString()).collect(Collectors.toUnmodifiableSet());
267 174 } else {
  175 + assert registration != null;
268 176 Link[] objectLinks = registration.getSortedObjectLinks();
269   - paths = Arrays.stream(objectLinks).map(link -> link.toString()).collect(Collectors.toUnmodifiableSet());
  177 + paths = Arrays.stream(objectLinks).map(Link::toString).collect(Collectors.toUnmodifiableSet());
  178 + String msg = String.format("%s: type operation %s paths - %s", LOG_LW2M_INFO,
  179 + typeOper.name(), paths);
  180 + serviceImpl.sendLogsToThingsboard(msg, registration.getId());
270 181 }
271   - String msg = String.format("%s: type operation %s paths - %s", LOG_LW2M_INFO,
272   - OBSERVE_READ_ALL.type, paths);
273   - serviceImpl.sendLogsToThingsboard(msg, registration.getId());
274   - log.warn("[{}] [{}], [{}]", typeOper.name(), registration.getEndpoint(), msg);
275 182 if (rpcRequest != null) {
276 183 String valueMsg = String.format("Paths - %s", paths);
277 184 serviceImpl.sentRpcRequest(rpcRequest, CONTENT.name(), valueMsg, LOG_LW2M_VALUE);
278 185 }
  186 + } else if (OBSERVE_CANCEL.name().equals(typeOper.name())) {
  187 + int observeCancelCnt = context.getServer().getObservationService().cancelObservations(registration);
  188 + String observeCancelMsgAll = String.format("%s: type operation %s paths: All count: %d", LOG_LW2M_INFO,
  189 + OBSERVE_CANCEL.name(), observeCancelCnt);
  190 + this.afterObserveCancel(registration, observeCancelCnt, observeCancelMsgAll, rpcRequest);
279 191 }
280 192 } catch (Exception e) {
281 193 String msg = String.format("%s: type operation %s %s", LOG_LW2M_ERROR,
282 194 typeOper.name(), e.getMessage());
283 195 serviceImpl.sendLogsToThingsboard(msg, registration.getId());
284   - try {
285   - throw new Exception(e);
286   - } catch (Exception exception) {
287   - exception.printStackTrace();
  196 + if (rpcRequest != null) {
  197 + String errorMsg = String.format("Path %s type operation %s %s", targetIdVer, typeOper.name(), e.getMessage());
  198 + serviceImpl.sentRpcRequest(rpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
288 199 }
289 200 }
290 201 }
291 202
  203 + private DownlinkRequest createRequest (Registration registration, LwM2mClient lwM2MClient, LwM2mTypeOper typeOper,
  204 + ContentFormat contentFormat, String target, String targetIdVer,
  205 + LwM2mPath resultIds, Object params, Lwm2mClientRpcRequest rpcRequest) {
  206 + DownlinkRequest request = null;
  207 + switch (typeOper) {
  208 + case READ:
  209 + request = new ReadRequest(contentFormat, target);
  210 + break;
  211 + case DISCOVER:
  212 + request = new DiscoverRequest(target);
  213 + break;
  214 + case OBSERVE:
  215 + String msg = String.format("%s: Send Observation %s.", LOG_LW2M_INFO, targetIdVer);
  216 + log.warn(msg);
  217 + if (resultIds.isResource()) {
  218 + Set<Observation> observations = context.getServer().getObservationService().getObservations(registration);
  219 + Set<Observation> paths = observations.stream().filter(observation -> observation.getPath().equals(resultIds)).collect(Collectors.toSet());
  220 + if (paths.size() == 0) {
  221 + request = new ObserveRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId());
  222 + } else {
  223 + request = new ReadRequest(contentFormat, target);
  224 + }
  225 + } else if (resultIds.isObjectInstance()) {
  226 + request = new ObserveRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId());
  227 + } else if (resultIds.getObjectId() >= 0) {
  228 + request = new ObserveRequest(contentFormat, resultIds.getObjectId());
  229 + }
  230 + break;
  231 + case OBSERVE_CANCEL:
  232 + /*
  233 + lwM2MTransportRequest.sendAllRequest(lwServer, registration, path, POST_TYPE_OPER_OBSERVE_CANCEL, null, null, null, null, context.getTimeout());
  234 + At server side this will not remove the observation from the observation store, to do it you need to use
  235 + {@code ObservationService#cancelObservation()}
  236 + */
  237 + int observeCancelCnt = context.getServer().getObservationService().cancelObservations(registration, target);
  238 + String observeCancelMsg = String.format("%s: type operation %s paths: %s count: %d", LOG_LW2M_INFO,
  239 + OBSERVE_CANCEL.name(), target, observeCancelCnt);
  240 + this.afterObserveCancel(registration, observeCancelCnt, observeCancelMsg, rpcRequest);
  241 + break;
  242 + case EXECUTE:
  243 + ResourceModel resourceModelExe = lwM2MClient.getResourceModel(targetIdVer, this.config.getModelProvider());
  244 + if (params != null && !resourceModelExe.multiple) {
  245 + request = new ExecuteRequest(target, (String) this.converter.convertValue(params, resourceModelExe.type, ResourceModel.Type.STRING, resultIds));
  246 + } else {
  247 + request = new ExecuteRequest(target);
  248 + }
  249 + break;
  250 + case WRITE_REPLACE:
  251 + /**
  252 + * Request to write a <b>String Single-Instance Resource</b> using the TLV content format.
  253 + * Type from resourceModel -> STRING, INTEGER, FLOAT, BOOLEAN, OPAQUE, TIME, OBJLNK
  254 + * contentFormat -> TLV, TLV, TLV, TLV, OPAQUE, TLV, LINK
  255 + * JSON, TEXT;
  256 + **/
  257 + ResourceModel resourceModelWrite = lwM2MClient.getResourceModel(targetIdVer, this.config.getModelProvider());
  258 + contentFormat = getContentFormatByResourceModelType(resourceModelWrite, contentFormat);
  259 + request = this.getWriteRequestSingleResource(contentFormat, resultIds.getObjectId(),
  260 + resultIds.getObjectInstanceId(), resultIds.getResourceId(), params, resourceModelWrite.type,
  261 + registration, rpcRequest);
  262 + break;
  263 + case WRITE_UPDATE:
  264 + if (resultIds.isResource()) {
  265 + /**
  266 + * send request: path = '/3/0' node == wM2mObjectInstance
  267 + * with params == "\"resources\": {15: resource:{id:15. value:'+01'...}}
  268 + **/
  269 + Collection<LwM2mResource> resources = lwM2MClient.getNewResourceForInstance(
  270 + targetIdVer, params,
  271 + this.config.getModelProvider(),
  272 + this.converter);
  273 + contentFormat = getContentFormatByResourceModelType(lwM2MClient.getResourceModel(targetIdVer, this.config.getModelProvider()),
  274 + contentFormat);
  275 + request = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(),
  276 + resultIds.getObjectInstanceId(), resources);
  277 + }
  278 + /**
  279 + * params = "{\"id\":0,\"resources\":[{\"id\":14,\"value\":\"+5\"},{\"id\":15,\"value\":\"+9\"}]}"
  280 + * int rscId = resultIds.getObjectInstanceId();
  281 + * contentFormat – Format of the payload (TLV or JSON).
  282 + */
  283 + else if (resultIds.isObjectInstance()) {
  284 + if (((ConcurrentHashMap) params).size() > 0) {
  285 + Collection<LwM2mResource> resources = lwM2MClient.getNewResourcesForInstance(
  286 + targetIdVer, params,
  287 + this.config.getModelProvider(),
  288 + this.converter);
  289 + if (resources.size() > 0) {
  290 + contentFormat = contentFormat.equals(ContentFormat.JSON) ? contentFormat : ContentFormat.TLV;
  291 + request = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(),
  292 + resultIds.getObjectInstanceId(), resources);
  293 + }
  294 + }
  295 + } else if (resultIds.getObjectId() >= 0) {
  296 + request = new ObserveRequest(resultIds.getObjectId());
  297 + }
  298 + break;
  299 + case WRITE_ATTRIBUTES:
  300 + request = createWriteAttributeRequest(target, params);
  301 + break;
  302 + case DELETE:
  303 + request = new DeleteRequest(target);
  304 + break;
  305 + }
  306 + return request;
  307 + }
  308 +
292 309 /**
293 310 * @param registration -
294 311 * @param request -
... ... @@ -314,6 +331,7 @@ public class LwM2mTransportRequest {
314 331 if (!lwM2MClient.isInit()) {
315 332 lwM2MClient.initReadValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration));
316 333 }
  334 + /** Not Found */
317 335 if (rpcRequest != null) {
318 336 serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), response.getErrorMessage(), LOG_LW2M_ERROR);
319 337 }
... ... @@ -322,7 +340,15 @@ public class LwM2mTransportRequest {
322 340 **/
323 341 if (lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) {
324 342 lwM2MClient.getFwUpdate().initReadValue(serviceImpl, request.getPath().toString());
325   - log.warn("updateFirmwareClient1");
  343 + }
  344 + if (lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) {
  345 + lwM2MClient.getSwUpdate().initReadValue(serviceImpl, request.getPath().toString());
  346 + }
  347 + if (request.getPath().toString().equals(FW_PACKAGE_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) {
  348 + this.afterWriteFwSWUpdateError(registration, request, response.getErrorMessage());
  349 + }
  350 + if (request.getPath().toString().equals(FW_UPDATE_ID) || request.getPath().toString().equals(SW_INSTALL_ID)) {
  351 + this.afterExecuteFwSwUpdateError(registration, request, response.getErrorMessage());
326 352 }
327 353 }
328 354 }, e -> {
... ... @@ -331,7 +357,15 @@ public class LwM2mTransportRequest {
331 357 **/
332 358 if (lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) {
333 359 lwM2MClient.getFwUpdate().initReadValue(serviceImpl, request.getPath().toString());
334   - log.warn("updateFirmwareClient2");
  360 + }
  361 + if (lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) {
  362 + lwM2MClient.getSwUpdate().initReadValue(serviceImpl, request.getPath().toString());
  363 + }
  364 + if (request.getPath().toString().equals(FW_PACKAGE_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) {
  365 + this.afterWriteFwSWUpdateError(registration, request, e.getMessage());
  366 + }
  367 + if (request.getPath().toString().equals(FW_UPDATE_ID) || request.getPath().toString().equals(SW_INSTALL_ID)) {
  368 + this.afterExecuteFwSwUpdateError(registration, request, e.getMessage());
335 369 }
336 370 if (!lwM2MClient.isInit()) {
337 371 lwM2MClient.initReadValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration));
... ... @@ -395,7 +429,7 @@ public class LwM2mTransportRequest {
395 429
396 430 private void handleResponse(Registration registration, final String path, LwM2mResponse response,
397 431 DownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) {
398   - executorResponse.submit(() -> {
  432 + responseRequestExecutor.submit(() -> {
399 433 try {
400 434 this.sendResponse(registration, path, response, request, rpcRequest);
401 435 } catch (Exception e) {
... ... @@ -414,28 +448,26 @@ public class LwM2mTransportRequest {
414 448 private void sendResponse(Registration registration, String path, LwM2mResponse response,
415 449 DownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) {
416 450 String pathIdVer = convertPathFromObjectIdToIdVer(path, registration);
  451 + String msgLog = "";
417 452 if (response instanceof ReadResponse) {
418 453 serviceImpl.onUpdateValueAfterReadResponse(registration, pathIdVer, (ReadResponse) response, rpcRequest);
419   - } else if (response instanceof CancelObservationResponse) {
420   - log.info("[{}] Path [{}] CancelObservationResponse 3_Send", pathIdVer, response);
421   -
422 454 } else if (response instanceof DeleteResponse) {
423   - log.info("[{}] Path [{}] DeleteResponse 5_Send", pathIdVer, response);
  455 + log.warn("[{}] Path [{}] DeleteResponse 5_Send", pathIdVer, response);
424 456 } else if (response instanceof DiscoverResponse) {
425   - log.info("[{}] [{}] - [{}] [{}] Discovery value: [{}]", registration.getEndpoint(),
426   - ((Response) response.getCoapResponse()).getCode(), response.getCode(),
427   - request.getPath().toString(), ((DiscoverResponse) response).getObjectLinks());
  457 + String discoverValue = Link.serialize(((DiscoverResponse)response).getObjectLinks());
  458 + msgLog = String.format("%s: type operation: %s path: %s value: %s",
  459 + LOG_LW2M_INFO, DISCOVER.name(), request.getPath().toString(), discoverValue);
  460 + serviceImpl.sendLogsToThingsboard(msgLog, registration.getId());
  461 + log.warn("DiscoverResponse: [{}]", (DiscoverResponse) response);
428 462 if (rpcRequest != null) {
429   - String discoveryMsg = String.format("%s",
430   - Arrays.stream(((DiscoverResponse) response).getObjectLinks()).collect(Collectors.toSet()));
431   - serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), discoveryMsg, LOG_LW2M_VALUE);
  463 + serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), discoverValue, LOG_LW2M_VALUE);
432 464 }
433 465 } else if (response instanceof ExecuteResponse) {
434   - log.info("[{}] Path [{}] ExecuteResponse 7_Send", pathIdVer, response);
  466 + log.warn("[{}] Path [{}] ExecuteResponse 7_Send", pathIdVer, response);
435 467 } else if (response instanceof WriteAttributesResponse) {
436   - log.info("[{}] Path [{}] WriteAttributesResponse 8_Send", pathIdVer, response);
  468 + log.warn("[{}] Path [{}] WriteAttributesResponse 8_Send", pathIdVer, response);
437 469 } else if (response instanceof WriteResponse) {
438   - log.info("[{}] Path [{}] WriteResponse 9_Send", pathIdVer, response);
  470 + log.warn("[{}] Path [{}] WriteResponse 9_Send", pathIdVer, response);
439 471 this.infoWriteResponse(registration, response, request);
440 472 serviceImpl.onWriteResponseOk(registration, pathIdVer, (WriteRequest) request);
441 473 }
... ... @@ -480,9 +512,8 @@ public class LwM2mTransportRequest {
480 512 }
481 513 if (msg != null) {
482 514 serviceImpl.sendLogsToThingsboard(msg, registration.getId());
483   - log.warn(msg);
484 515 if (request.getPath().toString().equals(FW_PACKAGE_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) {
485   - this.executeFwSwUpdate(registration, request);
  516 + this.afterWriteSuccessFwSwUpdate(registration, request);
486 517 }
487 518 }
488 519 } catch (Exception e) {
... ... @@ -490,15 +521,54 @@ public class LwM2mTransportRequest {
490 521 }
491 522 }
492 523
493   - private void executeFwSwUpdate(Registration registration, DownlinkRequest request) {
494   - LwM2mClient lwM2mClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId());
495   - if (request.getPath().toString().equals(FW_PACKAGE_ID)
496   - && FirmwareUpdateStatus.DOWNLOADING.name().equals(lwM2mClient.getFwUpdate().getStateUpdate())) {
497   - lwM2mClient.getFwUpdate().sendReadInfoForWrite();
  524 + /**
  525 + * After finish operation FwSwUpdate Write (success):
  526 + * fw_state/sw_state = DOWNLOADED
  527 + * send operation Execute
  528 + */
  529 + private void afterWriteSuccessFwSwUpdate(Registration registration, DownlinkRequest request) {
  530 + LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId());
  531 + if (request.getPath().toString().equals(FW_PACKAGE_ID) && lwM2MClient.getFwUpdate() != null) {
  532 + lwM2MClient.getFwUpdate().setStateUpdate(DOWNLOADED.name());
  533 + lwM2MClient.getFwUpdate().sendLogs(WRITE_REPLACE.name(), LOG_LW2M_INFO, null);
  534 + }
  535 + if (request.getPath().toString().equals(SW_PACKAGE_ID) && lwM2MClient.getSwUpdate() != null) {
  536 + lwM2MClient.getSwUpdate().setStateUpdate(DOWNLOADED.name());
  537 + lwM2MClient.getSwUpdate().sendLogs(WRITE_REPLACE.name(), LOG_LW2M_INFO, null);
  538 + }
  539 + }
  540 +
  541 + /**
  542 + * After finish operation FwSwUpdate Write (error): fw_state = FAILED
  543 + */
  544 + private void afterWriteFwSWUpdateError(Registration registration, DownlinkRequest request, String msgError) {
  545 + LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId());
  546 + if (request.getPath().toString().equals(FW_PACKAGE_ID) && lwM2MClient.getFwUpdate() != null) {
  547 + lwM2MClient.getFwUpdate().setStateUpdate(FAILED.name());
  548 + lwM2MClient.getFwUpdate().sendLogs(WRITE_REPLACE.name(), LOG_LW2M_ERROR, msgError);
  549 + }
  550 + if (request.getPath().toString().equals(SW_PACKAGE_ID) && lwM2MClient.getSwUpdate() != null) {
  551 + lwM2MClient.getSwUpdate().setStateUpdate(FAILED.name());
  552 + lwM2MClient.getSwUpdate().sendLogs(WRITE_REPLACE.name(), LOG_LW2M_ERROR, msgError);
498 553 }
499   - if (request.getPath().toString().equals(SW_PACKAGE_ID)
500   - && FirmwareUpdateStatus.DOWNLOADING.name().equals(lwM2mClient.getSwUpdate().getStateUpdate())) {
501   - lwM2mClient.getSwUpdate().sendReadInfoForWrite();
  554 + }
  555 +
  556 + private void afterExecuteFwSwUpdateError(Registration registration, DownlinkRequest request, String msgError) {
  557 + LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId());
  558 + if (request.getPath().toString().equals(FW_UPDATE_ID) && lwM2MClient.getFwUpdate() != null) {
  559 + lwM2MClient.getFwUpdate().sendLogs(EXECUTE.name(), LOG_LW2M_ERROR, msgError);
  560 + }
  561 + if (request.getPath().toString().equals(SW_INSTALL_ID) && lwM2MClient.getSwUpdate() != null) {
  562 + lwM2MClient.getSwUpdate().sendLogs(EXECUTE.name(), LOG_LW2M_ERROR, msgError);
  563 + }
  564 + }
  565 +
  566 + private void afterObserveCancel(Registration registration, int observeCancelCnt, String observeCancelMsg, Lwm2mClientRpcRequest rpcRequest) {
  567 + serviceImpl.sendLogsToThingsboard(observeCancelMsg, registration.getId());
  568 + log.warn("[{}]", observeCancelMsg);
  569 + if (rpcRequest != null) {
  570 + rpcRequest.setInfoMsg(String.format("Count: %d", observeCancelCnt));
  571 + serviceImpl.sentRpcRequest(rpcRequest, CONTENT.name(), null, LOG_LW2M_INFO);
502 572 }
503 573 }
504 574 }
... ...
... ... @@ -38,6 +38,7 @@ import org.eclipse.leshan.core.model.InvalidDDFFileException;
38 38 import org.eclipse.leshan.core.model.ObjectModel;
39 39 import org.eclipse.leshan.core.model.ResourceModel;
40 40 import org.eclipse.leshan.core.node.codec.CodecException;
  41 +import org.eclipse.leshan.core.request.ContentFormat;
41 42 import org.springframework.stereotype.Component;
42 43 import org.thingsboard.server.common.transport.TransportServiceCallback;
43 44 import org.thingsboard.server.gen.transport.TransportProtos;
... ... @@ -53,7 +54,6 @@ import java.util.ArrayList;
53 54 import java.util.List;
54 55
55 56 import static org.thingsboard.server.gen.transport.TransportProtos.KeyValueType.BOOLEAN_V;
56   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_TELEMETRY;
57 57
58 58 @Slf4j
59 59 @Component
... ... @@ -68,7 +68,7 @@ public class LwM2mTransportServerHelper {
68 68 * send to Thingsboard Attribute || Telemetry
69 69 *
70 70 * @param msg - JsonObject: [{name: value}]
71   - * @return - dummy
  71 + * @return - dummyWriteReplace {\"targetIdVer\":\"/19_1.0/0/0\",\"value\":0082}
72 72 */
73 73 private <T> TransportServiceCallback<Void> getPubAckCallbackSendAttrTelemetry(final T msg) {
74 74 return new TransportServiceCallback<>() {
... ... @@ -135,16 +135,16 @@ public class LwM2mTransportServerHelper {
135 135 }
136 136
137 137 /**
138   - *
139   - * @param logMsg - info about Logs
  138 + * @param value - info about Logs
140 139 * @return- KeyValueProto for telemetry (Logs)
141 140 */
142   - public List<TransportProtos.KeyValueProto> getKvLogyToThingsboard(String logMsg) {
  141 + public List<TransportProtos.KeyValueProto> getKvStringtoThingsboard(String key, String value) {
143 142 List<TransportProtos.KeyValueProto> result = new ArrayList<>();
  143 + value = value.replaceAll("<", "").replaceAll(">", "");
144 144 result.add(TransportProtos.KeyValueProto.newBuilder()
145   - .setKey(LOG_LW2M_TELEMETRY)
  145 + .setKey(key)
146 146 .setType(TransportProtos.KeyValueType.STRING_V)
147   - .setStringV(logMsg).build());
  147 + .setStringV(value).build());
148 148 return result;
149 149 }
150 150
... ... @@ -180,8 +180,7 @@ public class LwM2mTransportServerHelper {
180 180 }
181 181
182 182 /**
183   - *
184   - * @param currentType -
  183 + * @param currentType -
185 184 * @param resourcePath -
186 185 * @return
187 186 */
... ... @@ -203,6 +202,28 @@ public class LwM2mTransportServerHelper {
203 202 throw new CodecException("Invalid ResourceModel_Type for resource %s, got %s", resourcePath, currentType);
204 203 }
205 204
  205 + public static ContentFormat convertResourceModelTypeToContentFormat(ResourceModel.Type type) {
  206 + switch (type) {
  207 + case BOOLEAN:
  208 + case STRING:
  209 + case TIME:
  210 + case INTEGER:
  211 + case FLOAT:
  212 + return ContentFormat.TLV;
  213 + case OPAQUE:
  214 + return ContentFormat.OPAQUE;
  215 + case OBJLNK:
  216 + return ContentFormat.LINK;
  217 + default:
  218 + }
  219 + throw new CodecException("Invalid ResourceModel_Type for %s ContentFormat.", type);
  220 + }
  221 +
  222 + public static ContentFormat getContentFormatByResourceModelType(ResourceModel resourceModel, ContentFormat contentFormat) {
  223 + return contentFormat.equals(ContentFormat.TLV) ? convertResourceModelTypeToContentFormat(resourceModel.type) :
  224 + contentFormat;
  225 + }
  226 +
206 227 public static Object getValueFromKvProto(TransportProtos.KeyValueProto kv) {
207 228 switch (kv.getType()) {
208 229 case BOOLEAN_V:
... ...
... ... @@ -104,7 +104,8 @@ public class LwM2mTransportUtil {
104 104
105 105 public static final long DEFAULT_TIMEOUT = 2 * 60 * 1000L; // 2min in ms
106 106
107   - public static final String LOG_LW2M_TELEMETRY = "logLwm2m";
  107 + public static final String
  108 + LOG_LW2M_TELEMETRY = "logLwm2m";
108 109 public static final String LOG_LW2M_INFO = "info";
109 110 public static final String LOG_LW2M_ERROR = "error";
110 111 public static final String LOG_LW2M_WARN = "warn";
... ... @@ -208,8 +209,13 @@ public class LwM2mTransportUtil {
208 209 DELETE(10, "Delete"),
209 210
210 211 // only for RPC
211   - READ_INFO_FW(11, "ReadInfoFirmware"),
212   - READ_INFO_SW(12, "ReadInfoSoftware");
  212 + FW_READ_INFO(11, "FirmwareReadInfo"),
  213 + FW_UPDATE(12, "FirmwareUpdate"),
  214 + FW_UPDATE_URL(14, "FirmwareUpdateUrl"),
  215 + SW_READ_INFO(15, "SoftwareReadInfo"),
  216 + SW_UPDATE(16, "SoftwareUpdate"),
  217 + SW_UPDATE_URL(17, "SoftwareUpdateUrl"),
  218 + SW_UNINSTALL(18, "SoftwareUninstall");
213 219
214 220 public int code;
215 221 public String type;
... ... @@ -357,7 +363,7 @@ public class LwM2mTransportUtil {
357 363 }
358 364
359 365 /**
360   - * Update State R
  366 + * SW Update State R
361 367 * 0: INITIAL Before downloading. (see 5.1.2.1)
362 368 * 1: DOWNLOAD STARTED The downloading process has started and is on-going. (see 5.1.2.2)
363 369 * 2: DOWNLOADED The package has been completely downloaded (see 5.1.2.3)
... ... @@ -429,7 +435,7 @@ public class LwM2mTransportUtil {
429 435 INITIAL(0, "Initial value", false),
430 436 DOWNLOADING(1, "Downloading", false),
431 437 SUCCESSFULLY_INSTALLED(2, "Software successfully installed", false),
432   - SUCCESSFULLY_INSTALLED_VERIFIED(3, "Successfully Downloaded and package integrity verified", false),
  438 + SUCCESSFULLY_DOWNLOADED_VERIFIED(3, "Successfully Downloaded and package integrity verified", false),
433 439 NOT_ENOUGH_STORAGE(50, "Not enough storage for the new software package", true),
434 440 OUT_OFF_MEMORY(51, "Out of memory during downloading process", true),
435 441 CONNECTION_LOST(52, "Connection lost during downloading process", false),
... ... @@ -489,7 +495,7 @@ public class LwM2mTransportUtil {
489 495 return DOWNLOADING;
490 496 case SUCCESSFULLY_INSTALLED:
491 497 return UPDATED;
492   - case SUCCESSFULLY_INSTALLED_VERIFIED:
  498 + case SUCCESSFULLY_DOWNLOADED_VERIFIED:
493 499 return VERIFIED;
494 500 case NOT_ENOUGH_STORAGE:
495 501 case OUT_OFF_MEMORY:
... ... @@ -507,7 +513,9 @@ public class LwM2mTransportUtil {
507 513 }
508 514
509 515 public static final String EVENT_AWAKE = "AWAKE";
  516 + public static final String RESPONSE_REQUEST_CHANNEL = "RESP_REQ";
510 517 public static final String RESPONSE_CHANNEL = "RESP";
  518 + public static final String OBSERVE_CHANNEL = "OBSERVE";
511 519
512 520 public static boolean equalsResourceValue(Object valueOld, Object valueNew, ResourceModel.Type type, LwM2mPath
513 521 resourcePath) throws CodecException {
... ...
... ... @@ -82,7 +82,7 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider {
82 82 if (objectModel != null)
83 83 return objectModel.resources.get(resourceId);
84 84 else
85   - log.warn("TbResources (Object model) with id [{}/0/{}] not found on the server", objectId, resourceId);
  85 + log.trace("TbResources (Object model) with id [{}/0/{}] not found on the server", objectId, resourceId);
86 86 return null;
87 87 } catch (Exception e) {
88 88 log.error("", e);
... ...
... ... @@ -64,7 +64,6 @@ public class LwM2MJsonAdaptor implements LwM2MTransportAdaptor {
64 64 }
65 65 return result.build();
66 66 } catch (RuntimeException e) {
67   - log.warn("Failed to decode get attributes request", e);
68 67 throw new AdaptorException(e);
69 68 }
70 69 }
... ...
... ... @@ -18,7 +18,11 @@ package org.thingsboard.server.transport.lwm2m.server.client;
18 18 import lombok.Getter;
19 19 import lombok.Setter;
20 20 import lombok.extern.slf4j.Slf4j;
  21 +import org.eclipse.leshan.core.model.ObjectModel;
21 22 import org.eclipse.leshan.core.model.ResourceModel;
  23 +import org.eclipse.leshan.core.node.LwM2mMultipleResource;
  24 +import org.eclipse.leshan.core.node.LwM2mObject;
  25 +import org.eclipse.leshan.core.node.LwM2mObjectInstance;
22 26 import org.eclipse.leshan.core.node.LwM2mPath;
23 27 import org.eclipse.leshan.core.node.LwM2mResource;
24 28 import org.eclipse.leshan.core.node.LwM2mSingleResource;
... ... @@ -47,6 +51,8 @@ import java.util.concurrent.ConcurrentLinkedQueue;
47 51 import java.util.concurrent.CopyOnWriteArrayList;
48 52 import java.util.stream.Collectors;
49 53
  54 +import static org.eclipse.leshan.core.model.ResourceModel.Type.OPAQUE;
  55 +import static org.eclipse.leshan.core.model.ResourceModel.Type.STRING;
50 56 import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH;
51 57 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.TRANSPORT_DEFAULT_LWM2M_VERSION;
52 58 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromIdVerToObjectId;
... ... @@ -192,6 +198,14 @@ public class LwM2mClient implements Cloneable {
192 198 return null;
193 199 }
194 200
  201 + public Object getResourceName (String pathRezIdVer, String pathRezId) {
  202 + String pathRez = pathRezIdVer == null ? convertPathFromObjectIdToIdVer(pathRezId, this.registration) : pathRezIdVer;
  203 + if (this.resources.get(pathRez) != null) {
  204 + return this.resources.get(pathRez).getResourceModel().name;
  205 + }
  206 + return null;
  207 + }
  208 +
195 209 public ResourceModel getResourceModel(String pathIdVer, LwM2mModelProvider modelProvider) {
196 210 LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer));
197 211 String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId());
... ... @@ -200,8 +214,55 @@ public class LwM2mClient implements Cloneable {
200 214 .getResourceModel(pathIds.getObjectId(), pathIds.getResourceId()) : null;
201 215 }
202 216
203   - public Collection<LwM2mResource> getNewOneResourceForInstance(String pathRezIdVer, Object params, LwM2mModelProvider modelProvider,
204   - LwM2mValueConverterImpl converter) {
  217 + public ObjectModel getObjectModel(String pathIdVer, LwM2mModelProvider modelProvider) {
  218 + LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer));
  219 + String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId());
  220 + String verRez = getVerFromPathIdVerOrId(pathIdVer);
  221 + return verRez == null || verRez.equals(verSupportedObject) ? modelProvider.getObjectModel(registration)
  222 + .getObjectModel(pathIds.getObjectId()) : null;
  223 + }
  224 +
  225 + public String objectToString (LwM2mObject lwM2mObject, LwM2mValueConverterImpl converter, String pathIdVer) {
  226 + StringBuilder builder = new StringBuilder();
  227 + builder.append("LwM2mObject [id=").append(lwM2mObject.getId()).append(", instances={");
  228 + lwM2mObject.getInstances().forEach((instId, inst) -> {
  229 + builder.append(instId).append("=").append(this.instanceToString(inst, converter, pathIdVer)).append(", ");
  230 + });
  231 + int startInd = builder.lastIndexOf(", ");
  232 + if (startInd > 0) {
  233 + builder.delete(startInd, startInd + 2);
  234 + }
  235 + builder.append("}]");
  236 + return builder.toString();
  237 + }
  238 + public String instanceToString (LwM2mObjectInstance objectInstance, LwM2mValueConverterImpl converter, String pathIdVer) {
  239 + StringBuilder builder = new StringBuilder();
  240 + builder.append("LwM2mObjectInstance [id=").append(objectInstance.getId()).append(", resources={");
  241 + objectInstance.getResources().forEach((resId, res) -> {
  242 + builder.append(resId).append("=").append(this.resourceToString (res, converter, pathIdVer)).append(", ");
  243 + });
  244 + int startInd = builder.lastIndexOf(", ");
  245 + if (startInd > 0) {
  246 + builder.delete(startInd, startInd + 2);
  247 + }
  248 + builder.append("}]");
  249 + return builder.toString();
  250 + }
  251 +
  252 + public String resourceToString (LwM2mResource lwM2mResource, LwM2mValueConverterImpl converter, String pathIdVer) {
  253 + if (!OPAQUE.equals(lwM2mResource.getType())) {
  254 + return lwM2mResource.isMultiInstances() ? ((LwM2mMultipleResource) lwM2mResource).toString() :
  255 + ((LwM2mSingleResource) lwM2mResource).toString();
  256 + }
  257 + else {
  258 + return String.format("LwM2mSingleResource [id=%s, value=%s, type=%s]", lwM2mResource.getId(),
  259 + converter.convertValue(lwM2mResource.getValue(),
  260 + OPAQUE, STRING, new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer))), lwM2mResource.getType().name());
  261 + }
  262 + }
  263 +
  264 + public Collection<LwM2mResource> getNewResourceForInstance(String pathRezIdVer, Object params, LwM2mModelProvider modelProvider,
  265 + LwM2mValueConverterImpl converter) {
205 266 LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRezIdVer));
206 267 Collection<LwM2mResource> resources = ConcurrentHashMap.newKeySet();
207 268 Map<Integer, ResourceModel> resourceModels = modelProvider.getObjectModel(registration)
... ... @@ -215,8 +276,8 @@ public class LwM2mClient implements Cloneable {
215 276 return resources;
216 277 }
217 278
218   - public Collection<LwM2mResource> getNewManyResourcesForInstance(String pathRezIdVer, Object params, LwM2mModelProvider modelProvider,
219   - LwM2mValueConverterImpl converter) {
  279 + public Collection<LwM2mResource> getNewResourcesForInstance(String pathRezIdVer, Object params, LwM2mModelProvider modelProvider,
  280 + LwM2mValueConverterImpl converter) {
220 281 LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRezIdVer));
221 282 Collection<LwM2mResource> resources = ConcurrentHashMap.newKeySet();
222 283 Map<Integer, ResourceModel> resourceModels = modelProvider.getObjectModel(registration)
... ...
... ... @@ -34,6 +34,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
34 34 import static org.thingsboard.server.common.data.firmware.FirmwareKey.STATE;
35 35 import static org.thingsboard.server.common.data.firmware.FirmwareType.FIRMWARE;
36 36 import static org.thingsboard.server.common.data.firmware.FirmwareType.SOFTWARE;
  37 +import static org.thingsboard.server.common.data.firmware.FirmwareUpdateStatus.UPDATING;
37 38 import static org.thingsboard.server.common.data.firmware.FirmwareUtil.getAttributeKey;
38 39 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_NAME_ID;
39 40 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_ID;
... ... @@ -42,10 +43,10 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.F
42 43 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_UPDATE;
43 44 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_UPDATE_ID;
44 45 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_VER_ID;
  46 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_ERROR;
45 47 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_INFO;
46 48 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.EXECUTE;
47 49 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE;
48   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.READ;
49 50 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_REPLACE;
50 51 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_INSTALL_ID;
51 52 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_NAME_ID;
... ... @@ -56,6 +57,7 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.S
56 57 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_UPDATE_STATE_ID;
57 58 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_VER_ID;
58 59 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer;
  60 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.splitCamelCaseString;
59 61
60 62 @Slf4j
61 63 public class LwM2mFwSwUpdate {
... ... @@ -111,7 +113,7 @@ public class LwM2mFwSwUpdate {
111 113 }
112 114
113 115 private void initPathId() {
114   - if (this.type.equals(FIRMWARE)) {
  116 + if (FIRMWARE.equals(this.type) ) {
115 117 this.pathPackageId = FW_PACKAGE_ID;
116 118 this.pathStateId = FW_STATE_ID;
117 119 this.pathResultId = FW_RESULT_ID;
... ... @@ -119,7 +121,7 @@ public class LwM2mFwSwUpdate {
119 121 this.pathVerId = FW_VER_ID;
120 122 this.pathInstallId = FW_UPDATE_ID;
121 123 this.wUpdate = FW_UPDATE;
122   - } else if (this.type.equals(SOFTWARE)) {
  124 + } else if (SOFTWARE.equals(this.type) ) {
123 125 this.pathPackageId = SW_PACKAGE_ID;
124 126 this.pathStateId = SW_UPDATE_STATE_ID;
125 127 this.pathResultId = SW_RESULT_ID;
... ... @@ -142,25 +144,20 @@ public class LwM2mFwSwUpdate {
142 144 boolean conditionalStart = this.type.equals(FIRMWARE) ? this.conditionalFwUpdateStart() :
143 145 this.conditionalSwUpdateStart();
144 146 if (conditionalStart) {
145   - this.stateUpdate = FirmwareUpdateStatus.DOWNLOADING.name();
146   - this.observeStateUpdate();
147 147 this.writeFwSwWare();
148   - this.sendLogs(WRITE_REPLACE.name());
149   - }
150   - } else {
151   - boolean conditionalExecute = this.type.equals(FIRMWARE) ? conditionalFwUpdateExecute() :
152   - conditionalSwUpdateExecute();
153   - if (conditionalExecute) {
154   - this.stateUpdate = FirmwareUpdateStatus.DOWNLOADED.name();
155   - this.observeStateUpdate();
156   - this.executeFwSwWare();
157   - this.sendLogs(EXECUTE.name());
158 148 }
159 149 }
160 150 }
161 151 }
162 152
  153 + /**
  154 + * Send FsSw to Lwm2mClient:
  155 + * before operation Write: fw_state = DOWNLOADING
  156 + */
163 157 private void writeFwSwWare() {
  158 + this.stateUpdate = FirmwareUpdateStatus.DOWNLOADING.name();
  159 +// this.observeStateUpdate();
  160 + this.sendLogs(WRITE_REPLACE.name(), LOG_LW2M_INFO, null);
164 161 int chunkSize = 0;
165 162 int chunk = 0;
166 163 byte[] firmwareChunk = this.serviceImpl.firmwareDataCache.get(this.currentId.toString(), chunkSize, chunk);
... ... @@ -169,124 +166,155 @@ public class LwM2mFwSwUpdate {
169 166 firmwareChunk, this.serviceImpl.config.getTimeout(), null);
170 167 }
171 168
172   - public void sendLogs(String typeOper) {
  169 + public void sendLogs(String typeOper, String typeInfo, String msgError) {
173 170 this.sendSateOnThingsboard();
174   - String msg = String.format("%s: %s, %s, pkgVer: %s: pkgName - %s.",
175   - LOG_LW2M_INFO, this.wUpdate, typeOper, this.currentVersion, this.currentTitle);
  171 + String msg = String.format("%s: %s, %s, pkgVer: %s: pkgName - %s state - %s.",
  172 + typeInfo, this.wUpdate, typeOper, this.currentVersion, this.currentTitle, this.stateUpdate);
  173 + if (LOG_LW2M_ERROR.equals(typeInfo)) {
  174 + msg = String.format("%s Error: %s", msg, msgError);
  175 + }
176 176 serviceImpl.sendLogsToThingsboard(msg, lwM2MClient.getRegistration().getId());
177   - log.warn("{} state: [{}]", msg, this.stateUpdate);
178 177 }
179 178
  179 +
  180 + /**
  181 + * After inspection Update Result
  182 + * fw_state/sw_state = UPDATING
  183 + * send execute
  184 + */
180 185 public void executeFwSwWare() {
181   - this.serviceImpl.lwM2mTransportRequest.sendAllRequest(this.lwM2MClient.getRegistration(), this.pathInstallId, EXECUTE, ContentFormat.TLV.getName(),
182   - null, 0, null);
  186 + this.setStateUpdate(UPDATING.name());
  187 + this.sendLogs(EXECUTE.name(), LOG_LW2M_INFO, null);
  188 + this.serviceImpl.lwM2mTransportRequest.sendAllRequest(this.lwM2MClient.getRegistration(), this.pathInstallId, EXECUTE, ContentFormat.TLV.getName(),
  189 + null, 0, null);
183 190 }
184 191
185 192
186 193 /**
187   - * FW: start
188   - * Проверяем состояние State (5.3) и Update Result (5.5).
189   - * 1. Если Update Result > 1 (some errors) - Это означает что пред. апдейт не прошел.
190   - * - Запускаем апдейт в независимости от состяния прошивки и ее версии.
191   - * 2. Если Update Result = 1 && State = 0 - Это означает что пред. апдейт прошел.
192   - * 3. Если Update Result = 0 && State = 0 && Ver = "" - Это означает что апдейта еще не было.
  194 + * Firmware start:
  195 + * -- Если Update Result -errors (более 1) - Это означает что пред. апдейт не прошел.
  196 + * - Запускаем апдейт в независимости от состяния прошивки и ее версии.
  197 + * -- Если Update Result - не errors (менее или равно 1) и ver не пустой - Это означает что пред. апдейт прошел.
  198 + * -- Если Update Result - не errors и ver пустой - Это означает что апдейта еще не было.
193 199 * - Проверяем поменялась ли версия и запускаем новый апдейт.
194   - * Новый апдейт:
195   - * 1. Запись новой прошивки в Lwm2mClient
196   - * 2. Мониторим итог зиписи:
197   - * 2.1 State = 2 "Downloaded" и Update Result = 0 "INITIAL" стартуем Update 5.2 (Execute):
198   - * Мониторим состояние Update Result и State и мапим его на наш enum (DOWNLOADING, DOWNLOADED, VERIFIED, UPDATING, UPDATED, FAILED)
199   - * + пишем лог (в телеметрию отдельным полем error) с подробным статусом.
200   - *
201   - * @valerii.sosliuk Вопрос к клиенту - как будем реагировать на Failed update? Когда повторять операцию?
202   - * - На update reg?
203   - * - Или клиент должен послать комканду на рестарт девайса?
204   - * - или переодически?
205   - * отправили прошивку мониторим:
206   - * -- Observe "Update Result" id=5 && "State" id=3
207   - * --- "Update Result" id=5 value must be = 0
208   - * --- "State" id=3 value must be > 0
209   - * --- to telemetry - DOWNLOADING
210   - * "Update Result" id=5 value change > 1 "Firmware updated not successfully" отправили прошивку: telemetry - FAILED
211   - * "Update Result" id=5 value change ==1 "State" id=3 value == 0 "Firmware updated successfully" отправили прошивку: telemetry - UPDATED
212 200 */
213 201 private boolean conditionalFwUpdateStart() {
214   - Long stateFw = (Long) this.lwM2MClient.getResourceValue(null, this.pathStateId);
215 202 Long updateResultFw = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId);
216   - String pkgName = (String) this.lwM2MClient.getResourceValue(null, this.pathNameId);
217 203 // #1/#2
218 204 return updateResultFw > LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.code ||
219 205 (
220   - (
221   - (stateFw == LwM2mTransportUtil.StateFw.IDLE.code && updateResultFw == LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.code) ||
222   - (stateFw == LwM2mTransportUtil.StateFw.IDLE.code && updateResultFw == LwM2mTransportUtil.UpdateResultFw.INITIAL.code
223   - && StringUtils.trimToEmpty(pkgName).isEmpty())
  206 + (updateResultFw <= LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.code
224 207 ) &&
225 208 (
226 209 (this.currentVersion != null && !this.currentVersion.equals(this.lwM2MClient.getResourceValue(null, this.pathVerId))) ||
227 210 (this.currentTitle != null && !this.currentTitle.equals(this.lwM2MClient.getResourceValue(null, this.pathNameId)))
228 211 )
229 212 );
230   -// if (condFwUpdateStart) {
231   -// this.sendSateOnThingsboard(stateFw, updateResultFw, pkgName);
232   -// }
233   -// return condFwUpdateStart;
234 213 }
235 214
236   - private boolean conditionalFwUpdateExecute() {
237   - Long state = (Long) this.lwM2MClient.getResourceValue(null, this.pathStateId);
  215 +
  216 + /**
  217 + * Before operation Execute inspection Update Result :
  218 + * 0 - Initial value
  219 + */
  220 + public boolean conditionalFwExecuteStart() {
238 221 Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId);
239   - // #1/#2
240   - return updateResult == LwM2mTransportUtil.UpdateResultFw.INITIAL.code && state == LwM2mTransportUtil.StateFw.DOWNLOADED.code;
  222 + return LwM2mTransportUtil.UpdateResultFw.INITIAL.code == updateResult;
241 223 }
242 224
243 225 /**
244   - * FW: start
245   - * Проверяем состояние Update_State (9.7) и Update_Result (9.9).
246   - * 1. Если Update Result > 3 (some errors) - Это означает что пред. апдейт не прошел.
247   - * - Запускаем апдейт в независимости от состяния прошивки и ее версии.
248   - * 2. Если Update Result = 2 && Update State = 4 - Это означает что пред. апдейт прошел
249   - * 3. Если Update Result = 0 && Update State = 0 && Ver = "" - Это означает что апдейта еще не было.
250   - * 4. Если Update Result = 0 && Update State = 0 - Это означает что пред. апдейт UnInstall
  226 + * After operation Execute success inspection Update Result :
  227 + * 1 - "Firmware updated successfully"
  228 + */
  229 + public boolean conditionalFwExecuteAfterSuccess() {
  230 + Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId);
  231 + return LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.code == updateResult;
  232 + }
  233 +
  234 + /**
  235 + * After operation Execute success inspection Update Result :
  236 + * > 1 error: "Firmware updated successfully"
  237 + */
  238 + public boolean conditionalFwExecuteAfterError() {
  239 + Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId);
  240 + return LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.code < updateResult;
  241 + }
  242 +
  243 + /**
  244 + * Software start
  245 + * -- Если Update Result -errors (равно и более 50) - Это означает что пред. апдейт не прошел.
  246 + * * - Запускаем апдейт в независимости от состяния прошивки и ее версии.
  247 + * -- Если Update Result - не errors (менее 50) и ver не пустой - Это означает что пред. апдейт прошел.
  248 + * -- Если Update Result - не errors и ver пустой - Это означает что апдейта еще не было или пред. апдейт UnInstall
  249 + * -- Если Update Result - не errors и ver не пустой - Это означает что пред. апдейт UnInstall
251 250 * - Проверяем поменялась ли версия и запускаем новый апдейт.
252   - * Новый апдейт:
253   - * 1. Запись новой прошивки в Lwm2mClient
254   - * 2. Мониторим итог зиписи:
255   - * 2.1 Update State = 3 "DELIVERED" стартуем Install 9.4 (Execute):
256   - * Мониторим состояние Update Result и State и мапим его на наш enum (DOWNLOADING, DOWNLOADED, VERIFIED, UPDATING, UPDATED, FAILED)
257   - * + пишем лог (в телеметрию отдельным полем error) с подробным статусом.
258 251 */
259 252 private boolean conditionalSwUpdateStart() {
260   - Long updateState = (Long) this.lwM2MClient.getResourceValue(null, this.pathStateId);
261   - Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId);
262   - String pkgName = (String) this.lwM2MClient.getResourceValue(null, this.pathNameId);
  253 + Long updateResultSw = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId);
263 254 // #1/#2
264   - return updateResult > LwM2mTransportUtil.UpdateResultSw.SUCCESSFULLY_INSTALLED_VERIFIED.code ||
  255 + return updateResultSw >= LwM2mTransportUtil.UpdateResultSw.NOT_ENOUGH_STORAGE.code ||
265 256 (
266   - (
267   - (
268   - (
269   - (updateState == LwM2mTransportUtil.UpdateStateSw.INSTALLED.code && updateResult == LwM2mTransportUtil.UpdateResultSw.SUCCESSFULLY_INSTALLED.code) ||
270   - (updateState == LwM2mTransportUtil.UpdateStateSw.INITIAL.code && updateResult == LwM2mTransportUtil.UpdateResultSw.INITIAL.code &&
271   - StringUtils.trimToEmpty(pkgName).isEmpty())
272   - )
273   - ) &&
274   - (updateState == LwM2mTransportUtil.UpdateStateSw.INITIAL.code && updateResult == LwM2mTransportUtil.UpdateResultSw.INITIAL.code)
  257 + (updateResultSw <= LwM2mTransportUtil.UpdateResultSw.NOT_ENOUGH_STORAGE.code
275 258 ) &&
276 259 (
277 260 (this.currentVersion != null && !this.currentVersion.equals(this.lwM2MClient.getResourceValue(null, this.pathVerId))) ||
278 261 (this.currentTitle != null && !this.currentTitle.equals(this.lwM2MClient.getResourceValue(null, this.pathNameId)))
279 262 )
280 263 );
281   -// return condSwUpdateStart;
282 264 }
283 265
284   - private boolean conditionalSwUpdateExecute() {
285   - Long updateState = (Long) this.lwM2MClient.getResourceValue(null, this.pathStateId);
  266 + /**
  267 + * Before operation Execute inspection Update Result :
  268 + * 3 - Successfully Downloaded and package integrity verified
  269 + */
  270 + public boolean conditionalSwUpdateExecute() {
286 271 Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId);
287   - // #1/#2
288   - return (updateResult == LwM2mTransportUtil.UpdateResultSw.INITIAL.code || updateResult == LwM2mTransportUtil.UpdateResultSw.SUCCESSFULLY_INSTALLED_VERIFIED.code) &&
289   - updateState == LwM2mTransportUtil.UpdateStateSw.DELIVERED.code;
  272 + return LwM2mTransportUtil.UpdateResultSw.SUCCESSFULLY_DOWNLOADED_VERIFIED.code == updateResult;
  273 + }
  274 +
  275 + /**
  276 + * After finish operation Execute (success):
  277 + * -- inspection Update Result:
  278 + * ---- FW если Update Result == 1 ("Firmware updated successfully") или SW если Update Result == 2 ("Software successfully installed.")
  279 + * -- fw_state/sw_state = UPDATED
  280 + *
  281 + * After finish operation Execute (error):
  282 + * -- inspection updateResult and send to thingsboard info about error
  283 + * --- send to telemetry ( key - this is name Update Result in model) (
  284 + * -- fw_state/sw_state = FAILED
  285 + */
  286 + public void finishFwSwUpdate(boolean success) {
  287 + Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId);
  288 + String value = FIRMWARE.equals(this.type) ? LwM2mTransportUtil.UpdateResultFw.fromUpdateResultFwByCode(updateResult.intValue()).type :
  289 + LwM2mTransportUtil.UpdateResultSw.fromUpdateResultSwByCode(updateResult.intValue()).type;
  290 + String key = splitCamelCaseString((String) this.lwM2MClient.getResourceName (null, this.pathResultId));
  291 + if (success) {
  292 + this.stateUpdate = FirmwareUpdateStatus.UPDATED.name();
  293 + this.sendLogs(EXECUTE.name(), LOG_LW2M_INFO, null);
  294 + }
  295 + else {
  296 + this.stateUpdate = FirmwareUpdateStatus.FAILED.name();
  297 + this.sendLogs(EXECUTE.name(), LOG_LW2M_ERROR, value);
  298 + }
  299 + this.serviceImpl.helper.sendParametersOnThingsboardTelemetry(
  300 + this.serviceImpl.helper.getKvStringtoThingsboard(key, value), this.lwM2MClient.getSession());
  301 + }
  302 +
  303 + /**
  304 + * After operation Execute success inspection Update Result :
  305 + * 2 - "Software successfully installed."
  306 + */
  307 + public boolean conditionalSwExecuteAfterSuccess() {
  308 + Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId);
  309 + return LwM2mTransportUtil.UpdateResultSw.SUCCESSFULLY_INSTALLED.code == updateResult;
  310 + }
  311 + /**
  312 + * After operation Execute success inspection Update Result :
  313 + * >= 50 - error "NOT_ENOUGH_STORAGE"
  314 + */
  315 + public boolean conditionalSwExecuteAfterError() {
  316 + Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId);
  317 + return LwM2mTransportUtil.UpdateResultSw.NOT_ENOUGH_STORAGE.code <= updateResult;
290 318 }
291 319
292 320 private void observeStateUpdate() {
... ... @@ -309,25 +337,21 @@ public class LwM2mFwSwUpdate {
309 337 }
310 338 }
311 339
312   - public void sendReadInfo(DefaultLwM2MTransportMsgHandler serviceImpl) {
  340 + public void sendReadObserveInfo(DefaultLwM2MTransportMsgHandler serviceImpl) {
  341 + this.infoFwSwUpdate = true;
313 342 this.serviceImpl = this.serviceImpl == null ? serviceImpl : this.serviceImpl;
314 343 this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer(
315 344 this.pathVerId, this.lwM2MClient.getRegistration()));
316 345 this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer(
317 346 this.pathNameId, this.lwM2MClient.getRegistration()));
318   - this.sendReadInfoForWrite();
319   - }
320   -
321   - public void sendReadInfoForWrite() {
322   -
323   - this.infoFwSwUpdate = true;
324 347 this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer(
325 348 this.pathStateId, this.lwM2MClient.getRegistration()));
326 349 this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer(
327 350 this.pathResultId, this.lwM2MClient.getRegistration()));
328 351 this.pendingInfoRequestsStart.forEach(pathIdVer -> {
329   - this.serviceImpl.lwM2mTransportRequest.sendAllRequest(this.lwM2MClient.getRegistration(), pathIdVer, READ, ContentFormat.TLV.getName(),
  352 + this.serviceImpl.lwM2mTransportRequest.sendAllRequest(this.lwM2MClient.getRegistration(), pathIdVer, OBSERVE, ContentFormat.TLV.getName(),
330 353 null, 0, null);
331 354 });
  355 +
332 356 }
333 357 }
... ...
... ... @@ -70,7 +70,7 @@ public class TbLwM2mSecurityStore implements EditableSecurityStore {
70 70 add(securityInfo);
71 71 }
72 72 } catch (NonUniqueSecurityInfoException e) {
73   - log.warn("Failed to add security info: {}", securityInfo, e);
  73 + log.trace("Failed to add security info: {}", securityInfo, e);
74 74 }
75 75 }
76 76 return securityInfo;
... ... @@ -86,7 +86,7 @@ public class TbLwM2mSecurityStore implements EditableSecurityStore {
86 86 add(securityInfo);
87 87 }
88 88 } catch (NonUniqueSecurityInfoException e) {
89   - log.warn("Failed to add security info: {}", securityInfo, e);
  89 + log.trace("Failed to add security info: {}", securityInfo, e);
90 90 }
91 91 }
92 92 return securityInfo;
... ...
... ... @@ -121,9 +121,11 @@ public class LwM2mValueConverterImpl implements LwM2mValueConverter {
121 121 /** let's assume we received an ISO 8601 format date */
122 122 try {
123 123 return new Date(Long.decode(value.toString()));
124   -// DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
125   -// XMLGregorianCalendar cal = datatypeFactory.newXMLGregorianCalendar((String) value);
126   -// return cal.toGregorianCalendar().getTime();
  124 + /**
  125 + DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
  126 + XMLGregorianCalendar cal = datatypeFactory.newXMLGregorianCalendar((String) value);
  127 + return cal.toGregorianCalendar().getTime();
  128 + **/
127 129 } catch (IllegalArgumentException e) {
128 130 log.debug("Unable to convert string to date", e);
129 131 throw new CodecException("Unable to convert string (%s) to date for resource %s", value,
... ...
... ... @@ -117,7 +117,6 @@ public final class DeviceProfileEntity extends BaseSqlEntity<DeviceProfile> impl
117 117 this.setCreatedTime(deviceProfile.getCreatedTime());
118 118 this.name = deviceProfile.getName();
119 119 this.type = deviceProfile.getType();
120   - this.image = deviceProfile.getImage();
121 120 this.transportType = deviceProfile.getTransportType();
122 121 this.provisionType = deviceProfile.getProvisionType();
123 122 this.description = deviceProfile.getDescription();
... ... @@ -126,16 +125,13 @@ public final class DeviceProfileEntity extends BaseSqlEntity<DeviceProfile> impl
126 125 if (deviceProfile.getDefaultRuleChainId() != null) {
127 126 this.defaultRuleChainId = deviceProfile.getDefaultRuleChainId().getId();
128 127 }
129   - if (deviceProfile.getDefaultDashboardId() != null) {
130   - this.defaultDashboardId = deviceProfile.getDefaultDashboardId().getId();
131   - }
132 128 this.defaultQueueName = deviceProfile.getDefaultQueueName();
133 129 this.provisionDeviceKey = deviceProfile.getProvisionDeviceKey();
134 130 if (deviceProfile.getFirmwareId() != null) {
135 131 this.firmwareId = deviceProfile.getFirmwareId().getId();
136 132 }
137 133 if (deviceProfile.getSoftwareId() != null) {
138   - this.firmwareId = deviceProfile.getSoftwareId().getId();
  134 + this.softwareId = deviceProfile.getSoftwareId().getId();
139 135 }
140 136 }
141 137
... ...