Commit 615af6bcb28eb7768979d7502cb3397b69cb6719

Authored by Andrii Shvaika
2 parents e86af4b6 334ee3c3

Merge with FW/SW improvements

Showing 27 changed files with 1001 additions and 336 deletions
... ... @@ -17,9 +17,9 @@
17 17 "sizeY": 5.5,
18 18 "resources": [],
19 19 "templateHtml": "<div style=\"height: 100%; overflow-y: auto;\" id=\"device-terminal\"></div>",
20   - "templateCss": ".cmd .cursor.blink {\n -webkit-animation-name: terminal-underline;\n -moz-animation-name: terminal-underline;\n -ms-animation-name: terminal-underline;\n animation-name: terminal-underline;\n}\n.terminal .inverted, .cmd .inverted {\n border-bottom-color: #aaa;\n}\n",
21   - "controllerScript": "var requestTimeout = 500;\nvar multiParams = false;\n\nself.onInit = function() {\n var subscription = self.ctx.defaultSubscription;\n var utils = self.ctx.$scope.$injector.get(self.ctx.servicesMap.get('utils'));\n var rpcEnabled = subscription.rpcEnabled;\n var deviceName = 'Simulated';\n var prompt;\n if (subscription.targetDeviceName && subscription.targetDeviceName.length) {\n deviceName = subscription.targetDeviceName;\n }\n if (self.ctx.settings.requestTimeout) {\n requestTimeout = self.ctx.settings.requestTimeout;\n }\n if (self.ctx.settings.multiParams) {\n multiParams = self.ctx.settings.multiParams;\n }\n var greetings = 'Welcome to ThingsBoard RPC debug terminal.\\n\\n';\n if (!rpcEnabled) {\n greetings += 'Target device is not set!\\n\\n';\n prompt = '';\n } else {\n greetings += 'Current target device for RPC commands: [[b;#fff;]' + deviceName + ']\\n\\n';\n greetings += 'Please type [[b;#fff;]\\'help\\'] to see usage.\\n';\n prompt = '[[b;#8bc34a;]' + deviceName +']> ';\n }\n \n var terminal = $('#device-terminal', self.ctx.$container).terminal(\n function(command) {\n if (command !== '') {\n try {\n var localCommand = command.trim();\n var requestUUID = utils.guid();\n if (localCommand === 'help') {\n printUsage(this);\n } else {\n var cmdObj = $.terminal.parse_command(localCommand);\n if (cmdObj.args) {\n if (!multiParams && cmdObj.args.length > 1) {\n this.error(\"Wrong number of arguments!\");\n this.echo(' ');\n }\n else {\n if (cmdObj.args.length) {\n var params = getMultiParams(cmdObj.args);\n }\n performRpc(this, cmdObj.name, params, requestUUID);\n }\n }\n }\n } catch(e) {\n this.error(new String(e));\n }\n } else {\n this.echo('');\n }\n }, {\n greetings: greetings,\n prompt: prompt,\n enabled: rpcEnabled\n });\n \n \n \n if (!rpcEnabled) {\n terminal.error('No RPC target detected!').pause();\n }\n}\n\n\nfunction printUsage(terminal) {\n var commandsListText = '\\n[[b;#fff;]Usage:]\\n';\n commandsListText += ' <method> [params body]]\\n\\n';\n commandsListText += '[[b;#fff;]Example 1 (multiParams===false):]\\n'; \n commandsListText += ' myRemoteMethod1 myText\\n\\n'; \n commandsListText += '[[b;#fff;]Example 2 (multiParams===false):]\\n'; \n commandsListText += ' myOtherRemoteMethod \"{\\\\\"key1\\\\\":2,\\\\\"key2\\\\\":\\\\\"myVal\\\\\"}\"\\n\\n'; \n commandsListText += '[[b;#fff;]Example 3 (multiParams===true)]\\n'; \n commandsListText += ' <method> [params body] = \"all the string after the method, including spaces\"]\\n';\n commandsListText += ' myOtherRemoteMethod \"{\\\\\"key1\\\\\": \"battery level\", \\\\\"key2\\\\\": \\\\\"myVal\\\\\"}\"\\n'; \n terminal.echo(new String(commandsListText));\n}\n\nfunction performRpc(terminal, method, params, requestUUID) {\n terminal.pause();\n self.ctx.controlApi.sendTwoWayCommand(method, params, requestTimeout, requestUUID).subscribe(\n function success(responseBody) {\n terminal.echo(JSON.stringify(responseBody));\n terminal.echo(' ');\n terminal.resume();\n },\n function fail() {\n var errorText = self.ctx.defaultSubscription.rpcErrorText;\n terminal.error(errorText);\n terminal.echo(' ');\n terminal.resume();\n }\n );\n}\n\nfunction getMultiParams(cmdObj) {\n var params = \"\";\n cmdObj.forEach((element) => {\n try {\n params += \" \" + JSON.strigify(JSON.parse(element));\n } catch (e) {\n params += \" \" + element;\n }\n })\n return params.trim();\n}\n\n \nself.onDestroy = function() {\n}",
22   - "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"requestTimeout\": {\n \"title\": \"RPC request timeout (ms)\",\n \"type\": \"number\",\n \"default\": 500\n },\n \"multiParams\": {\n \"title\": \"RPC params All line\",\n \"type\": \"boolean\",\n \"default\": false\n }\n },\n \"required\": [\"requestTimeout\"]\n },\n \"form\": [\n \"requestTimeout\",\n \"multiParams\"\n ]\n}",
  20 + "templateCss": ".cmd .cursor.blink {\n -webkit-animation-name: terminal-underline;\n -moz-animation-name: terminal-underline;\n -ms-animation-name: terminal-underline;\n animation-name: terminal-underline;\n}\n.terminal .inverted, .cmd .inverted {\n border-bottom-color: #aaa;\n}\n\n",
  21 + "controllerScript": "var requestTimeout = 500;\nvar multiParams = false;\nvar useRowStyleFunction = false;\nvar styleObj = {};\n\nself.onInit = function() {\n var subscription = self.ctx.defaultSubscription;\n var rpcEnabled = subscription.rpcEnabled;\n var deviceName = 'Simulated';\n var prompt;\n if (subscription.targetDeviceName && subscription.targetDeviceName.length) {\n deviceName = subscription.targetDeviceName;\n }\n if (self.ctx.settings.requestTimeout) {\n requestTimeout = self.ctx.settings.requestTimeout;\n }\n if (self.ctx.settings.multiParams) {\n multiParams = self.ctx.settings.multiParams;\n }\n if (self.ctx.settings.useRowStyleFunction && self.ctx.settings.rowStyleFunction) {\n try {\n var style = self.ctx.settings.rowStyleFunction;\n styleObj = JSON.parse(style);\n if ((typeof styleObj !== \"object\")) {\n styleObj = null;\n throw new URIError(`${style === null ? 'null' : typeof style} instead of style object`);\n }\n else if (typeof styleObj === \"object\" && (typeof styleObj.length) === \"number\") {\n styleObj = null;\n throw new URIError('Array instead of style object');\n }\n }\n catch (e) {\n console.log(`Row style function in widget ` +\n `returns '${e}'. Please check your row style function.`); \n }\n useRowStyleFunction = self.ctx.settings.useRowStyleFunction;\n \n }\n var greetings = 'Welcome to ThingsBoard RPC debug terminal.\\n\\n';\n if (!rpcEnabled) {\n greetings += 'Target device is not set!\\n\\n';\n prompt = '';\n } else {\n greetings += 'Current target device for RPC commands: [[b;#fff;]' + deviceName + ']\\n\\n';\n greetings += 'Please type [[b;#fff;]\\'help\\'] to see usage.\\n';\n prompt = '[[b;#8bc34a;]' + deviceName +']> ';\n }\n \n var terminal = $('#device-terminal', self.ctx.$container).terminal(\n function(command) {\n if (command !== '') {\n try {\n var localCommand = command.trim();\n var requestUUID = uuidv4();\n if (localCommand === 'help') {\n printUsage(this);\n } else {\n var cmdObj = $.terminal.parse_command(localCommand);\n if (cmdObj.args) {\n if (!multiParams && cmdObj.args.length > 1) {\n this.error(\"Wrong number of arguments!\");\n this.echo(' ');\n }\n else {\n if (cmdObj.args.length) {\n var params = getMultiParams(cmdObj.args);\n }\n performRpc(this, cmdObj.name, params, requestUUID);\n }\n }\n \n }\n } catch(e) {\n this.error(new String(e));\n }\n } else {\n this.echo('');\n }\n }, {\n greetings: greetings,\n prompt: prompt,\n enabled: rpcEnabled\n });\n \n if (styleObj && styleObj !== null) {\n terminal.css(styleObj);\n }\n \n if (!rpcEnabled) {\n terminal.error('No RPC target detected!').pause();\n }\n}\n\n\nfunction printUsage(terminal) {\n var commandsListText = '\\n[[b;#fff;]Usage:]\\n';\n commandsListText += ' <method> [params body]]\\n\\n';\n commandsListText += '[[b;#fff;]Example 1 (multiParams===false):]\\n'; \n commandsListText += ' myRemoteMethod1 myText\\n\\n'; \n commandsListText += '[[b;#fff;]Example 2 (multiParams===false):]\\n'; \n commandsListText += ' myOtherRemoteMethod \"{\\\\\"key1\\\\\":2,\\\\\"key2\\\\\":\\\\\"myVal\\\\\"}\"\\n\\n'; \n commandsListText += '[[b;#fff;]Example 3 (multiParams===true)]\\n'; \n commandsListText += ' <method> [params body] = \"all the string after the method, including spaces\"]\\n';\n commandsListText += ' myOtherRemoteMethod \"{\\\\\"key1\\\\\": \"battery level\", \\\\\"key2\\\\\": \\\\\"myVal\\\\\"}\"\\n'; \n terminal.echo(new String(commandsListText));\n}\n\nfunction performRpc(terminal, method, params, requestUUID) {\n terminal.pause();\n self.ctx.controlApi.sendTwoWayCommand(method, params, requestTimeout, requestUUID).subscribe(\n function success(responseBody) {\n terminal.echo(JSON.stringify(responseBody));\n terminal.echo(' ');\n terminal.resume();\n },\n function fail() {\n var errorText = self.ctx.defaultSubscription.rpcErrorText;\n terminal.error(errorText);\n terminal.echo(' ');\n terminal.resume();\n }\n );\n}\n\nfunction getMultiParams(cmdObj) {\n var params = \"\";\n cmdObj.forEach((element) => {\n try {\n params += \" \" + JSON.strigify(JSON.parse(element));\n } catch (e) {\n params += \" \" + element;\n }\n })\n return params.trim();\n}\n\n\nfunction uuidv4() {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n}\n\n \nself.onDestroy = function() {\n}",
  22 + "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"requestTimeout\": {\n \"title\": \"RPC request timeout (ms)\",\n \"type\": \"number\",\n \"default\": 500\n },\n \"multiParams\": {\n \"title\": \"RPC params All line\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"useRowStyleFunction\": {\n \"title\": \"Use row style function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"rowStyleFunction\": {\n \"title\": \"Row style function: f(entity, ctx)\",\n \"type\": \"string\",\n \"default\": \"\"\n }\n },\n \"required\": [\"requestTimeout\"]\n },\n \"form\": [\n \"requestTimeout\",\n \"multiParams\",\n \"useRowStyleFunction\",\n {\n \"key\": \"rowStyleFunction\",\n \"type\": \"javascript\",\n \"condition\": \"model.useRowStyleFunction === true\"\n }\n ]\n}",
23 23 "dataKeySettingsSchema": "{}\n",
24 24 "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":true,\"backgroundColor\":\"#010101\",\"color\":\"rgba(255, 254, 254, 0.87)\",\"padding\":\"0px\",\"settings\":{\"parseGpioStatusFunction\":\"return body[pin] === true;\",\"gpioStatusChangeRequest\":{\"method\":\"setGpioStatus\",\"paramsBody\":\"{\\n \\\"pin\\\": \\\"{$pin}\\\",\\n \\\"enabled\\\": \\\"{$enabled}\\\"\\n}\"},\"requestTimeout\":500,\"switchPanelBackgroundColor\":\"#b71c1c\",\"gpioStatusRequest\":{\"method\":\"getGpioStatus\",\"paramsBody\":\"{}\"},\"gpioList\":[{\"pin\":1,\"label\":\"GPIO 1\",\"row\":0,\"col\":0,\"_uniqueKey\":0},{\"pin\":2,\"label\":\"GPIO 2\",\"row\":0,\"col\":1,\"_uniqueKey\":1},{\"pin\":3,\"label\":\"GPIO 3\",\"row\":1,\"col\":0,\"_uniqueKey\":2}]},\"title\":\"RPC debug terminal\",\"dropShadow\":true,\"enableFullscreen\":true,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}"
25 25 }
... ...
... ... @@ -192,6 +192,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor {
192 192 syncSessionSet.add(key);
193 193 }
194 194 });
  195 + log.trace("46) Rpc syncSessionSet [{}] subscription after sent [{}]",syncSessionSet, rpcSubscriptions);
195 196 syncSessionSet.forEach(rpcSubscriptions::remove);
196 197 }
197 198
... ... @@ -454,7 +455,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor {
454 455 } else {
455 456 SessionInfoMetaData sessionMD = sessions.get(sessionId);
456 457 if (sessionMD == null) {
457   - sessionMD = new SessionInfoMetaData(new SessionInfo(SessionType.SYNC, sessionInfo.getNodeId()));
  458 + sessionMD = new SessionInfoMetaData(new SessionInfo(subscribeCmd.getSessionType(), sessionInfo.getNodeId()));
458 459 }
459 460 sessionMD.setSubscribedToAttributes(true);
460 461 log.debug("[{}] Registering attributes subscription for session [{}]", deviceId, sessionId);
... ... @@ -475,7 +476,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor {
475 476 } else {
476 477 SessionInfoMetaData sessionMD = sessions.get(sessionId);
477 478 if (sessionMD == null) {
478   - sessionMD = new SessionInfoMetaData(new SessionInfo(SessionType.SYNC, sessionInfo.getNodeId()));
  479 + sessionMD = new SessionInfoMetaData(new SessionInfo(subscribeCmd.getSessionType(), sessionInfo.getNodeId()));
479 480 }
480 481 sessionMD.setSubscribedToRPC(true);
481 482 log.debug("[{}] Registering rpc subscription for session [{}]", deviceId, sessionId);
... ...
... ... @@ -656,7 +656,7 @@ transport:
656 656 bind_address: "${LWM2M_BIND_ADDRESS_BS:0.0.0.0}"
657 657 bind_port: "${LWM2M_BIND_PORT_BS:5687}"
658 658 security:
659   - bind_address: "${LWM2M_BIND_ADDRESS_BS:0.0.0.0}"
  659 + bind_address: "${LWM2M_BIND_ADDRESS_SECURITY_BS:0.0.0.0}"
660 660 bind_port: "${LWM2M_BIND_PORT_SECURITY_BS:5688}"
661 661 # Only for RPK: Public & Private Key. If the keystore file is missing or not working
662 662 public_x: "${LWM2M_SERVER_PUBLIC_X_BS:5017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f91}"
... ...
... ... @@ -310,10 +310,12 @@ message SessionCloseNotificationProto {
310 310
311 311 message SubscribeToAttributeUpdatesMsg {
312 312 bool unsubscribe = 1;
  313 + SessionType sessionType = 2;
313 314 }
314 315
315 316 message SubscribeToRPCMsg {
316 317 bool unsubscribe = 1;
  318 + SessionType sessionType = 2;
317 319 }
318 320
319 321 message ToDeviceRpcRequestMsg {
... ...
... ... @@ -102,7 +102,7 @@ public class LwM2MTransportBootstrapService {
102 102 builder.setLocalSecureAddress(bootstrapConfig.getSecureHost(), bootstrapConfig.getSecurePort());
103 103
104 104 /** Create CoAP Config */
105   - builder.setCoapConfig(getCoapConfig(bootstrapConfig.getPort(), bootstrapConfig.getSecurePort()));
  105 + builder.setCoapConfig(getCoapConfig(bootstrapConfig.getPort(), bootstrapConfig.getSecurePort(), serverConfig));
106 106
107 107 /** Define model provider (Create Models )*/
108 108
... ...
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.transport.lwm2m.server;
  17 +
  18 +import lombok.extern.slf4j.Slf4j;
  19 +import org.eclipse.californium.core.coap.CoAP;
  20 +import org.eclipse.californium.core.coap.Response;
  21 +import org.eclipse.californium.core.server.resources.CoapExchange;
  22 +import org.eclipse.leshan.core.californium.LwM2mCoapResource;
  23 +import org.thingsboard.server.common.transport.TransportServiceCallback;
  24 +
  25 +@Slf4j
  26 +public abstract class AbstractLwM2mTransportResource extends LwM2mCoapResource {
  27 +
  28 + public AbstractLwM2mTransportResource(String name) {
  29 + super(name);
  30 + }
  31 +
  32 + @Override
  33 + public void handleGET(CoapExchange exchange) {
  34 + processHandleGet(exchange);
  35 + }
  36 +
  37 + @Override
  38 + public void handlePOST(CoapExchange exchange) {
  39 + processHandlePost(exchange);
  40 + }
  41 +
  42 + protected abstract void processHandleGet(CoapExchange exchange);
  43 +
  44 + protected abstract void processHandlePost(CoapExchange exchange);
  45 +
  46 + public static class CoapOkCallback implements TransportServiceCallback<Void> {
  47 + private final CoapExchange exchange;
  48 + private final CoAP.ResponseCode onSuccessResponse;
  49 + private final CoAP.ResponseCode onFailureResponse;
  50 +
  51 + public CoapOkCallback(CoapExchange exchange, CoAP.ResponseCode onSuccessResponse, CoAP.ResponseCode onFailureResponse) {
  52 + this.exchange = exchange;
  53 + this.onSuccessResponse = onSuccessResponse;
  54 + this.onFailureResponse = onFailureResponse;
  55 + }
  56 +
  57 + @Override
  58 + public void onSuccess(Void msg) {
  59 + Response response = new Response(onSuccessResponse);
  60 + response.setAcknowledged(isConRequest());
  61 + exchange.respond(response);
  62 + }
  63 +
  64 + @Override
  65 + public void onError(Throwable e) {
  66 + exchange.respond(onFailureResponse);
  67 + }
  68 +
  69 + private boolean isConRequest() {
  70 + return exchange.advanced().getRequest().isConfirmable();
  71 + }
  72 + }
  73 +
  74 + public static class CoapNoOpCallback implements TransportServiceCallback<Void> {
  75 + private final CoapExchange exchange;
  76 +
  77 + CoapNoOpCallback(CoapExchange exchange) {
  78 + this.exchange = exchange;
  79 + }
  80 +
  81 + @Override
  82 + public void onSuccess(Void msg) {
  83 + }
  84 +
  85 + @Override
  86 + public void onError(Throwable e) {
  87 + exchange.respond(CoAP.ResponseCode.INTERNAL_SERVER_ERROR);
  88 + }
  89 + }
  90 +
  91 +
  92 +}
... ...
... ... @@ -5,7 +5,7 @@
5 5 * you may not use this file except in compliance with the License.
6 6 * You may obtain a copy of the License at
7 7 *
8   - * http://www.apache.org/licenses/LICENSE-2.0
  8 + * http://www.apache.org/licenses/LICENSE-2.0
9 9 *
10 10 * Unless required by applicable law or agreed to in writing, software
11 11 * distributed under the License is distributed on an "AS IS" BASIS,
... ... @@ -62,7 +62,8 @@ import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClientStateExce
62 62 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
63 63 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
64 64 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile;
65   -import org.thingsboard.server.transport.lwm2m.server.client.Lwm2mClientRpcRequest;
  65 +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientRpcRequest;
  66 +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mFwSwUpdate;
66 67 import org.thingsboard.server.transport.lwm2m.server.client.ResourceValue;
67 68 import org.thingsboard.server.transport.lwm2m.server.client.ResultsAddKeyValueProto;
68 69 import org.thingsboard.server.transport.lwm2m.server.client.ResultsAnalyzerParameters;
... ... @@ -89,20 +90,21 @@ import java.util.stream.Collectors;
89 90 import static org.eclipse.californium.core.coap.CoAP.ResponseCode.BAD_REQUEST;
90 91 import static org.eclipse.leshan.core.attributes.Attribute.OBJECT_VERSION;
91 92 import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.DOWNLOADED;
  93 +import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.FAILED;
  94 +import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.INITIATED;
92 95 import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDATING;
93 96 import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH;
94 97 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper.getValueFromKvProto;
95 98 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.DEVICE_ATTRIBUTES_REQUEST;
96   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_ID;
  99 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_5_ID;
97 100 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_RESULT_ID;
  101 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_STATE_ID;
98 102 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_ERROR;
99 103 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_INFO;
100 104 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_TELEMETRY;
101 105 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_VALUE;
102 106 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_WARN;
103   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LWM2M_STRATEGY_2;
104 107 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER;
105   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.EXECUTE;
106 108 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE;
107 109 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_CANCEL;
108 110 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE_CANCEL_ALL;
... ... @@ -110,8 +112,8 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.L
110 112 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_ATTRIBUTES;
111 113 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_REPLACE;
112 114 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_ID;
113   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_RESULT_ID;
114 115 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertJsonArrayToSet;
  116 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertOtaUpdateValueToString;
115 117 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromIdVerToObjectId;
116 118 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer;
117 119 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.getAckCallback;
... ... @@ -140,6 +142,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
140 142 public final LwM2mClientContext clientContext;
141 143 public final LwM2mTransportRequest lwM2mTransportRequest;
142 144 private final Map<UUID, Long> rpcSubscriptions;
  145 + public final Map<String, Integer> firmwareUpdateState;
143 146
144 147 public DefaultLwM2MTransportMsgHandler(TransportService transportService, LwM2MTransportServerConfig config, LwM2mTransportServerHelper helper,
145 148 LwM2mClientContext clientContext,
... ... @@ -155,6 +158,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
155 158 this.context = context;
156 159 this.adaptor = adaptor;
157 160 this.rpcSubscriptions = new ConcurrentHashMap<>();
  161 + this.firmwareUpdateState = new ConcurrentHashMap<>();
158 162 this.sessionStore = sessionStore;
159 163 }
160 164
... ... @@ -191,11 +195,12 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
191 195 this.sendLogsToThingsboard(lwM2MClient, LOG_LW2M_INFO + ": Client registered with registration id: " + registration.getId());
192 196 SessionInfoProto sessionInfo = lwM2MClient.getSession();
193 197 transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(this, sessionInfo));
  198 + log.warn("40) sessionId [{}] Registering rpc subscription after Registration client", new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()));
194 199 TransportProtos.TransportToDeviceActorMsg msg = TransportProtos.TransportToDeviceActorMsg.newBuilder()
195 200 .setSessionInfo(sessionInfo)
196 201 .setSessionEvent(DefaultTransportService.getSessionEventMsg(SessionEvent.OPEN))
197   - .setSubscribeToAttributes(TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build())
198   - .setSubscribeToRPC(TransportProtos.SubscribeToRPCMsg.newBuilder().build())
  202 + .setSubscribeToAttributes(TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().setSessionType(TransportProtos.SessionType.ASYNC).build())
  203 + .setSubscribeToRPC(TransportProtos.SubscribeToRPCMsg.newBuilder().setSessionType(TransportProtos.SessionType.ASYNC).build())
199 204 .build();
200 205 transportService.process(msg, null);
201 206 this.getInfoFirmwareUpdate(lwM2MClient, null);
... ... @@ -238,10 +243,10 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
238 243 }
239 244 }
240 245 } catch (LwM2MClientStateException stateException) {
241   - if (LwM2MClientState.UNREGISTERED.equals(stateException.getState())) {
242   - log.info("[{}] update registration failed because client was already unregistered: [{}].", registration.getEndpoint(), stateException.getState());
  246 + if (LwM2MClientState.REGISTERED.equals(stateException.getState())) {
  247 + log.info("[{}] update registration failed because client has different registration id: [{}] {}.", registration.getEndpoint(), stateException.getState(), stateException.getMessage());
243 248 } else {
244   - log.info("[{}] update registration: [{}] {}.", registration.getEndpoint(), stateException.getState(), stateException.getMessage());
  249 + onRegistered(registration, Collections.emptyList());
245 250 }
246 251 } catch (Throwable t) {
247 252 log.error("[{}] endpoint [{}] error Unable update registration.", registration.getEndpoint(), t);
... ... @@ -263,8 +268,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
263 268 SessionInfoProto sessionInfo = client.getSession();
264 269 if (sessionInfo != null) {
265 270 transportService.deregisterSession(sessionInfo);
266   - sessionStore.remove(registration.getEndpoint());
267 271 this.doCloseSession(sessionInfo);
  272 + sessionStore.remove(registration.getEndpoint());
268 273 log.info("Client close session: [{}] unReg [{}] name [{}] profile ", registration.getId(), registration.getEndpoint(), sessionInfo.getDeviceType());
269 274 } else {
270 275 log.error("Client close session: [{}] unReg [{}] name [{}] sessionInfo ", registration.getId(), registration.getEndpoint(), null);
... ... @@ -307,7 +312,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
307 312 * @param response - observe
308 313 */
309 314 @Override
310   - public void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response, Lwm2mClientRpcRequest rpcRequest) {
  315 + public void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response, LwM2mClientRpcRequest rpcRequest) {
311 316 if (response.getContent() != null) {
312 317 LwM2mClient lwM2MClient = clientContext.getClientByEndpoint(registration.getEndpoint());
313 318 ObjectModel objectModelVersion = lwM2MClient.getObjectModel(path, this.config.getModelProvider());
... ... @@ -330,7 +335,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
330 335 }
331 336
332 337 private void sendRpcRequestAfterReadResponse(Registration registration, LwM2mClient lwM2MClient, String pathIdVer, ReadResponse response,
333   - Lwm2mClientRpcRequest rpcRequest) {
  338 + LwM2mClientRpcRequest rpcRequest) {
334 339 Object value = null;
335 340 if (response.getContent() instanceof LwM2mObject) {
336 341 value = lwM2MClient.objectToString((LwM2mObject) response.getContent(), this.converter, pathIdVer);
... ... @@ -447,7 +452,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
447 452
448 453 /**
449 454 * #1 del from rpcSubscriptions by timeout
450   - * #2 if not present in rpcSubscriptions by requestId: create new Lwm2mClientRpcRequest, after success - add requestId, timeout
  455 + * #2 if not present in rpcSubscriptions by requestId: create new LwM2mClientRpcRequest, after success - add requestId, timeout
451 456 */
452 457 @Override
453 458 public void onToDeviceRpcRequest(TransportProtos.ToDeviceRpcRequestMsg toDeviceRpcRequestMsg, SessionInfoProto sessionInfo) {
... ... @@ -459,39 +464,53 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
459 464 UUID requestUUID = new UUID(toDeviceRpcRequestMsg.getRequestIdMSB(), toDeviceRpcRequestMsg.getRequestIdLSB());
460 465 if (!this.rpcSubscriptions.containsKey(requestUUID)) {
461 466 this.rpcSubscriptions.put(requestUUID, toDeviceRpcRequestMsg.getExpirationTime());
462   - Lwm2mClientRpcRequest lwm2mClientRpcRequest = null;
  467 + LwM2mClientRpcRequest lwm2mClientRpcRequest = null;
463 468 try {
464 469 LwM2mClient client = clientContext.getClientBySessionInfo(sessionInfo);
465 470 Registration registration = client.getRegistration();
466   - lwm2mClientRpcRequest = new Lwm2mClientRpcRequest(lwM2mTypeOper, bodyParams, toDeviceRpcRequestMsg.getRequestId(), sessionInfo, registration, this);
467   - if (lwm2mClientRpcRequest.getErrorMsg() != null) {
468   - lwm2mClientRpcRequest.setResponseCode(BAD_REQUEST.name());
469   - this.onToDeviceRpcResponse(lwm2mClientRpcRequest.getDeviceRpcResponseResultMsg(), sessionInfo);
  471 + if(registration != null) {
  472 + lwm2mClientRpcRequest = new LwM2mClientRpcRequest(lwM2mTypeOper, bodyParams, toDeviceRpcRequestMsg.getRequestId(), sessionInfo, registration, this);
  473 + if (lwm2mClientRpcRequest.getErrorMsg() != null) {
  474 + lwm2mClientRpcRequest.setResponseCode(BAD_REQUEST.name());
  475 + this.onToDeviceRpcResponse(lwm2mClientRpcRequest.getDeviceRpcResponseResultMsg(), sessionInfo);
  476 + } else {
  477 + lwM2mTransportRequest.sendAllRequest(client, lwm2mClientRpcRequest.getTargetIdVer(), lwm2mClientRpcRequest.getTypeOper(),
  478 + null,
  479 + lwm2mClientRpcRequest.getValue() == null ? lwm2mClientRpcRequest.getParams() : lwm2mClientRpcRequest.getValue(),
  480 + this.config.getTimeout(), lwm2mClientRpcRequest);
  481 + }
470 482 } else {
471   - lwM2mTransportRequest.sendAllRequest(client, lwm2mClientRpcRequest.getTargetIdVer(), lwm2mClientRpcRequest.getTypeOper(),
472   - null,
473   - lwm2mClientRpcRequest.getValue() == null ? lwm2mClientRpcRequest.getParams() : lwm2mClientRpcRequest.getValue(),
474   - this.config.getTimeout(), lwm2mClientRpcRequest);
  483 + this.sendErrorRpcResponse(lwm2mClientRpcRequest, "registration == null", sessionInfo);
475 484 }
476 485 } catch (Exception e) {
477   - if (lwm2mClientRpcRequest == null) {
478   - lwm2mClientRpcRequest = new Lwm2mClientRpcRequest();
479   - }
480   - lwm2mClientRpcRequest.setResponseCode(BAD_REQUEST.name());
481   - if (lwm2mClientRpcRequest.getErrorMsg() == null) {
482   - lwm2mClientRpcRequest.setErrorMsg(e.getMessage());
483   - }
484   - this.onToDeviceRpcResponse(lwm2mClientRpcRequest.getDeviceRpcResponseResultMsg(), sessionInfo);
  486 + this.sendErrorRpcResponse(lwm2mClientRpcRequest, e.getMessage(), sessionInfo);
485 487 }
486 488 }
487 489 }
488 490
  491 + private void sendErrorRpcResponse(LwM2mClientRpcRequest lwm2mClientRpcRequest, String msgError, SessionInfoProto sessionInfo) {
  492 + if (lwm2mClientRpcRequest == null) {
  493 + lwm2mClientRpcRequest = new LwM2mClientRpcRequest();
  494 + }
  495 + lwm2mClientRpcRequest.setResponseCode(BAD_REQUEST.name());
  496 + if (lwm2mClientRpcRequest.getErrorMsg() == null) {
  497 + lwm2mClientRpcRequest.setErrorMsg(msgError);
  498 + }
  499 + this.onToDeviceRpcResponse(lwm2mClientRpcRequest.getDeviceRpcResponseResultMsg(), sessionInfo);
  500 + }
  501 +
489 502 private void checkRpcRequestTimeout() {
490   - Set<UUID> rpcSubscriptionsToRemove = rpcSubscriptions.entrySet().stream().filter(kv -> System.currentTimeMillis() > kv.getValue()).map(Map.Entry::getKey).collect(Collectors.toSet());
491   - rpcSubscriptionsToRemove.forEach(rpcSubscriptions::remove);
  503 + log.warn("4.1) before rpcSubscriptions.size(): [{}]", rpcSubscriptions.size());
  504 + if (rpcSubscriptions.size() > 0) {
  505 + Set<UUID> rpcSubscriptionsToRemove = rpcSubscriptions.entrySet().stream().filter(kv -> System.currentTimeMillis() > kv.getValue()).map(Map.Entry::getKey).collect(Collectors.toSet());
  506 + log.warn("4.2) System.currentTimeMillis(): [{}]", System.currentTimeMillis());
  507 + log.warn("4.3) rpcSubscriptionsToRemove: [{}]", rpcSubscriptionsToRemove);
  508 + rpcSubscriptionsToRemove.forEach(rpcSubscriptions::remove);
  509 + }
  510 + log.warn("4.4) after rpcSubscriptions.size(): [{}]", rpcSubscriptions.size());
492 511 }
493 512
494   - public void sentRpcResponse(Lwm2mClientRpcRequest rpcRequest, String requestCode, String msg, String typeMsg) {
  513 + public void sentRpcResponse(LwM2mClientRpcRequest rpcRequest, String requestCode, String msg, String typeMsg) {
495 514 rpcRequest.setResponseCode(requestCode);
496 515 if (LOG_LW2M_ERROR.equals(typeMsg)) {
497 516 rpcRequest.setInfoMsg(null);
... ... @@ -593,7 +612,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
593 612 LwM2mClientProfile lwM2MClientProfile = clientContext.getProfile(lwM2MClient.getProfileId());
594 613 Set<String> clientObjects = clientContext.getSupportedIdVerInClient(lwM2MClient);
595 614 if (clientObjects != null && clientObjects.size() > 0) {
596   - if (LWM2M_STRATEGY_2 == LwM2mTransportUtil.getClientOnlyObserveAfterConnect(lwM2MClientProfile)) {
  615 + if (LwM2mTransportUtil.LwM2MClientStrategy.CLIENT_STRATEGY_2.code == lwM2MClientProfile.getClientStrategy()) {
597 616 // #2
598 617 lwM2MClient.getPendingReadRequests().addAll(clientObjects);
599 618 clientObjects.forEach(path -> lwM2mTransportRequest.sendAllRequest(lwM2MClient, path, READ,
... ... @@ -650,60 +669,18 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
650 669 /** version != null
651 670 * set setClient_fw_info... = value
652 671 **/
653   - if (lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) {
  672 + if (lwM2MClient.getFwUpdate() != null && lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) {
654 673 lwM2MClient.getFwUpdate().initReadValue(this, this.lwM2mTransportRequest, path);
655 674 }
656   - if (lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) {
  675 + if (lwM2MClient.getSwUpdate() != null && lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) {
657 676 lwM2MClient.getSwUpdate().initReadValue(this, this.lwM2mTransportRequest, path);
658 677 }
659 678
660   - /**
661   - * Before operation Execute (FwUpdate) inspection Update Result :
662   - * - after finished operation Write result: success (FwUpdate): fw_state = DOWNLOADED
663   - * - before start operation Execute (FwUpdate) Update Result = 0 - Initial value
664   - * - start Execute (FwUpdate)
665   - * After finished operation Execute (FwUpdate) inspection Update Result :
666   - * - after start operation Execute (FwUpdate): fw_state = UPDATING
667   - * - after success finished operation Execute (FwUpdate) Update Result == 1 ("Firmware updated successfully")
668   - * - finished operation Execute (FwUpdate)
669   - */
670   - if (lwM2MClient.getFwUpdate() != null
671   - && (convertPathFromObjectIdToIdVer(FW_RESULT_ID, registration).equals(path))) {
672   - if (DOWNLOADED.name().equals(lwM2MClient.getFwUpdate().getStateUpdate())
673   - && lwM2MClient.getFwUpdate().conditionalFwExecuteStart()) {
674   - lwM2MClient.getFwUpdate().executeFwSwWare(this, this.lwM2mTransportRequest);
675   - } else if (UPDATING.name().equals(lwM2MClient.getFwUpdate().getStateUpdate())
676   - && lwM2MClient.getFwUpdate().conditionalFwExecuteAfterSuccess()) {
677   - lwM2MClient.getFwUpdate().finishFwSwUpdate(this, true);
678   - } else if (UPDATING.name().equals(lwM2MClient.getFwUpdate().getStateUpdate())
679   - && lwM2MClient.getFwUpdate().conditionalFwExecuteAfterError()) {
680   - lwM2MClient.getFwUpdate().finishFwSwUpdate(this, false);
681   - }
682   - }
683   -
684   - /**
685   - * Before operation Execute (SwUpdate) inspection Update Result :
686   - * - after finished operation Write result: success (SwUpdate): fw_state = DOWNLOADED
687   - * - before operation Execute (SwUpdate) Update Result = 3 - Successfully Downloaded and package integrity verified
688   - * - start Execute (SwUpdate)
689   - * After finished operation Execute (SwUpdate) inspection Update Result :
690   - * - after start operation Execute (SwUpdate): fw_state = UPDATING
691   - * - after success finished operation Execute (SwUpdate) Update Result == 2 "Software successfully installed.""
692   - * - after success finished operation Execute (SwUpdate) Update Result == 2 "Software successfully installed.""
693   - * - finished operation Execute (SwUpdate)
694   - */
695   - if (lwM2MClient.getSwUpdate() != null
696   - && (convertPathFromObjectIdToIdVer(SW_RESULT_ID, registration).equals(path))) {
697   - if (DOWNLOADED.name().equals(lwM2MClient.getSwUpdate().getStateUpdate())
698   - && lwM2MClient.getSwUpdate().conditionalSwUpdateExecute()) {
699   - lwM2MClient.getSwUpdate().executeFwSwWare(this, this.lwM2mTransportRequest);
700   - } else if (UPDATING.name().equals(lwM2MClient.getSwUpdate().getStateUpdate())
701   - && lwM2MClient.getSwUpdate().conditionalSwExecuteAfterSuccess()) {
702   - lwM2MClient.getSwUpdate().finishFwSwUpdate(this, true);
703   - } else if (UPDATING.name().equals(lwM2MClient.getSwUpdate().getStateUpdate())
704   - && lwM2MClient.getSwUpdate().conditionalSwExecuteAfterError()) {
705   - lwM2MClient.getSwUpdate().finishFwSwUpdate(this, false);
706   - }
  679 + if ((convertPathFromObjectIdToIdVer(FW_RESULT_ID, registration).equals(path)) ||
  680 + (convertPathFromObjectIdToIdVer(FW_STATE_ID, registration).equals(path))) {
  681 + LwM2mFwSwUpdate fwUpdate = lwM2MClient.getFwUpdate(clientContext);
  682 + log.warn("93) path: [{}] value: [{}]", path, lwM2mResource.getValue());
  683 + fwUpdate.updateStateOta(this, lwM2mTransportRequest, registration, path, ((Long) lwM2mResource.getValue()).intValue());
707 684 }
708 685 Set<String> paths = new HashSet<>();
709 686 paths.add(path);
... ... @@ -865,8 +842,9 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
865 842 valueKvProto = new JsonObject();
866 843 Object finalvalueKvProto = valueKvProto;
867 844 Gson gson = new GsonBuilder().create();
  845 + ResourceModel.Type finalCurrentType = currentType;
868 846 resourceValue.getInstances().forEach((k, v) -> {
869   - Object val = this.converter.convertValue(v, currentType, expectedType,
  847 + Object val = this.converter.convertValue(v, finalCurrentType, expectedType,
870 848 new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer)));
871 849 JsonElement element = gson.toJsonTree(val, val.getClass());
872 850 ((JsonObject) finalvalueKvProto).add(String.valueOf(k), element);
... ... @@ -876,6 +854,9 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
876 854 valueKvProto = this.converter.convertValue(resourceValue.getValue(), currentType, expectedType,
877 855 new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer)));
878 856 }
  857 + LwM2mOtaConvert lwM2mOtaConvert = convertOtaUpdateValueToString(pathIdVer, valueKvProto, currentType);
  858 + valueKvProto = lwM2mOtaConvert.getValue();
  859 + currentType = lwM2mOtaConvert.getCurrentType();
879 860 return valueKvProto != null ? this.helper.getKvAttrTelemetryToThingsboard(currentType, resourceName, valueKvProto, resourceValue.isMultiInstances()) : null;
880 861 }
881 862 } catch (Exception e) {
... ... @@ -1340,8 +1321,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1340 1321 }
1341 1322 }
1342 1323
1343   - public void getInfoFirmwareUpdate(LwM2mClient lwM2MClient, Lwm2mClientRpcRequest rpcRequest) {
1344   - if (lwM2MClient.getRegistration().getSupportedVersion(FW_ID) != null) {
  1324 + public void getInfoFirmwareUpdate(LwM2mClient lwM2MClient, LwM2mClientRpcRequest rpcRequest) {
  1325 + if (lwM2MClient.getRegistration().getSupportedVersion(FW_5_ID) != null) {
1345 1326 SessionInfoProto sessionInfo = this.getSessionInfo(lwM2MClient);
1346 1327 if (sessionInfo != null) {
1347 1328 DefaultLwM2MTransportMsgHandler handler = this;
... ... @@ -1351,18 +1332,33 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1351 1332 public void onSuccess(TransportProtos.GetOtaPackageResponseMsg response) {
1352 1333 if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus())
1353 1334 && response.getType().equals(OtaPackageType.FIRMWARE.name())) {
1354   - log.warn("7) firmware start with ver: [{}]", response.getVersion());
1355   - lwM2MClient.getFwUpdate().setRpcRequest(rpcRequest);
1356   - lwM2MClient.getFwUpdate().setCurrentVersion(response.getVersion());
1357   - lwM2MClient.getFwUpdate().setCurrentTitle(response.getTitle());
1358   - lwM2MClient.getFwUpdate().setCurrentId(new OtaPackageId(new UUID(response.getOtaPackageIdMSB(), response.getOtaPackageIdLSB())).getId());
1359   - if (rpcRequest == null) {
1360   - lwM2MClient.getFwUpdate().sendReadObserveInfo(lwM2mTransportRequest);
  1335 + LwM2mFwSwUpdate fwUpdate = lwM2MClient.getFwUpdate(clientContext);
  1336 + if (rpcRequest != null) {
  1337 + fwUpdate.setStateUpdate(INITIATED.name());
  1338 + }
  1339 + if (!FAILED.name().equals(fwUpdate.getStateUpdate())) {
  1340 + log.warn("7) firmware start with ver: [{}]", response.getVersion());
  1341 + fwUpdate.setRpcRequest(rpcRequest);
  1342 + fwUpdate.setCurrentVersion(response.getVersion());
  1343 + fwUpdate.setCurrentTitle(response.getTitle());
  1344 + fwUpdate.setCurrentId(new UUID(response.getOtaPackageIdMSB(), response.getOtaPackageIdLSB()));
  1345 + if (rpcRequest == null) {
  1346 + fwUpdate.sendReadObserveInfo(lwM2mTransportRequest);
  1347 + } else {
  1348 + fwUpdate.writeFwSwWare(handler, lwM2mTransportRequest);
  1349 + }
1361 1350 } else {
1362   - lwM2MClient.getFwUpdate().writeFwSwWare(handler, lwM2mTransportRequest);
  1351 + String msgError = String.format("OtaPackage device: %s, version: %s, stateUpdate: %s",
  1352 + lwM2MClient.getDeviceName(), response.getVersion(), fwUpdate.getStateUpdate());
  1353 + log.warn("7_1 [{}]", msgError);
1363 1354 }
1364 1355 } else {
1365   - log.trace("OtaPackage [{}] [{}]", lwM2MClient.getDeviceName(), response.getResponseStatus().toString());
  1356 + String msgError = String.format("OtaPackage device: %s, responseStatus: %s",
  1357 + lwM2MClient.getDeviceName(), response.getResponseStatus().toString());
  1358 + log.trace(msgError);
  1359 + if (rpcRequest != null) {
  1360 + sendErrorRpcResponse(rpcRequest, msgError, sessionInfo);
  1361 + }
1366 1362 }
1367 1363 }
1368 1364
... ... @@ -1375,7 +1371,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1375 1371 }
1376 1372 }
1377 1373
1378   - public void getInfoSoftwareUpdate(LwM2mClient lwM2MClient, Lwm2mClientRpcRequest rpcRequest) {
  1374 + public void getInfoSoftwareUpdate(LwM2mClient lwM2MClient, LwM2mClientRpcRequest rpcRequest) {
1379 1375 if (lwM2MClient.getRegistration().getSupportedVersion(SW_ID) != null) {
1380 1376 SessionInfoProto sessionInfo = this.getSessionInfo(lwM2MClient);
1381 1377 if (sessionInfo != null) {
... ...
... ... @@ -28,7 +28,6 @@ import org.eclipse.leshan.server.californium.registration.CaliforniumRegistratio
28 28 import org.eclipse.leshan.server.model.LwM2mModelProvider;
29 29 import org.eclipse.leshan.server.security.EditableSecurityStore;
30 30 import org.springframework.stereotype.Component;
31   -import org.thingsboard.common.util.ThingsBoardThreadFactory;
32 31 import org.thingsboard.server.common.data.StringUtils;
33 32 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
34 33 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
... ... @@ -60,14 +59,13 @@ import java.security.spec.InvalidParameterSpecException;
60 59 import java.security.spec.KeySpec;
61 60 import java.security.spec.PKCS8EncodedKeySpec;
62 61 import java.util.Arrays;
63   -import java.util.concurrent.Executors;
64   -import java.util.concurrent.ScheduledExecutorService;
65 62
66 63 import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256;
67 64 import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
68 65 import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256;
69 66 import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CCM_8;
70 67 import static org.thingsboard.server.transport.lwm2m.server.LwM2mNetworkConfig.getCoapConfig;
  68 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FIRMWARE_UPDATE_COAP_RECOURSE;
71 69
72 70 @Slf4j
73 71 @Component
... ... @@ -83,7 +81,7 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
83 81 private final LwM2mTransportContext context;
84 82 private final LwM2MTransportServerConfig config;
85 83 private final LwM2mTransportServerHelper helper;
86   - private final LwM2mTransportMsgHandler handler;
  84 + private final DefaultLwM2MTransportMsgHandler handler;
87 85 private final CaliforniumRegistrationStore registrationStore;
88 86 private final TbSecurityStore securityStore;
89 87 private final LwM2mClientContext lwM2mClientContext;
... ... @@ -98,6 +96,17 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
98 96 new LWM2MGenerationPSkRPkECC();
99 97 }
100 98 this.server = getLhServer();
  99 + /**
  100 + * Add a resource to the server.
  101 + * CoapResource ->
  102 + * path = FW_PACKAGE or SW_PACKAGE
  103 + * nameFile = "BC68JAR01A09_TO_BC68JAR01A10.bin"
  104 + * "coap://host:port/{path}/{token}/{nameFile}"
  105 + */
  106 +
  107 +
  108 + LwM2mTransportCoapResource otaCoapResource = new LwM2mTransportCoapResource(handler, FIRMWARE_UPDATE_COAP_RECOURSE);
  109 + this.server.coap().getServer().add(otaCoapResource);
101 110 this.startLhServer();
102 111 this.context.setServer(server);
103 112 }
... ... @@ -128,7 +137,7 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
128 137 builder.setEncoder(new DefaultLwM2mNodeEncoder(LwM2mValueConverterImpl.getInstance()));
129 138
130 139 /* Create CoAP Config */
131   - builder.setCoapConfig(getCoapConfig(config.getPort(), config.getSecurePort()));
  140 + builder.setCoapConfig(getCoapConfig(config.getPort(), config.getSecurePort(), config));
132 141
133 142 /* Define model provider (Create Models )*/
134 143 LwM2mModelProvider modelProvider = new LwM2mVersionedModelProvider(this.lwM2mClientContext, this.helper, this.context);
... ...
... ... @@ -16,10 +16,14 @@
16 16 package org.thingsboard.server.transport.lwm2m.server;
17 17
18 18 import org.eclipse.californium.core.network.config.NetworkConfig;
  19 +import org.eclipse.californium.core.network.config.NetworkConfigDefaults;
  20 +import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
  21 +
  22 +import static org.eclipse.californium.core.network.config.NetworkConfigDefaults.DEFAULT_BLOCKWISE_STATUS_LIFETIME;
19 23
20 24 public class LwM2mNetworkConfig {
21 25
22   - public static NetworkConfig getCoapConfig(Integer serverPortNoSec, Integer serverSecurePort) {
  26 + public static NetworkConfig getCoapConfig(Integer serverPortNoSec, Integer serverSecurePort, LwM2MTransportServerConfig config) {
23 27 NetworkConfig coapConfig = new NetworkConfig();
24 28 coapConfig.setInt(NetworkConfig.Keys.COAP_PORT,serverPortNoSec);
25 29 coapConfig.setInt(NetworkConfig.Keys.COAP_SECURE_PORT,serverSecurePort);
... ... @@ -49,8 +53,15 @@ public class LwM2mNetworkConfig {
49 53 - value of true indicate that the server will response with block2 option event if no further blocks are required.
50 54 */
51 55 coapConfig.setBoolean(NetworkConfig.Keys.BLOCKWISE_ENTITY_TOO_LARGE_AUTO_FAILOVER, true);
52   -
53   - coapConfig.setInt(NetworkConfig.Keys.BLOCKWISE_STATUS_LIFETIME, 300000);
  56 + /**
  57 + * The maximum amount of time (in milliseconds) allowed between
  58 + * transfers of individual blocks in a blockwise transfer before the
  59 + * blockwise transfer state is discarded.
  60 + * <p>
  61 + * The default value of this property is
  62 + * {@link NetworkConfigDefaults#DEFAULT_BLOCKWISE_STATUS_LIFETIME} = 5 * 60 * 1000; // 5 mins [ms].
  63 + */
  64 + coapConfig.setLong(NetworkConfig.Keys.BLOCKWISE_STATUS_LIFETIME, DEFAULT_BLOCKWISE_STATUS_LIFETIME);
54 65 /**
55 66 !!! REQUEST_ENTITY_TOO_LARGE CODE=4.13
56 67 The maximum size of a resource body (in bytes) that will be accepted
... ...
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.transport.lwm2m.server;
  17 +
  18 +import lombok.Data;
  19 +import org.eclipse.leshan.core.model.ResourceModel;
  20 +
  21 +@Data
  22 +public class LwM2mOtaConvert {
  23 + private ResourceModel.Type currentType;
  24 + private Object value;
  25 +}
... ...
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.transport.lwm2m.server;
  17 +
  18 +import lombok.extern.slf4j.Slf4j;
  19 +import org.eclipse.californium.core.coap.CoAP;
  20 +import org.eclipse.californium.core.coap.Request;
  21 +import org.eclipse.californium.core.coap.Response;
  22 +import org.eclipse.californium.core.network.Exchange;
  23 +import org.eclipse.californium.core.observe.ObserveRelation;
  24 +import org.eclipse.californium.core.server.resources.CoapExchange;
  25 +import org.eclipse.californium.core.server.resources.Resource;
  26 +import org.eclipse.californium.core.server.resources.ResourceObserver;
  27 +
  28 +import java.util.UUID;
  29 +import java.util.concurrent.ConcurrentHashMap;
  30 +import java.util.concurrent.ConcurrentMap;
  31 +import java.util.concurrent.atomic.AtomicInteger;
  32 +
  33 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FIRMWARE_UPDATE_COAP_RECOURSE;
  34 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SOFTWARE_UPDATE_COAP_RECOURSE;
  35 +
  36 +@Slf4j
  37 +public class LwM2mTransportCoapResource extends AbstractLwM2mTransportResource {
  38 + private final ConcurrentMap<String, ObserveRelation> tokenToObserveRelationMap = new ConcurrentHashMap<>();
  39 + private final ConcurrentMap<String, AtomicInteger> tokenToObserveNotificationSeqMap = new ConcurrentHashMap<>();
  40 + private final LwM2mTransportMsgHandler handler;
  41 +
  42 + public LwM2mTransportCoapResource(LwM2mTransportMsgHandler handler, String name) {
  43 + super(name);
  44 + this.handler = handler;
  45 + this.setObservable(true); // enable observing
  46 + this.addObserver(new CoapResourceObserver());
  47 + }
  48 +
  49 +
  50 + @Override
  51 + public void checkObserveRelation(Exchange exchange, Response response) {
  52 + String token = getTokenFromRequest(exchange.getRequest());
  53 + final ObserveRelation relation = exchange.getRelation();
  54 + if (relation == null || relation.isCanceled()) {
  55 + return; // because request did not try to establish a relation
  56 + }
  57 + if (CoAP.ResponseCode.isSuccess(response.getCode())) {
  58 +
  59 + if (!relation.isEstablished()) {
  60 + relation.setEstablished();
  61 + addObserveRelation(relation);
  62 + }
  63 + AtomicInteger notificationCounter = tokenToObserveNotificationSeqMap.computeIfAbsent(token, s -> new AtomicInteger(0));
  64 + response.getOptions().setObserve(notificationCounter.getAndIncrement());
  65 + } // ObserveLayer takes care of the else case
  66 + }
  67 +
  68 +
  69 + @Override
  70 + protected void processHandleGet(CoapExchange exchange) {
  71 + log.warn("90) processHandleGet [{}]", exchange);
  72 + if (exchange.getRequestOptions().getUriPath().size() == 2 &&
  73 + (FIRMWARE_UPDATE_COAP_RECOURSE.equals(exchange.getRequestOptions().getUriPath().get(0)) ||
  74 + SOFTWARE_UPDATE_COAP_RECOURSE.equals(exchange.getRequestOptions().getUriPath().get(0)))) {
  75 + this.sentOtaData(exchange);
  76 + }
  77 + }
  78 +
  79 + @Override
  80 + protected void processHandlePost(CoapExchange exchange) {
  81 + log.warn("2) processHandleGet [{}]", exchange);
  82 + }
  83 +
  84 + /**
  85 + * Override the default behavior so that requests to sub resources (typically /{name}/{token}) are handled by
  86 + * /name resource.
  87 + */
  88 + @Override
  89 + public Resource getChild(String name) {
  90 + return this;
  91 + }
  92 +
  93 +
  94 + private String getTokenFromRequest(Request request) {
  95 + return (request.getSourceContext() != null ? request.getSourceContext().getPeerAddress().getAddress().getHostAddress() : "null")
  96 + + ":" + (request.getSourceContext() != null ? request.getSourceContext().getPeerAddress().getPort() : -1) + ":" + request.getTokenString();
  97 + }
  98 +
  99 + public class CoapResourceObserver implements ResourceObserver {
  100 +
  101 + @Override
  102 + public void changedName(String old) {
  103 +
  104 + }
  105 +
  106 + @Override
  107 + public void changedPath(String old) {
  108 +
  109 + }
  110 +
  111 + @Override
  112 + public void addedChild(Resource child) {
  113 +
  114 + }
  115 +
  116 + @Override
  117 + public void removedChild(Resource child) {
  118 +
  119 + }
  120 +
  121 + @Override
  122 + public void addedObserveRelation(ObserveRelation relation) {
  123 +
  124 + }
  125 +
  126 + @Override
  127 + public void removedObserveRelation(ObserveRelation relation) {
  128 +
  129 + }
  130 + }
  131 +
  132 + private void sentOtaData(CoapExchange exchange) {
  133 + String idStr = exchange.getRequestOptions().getUriPath().get(1);
  134 + UUID currentId = UUID.fromString(idStr);
  135 + if (exchange.getRequestOptions().getBlock2() != null) {
  136 + int chunkSize = exchange.getRequestOptions().getBlock2().getSzx();
  137 + int chunk = 0;
  138 + Response response = new Response(CoAP.ResponseCode.CONTENT);
  139 + byte[] fwData = this.getOtaData(currentId);
  140 + log.warn("91) read softWare data (length): [{}]", fwData.length);
  141 + if (fwData != null && fwData.length > 0) {
  142 + response.setPayload(fwData);
  143 + boolean moreFlag = fwData.length > chunkSize;
  144 + response.getOptions().setBlock2(chunkSize, moreFlag, chunk);
  145 + log.warn("92) Send currentId: [{}], length: [{}], chunkSize [{}], moreFlag [{}]", currentId.toString(), fwData.length, chunkSize, moreFlag);
  146 + exchange.respond(response);
  147 + }
  148 +
  149 + }
  150 + }
  151 +
  152 + private byte[] getOtaData(UUID currentId) {
  153 + return ((DefaultLwM2MTransportMsgHandler) handler).otaPackageDataCache.get(currentId.toString());
  154 + }
  155 +
  156 +}
... ...
... ... @@ -23,7 +23,7 @@ import org.thingsboard.server.common.data.DeviceProfile;
23 23 import org.thingsboard.server.gen.transport.TransportProtos;
24 24 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
25 25 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
26   -import org.thingsboard.server.transport.lwm2m.server.client.Lwm2mClientRpcRequest;
  26 +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientRpcRequest;
27 27
28 28 import java.util.Collection;
29 29 import java.util.Optional;
... ... @@ -40,7 +40,7 @@ public interface LwM2mTransportMsgHandler {
40 40
41 41 void setCancelObservationsAll(Registration registration);
42 42
43   - void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response, Lwm2mClientRpcRequest rpcRequest);
  43 + void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response, LwM2mClientRpcRequest rpcRequest);
44 44
45 45 void onAttributeUpdate(TransportProtos.AttributeUpdateNotificationMsg msg, TransportProtos.SessionInfoProto sessionInfo);
46 46
... ...
... ... @@ -55,7 +55,7 @@ import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
55 55 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
56 56 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
57 57 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
58   -import org.thingsboard.server.transport.lwm2m.server.client.Lwm2mClientRpcRequest;
  58 +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientRpcRequest;
59 59 import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;
60 60
61 61 import javax.annotation.PostConstruct;
... ... @@ -75,7 +75,7 @@ import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.DOWN
75 75 import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.FAILED;
76 76 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper.getContentFormatByResourceModelType;
77 77 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.DEFAULT_TIMEOUT;
78   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_ID;
  78 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_5_ID;
79 79 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_UPDATE_ID;
80 80 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_ERROR;
81 81 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_INFO;
... ... @@ -116,13 +116,13 @@ public class LwM2mTransportRequest {
116 116 new NamedThreadFactory(String.format("LwM2M %s channel response after request", RESPONSE_REQUEST_CHANNEL)));
117 117 }
118 118
119   - public void sendAllRequest(LwM2mClient lwM2MClient, String targetIdVer, LwM2mTypeOper typeOper, Object params, long timeoutInMs, Lwm2mClientRpcRequest lwm2mClientRpcRequest) {
  119 + public void sendAllRequest(LwM2mClient lwM2MClient, String targetIdVer, LwM2mTypeOper typeOper, Object params, long timeoutInMs, LwM2mClientRpcRequest lwm2mClientRpcRequest) {
120 120 sendAllRequest(lwM2MClient, targetIdVer, typeOper, lwM2MClient.getDefaultContentFormat(), params, timeoutInMs, lwm2mClientRpcRequest);
121 121 }
122 122
123 123
124 124 public void sendAllRequest(LwM2mClient lwM2MClient, String targetIdVer, LwM2mTypeOper typeOper,
125   - ContentFormat contentFormat, Object params, long timeoutInMs, Lwm2mClientRpcRequest lwm2mClientRpcRequest) {
  125 + ContentFormat contentFormat, Object params, long timeoutInMs, LwM2mClientRpcRequest lwm2mClientRpcRequest) {
126 126 Registration registration = lwM2MClient.getRegistration();
127 127 try {
128 128 String target = convertPathFromIdVerToObjectId(targetIdVer);
... ... @@ -141,7 +141,7 @@ public class LwM2mTransportRequest {
141 141 } catch (ClientSleepingException e) {
142 142 SimpleDownlinkRequest finalRequest = request;
143 143 long finalTimeoutInMs = timeoutInMs;
144   - Lwm2mClientRpcRequest finalRpcRequest = lwm2mClientRpcRequest;
  144 + LwM2mClientRpcRequest finalRpcRequest = lwm2mClientRpcRequest;
145 145 lwM2MClient.getQueuedRequests().add(() -> sendRequest(registration, lwM2MClient, finalRequest, finalTimeoutInMs, finalRpcRequest));
146 146 } catch (Exception e) {
147 147 log.error("[{}] [{}] [{}] Failed to send downlink.", registration.getEndpoint(), targetIdVer, typeOper.name(), e);
... ... @@ -161,12 +161,12 @@ public class LwM2mTransportRequest {
161 161 if (lwm2mClientRpcRequest != null) {
162 162 ResourceModel resourceModel = lwM2MClient.getResourceModel(targetIdVer, this.config.getModelProvider());
163 163 String errorMsg = resourceModel == null ? String.format("Path %s not found in object version", targetIdVer) : "SendRequest - null";
164   - this.handler.sentRpcResponse(lwm2mClientRpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
  164 + handler.sentRpcResponse(lwm2mClientRpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
165 165 }
166 166 }
167 167 } else if (lwm2mClientRpcRequest != null) {
168 168 String errorMsg = String.format("Path %s not found in object version", targetIdVer);
169   - this.handler.sentRpcResponse(lwm2mClientRpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
  169 + handler.sentRpcResponse(lwm2mClientRpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
170 170 }
171 171 } else {
172 172 switch (typeOper) {
... ... @@ -186,7 +186,7 @@ public class LwM2mTransportRequest {
186 186 this.handler.sendLogsToThingsboard(lwM2MClient, msg);
187 187 if (lwm2mClientRpcRequest != null) {
188 188 String valueMsg = String.format("Paths - %s", paths);
189   - this.handler.sentRpcResponse(lwm2mClientRpcRequest, CONTENT.name(), valueMsg, LOG_LW2M_VALUE);
  189 + handler.sentRpcResponse(lwm2mClientRpcRequest, CONTENT.name(), valueMsg, LOG_LW2M_VALUE);
190 190 }
191 191 break;
192 192 case OBSERVE_CANCEL:
... ... @@ -206,7 +206,7 @@ public class LwM2mTransportRequest {
206 206 break;
207 207 // lwm2mClientRpcRequest != null
208 208 case FW_UPDATE:
209   - this.handler.getInfoFirmwareUpdate(lwM2MClient, lwm2mClientRpcRequest);
  209 + handler.getInfoFirmwareUpdate(lwM2MClient, lwm2mClientRpcRequest);
210 210 break;
211 211 }
212 212 }
... ... @@ -223,7 +223,7 @@ public class LwM2mTransportRequest {
223 223
224 224 private SimpleDownlinkRequest createRequest(Registration registration, LwM2mClient lwM2MClient, LwM2mTypeOper typeOper,
225 225 ContentFormat contentFormat, String target, String targetIdVer,
226   - LwM2mPath resultIds, Object params, Lwm2mClientRpcRequest rpcRequest) {
  226 + LwM2mPath resultIds, Object params, LwM2mClientRpcRequest rpcRequest) {
227 227 SimpleDownlinkRequest request = null;
228 228 switch (typeOper) {
229 229 case READ:
... ... @@ -328,7 +328,7 @@ public class LwM2mTransportRequest {
328 328
329 329 @SuppressWarnings({"error sendRequest"})
330 330 private void sendRequest(Registration registration, LwM2mClient lwM2MClient, SimpleDownlinkRequest request,
331   - long timeoutInMs, Lwm2mClientRpcRequest rpcRequest) {
  331 + long timeoutInMs, LwM2mClientRpcRequest rpcRequest) {
332 332 context.getServer().send(registration, request, timeoutInMs, (ResponseCallback<?>) response -> {
333 333
334 334 if (!lwM2MClient.isInit()) {
... ... @@ -352,13 +352,13 @@ public class LwM2mTransportRequest {
352 352 /** Not Found
353 353 set setClient_fw_info... = empty
354 354 **/
355   - if (lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) {
  355 + if (lwM2MClient.getFwUpdate() != null && lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) {
356 356 lwM2MClient.getFwUpdate().initReadValue(handler, this, request.getPath().toString());
357 357 }
358   - if (lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) {
  358 + if (lwM2MClient.getSwUpdate() != null && lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) {
359 359 lwM2MClient.getSwUpdate().initReadValue(handler, this, request.getPath().toString());
360 360 }
361   - if (request.getPath().toString().equals(FW_PACKAGE_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) {
  361 + if (request.getPath().toString().equals(FW_PACKAGE_5_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) {
362 362 this.afterWriteFwSWUpdateError(registration, request, response.getErrorMessage());
363 363 }
364 364 if (request.getPath().toString().equals(FW_UPDATE_ID) || request.getPath().toString().equals(SW_INSTALL_ID)) {
... ... @@ -369,13 +369,13 @@ public class LwM2mTransportRequest {
369 369 /** version == null
370 370 set setClient_fw_info... = empty
371 371 **/
372   - if (lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) {
  372 + if (lwM2MClient.getFwUpdate() != null && lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) {
373 373 lwM2MClient.getFwUpdate().initReadValue(handler, this, request.getPath().toString());
374 374 }
375   - if (lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) {
  375 + if (lwM2MClient.getSwUpdate() != null && lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) {
376 376 lwM2MClient.getSwUpdate().initReadValue(handler, this, request.getPath().toString());
377 377 }
378   - if (request.getPath().toString().equals(FW_PACKAGE_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) {
  378 + if (request.getPath().toString().equals(FW_PACKAGE_5_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) {
379 379 this.afterWriteFwSWUpdateError(registration, request, e.getMessage());
380 380 }
381 381 if (request.getPath().toString().equals(FW_UPDATE_ID) || request.getPath().toString().equals(SW_INSTALL_ID)) {
... ... @@ -396,7 +396,7 @@ public class LwM2mTransportRequest {
396 396
397 397 private WriteRequest getWriteRequestSingleResource(ContentFormat contentFormat, Integer objectId, Integer instanceId,
398 398 Integer resourceId, Object value, ResourceModel.Type type,
399   - LwM2mClient client, Lwm2mClientRpcRequest rpcRequest) {
  399 + LwM2mClient client, LwM2mClientRpcRequest rpcRequest) {
400 400 try {
401 401 if (type != null) {
402 402 switch (type) {
... ... @@ -442,7 +442,7 @@ public class LwM2mTransportRequest {
442 442 }
443 443
444 444 private void handleResponse(LwM2mClient lwM2mClient, final String path, LwM2mResponse response,
445   - SimpleDownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) {
  445 + SimpleDownlinkRequest request, LwM2mClientRpcRequest rpcRequest) {
446 446 responseRequestExecutor.submit(() -> {
447 447 try {
448 448 this.sendResponse(lwM2mClient, path, response, request, rpcRequest);
... ... @@ -455,12 +455,11 @@ public class LwM2mTransportRequest {
455 455 /**
456 456 * processing a response from a client
457 457 *
458   - * @param registration -
459 458 * @param path -
460 459 * @param response -
461 460 */
462 461 private void sendResponse(LwM2mClient lwM2mClient, String path, LwM2mResponse response,
463   - SimpleDownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) {
  462 + SimpleDownlinkRequest request, LwM2mClientRpcRequest rpcRequest) {
464 463 Registration registration = lwM2mClient.getRegistration();
465 464 String pathIdVer = convertPathFromObjectIdToIdVer(path, registration);
466 465 String msgLog = "";
... ... @@ -508,7 +507,7 @@ public class LwM2mTransportRequest {
508 507 }
509 508 }
510 509
511   - private void infoWriteResponse(LwM2mClient lwM2mClient, LwM2mResponse response, SimpleDownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) {
  510 + private void infoWriteResponse(LwM2mClient lwM2mClient, LwM2mResponse response, SimpleDownlinkRequest request, LwM2mClientRpcRequest rpcRequest) {
512 511 try {
513 512 Registration registration = lwM2mClient.getRegistration();
514 513 LwM2mNode node = ((WriteRequest) request).getNode();
... ... @@ -546,7 +545,7 @@ public class LwM2mTransportRequest {
546 545 }
547 546 if (msg != null) {
548 547 handler.sendLogsToThingsboard(lwM2mClient, msg);
549   - if (request.getPath().toString().equals(FW_PACKAGE_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) {
  548 + if (request.getPath().toString().equals(FW_PACKAGE_5_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) {
550 549 this.afterWriteSuccessFwSwUpdate(registration, request);
551 550 if (rpcRequest != null) {
552 551 rpcRequest.setInfoMsg(msg);
... ... @@ -568,7 +567,7 @@ public class LwM2mTransportRequest {
568 567 */
569 568 private void afterWriteSuccessFwSwUpdate(Registration registration, SimpleDownlinkRequest request) {
570 569 LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId());
571   - if (request.getPath().toString().equals(FW_PACKAGE_ID) && lwM2MClient.getFwUpdate() != null) {
  570 + if (request.getPath().toString().equals(FW_PACKAGE_5_ID) && lwM2MClient.getFwUpdate() != null) {
572 571 lwM2MClient.getFwUpdate().setStateUpdate(DOWNLOADED.name());
573 572 lwM2MClient.getFwUpdate().sendLogs(this.handler, WRITE_REPLACE.name(), LOG_LW2M_INFO, null);
574 573 }
... ... @@ -583,7 +582,7 @@ public class LwM2mTransportRequest {
583 582 */
584 583 private void afterWriteFwSWUpdateError(Registration registration, SimpleDownlinkRequest request, String msgError) {
585 584 LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId());
586   - if (request.getPath().toString().equals(FW_PACKAGE_ID) && lwM2MClient.getFwUpdate() != null) {
  585 + if (request.getPath().toString().equals(FW_PACKAGE_5_ID) && lwM2MClient.getFwUpdate() != null) {
587 586 lwM2MClient.getFwUpdate().setStateUpdate(FAILED.name());
588 587 lwM2MClient.getFwUpdate().sendLogs(this.handler, WRITE_REPLACE.name(), LOG_LW2M_ERROR, msgError);
589 588 }
... ... @@ -603,7 +602,7 @@ public class LwM2mTransportRequest {
603 602 }
604 603 }
605 604
606   - private void afterObserveCancel(LwM2mClient lwM2mClient, int observeCancelCnt, String observeCancelMsg, Lwm2mClientRpcRequest rpcRequest) {
  605 + private void afterObserveCancel(LwM2mClient lwM2mClient, int observeCancelCnt, String observeCancelMsg, LwM2mClientRpcRequest rpcRequest) {
607 606 handler.sendLogsToThingsboard(lwM2mClient, observeCancelMsg);
608 607 log.warn("[{}]", observeCancelMsg);
609 608 if (rpcRequest != null) {
... ...
... ... @@ -65,13 +65,11 @@ import static org.thingsboard.server.gen.transport.TransportProtos.KeyValueType.
65 65 public class LwM2mTransportServerHelper {
66 66
67 67 private final LwM2mTransportContext context;
68   - private final LwM2MJsonAdaptor adaptor;
69 68 private final AtomicInteger atomicTs = new AtomicInteger(0);
70 69
71 70
72 71 public long getTS() {
73   - int addTs = atomicTs.getAndIncrement() >= 1000 ? atomicTs.getAndSet(0) : atomicTs.get();
74   - return TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()) * 1000L + addTs;
  72 + return TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()) * 1000L + (atomicTs.getAndIncrement() % 1000);
75 73 }
76 74
77 75 /**
... ...
... ... @@ -43,11 +43,11 @@ import org.eclipse.leshan.server.registration.Registration;
43 43 import org.nustaq.serialization.FSTConfiguration;
44 44 import org.thingsboard.server.common.data.DeviceProfile;
45 45 import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration;
  46 +import org.thingsboard.server.common.data.id.TenantId;
46 47 import org.thingsboard.server.common.data.ota.OtaPackageKey;
47 48 import org.thingsboard.server.common.data.ota.OtaPackageType;
48 49 import org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus;
49 50 import org.thingsboard.server.common.data.ota.OtaPackageUtil;
50   -import org.thingsboard.server.common.data.id.TenantId;
51 51 import org.thingsboard.server.common.transport.TransportServiceCallback;
52 52 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
53 53 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile;
... ... @@ -77,18 +77,23 @@ import static org.eclipse.leshan.core.model.ResourceModel.Type.OBJLNK;
77 77 import static org.eclipse.leshan.core.model.ResourceModel.Type.OPAQUE;
78 78 import static org.eclipse.leshan.core.model.ResourceModel.Type.STRING;
79 79 import static org.eclipse.leshan.core.model.ResourceModel.Type.TIME;
  80 +import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY;
  81 +import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH;
80 82 import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.DOWNLOADED;
81 83 import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.DOWNLOADING;
82 84 import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.FAILED;
83 85 import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDATED;
84 86 import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDATING;
85 87 import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.VERIFIED;
86   -import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY;
87   -import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH;
88 88
89 89 @Slf4j
90 90 public class LwM2mTransportUtil {
91 91
  92 + public static final String EVENT_AWAKE = "AWAKE";
  93 + public static final String RESPONSE_REQUEST_CHANNEL = "RESP_REQ";
  94 + public static final String RESPONSE_CHANNEL = "RESP";
  95 + public static final String OBSERVE_CHANNEL = "OBSERVE";
  96 +
92 97 public static final String TRANSPORT_DEFAULT_LWM2M_VERSION = "1.0";
93 98 public static final String CLIENT_LWM2M_SETTINGS = "clientLwM2mSettings";
94 99 public static final String BOOTSTRAP = "bootstrap";
... ... @@ -116,9 +121,6 @@ public class LwM2mTransportUtil {
116 121 public static final String LOG_LW2M_WARN = "warn";
117 122 public static final String LOG_LW2M_VALUE = "value";
118 123
119   - public static final int LWM2M_STRATEGY_1 = 1;
120   - public static final int LWM2M_STRATEGY_2 = 2;
121   -
122 124 public static final String CLIENT_NOT_AUTHORIZED = "Client not authorized";
123 125 public static final String LWM2M_VERSION_DEFAULT = "1.0";
124 126
... ... @@ -132,18 +134,23 @@ public class LwM2mTransportUtil {
132 134 public static final String FINISH_VALUE_KEY = ",";
133 135 public static final String START_JSON_KEY = "{";
134 136 public static final String FINISH_JSON_KEY = "}";
135   - // public static final String contentFormatNameKey = "contentFormatName";
136 137 public static final String INFO_KEY = "info";
137   - // public static final String TIME_OUT_IN_MS = "timeOutInMs";
138 138 public static final String RESULT_KEY = "result";
139 139 public static final String ERROR_KEY = "error";
140 140 public static final String METHOD_KEY = "methodName";
141 141
  142 +
142 143 // Firmware
  144 + public static final String FIRMWARE_UPDATE_COAP_RECOURSE = "firmwareUpdateCoapRecourse";
143 145 public static final String FW_UPDATE = "Firmware update";
144   - public static final Integer FW_ID = 5;
  146 + public static final Integer FW_5_ID = 5;
  147 + public static final Integer FW_19_ID = 19;
  148 +
145 149 // Package W
146   - public static final String FW_PACKAGE_ID = "/5/0/0";
  150 + public static final String FW_PACKAGE_5_ID = "/5/0/0";
  151 + public static final String FW_PACKAGE_19_ID = "/19/0/0";
  152 + // Package URI
  153 + public static final String FW_PACKAGE_URI_ID = "/5/0/1";
147 154 // State R
148 155 public static final String FW_STATE_ID = "/5/0/3";
149 156 // Update Result R
... ... @@ -151,15 +158,28 @@ public class LwM2mTransportUtil {
151 158 // PkgName R
152 159 public static final String FW_NAME_ID = "/5/0/6";
153 160 // PkgVersion R
154   - public static final String FW_VER_ID = "/5/0/7";
  161 + public static final String FW_5_VER_ID = "/5/0/7";
  162 + /**
  163 + * Quectel@Hi15RM1-HLB_V1.0@BC68JAR01A10,V150R100C20B300SP7,V150R100C20B300SP7@8
  164 + * BC68JAR01A10
  165 + * # Request prodct type number
  166 + * ATI
  167 + * Quectel
  168 + * BC68
  169 + * Revision:BC68JAR01A10
  170 + */
  171 + public static final String FW_3_VER_ID = "/3/0/3";
155 172 // Update E
156 173 public static final String FW_UPDATE_ID = "/5/0/2";
157 174
158 175 // Software
  176 + public static final String SOFTWARE_UPDATE_COAP_RECOURSE = "softwareUpdateCoapRecourse";
159 177 public static final String SW_UPDATE = "Software update";
160 178 public static final Integer SW_ID = 9;
161 179 // Package W
162 180 public static final String SW_PACKAGE_ID = "/9/0/2";
  181 + // Package URI
  182 + public static final String SW_PACKAGE_URI_ID = "/9/0/3";
163 183 // Update State R
164 184 public static final String SW_UPDATE_STATE_ID = "/9/0/7";
165 185 // Update Result R
... ... @@ -232,7 +252,7 @@ public class LwM2mTransportUtil {
232 252 DELETE(11, "Delete"),
233 253
234 254 // only for RPC
235   - FW_UPDATE(12,"FirmwareUpdate");
  255 + FW_UPDATE(12, "FirmwareUpdate");
236 256 // FW_READ_INFO(12, "FirmwareReadInfo"),
237 257
238 258 // SW_READ_INFO(15, "SoftwareReadInfo"),
... ... @@ -355,20 +375,11 @@ public class LwM2mTransportUtil {
355 375 * FirmwareUpdateStatus {
356 376 * DOWNLOADING, DOWNLOADED, VERIFIED, UPDATING, UPDATED, FAILED
357 377 */
358   - public static OtaPackageUpdateStatus EqualsFwSateToFirmwareUpdateStatus(StateFw stateFw, UpdateResultFw updateResultFw) {
  378 + public static OtaPackageUpdateStatus equalsFwSateFwResultToFirmwareUpdateStatus(StateFw stateFw, UpdateResultFw updateResultFw) {
359 379 switch (updateResultFw) {
360 380 case INITIAL:
361   - switch (stateFw) {
362   - case IDLE:
363   - return VERIFIED;
364   - case DOWNLOADING:
365   - return DOWNLOADING;
366   - case DOWNLOADED:
367   - return DOWNLOADED;
368   - case UPDATING:
369   - return UPDATING;
370   - }
371   - case UPDATE_SUCCESSFULLY:
  381 + return equalsFwSateToFirmwareUpdateStatus(stateFw);
  382 + case UPDATE_SUCCESSFULLY:
372 383 return UPDATED;
373 384 case NOT_ENOUGH:
374 385 case OUT_OFF_MEMORY:
... ... @@ -384,6 +395,41 @@ public class LwM2mTransportUtil {
384 395 }
385 396 }
386 397
  398 + public static OtaPackageUpdateStatus equalsFwResultToFirmwareUpdateStatus(UpdateResultFw updateResultFw) {
  399 + switch (updateResultFw) {
  400 + case INITIAL:
  401 + return VERIFIED;
  402 + case UPDATE_SUCCESSFULLY:
  403 + return UPDATED;
  404 + case NOT_ENOUGH:
  405 + case OUT_OFF_MEMORY:
  406 + case CONNECTION_LOST:
  407 + case INTEGRITY_CHECK_FAILURE:
  408 + case UNSUPPORTED_TYPE:
  409 + case INVALID_URI:
  410 + case UPDATE_FAILED:
  411 + case UNSUPPORTED_PROTOCOL:
  412 + return FAILED;
  413 + default:
  414 + throw new CodecException("Invalid value stateFw %s for FirmwareUpdateStatus.", updateResultFw.name());
  415 + }
  416 + }
  417 +
  418 + public static OtaPackageUpdateStatus equalsFwSateToFirmwareUpdateStatus(StateFw stateFw) {
  419 + switch (stateFw) {
  420 + case IDLE:
  421 + return VERIFIED;
  422 + case DOWNLOADING:
  423 + return DOWNLOADING;
  424 + case DOWNLOADED:
  425 + return DOWNLOADED;
  426 + case UPDATING:
  427 + return UPDATING;
  428 + default:
  429 + throw new CodecException("Invalid value stateFw %d for FirmwareUpdateStatus.", stateFw);
  430 + }
  431 + }
  432 +
387 433 /**
388 434 * SW Update State R
389 435 * 0: INITIAL Before downloading. (see 5.1.2.1)
... ... @@ -497,6 +543,101 @@ public class LwM2mTransportUtil {
497 543 }
498 544 }
499 545
  546 + public enum LwM2MClientStrategy {
  547 + CLIENT_STRATEGY_1(1, "Read only resources marked as observation"),
  548 + CLIENT_STRATEGY_2(2, "Read all client resources");
  549 +
  550 + public int code;
  551 + public String type;
  552 +
  553 + LwM2MClientStrategy(int code, String type) {
  554 + this.code = code;
  555 + this.type = type;
  556 + }
  557 +
  558 + public static LwM2MClientStrategy fromStrategyClientByType(String type) {
  559 + for (LwM2MClientStrategy to : LwM2MClientStrategy.values()) {
  560 + if (to.type.equals(type)) {
  561 + return to;
  562 + }
  563 + }
  564 + throw new IllegalArgumentException(String.format("Unsupported Client Strategy type : %s", type));
  565 + }
  566 +
  567 + public static LwM2MClientStrategy fromStrategyClientByCode(int code) {
  568 + for (LwM2MClientStrategy to : LwM2MClientStrategy.values()) {
  569 + if (to.code == code) {
  570 + return to;
  571 + }
  572 + }
  573 + throw new IllegalArgumentException(String.format("Unsupported Client Strategy code : %s", code));
  574 + }
  575 + }
  576 +
  577 + public enum LwM2MFirmwareUpdateStrategy {
  578 + OBJ_5_BINARY(1, "ObjectId 5, Binary"),
  579 + OBJ_5_TEMP_URL(2, "ObjectId 5, URI"),
  580 + OBJ_19_BINARY(3, "ObjectId 19, Binary");
  581 +
  582 + public int code;
  583 + public String type;
  584 +
  585 + LwM2MFirmwareUpdateStrategy(int code, String type) {
  586 + this.code = code;
  587 + this.type = type;
  588 + }
  589 +
  590 + public static LwM2MFirmwareUpdateStrategy fromStrategyFwByType(String type) {
  591 + for (LwM2MFirmwareUpdateStrategy to : LwM2MFirmwareUpdateStrategy.values()) {
  592 + if (to.type.equals(type)) {
  593 + return to;
  594 + }
  595 + }
  596 + throw new IllegalArgumentException(String.format("Unsupported FW State type : %s", type));
  597 + }
  598 +
  599 + public static LwM2MFirmwareUpdateStrategy fromStrategyFwByCode(int code) {
  600 + for (LwM2MFirmwareUpdateStrategy to : LwM2MFirmwareUpdateStrategy.values()) {
  601 + if (to.code == code) {
  602 + return to;
  603 + }
  604 + }
  605 + throw new IllegalArgumentException(String.format("Unsupported FW Strategy code : %s", code));
  606 + }
  607 + }
  608 +
  609 + public enum LwM2MSoftwareUpdateStrategy {
  610 + BINARY(1, "ObjectId 9, Binary"),
  611 + TEMP_URL(2, "ObjectId 9, URI");
  612 +
  613 + public int code;
  614 + public String type;
  615 +
  616 + LwM2MSoftwareUpdateStrategy(int code, String type) {
  617 + this.code = code;
  618 + this.type = type;
  619 + }
  620 +
  621 + public static LwM2MSoftwareUpdateStrategy fromStrategySwByType(String type) {
  622 + for (LwM2MSoftwareUpdateStrategy to : LwM2MSoftwareUpdateStrategy.values()) {
  623 + if (to.type.equals(type)) {
  624 + return to;
  625 + }
  626 + }
  627 + throw new IllegalArgumentException(String.format("Unsupported SW Strategy type : %s", type));
  628 + }
  629 +
  630 + public static LwM2MSoftwareUpdateStrategy fromStrategySwByCode(int code) {
  631 + for (LwM2MSoftwareUpdateStrategy to : LwM2MSoftwareUpdateStrategy.values()) {
  632 + if (to.code == code) {
  633 + return to;
  634 + }
  635 + }
  636 + throw new IllegalArgumentException(String.format("Unsupported SW Strategy code : %s", code));
  637 + }
  638 +
  639 + }
  640 +
500 641 /**
501 642 * FirmwareUpdateStatus {
502 643 * DOWNLOADING, DOWNLOADED, VERIFIED, UPDATING, UPDATED, FAILED
... ... @@ -534,10 +675,6 @@ public class LwM2mTransportUtil {
534 675 }
535 676 }
536 677
537   - public static final String EVENT_AWAKE = "AWAKE";
538   - public static final String RESPONSE_REQUEST_CHANNEL = "RESP_REQ";
539   - public static final String RESPONSE_CHANNEL = "RESP";
540   - public static final String OBSERVE_CHANNEL = "OBSERVE";
541 678
542 679 public static boolean equalsResourceValue(Object valueOld, Object valueNew, ResourceModel.Type type, LwM2mPath
543 680 resourcePath) throws CodecException {
... ... @@ -558,6 +695,36 @@ public class LwM2mTransportUtil {
558 695 }
559 696 }
560 697
  698 + public static LwM2mOtaConvert convertOtaUpdateValueToString (String pathIdVer, Object value, ResourceModel.Type currentType) {
  699 + String path = convertPathFromIdVerToObjectId(pathIdVer);
  700 + LwM2mOtaConvert lwM2mOtaConvert = new LwM2mOtaConvert();
  701 + if (path != null) {
  702 + if (FW_STATE_ID.equals(path)) {
  703 + lwM2mOtaConvert.setCurrentType(STRING);
  704 + lwM2mOtaConvert.setValue(StateFw.fromStateFwByCode(((Long) value).intValue()).type);
  705 + return lwM2mOtaConvert;
  706 + }
  707 + else if (FW_RESULT_ID.equals(path)) {
  708 + lwM2mOtaConvert.setCurrentType(STRING);
  709 + lwM2mOtaConvert.setValue(UpdateResultFw.fromUpdateResultFwByCode(((Long) value).intValue()).type);
  710 + return lwM2mOtaConvert;
  711 + }
  712 + else if (SW_UPDATE_STATE_ID.equals(path)) {
  713 + lwM2mOtaConvert.setCurrentType(STRING);
  714 + lwM2mOtaConvert.setValue(UpdateStateSw.fromUpdateStateSwByCode(((Long) value).intValue()).type);
  715 + return lwM2mOtaConvert;
  716 + }
  717 + else if (SW_RESULT_ID.equals(path)) {
  718 + lwM2mOtaConvert.setCurrentType(STRING);
  719 + lwM2mOtaConvert.setValue(UpdateResultSw.fromUpdateResultSwByCode(((Long) value).intValue()).type);
  720 + return lwM2mOtaConvert;
  721 + }
  722 + }
  723 + lwM2mOtaConvert.setCurrentType(currentType);
  724 + lwM2mOtaConvert.setValue(value);
  725 + return lwM2mOtaConvert;
  726 + }
  727 +
561 728 public static LwM2mNode getLvM2mNodeToObject(LwM2mNode content) {
562 729 if (content instanceof LwM2mObject) {
563 730 return (LwM2mObject) content;
... ... @@ -633,11 +800,6 @@ public class LwM2mTransportUtil {
633 800 return null;
634 801 }
635 802
636   - public static int getClientOnlyObserveAfterConnect(LwM2mClientProfile profile) {
637   - return profile.getPostClientLwM2mSettings().getAsJsonObject().has("clientOnlyObserveAfterConnect") ?
638   - profile.getPostClientLwM2mSettings().getAsJsonObject().get("clientOnlyObserveAfterConnect").getAsInt() : 1;
639   - }
640   -
641 803 private static boolean getValidateCredentialsBodyFromThingsboard(JsonObject objectMsg) {
642 804 return (objectMsg != null &&
643 805 !objectMsg.isJsonNull() &&
... ... @@ -914,7 +1076,7 @@ public class LwM2mTransportUtil {
914 1076 case GREATER_THAN:
915 1077 case LESSER_THAN:
916 1078 case STEP:
917   - if (value.getClass().getSimpleName().equals("String") ) {
  1079 + if (value.getClass().getSimpleName().equals("String")) {
918 1080 value = Double.valueOf((String) value);
919 1081 }
920 1082 return serviceImpl.converter.convertValue(value, equalsResourceTypeGetSimpleName(value), FLOAT, new LwM2mPath(target));
... ... @@ -928,11 +1090,11 @@ public class LwM2mTransportUtil {
928 1090 return new Attribute(key, attrValue);
929 1091 } catch (Exception e) {
930 1092 log.error("CreateAttribute, not valid parameter key: [{}], attrValue: [{}], error: [{}]", key, attrValue, e.getMessage());
931   - return null;
  1093 + return null;
932 1094 }
933 1095 }
934 1096
935   - public static boolean isFwSwWords (String pathName) {
  1097 + public static boolean isFwSwWords(String pathName) {
936 1098 return OtaPackageUtil.getAttributeKey(OtaPackageType.FIRMWARE, OtaPackageKey.VERSION).equals(pathName)
937 1099 || OtaPackageUtil.getAttributeKey(OtaPackageType.FIRMWARE, OtaPackageKey.TITLE).equals(pathName)
938 1100 || OtaPackageUtil.getAttributeKey(OtaPackageType.FIRMWARE, OtaPackageKey.CHECKSUM).equals(pathName)
... ...
... ... @@ -94,8 +94,6 @@ public class LwM2mClient implements Cloneable {
94 94 @Getter
95 95 private UUID deviceId;
96 96 @Getter
97   - private UUID sessionId;
98   - @Getter
99 97 private SessionInfoProto session;
100 98 @Getter
101 99 private UUID profileId;
... ... @@ -135,8 +133,6 @@ public class LwM2mClient implements Cloneable {
135 133 this.credentials = credentials;
136 134 this.profileId = profileId;
137 135 this.init = false;
138   - this.fwUpdate = new LwM2mFwSwUpdate(this, OtaPackageType.FIRMWARE);
139   - this.swUpdate = new LwM2mFwSwUpdate(this, OtaPackageType.SOFTWARE);
140 136 if (this.credentials != null && this.credentials.hasDeviceInfo()) {
141 137 this.session = createSession(nodeId, sessionId, credentials);
142 138 this.deviceId = new UUID(session.getDeviceIdMSB(), session.getDeviceIdLSB());
... ... @@ -396,5 +392,22 @@ public class LwM2mClient implements Cloneable {
396 392 return ContentFormat.TEXT;
397 393 }
398 394 }
  395 +
  396 + public LwM2mFwSwUpdate getFwUpdate (LwM2mClientContext clientContext) {
  397 + if (this.fwUpdate == null) {
  398 + LwM2mClientProfile lwM2mClientProfile = clientContext.getProfile(this.getProfileId());
  399 + this.fwUpdate = new LwM2mFwSwUpdate(this, OtaPackageType.FIRMWARE, lwM2mClientProfile.getFwUpdateStrategy());
  400 + }
  401 + return this.fwUpdate;
  402 + }
  403 +
  404 + public LwM2mFwSwUpdate getSwUpdate (LwM2mClientContext clientContext) {
  405 + if (this.swUpdate == null) {
  406 + LwM2mClientProfile lwM2mClientProfile = clientContext.getProfile(this.getProfileId());
  407 + this.swUpdate = new LwM2mFwSwUpdate(this, OtaPackageType.SOFTWARE, lwM2mClientProfile.getSwUpdateStrategy());
  408 + }
  409 + return this.fwUpdate;
  410 + }
  411 +
399 412 }
400 413
... ...
... ... @@ -16,7 +16,6 @@
16 16 package org.thingsboard.server.transport.lwm2m.server.client;
17 17
18 18 import org.eclipse.leshan.server.registration.Registration;
19   -import org.eclipse.leshan.server.security.SecurityInfo;
20 19 import org.thingsboard.server.common.data.DeviceProfile;
21 20 import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
22 21 import org.thingsboard.server.gen.transport.TransportProtos;
... ...
... ... @@ -96,12 +96,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
96 96 if (!LwM2MClientState.REGISTERED.equals(lwM2MClient.getState())) {
97 97 throw new LwM2MClientStateException(lwM2MClient.getState(), "Client is in invalid state.");
98 98 }
99   - Registration currentRegistration = lwM2MClient.getRegistration();
100   - if (currentRegistration.getId().equals(registration.getId())) {
101   - lwM2MClient.setRegistration(registration);
102   - } else {
103   - throw new LwM2MClientStateException(lwM2MClient.getState(), "Client has different registration.");
104   - }
  99 + lwM2MClient.setRegistration(registration);
105 100 } finally {
106 101 lwM2MClient.unlock();
107 102 }
... ... @@ -120,7 +115,6 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
120 115 lwM2MClient.setState(LwM2MClientState.UNREGISTERED);
121 116 lwM2mClientsByEndpoint.remove(lwM2MClient.getEndpoint());
122 117 this.securityStore.remove(lwM2MClient.getEndpoint());
123   - this.lwM2mClientsByRegistrationId.remove(registration.getId());
124 118 UUID profileId = lwM2MClient.getProfileId();
125 119 if (profileId != null) {
126 120 Optional<LwM2mClient> otherClients = lwM2mClientsByRegistrationId.values().stream().filter(e -> e.getProfileId().equals(profileId)).findFirst();
... ...
... ... @@ -20,15 +20,23 @@ import com.google.gson.JsonArray;
20 20 import com.google.gson.JsonObject;
21 21 import lombok.Data;
22 22 import org.thingsboard.server.common.data.id.TenantId;
  23 +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2MClientStrategy;
  24 +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy;
  25 +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2MSoftwareUpdateStrategy;
23 26
24 27 @Data
25 28 public class LwM2mClientProfile {
  29 + private final String clientStrategyStr = "clientStrategy";
  30 + private final String fwUpdateStrategyStr = "fwUpdateStrategy";
  31 + private final String swUpdateStrategyStr = "swUpdateStrategy";
26 32
27 33 private TenantId tenantId;
28 34 /**
29   - * {"clientLwM2mSettings": {
30   - * clientUpdateValueAfterConnect: false;
31   - * }
  35 + * "clientLwM2mSettings": {
  36 + * "fwUpdateStrategy": "1",
  37 + * "swUpdateStrategy": "1",
  38 + * "clientStrategy": "1"
  39 + * }
32 40 **/
33 41 private JsonObject postClientLwM2mSettings;
34 42
... ... @@ -85,5 +93,21 @@ public class LwM2mClientProfile {
85 93 }
86 94 }
87 95
  96 + public int getClientStrategy() {
  97 + return this.postClientLwM2mSettings.getAsJsonObject().has(this.clientStrategyStr) ?
  98 + Integer.parseInt(this.postClientLwM2mSettings.getAsJsonObject().get(this.clientStrategyStr).getAsString()) :
  99 + LwM2MClientStrategy.CLIENT_STRATEGY_1.code;
  100 + }
88 101
  102 + public int getFwUpdateStrategy() {
  103 + return this.postClientLwM2mSettings.getAsJsonObject().has(this.fwUpdateStrategyStr) ?
  104 + Integer.parseInt(this.postClientLwM2mSettings.getAsJsonObject().get(this.fwUpdateStrategyStr).getAsString()) :
  105 + LwM2MFirmwareUpdateStrategy.OBJ_5_BINARY.code;
  106 + }
  107 +
  108 + public int getSwUpdateStrategy() {
  109 + return this.postClientLwM2mSettings.getAsJsonObject().has(this.swUpdateStrategyStr) ?
  110 + Integer.parseInt(this.postClientLwM2mSettings.getAsJsonObject().get(this.swUpdateStrategyStr).getAsString()) :
  111 + LwM2MSoftwareUpdateStrategy.BINARY.code;
  112 + }
89 113 }
... ...
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientRpcRequest.java renamed from common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/Lwm2mClientRpcRequest.java
... ... @@ -57,7 +57,7 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.v
57 57
58 58 @Slf4j
59 59 @Data
60   -public class Lwm2mClientRpcRequest {
  60 +public class LwM2mClientRpcRequest {
61 61
62 62 private Registration registration;
63 63 private TransportProtos.SessionInfoProto sessionInfo;
... ... @@ -75,10 +75,10 @@ public class Lwm2mClientRpcRequest {
75 75 private String infoMsg;
76 76 private String responseCode;
77 77
78   - public Lwm2mClientRpcRequest() {
  78 + public LwM2mClientRpcRequest() {
79 79 }
80 80
81   - public Lwm2mClientRpcRequest(LwM2mTypeOper lwM2mTypeOper, String bodyParams, int requestId,
  81 + public LwM2mClientRpcRequest(LwM2mTypeOper lwM2mTypeOper, String bodyParams, int requestId,
82 82 TransportProtos.SessionInfoProto sessionInfo, Registration registration, DefaultLwM2MTransportMsgHandler handler) {
83 83 this.registration = registration;
84 84 this.sessionInfo = sessionInfo;
... ...
... ... @@ -20,6 +20,7 @@ import lombok.Setter;
20 20 import lombok.extern.slf4j.Slf4j;
21 21 import org.apache.commons.lang3.StringUtils;
22 22 import org.eclipse.leshan.core.request.ContentFormat;
  23 +import org.eclipse.leshan.server.registration.Registration;
23 24 import org.thingsboard.server.common.data.ota.OtaPackageType;
24 25 import org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus;
25 26 import org.thingsboard.server.gen.transport.TransportProtos;
... ... @@ -32,21 +33,32 @@ import java.util.List;
32 33 import java.util.UUID;
33 34 import java.util.concurrent.CopyOnWriteArrayList;
34 35
  36 +import static org.eclipse.californium.core.coap.CoAP.ResponseCode.CONTENT;
35 37 import static org.thingsboard.server.common.data.ota.OtaPackageKey.STATE;
36 38 import static org.thingsboard.server.common.data.ota.OtaPackageType.FIRMWARE;
37 39 import static org.thingsboard.server.common.data.ota.OtaPackageType.SOFTWARE;
  40 +import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.DOWNLOADED;
  41 +import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.FAILED;
  42 +import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.INITIATED;
  43 +import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDATED;
38 44 import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDATING;
39 45 import static org.thingsboard.server.common.data.ota.OtaPackageUtil.getAttributeKey;
40   -import static org.eclipse.californium.core.coap.CoAP.ResponseCode.CONTENT;
  46 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FIRMWARE_UPDATE_COAP_RECOURSE;
  47 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_3_VER_ID;
  48 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_5_VER_ID;
41 49 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_NAME_ID;
42   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_ID;
  50 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_19_ID;
  51 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_5_ID;
  52 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_URI_ID;
43 53 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_RESULT_ID;
44 54 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_STATE_ID;
45 55 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_UPDATE;
46 56 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_UPDATE_ID;
47   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_VER_ID;
48 57 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_ERROR;
49 58 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_INFO;
  59 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_19_BINARY;
  60 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_5_BINARY;
  61 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_5_TEMP_URL;
50 62 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.EXECUTE;
51 63 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE;
52 64 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_REPLACE;
... ... @@ -59,6 +71,7 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.S
59 71 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_UPDATE_STATE_ID;
60 72 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_VER_ID;
61 73 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer;
  74 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.equalsFwSateToFirmwareUpdateStatus;
62 75 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.splitCamelCaseString;
63 76
64 77 @Slf4j
... ... @@ -106,23 +119,29 @@ public class LwM2mFwSwUpdate {
106 119 private final List<String> pendingInfoRequestsStart;
107 120 @Getter
108 121 @Setter
109   - private volatile Lwm2mClientRpcRequest rpcRequest;
  122 + private volatile LwM2mClientRpcRequest rpcRequest;
  123 + @Getter
  124 + @Setter
  125 + private volatile int updateStrategy;
110 126
111   - public LwM2mFwSwUpdate(LwM2mClient lwM2MClient, OtaPackageType type) {
  127 + public LwM2mFwSwUpdate(LwM2mClient lwM2MClient, OtaPackageType type, int updateStrategy) {
112 128 this.lwM2MClient = lwM2MClient;
113 129 this.pendingInfoRequestsStart = new CopyOnWriteArrayList<>();
114 130 this.type = type;
115 131 this.stateUpdate = null;
  132 + this.updateStrategy = updateStrategy;
116 133 this.initPathId();
117 134 }
118 135
119 136 private void initPathId() {
120 137 if (FIRMWARE.equals(this.type)) {
121   - this.pathPackageId = FW_PACKAGE_ID;
  138 + this.pathPackageId = LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_5_BINARY.code == this.updateStrategy ?
  139 + FW_PACKAGE_5_ID : LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_5_TEMP_URL.code == this.updateStrategy ?
  140 + FW_PACKAGE_URI_ID : FW_PACKAGE_19_ID;
122 141 this.pathStateId = FW_STATE_ID;
123 142 this.pathResultId = FW_RESULT_ID;
124 143 this.pathNameId = FW_NAME_ID;
125   - this.pathVerId = FW_VER_ID;
  144 + this.pathVerId = FW_5_VER_ID;
126 145 this.pathInstallId = FW_UPDATE_ID;
127 146 this.wUpdate = FW_UPDATE;
128 147 } else if (SOFTWARE.equals(this.type)) {
... ... @@ -143,13 +162,13 @@ public class LwM2mFwSwUpdate {
143 162 }
144 163 if (this.pendingInfoRequestsStart.size() == 0) {
145 164 this.infoFwSwUpdate = false;
146   - if (!OtaPackageUpdateStatus.DOWNLOADING.name().equals(this.stateUpdate)) {
147   - boolean conditionalStart = this.type.equals(FIRMWARE) ? this.conditionalFwUpdateStart() :
148   - this.conditionalSwUpdateStart();
149   - if (conditionalStart) {
150   - this.writeFwSwWare(handler, request);
151   - }
  165 +// if (!FAILED.name().equals(this.stateUpdate)) {
  166 + boolean conditionalStart = this.type.equals(FIRMWARE) ? this.conditionalFwUpdateStart(handler) :
  167 + this.conditionalSwUpdateStart(handler);
  168 + if (conditionalStart) {
  169 + this.writeFwSwWare(handler, request);
152 170 }
  171 +// }
153 172 }
154 173 }
155 174
... ... @@ -159,32 +178,44 @@ public class LwM2mFwSwUpdate {
159 178 */
160 179 public void writeFwSwWare(DefaultLwM2MTransportMsgHandler handler, LwM2mTransportRequest request) {
161 180 if (this.currentId != null) {
162   - this.stateUpdate = OtaPackageUpdateStatus.DOWNLOADING.name();
  181 + this.stateUpdate = OtaPackageUpdateStatus.INITIATED.name();
163 182 this.sendLogs(handler, WRITE_REPLACE.name(), LOG_LW2M_INFO, null);
164   - int chunkSize = 0;
165   - int chunk = 0;
166   - byte[] firmwareChunk = handler.otaPackageDataCache.get(this.currentId.toString(), chunkSize, chunk);
167 183 String targetIdVer = convertPathFromObjectIdToIdVer(this.pathPackageId, this.lwM2MClient.getRegistration());
168 184 String fwMsg = String.format("%s: Start type operation %s paths: %s", LOG_LW2M_INFO,
169   - LwM2mTransportUtil.LwM2mTypeOper.FW_UPDATE.name(), FW_PACKAGE_ID);
170   - handler.sendLogsToThingsboard(lwM2MClient, fwMsg);
  185 + LwM2mTransportUtil.LwM2mTypeOper.FW_UPDATE.name(), this.pathPackageId);
  186 + handler.sendLogsToThingsboard(fwMsg, lwM2MClient.getRegistration().getId());
171 187 log.warn("8) Start firmware Update. Send save to: [{}] ver: [{}] path: [{}]", this.lwM2MClient.getDeviceName(), this.currentVersion, targetIdVer);
172   - request.sendAllRequest(this.lwM2MClient, targetIdVer, WRITE_REPLACE, ContentFormat.OPAQUE,
173   - firmwareChunk, handler.config.getTimeout(), this.rpcRequest);
174   - }
175   - else {
  188 + if (LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_5_BINARY.code == this.updateStrategy) {
  189 + int chunkSize = 0;
  190 + int chunk = 0;
  191 + byte[] firmwareChunk = handler.otaPackageDataCache.get(this.currentId.toString(), chunkSize, chunk);
  192 + request.sendAllRequest(this.lwM2MClient, targetIdVer, WRITE_REPLACE, ContentFormat.OPAQUE,
  193 + firmwareChunk, handler.config.getTimeout(), this.rpcRequest);
  194 + } else if (LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_5_TEMP_URL.code == this.updateStrategy) {
  195 + Registration registration = this.getLwM2MClient().getRegistration();
  196 +// String api = handler.config.getHostRequests();
  197 + String api = "0.0.0.0";
  198 + int port = registration.getIdentity().isSecure() ? handler.config.getSecurePort() : handler.config.getPort();
  199 + String uri = "coap://" + api + ":" + Integer.valueOf(port) + "/" + FIRMWARE_UPDATE_COAP_RECOURSE + "/" + this.currentId.toString();
  200 + log.warn("89) coapUri: [{}]", uri);
  201 + request.sendAllRequest(this.lwM2MClient, targetIdVer, WRITE_REPLACE, null,
  202 + uri, handler.config.getTimeout(), this.rpcRequest);
  203 + } else if (LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_19_BINARY.code == this.updateStrategy) {
  204 +
  205 + }
  206 + } else {
176 207 String msgError = "FirmWareId is null.";
177 208 log.warn("6) [{}]", msgError);
178 209 if (this.rpcRequest != null) {
179 210 handler.sentRpcResponse(this.rpcRequest, CONTENT.name(), msgError, LOG_LW2M_ERROR);
180 211 }
181   - log.error (msgError);
  212 + log.error(msgError);
182 213 this.sendLogs(handler, WRITE_REPLACE.name(), LOG_LW2M_ERROR, msgError);
183 214 }
184 215 }
185 216
186 217 public void sendLogs(DefaultLwM2MTransportMsgHandler handler, String typeOper, String typeInfo, String msgError) {
187   - this.sendSateOnThingsBoard(handler);
  218 +// this.sendSateOnThingsBoard(handler);
188 219 String msg = String.format("%s: %s, %s, pkgVer: %s: pkgName - %s state - %s.",
189 220 typeInfo, this.wUpdate, typeOper, this.currentVersion, this.currentTitle, this.stateUpdate);
190 221 if (LOG_LW2M_ERROR.equals(typeInfo)) {
... ... @@ -200,31 +231,49 @@ public class LwM2mFwSwUpdate {
200 231 * send execute
201 232 */
202 233 public void executeFwSwWare(DefaultLwM2MTransportMsgHandler handler, LwM2mTransportRequest request) {
203   - this.setStateUpdate(UPDATING.name());
204 234 this.sendLogs(handler, EXECUTE.name(), LOG_LW2M_INFO, null);
205 235 request.sendAllRequest(this.lwM2MClient, this.pathInstallId, EXECUTE, null, 0, this.rpcRequest);
206 236 }
207 237
208 238 /**
209   - * Firmware start:
  239 + * Firmware start: Check if the version has changed and launch a new update.
  240 + * -ObjectId 5, Binary or ObjectId 5, URI
210 241 * -- If the result of the update - errors (more than 1) - This means that the previous. the update failed.
211 242 * - We launch the update regardless of the state of the firmware and its version.
212   - * -- If the result of the update is not errors (equal to 1 or 0) and ver is not empty - This means that before the update has passed.
213   - * -- If the result of the update is not errors and is empty - This means that there has not been an update yet.
214   - * - Check if the version has changed and launch a new update.
  243 + * -- If the result of the update - errors (more than 1) - This means that the previous. the update failed.
  244 + * * ObjectId 5, Binary
  245 + * -- If the result of the update is not errors (equal to 1 or 0) and ver in Object 5 is not empty - it means that the previous update has passed.
  246 + * Compare current versions by equals.
  247 + * * ObjectId 5, URI
  248 + * -- If the result of the update is not errors (equal to 1 or 0) and ver in Object 5 is not empty - it means that the previous update has passed.
  249 + * Compare current versions by contains.
215 250 */
216   - private boolean conditionalFwUpdateStart() {
  251 + private boolean conditionalFwUpdateStart(DefaultLwM2MTransportMsgHandler handler) {
217 252 Long updateResultFw = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId);
  253 + String ver5 = (String) this.lwM2MClient.getResourceValue(null, this.pathVerId);
  254 + String pathName = (String) this.lwM2MClient.getResourceValue(null, this.pathNameId);
  255 + String ver3 = (String) this.lwM2MClient.getResourceValue(null, FW_3_VER_ID);
218 256 // #1/#2
219   - return updateResultFw > LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.code ||
220   - (
221   - (updateResultFw <= LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.code
222   - ) &&
223   - (
224   - (this.currentVersion != null && !this.currentVersion.equals(this.lwM2MClient.getResourceValue(null, this.pathVerId))) ||
225   - (this.currentTitle != null && !this.currentTitle.equals(this.lwM2MClient.getResourceValue(null, this.pathNameId)))
226   - )
227   - );
  257 + String fwMsg = null;
  258 + if ((this.currentVersion != null && (
  259 + ver5 != null && ver5.equals(this.currentVersion) ||
  260 + ver3 != null && ver3.contains(this.currentVersion)
  261 + )) ||
  262 + (this.currentTitle != null && pathName != null && this.currentTitle.equals(pathName))) {
  263 + fwMsg = String.format("%s: The update was interrupted. The device has the same version: %s.", LOG_LW2M_ERROR,
  264 + this.currentVersion);
  265 + }
  266 + else if (updateResultFw != null && updateResultFw > LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.code) {
  267 + fwMsg = String.format("%s: The update was interrupted. The device has the status UpdateResult: error (%d).", LOG_LW2M_ERROR,
  268 + updateResultFw);
  269 + }
  270 + if (fwMsg != null) {
  271 + handler.sendLogsToThingsboard(fwMsg, lwM2MClient.getRegistration().getId());
  272 + return false;
  273 + }
  274 + else {
  275 + return true;
  276 + }
228 277 }
229 278
230 279
... ... @@ -248,7 +297,7 @@ public class LwM2mFwSwUpdate {
248 297
249 298 /**
250 299 * After operation Execute success inspection Update Result :
251   - * > 1 error: "Firmware updated successfully"
  300 + * > 1 error: "Firmware updated successfully"
252 301 */
253 302 public boolean conditionalFwExecuteAfterError() {
254 303 Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId);
... ... @@ -264,7 +313,7 @@ public class LwM2mFwSwUpdate {
264 313 * - If Update Result is not errors and ver is not empty - This means that before unInstall update
265 314 * * - Check if the version has changed and launch a new update.
266 315 */
267   - private boolean conditionalSwUpdateStart() {
  316 + private boolean conditionalSwUpdateStart(DefaultLwM2MTransportMsgHandler handler) {
268 317 Long updateResultSw = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId);
269 318 // #1/#2
270 319 return updateResultSw >= LwM2mTransportUtil.UpdateResultSw.NOT_ENOUGH_STORAGE.code ||
... ... @@ -292,7 +341,7 @@ public class LwM2mFwSwUpdate {
292 341 * -- inspection Update Result:
293 342 * ---- FW если Update Result == 1 ("Firmware updated successfully") или SW если Update Result == 2 ("Software successfully installed.")
294 343 * -- fw_state/sw_state = UPDATED
295   - *
  344 + * <p>
296 345 * After finish operation Execute (error):
297 346 * -- inspection updateResult and send to thingsboard info about error
298 347 * --- send to telemetry ( key - this is name Update Result in model) (
... ... @@ -325,7 +374,7 @@ public class LwM2mFwSwUpdate {
325 374
326 375 /**
327 376 * After operation Execute success inspection Update Result :
328   - * >= 50 - error "NOT_ENOUGH_STORAGE"
  377 + * >= 50 - error "NOT_ENOUGH_STORAGE"
329 378 */
330 379 public boolean conditionalSwExecuteAfterError() {
331 380 Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId);
... ... @@ -355,16 +404,74 @@ public class LwM2mFwSwUpdate {
355 404 public void sendReadObserveInfo(LwM2mTransportRequest request) {
356 405 this.infoFwSwUpdate = true;
357 406 this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer(
358   - this.pathVerId, this.lwM2MClient.getRegistration()));
359   - this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer(
360   - this.pathNameId, this.lwM2MClient.getRegistration()));
361   - this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer(
362 407 this.pathStateId, this.lwM2MClient.getRegistration()));
363 408 this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer(
364 409 this.pathResultId, this.lwM2MClient.getRegistration()));
  410 + this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer(
  411 + FW_3_VER_ID, this.lwM2MClient.getRegistration()));
  412 + if (LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_5_BINARY.code == this.updateStrategy ||
  413 + LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_19_BINARY.code == this.updateStrategy ||
  414 + SOFTWARE.equals(this.type)) {
  415 + this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer(
  416 + this.pathVerId, this.lwM2MClient.getRegistration()));
  417 + this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer(
  418 + this.pathNameId, this.lwM2MClient.getRegistration()));
  419 + }
365 420 this.pendingInfoRequestsStart.forEach(pathIdVer -> {
366 421 request.sendAllRequest(this.lwM2MClient, pathIdVer, OBSERVE, null, 0, this.rpcRequest);
367 422 });
368 423
369 424 }
  425 +
  426 + /**
  427 + * Before operation Execute (FwUpdate) inspection Update Result :
  428 + * - after finished operation Write result: success (FwUpdate): fw_state = DOWNLOADED
  429 + * - before start operation Execute (FwUpdate) Update Result = 0 - Initial value
  430 + * - start Execute (FwUpdate)
  431 + * After finished operation Execute (FwUpdate) inspection Update Result :
  432 + * - after start operation Execute (FwUpdate): fw_state = UPDATING
  433 + * - after success finished operation Execute (FwUpdate) Update Result == 1 ("Firmware updated successfully")
  434 + * - finished operation Execute (FwUpdate)
  435 + */
  436 + public void updateStateOta(DefaultLwM2MTransportMsgHandler handler, LwM2mTransportRequest request,
  437 + Registration registration, String path, int value) {
  438 + if (OBJ_5_BINARY.code == this.getUpdateStrategy()) {
  439 + if ((convertPathFromObjectIdToIdVer(FW_RESULT_ID, registration).equals(path))) {
  440 + if (DOWNLOADED.name().equals(this.getStateUpdate())
  441 + && this.conditionalFwExecuteStart()) {
  442 + this.executeFwSwWare(handler, request);
  443 + } else if (UPDATING.name().equals(this.getStateUpdate())
  444 + && this.conditionalFwExecuteAfterSuccess()) {
  445 + this.finishFwSwUpdate(handler, true);
  446 + } else if (UPDATING.name().equals(this.getStateUpdate())
  447 + && this.conditionalFwExecuteAfterError()) {
  448 + this.finishFwSwUpdate(handler, false);
  449 + }
  450 + }
  451 + } else if (OBJ_5_TEMP_URL.code == this.getUpdateStrategy()) {
  452 + if (this.currentId != null && (convertPathFromObjectIdToIdVer(FW_STATE_ID, registration).equals(path))) {
  453 + String state = equalsFwSateToFirmwareUpdateStatus(LwM2mTransportUtil.StateFw.fromStateFwByCode(value)).name();
  454 + if (StringUtils.isNotEmpty(state) && !FAILED.name().equals(this.stateUpdate) && !state.equals(this.stateUpdate)) {
  455 + this.stateUpdate = state;
  456 + this.sendSateOnThingsBoard(handler);
  457 + }
  458 + if (value == LwM2mTransportUtil.StateFw.DOWNLOADED.code) {
  459 + this.executeFwSwWare(handler, request);
  460 + }
  461 + handler.firmwareUpdateState.put(lwM2MClient.getEndpoint(), value);
  462 + }
  463 + if ((convertPathFromObjectIdToIdVer(FW_RESULT_ID, registration).equals(path))) {
  464 + if (this.currentId != null && value == LwM2mTransportUtil.UpdateResultFw.INITIAL.code) {
  465 + this.setStateUpdate(INITIATED.name());
  466 + } else if (this.currentId != null && value == LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.code) {
  467 + this.setStateUpdate(UPDATED.name());
  468 + } else if (value > LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.code) {
  469 + this.setStateUpdate(FAILED.name());
  470 + }
  471 + this.sendSateOnThingsBoard(handler);
  472 + }
  473 + } else if (OBJ_19_BINARY.code == this.getUpdateStrategy()) {
  474 +
  475 + }
  476 + }
370 477 }
... ...
... ... @@ -259,8 +259,10 @@ public class GatewaySessionHandler {
259 259 transportService.process(TransportProtos.TransportToDeviceActorMsg.newBuilder()
260 260 .setSessionInfo(deviceSessionInfo)
261 261 .setSessionEvent(DefaultTransportService.getSessionEventMsg(TransportProtos.SessionEvent.OPEN))
262   - .setSubscribeToAttributes(TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build())
263   - .setSubscribeToRPC(TransportProtos.SubscribeToRPCMsg.newBuilder().build())
  262 + .setSubscribeToAttributes(TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder()
  263 + .setSessionType(TransportProtos.SessionType.ASYNC).build())
  264 + .setSubscribeToRPC(TransportProtos.SubscribeToRPCMsg.newBuilder()
  265 + .setSessionType(TransportProtos.SessionType.ASYNC).build())
264 266 .build(), null);
265 267 }
266 268 futureToSet.set(devices.get(deviceName));
... ...
... ... @@ -114,13 +114,14 @@ transport:
114 114 private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED:308193020100301306072a8648ce3d020106082a8648ce3d030107047930770201010420dc774b309e547ceb48fee547e104ce201a9c48c449dc5414cd04e7f5cf05f67ba00a06082a8648ce3d030107a1440342000405064b9e6762dd8d8b8a52355d7b4d8b9a3d64e6d2ee277d76c248861353f3585eeb1838e4f9e37b31fa347aef5ce3431eb54e0a2506910c5e0298817445721b}"
115 115 # Only Certificate_x509:
116 116 alias: "${LWM2M_KEYSTORE_ALIAS_SERVER:server}"
  117 + skip_validity_check_for_client_cert: "${TB_LWM2M_SERVER_SECURITY_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}"
117 118 bootstrap:
118 119 enable: "${LWM2M_ENABLED_BS:true}"
119 120 id: "${LWM2M_SERVER_ID_BS:111}"
120 121 bind_address: "${LWM2M_BIND_ADDRESS_BS:0.0.0.0}"
121 122 bind_port: "${LWM2M_BIND_PORT_BS:5687}"
122 123 security:
123   - bind_address: "${LWM2M_BIND_ADDRESS_BS:0.0.0.0}"
  124 + bind_address: "${LWM2M_BIND_ADDRESS_SECURITY_BS:0.0.0.0}"
124 125 bind_port: "${LWM2M_BIND_PORT_SECURITY_BS:5688}"
125 126 # Only for RPK: Public & Private Key. If the keystore file is missing or not working
126 127 public_x: "${LWM2M_SERVER_PUBLIC_X_BS:5017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f91}"
... ...
... ... @@ -15,112 +15,123 @@
15 15 limitations under the License.
16 16
17 17 -->
18   -<section style="padding-bottom: 16px; margin: 0">
  18 +<section style="padding-bottom: 16px; margin: 0" mat-dialog-content>
19 19 <mat-tab-group dynamicHeight>
20 20 <mat-tab label="{{ 'device-profile.lwm2m.model-tab' | translate }}">
21 21 <ng-template matTabContent>
22 22 <section [formGroup]="lwm2mDeviceProfileFormGroup">
23   - <div *ngIf="false" class="mat-padding" style="padding-bottom: 0">
24   - <mat-form-field class="mat-block">
25   - <mat-label>{{ 'device-profile.lwm2m.client-only-observe-after-connect-label' | translate }}</mat-label>
26   - <mat-select formControlName="clientOnlyObserveAfterConnect"
27   - matTooltip="{{ 'device-profile.lwm2m.client-only-observe-after-connect-tip' | translate:
28   - { count: +lwm2mDeviceProfileFormGroup.get('clientOnlyObserveAfterConnect').value } }}"
29   - matTooltipPosition="above">
30   - <mat-option value=1>{{ 'device-profile.lwm2m.client-only-observe-after-connect' | translate:
31   - {count: 1} }}</mat-option>
32   - <mat-option value=2>{{ 'device-profile.lwm2m.client-only-observe-after-connect' | translate:
33   - {count: 2} }}</mat-option>
34   - </mat-select>
35   - </mat-form-field>
  23 + <div class="mat-padding" style="padding-top: 0">
  24 + <tb-profile-lwm2m-object-list
  25 + (addList)="addObjectsList($event)"
  26 + (removeList)="removeObjectsList($event)"
  27 + [required]="required"
  28 + formControlName="objectIds">
  29 + </tb-profile-lwm2m-object-list>
  30 + </div>
  31 + <div class="mat-padding">
  32 + <tb-profile-lwm2m-observe-attr-telemetry
  33 + [required]="required"
  34 + formControlName="observeAttrTelemetry">
  35 + </tb-profile-lwm2m-observe-attr-telemetry>
36 36 </div>
37   - <tb-profile-lwm2m-object-list
38   - (addList)="addObjectsList($event)"
39   - (removeList)="removeObjectsList($event)"
40   - [required]="required"
41   - formControlName="objectIds">
42   - </tb-profile-lwm2m-object-list>
43   - <tb-profile-lwm2m-observe-attr-telemetry
44   - [required]="required"
45   - formControlName="observeAttrTelemetry">
46   - </tb-profile-lwm2m-observe-attr-telemetry>
47 37 </section>
48 38 </ng-template>
49 39 </mat-tab>
50   - <mat-tab label="{{ 'device-profile.lwm2m.servers' | translate }}">
  40 + <mat-tab label="{{ 'device-profile.lwm2m.bootstrap-tab' | translate }}">
51 41 <ng-template matTabContent>
52 42 <section [formGroup]="lwm2mDeviceProfileFormGroup">
53 43 <div class="mat-padding">
54 44 <mat-accordion multi="true" class="mat-body-1">
55 45 <mat-expansion-panel>
56 46 <mat-expansion-panel-header>
57   - <mat-panel-title>{{ 'device-profile.lwm2m.servers' | translate }}</mat-panel-title>
  47 + <mat-panel-title>
  48 + <div class="tb-panel-title">{{ 'device-profile.lwm2m.servers' | translate | uppercase }}</div>
  49 + </mat-panel-title>
58 50 </mat-expansion-panel-header>
59 51 <ng-template matExpansionPanelContent>
60   - <div fxLayout="row" fxLayout.xs="column" fxLayoutGap="8px" fxLayoutGap.xs="0px">
61   - <mat-form-field fxFlex>
62   - <mat-label>{{ 'device-profile.lwm2m.short-id' | translate }}</mat-label>
63   - <input matInput type="number" formControlName="shortId" required>
64   - <mat-error *ngIf="lwm2mDeviceProfileFormGroup.get('shortId').hasError('required')">
65   - {{ 'device-profile.lwm2m.short-id' | translate }}
66   - <strong>{{ 'device-profile.lwm2m.required' | translate }}</strong>
67   - </mat-error>
68   - </mat-form-field>
69   - <mat-form-field fxFlex>
70   - <mat-label>{{ 'device-profile.lwm2m.lifetime' | translate }}</mat-label>
71   - <input matInput type="number" formControlName="lifetime" required>
72   - <mat-error
73   - *ngIf="lwm2mDeviceProfileFormGroup.get('lifetime').hasError('required')">
74   - {{ 'device-profile.lwm2m.lifetime' | translate }}
75   - <strong>{{ 'device-profile.lwm2m.required' | translate }}</strong>
76   - </mat-error>
77   - </mat-form-field>
78   - <mat-form-field fxFlex>
79   - <mat-label>{{ 'device-profile.lwm2m.default-min-period' | translate }}</mat-label>
80   - <input matInput type="number" formControlName="defaultMinPeriod" required>
81   - <mat-error
82   - *ngIf="lwm2mDeviceProfileFormGroup.get('defaultMinPeriod').hasError('required')">
83   - {{ 'device-profile.lwm2m.default-min-period' | translate }}
84   - <strong>{{ 'device-profile.lwm2m.required' | translate }}</strong>
85   - </mat-error>
86   - </mat-form-field>
  52 + <div fxLayout="column">
  53 + <div fxLayout="row" fxLayoutGap="8px">
  54 + <mat-form-field fxFlex>
  55 + <mat-label>{{ 'device-profile.lwm2m.short-id' | translate }}</mat-label>
  56 + <input matInput type="number" formControlName="shortId" required>
  57 + <mat-error *ngIf="lwm2mDeviceProfileFormGroup.get('shortId').hasError('required')">
  58 + {{ 'device-profile.lwm2m.short-id' | translate }}
  59 + <strong>{{ 'device-profile.lwm2m.required' | translate }}</strong>
  60 + </mat-error>
  61 + </mat-form-field>
  62 + <mat-form-field fxFlex>
  63 + <mat-label>{{ 'device-profile.lwm2m.lifetime' | translate }}</mat-label>
  64 + <input matInput type="number" formControlName="lifetime" required>
  65 + <mat-error
  66 + *ngIf="lwm2mDeviceProfileFormGroup.get('lifetime').hasError('required')">
  67 + {{ 'device-profile.lwm2m.lifetime' | translate }}
  68 + <strong>{{ 'device-profile.lwm2m.required' | translate }}</strong>
  69 + </mat-error>
  70 + </mat-form-field>
  71 + <mat-form-field fxFlex>
  72 + <mat-label>{{ 'device-profile.lwm2m.default-min-period' | translate }}</mat-label>
  73 + <input matInput type="number" formControlName="defaultMinPeriod" required>
  74 + <mat-error
  75 + *ngIf="lwm2mDeviceProfileFormGroup.get('defaultMinPeriod').hasError('required')">
  76 + {{ 'device-profile.lwm2m.default-min-period' | translate }}
  77 + <strong>{{ 'device-profile.lwm2m.required' | translate }}</strong>
  78 + </mat-error>
  79 + </mat-form-field>
  80 + </div>
  81 + <div fxLayout="row" fxLayoutGap="8px">
  82 + <mat-form-field class="mat-block" fxFlex="100">
  83 + <mat-label>{{ 'device-profile.lwm2m.binding' | translate }}</mat-label>
  84 + <mat-select formControlName="binding">
  85 + <mat-option *ngFor="let bindingMode of bindingModeTypes"
  86 + [value]="bindingMode">
  87 + {{ bindingModeTypeNamesMap.get(bindingModeType[bindingMode]) }}
  88 + </mat-option>
  89 + </mat-select>
  90 + </mat-form-field>
  91 + </div>
  92 + <div>
  93 + <mat-checkbox formControlName="notifIfDisabled" color="primary">
  94 + {{ 'device-profile.lwm2m.notif-if-disabled' | translate }}
  95 + </mat-checkbox>
  96 + </div>
87 97 </div>
88   - <mat-form-field class="mat-block">
89   - <mat-label>{{ 'device-profile.lwm2m.binding' | translate }}</mat-label>
90   - <mat-select formControlName="binding">
91   - <mat-option *ngFor="let bindingMode of bindingModeTypes"
92   - [value]="bindingMode">
93   - {{ bindingModeTypeNamesMap.get(bindingModeType[bindingMode]) }}
94   - </mat-option>
95   - </mat-select>
96   - </mat-form-field>
97   - <mat-checkbox formControlName="notifIfDisabled" color="primary">
98   - {{ 'device-profile.lwm2m.notif-if-disabled' | translate }}
99   - </mat-checkbox>
100 98 </ng-template>
101 99 </mat-expansion-panel>
  100 + </mat-accordion>
  101 + <mat-accordion multi="true" class="mat-body-1">
102 102 <mat-expansion-panel>
103 103 <mat-expansion-panel-header>
104   - <mat-panel-title>{{ 'device-profile.lwm2m.bootstrap-server' | translate }}</mat-panel-title>
  104 + <mat-panel-title>
  105 + <div
  106 + class="tb-panel-title">{{ 'device-profile.lwm2m.bootstrap-server' | translate | uppercase }}</div>
  107 + </mat-panel-title>
105 108 </mat-expansion-panel-header>
106 109 <ng-template matExpansionPanelContent>
107   - <tb-profile-lwm2m-device-config-server
108   - [required]="required"
109   - formControlName="bootstrapServer"
110   - [bootstrapServerIs]=true>
111   - </tb-profile-lwm2m-device-config-server>
  110 + <div class="mat-padding">
  111 + <tb-profile-lwm2m-device-config-server
  112 + [required]="required"
  113 + formControlName="bootstrapServer"
  114 + [bootstrapServerIs]=true>
  115 + </tb-profile-lwm2m-device-config-server>
  116 + </div>
112 117 </ng-template>
113 118 </mat-expansion-panel>
  119 + </mat-accordion>
  120 + <mat-accordion multi="true" class="mat-body-1">
114 121 <mat-expansion-panel>
115 122 <mat-expansion-panel-header>
116   - <mat-panel-title>{{ 'device-profile.lwm2m.lwm2m-server' | translate }}</mat-panel-title>
  123 + <mat-panel-title>
  124 + <div class="tb-panel-title">{{ 'device-profile.lwm2m.lwm2m-server' | translate | uppercase }}</div>
  125 + </mat-panel-title>
117 126 </mat-expansion-panel-header>
118 127 <ng-template matExpansionPanelContent>
119   - <tb-profile-lwm2m-device-config-server
120   - [required]="required"
121   - formControlName="lwm2mServer"
122   - [bootstrapServerIs]=false>
123   - </tb-profile-lwm2m-device-config-server>
  128 + <div class="mat-padding">
  129 + <tb-profile-lwm2m-device-config-server
  130 + [required]="required"
  131 + formControlName="lwm2mServer"
  132 + [bootstrapServerIs]=false>
  133 + </tb-profile-lwm2m-device-config-server>
  134 + </div>
124 135 </ng-template>
125 136 </mat-expansion-panel>
126 137 </mat-accordion>
... ... @@ -128,6 +139,48 @@
128 139 </section>
129 140 </ng-template>
130 141 </mat-tab>
  142 + <mat-tab label="{{ 'device-profile.lwm2m.others-tab' | translate }}">
  143 + <ng-template matTabContent>
  144 + <section [formGroup]="lwm2mDeviceProfileFormGroup">
  145 + <div *ngIf="false" class="mat-padding" style="padding-bottom: 0px">
  146 + <mat-form-field class="mat-block">
  147 + <mat-label>{{ 'device-profile.lwm2m.client-strategy-label' | translate }}</mat-label>
  148 + <mat-select formControlName="clientStrategy"
  149 + matTooltip="{{ 'device-profile.lwm2m.client-strategy-tip' | translate:
  150 + { count: +lwm2mDeviceProfileFormGroup.get('clientStrategy').value } }}"
  151 + matTooltipPosition="above">
  152 + <mat-option value=1>{{ 'device-profile.lwm2m.client-strategy' | translate:
  153 + {count: 1} }}</mat-option>
  154 + <mat-option value=2>{{ 'device-profile.lwm2m.client-strategy' | translate:
  155 + {count: 2} }}</mat-option>
  156 + </mat-select>
  157 + </mat-form-field>
  158 + </div>
  159 + <div class="mat-padding" style="padding-bottom: 0px">
  160 + <mat-form-field class="mat-block">
  161 + <mat-label>{{ 'device-profile.lwm2m.fw-update-strategy-label' | translate }}</mat-label>
  162 + <mat-select formControlName="fwUpdateStrategy">
  163 + <mat-option value=1>{{ 'device-profile.lwm2m.fw-update-strategy' | translate:
  164 + {count: 1} }}</mat-option>
  165 + <mat-option value=2>{{ 'device-profile.lwm2m.fw-update-strategy' | translate:
  166 + {count: 2} }}</mat-option>
  167 + <mat-option value=2>{{ 'device-profile.lwm2m.fw-update-strategy' | translate:
  168 + {count: 3} }}</mat-option>
  169 + </mat-select>
  170 + </mat-form-field>
  171 + <mat-form-field class="mat-block">
  172 + <mat-label>{{ 'device-profile.lwm2m.sw-update-strategy-label' | translate }}</mat-label>
  173 + <mat-select formControlName="swUpdateStrategy">
  174 + <mat-option value=1>{{ 'device-profile.lwm2m.sw-update-strategy' | translate:
  175 + {count: 1} }}</mat-option>
  176 + <mat-option value=2>{{ 'device-profile.lwm2m.sw-update-strategy' | translate:
  177 + {count: 2} }}</mat-option>
  178 + </mat-select>
  179 + </mat-form-field>
  180 + </div>
  181 + </section>
  182 + </ng-template>
  183 + </mat-tab>
131 184 <mat-tab label="{{ 'device-profile.lwm2m.config-json-tab' | translate }}">
132 185 <ng-template matTabContent>
133 186 <section [formGroup]="lwm2mDeviceConfigFormGroup" class="mat-padding">
... ...
... ... @@ -83,7 +83,6 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
83 83 constructor(private fb: FormBuilder,
84 84 private deviceProfileService: DeviceProfileService) {
85 85 this.lwm2mDeviceProfileFormGroup = this.fb.group({
86   - clientOnlyObserveAfterConnect: [1, []],
87 86 objectIds: [null, Validators.required],
88 87 observeAttrTelemetry: [null, Validators.required],
89 88 shortId: [null, Validators.required],
... ... @@ -93,6 +92,9 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
93 92 binding: [],
94 93 bootstrapServer: [null, Validators.required],
95 94 lwm2mServer: [null, Validators.required],
  95 + clientStrategy: [1, []],
  96 + fwUpdateStrategy: [1, []],
  97 + swUpdateStrategy: [1, []],
96 98 });
97 99 this.lwm2mDeviceConfigFormGroup = this.fb.group({
98 100 configurationJson: [null, Validators.required]
... ... @@ -168,7 +170,6 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
168 170
169 171 private updateWriteValue = (value: ModelValue): void => {
170 172 this.lwm2mDeviceProfileFormGroup.patchValue({
171   - clientOnlyObserveAfterConnect: this.configurationValue.clientLwM2mSettings.clientOnlyObserveAfterConnect,
172 173 objectIds: value,
173 174 observeAttrTelemetry: this.getObserveAttrTelemetryObjects(value.objectsList),
174 175 shortId: this.configurationValue.bootstrap.servers.shortId,
... ... @@ -177,7 +178,10 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
177 178 notifIfDisabled: this.configurationValue.bootstrap.servers.notifIfDisabled,
178 179 binding: this.configurationValue.bootstrap.servers.binding,
179 180 bootstrapServer: this.configurationValue.bootstrap.bootstrapServer,
180   - lwm2mServer: this.configurationValue.bootstrap.lwm2mServer
  181 + lwm2mServer: this.configurationValue.bootstrap.lwm2mServer,
  182 + clientStrategy: this.configurationValue.clientLwM2mSettings.clientStrategy,
  183 + fwUpdateStrategy: this.configurationValue.clientLwM2mSettings.fwUpdateStrategy,
  184 + swUpdateStrategy: this.configurationValue.clientLwM2mSettings.swUpdateStrategy
181 185 },
182 186 {emitEvent: false});
183 187 }
... ... @@ -199,8 +203,6 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
199 203
200 204 private updateDeviceProfileValue(config): void {
201 205 if (this.lwm2mDeviceProfileFormGroup.valid) {
202   - this.configurationValue.clientLwM2mSettings.clientOnlyObserveAfterConnect =
203   - config.clientOnlyObserveAfterConnect;
204 206 this.updateObserveAttrTelemetryFromGroupToJson(config.observeAttrTelemetry.clientLwM2M);
205 207 this.configurationValue.bootstrap.bootstrapServer = config.bootstrapServer;
206 208 this.configurationValue.bootstrap.lwm2mServer = config.lwm2mServer;
... ... @@ -210,6 +212,9 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
210 212 bootstrapServers.defaultMinPeriod = config.defaultMinPeriod;
211 213 bootstrapServers.notifIfDisabled = config.notifIfDisabled;
212 214 bootstrapServers.binding = config.binding;
  215 + this.configurationValue.clientLwM2mSettings.clientStrategy = config.clientStrategy;
  216 + this.configurationValue.clientLwM2mSettings.fwUpdateStrategy = config.fwUpdateStrategy;
  217 + this.configurationValue.clientLwM2mSettings.swUpdateStrategy = config.swUpdateStrategy;
213 218 this.upDateJsonAllConfig();
214 219 this.updateModel();
215 220 }
... ...
... ... @@ -165,7 +165,9 @@ export interface Lwm2mProfileConfigModels {
165 165 }
166 166
167 167 export interface ClientLwM2mSettings {
168   - clientOnlyObserveAfterConnect: number;
  168 + clientStrategy: string;
  169 + fwUpdateStrategy: string;
  170 + swUpdateStrategy: string;
169 171 }
170 172
171 173 export interface ObservableAttributes {
... ... @@ -235,7 +237,9 @@ export function getDefaultProfileConfig(hostname?: any): Lwm2mProfileConfigModel
235 237
236 238 function getDefaultProfileClientLwM2mSettingsConfig(): ClientLwM2mSettings {
237 239 return {
238   - clientOnlyObserveAfterConnect: 1
  240 + clientStrategy: "1",
  241 + fwUpdateStrategy: "1",
  242 + swUpdateStrategy: "1"
239 243 };
240 244 }
241 245
... ...
... ... @@ -1192,9 +1192,6 @@
1192 1192 "device-profile-file": "Device profile file",
1193 1193 "invalid-device-profile-file-error": "Unable to import device profile: Invalid device profile data structure.",
1194 1194 "lwm2m": {
1195   - "client-only-observe-after-connect-label": "Strategy",
1196   - "client-only-observe-after-connect": "{ count, plural, 1 {1: Only Observe Request to the client after the initial connection} other {2: Read All Resources & Observe Request to the client after registration} }",
1197   - "client-only-observe-after-connect-tip": "{ count, plural, 1 {Strategy 1: After the initial connection of the LWM2M Client, the server sends Observe resources Request to the client, those resources that are marked as observation in the Device profile and which exist on the LWM2M client.} other {Strategy 2: After the registration, request the client to read all the resource values for all objects that the LWM2M client has,\n then execute: the server sends Observe resources Request to the client, those resources that are marked as observation in the Device profile and which exist on the LWM2M client.} }",
1198 1195 "object-list": "Object list",
1199 1196 "object-list-empty": "No objects selected.",
1200 1197 "no-objects-matching": "No objects matching '{{object}}' were found.",
... ... @@ -1242,6 +1239,7 @@
1242 1239 "default-min-period": "Minimum Period between two notifications (sec)",
1243 1240 "notif-if-disabled": "Notification Storing When Disabled or Offline",
1244 1241 "binding": "Binding",
  1242 + "bootstrap-tab": "Bootstrap",
1245 1243 "bootstrap-server": "Bootstrap Server",
1246 1244 "lwm2m-server": "LwM2M Server",
1247 1245 "server-host": "Host",
... ... @@ -1254,6 +1252,20 @@
1254 1252 "client-hold-off-time-tip": "Client Hold Off Time for use with a Bootstrap-Server only",
1255 1253 "bootstrap-server-account-timeout": "Account after the timeout",
1256 1254 "bootstrap-server-account-timeout-tip": "Bootstrap-Server Account after the timeout value given by this resource.",
  1255 + "others-tab": "Other settings...",
  1256 + "client-strategy-label": "Strategy",
  1257 + "client-strategy-connect": "{ count, plural, 1 {1: Only Observe Request to the client after the initial connection} other {2: Read All Resources & Observe Request to the client after registration} }",
  1258 + "client-strategy-tip": "{ count, plural, 1 {Strategy 1: After the initial connection of the LWM2M Client, the server sends Observe resources Request to the client, those resources that are marked as observation in the Device profile and which exist on the LWM2M client.} other {Strategy 2: After the registration, request the client to read all the resource values for all objects that the LWM2M client has,\n then execute: the server sends Observe resources Request to the client, those resources that are marked as observation in the Device profile and which exist on the LWM2M client.} }",
  1259 + "ota-update-strategy": "Ota update strategy",
  1260 + "fw-update-strategy-label": "Firmware update strategy",
  1261 + "fw-update-strategy": "{ count, plural, 1 {Push firmware update as binary file using Object 5 and Resource 0 (Package).} 2 {Auto-generate unique CoAP URL to download the package and push firmware update as Object 5 and Resource 1 (Package URI).} other {Push firmware update as binary file using Object 19 and Resource 0 (Data).} }",
  1262 + "sw-update-strategy-label": "Software update strategy",
  1263 + "sw-update-strategy": "{ count, plural, 1 {Push binary file using Object 9 and Resource 2 (Package).} other {Auto-generate unique CoAP URL to download the package and push software update using Object 9 and Resource 3 (Package URI).} }",
  1264 + "blockwise-settings": "Blockwise settings",
  1265 + "blockwise-enabled": "Enable blockwise",
  1266 + "blockwise-status-lifetime": "Blockwise Status Lifetime",
  1267 + "fw-update-recourse": "Firmware update Coap recourse",
  1268 + "sw-update-recourse": "Software update Coap recourse",
1257 1269 "config-json-tab": "Json Config Profile Device"
1258 1270 }
1259 1271 },
... ...