From 6fbd34d6a11d9227932e44fca4e15e7020ee9ec7 Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Sun, 6 Jun 2021 21:46:30 +0300 Subject: [PATCH] LWM2M: firmwareUpdate & coapRecourse --- .../widget_bundles/control_widgets.json | 2 +- .../LwM2MServerSecurityInfoRepository.java | 6 +- .../src/main/resources/thingsboard.yml | 12 +- .../LwM2MTransportBootstrapService.java | 2 +- .../lwm2m/config/LwM2MSecureServerConfig.java | 4 + .../config/LwM2MTransportBootstrapConfig.java | 7 + .../config/LwM2MTransportServerConfig.java | 16 ++ ...va => AbstractLwM2mTransportResource.java} | 4 +- .../DefaultLwM2MTransportMsgHandler.java | 216 ++++++++--------- .../server/DefaultLwM2mTransportService.java | 11 +- .../lwm2m/server/LwM2mNetworkConfig.java | 17 +- .../lwm2m/server/LwM2mOtaConvert.java | 25 ++ .../server/LwM2mTransportCoapResource.java | 75 ++---- .../server/LwM2mTransportMsgHandler.java | 4 +- .../lwm2m/server/LwM2mTransportRequest.java | 42 ++-- .../lwm2m/server/LwM2mTransportUtil.java | 228 +++++++++++++++--- .../lwm2m/server/client/LwM2mClient.java | 17 ++ .../server/client/LwM2mClientProfile.java | 30 ++- ...equest.java => LwM2mClientRpcRequest.java} | 6 +- .../lwm2m/server/client/LwM2mFwSwUpdate.java | 193 +++++++++++---- .../src/main/resources/tb-lwm2m-transport.yml | 20 +- ...ile-transport-configuration.component.html | 30 +-- ...ofile-transport-configuration.component.ts | 18 +- .../lwm2m/lwm2m-profile-config.models.ts | 12 +- .../assets/locale/locale.constant-en_US.json | 14 +- 25 files changed, 676 insertions(+), 335 deletions(-) rename common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/{AbstractLwm2mTransportResource.java => AbstractLwM2mTransportResource.java} (95%) create mode 100644 common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mOtaConvert.java rename common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/{Lwm2mClientRpcRequest.java => LwM2mClientRpcRequest.java} (98%) diff --git a/application/src/main/data/json/system/widget_bundles/control_widgets.json b/application/src/main/data/json/system/widget_bundles/control_widgets.json index cd0d95ef2a..23b0b90ac3 100644 --- a/application/src/main/data/json/system/widget_bundles/control_widgets.json +++ b/application/src/main/data/json/system/widget_bundles/control_widgets.json @@ -18,7 +18,7 @@ "resources": [], "templateHtml": "
", "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", - "controllerScript": "var requestTimeout = 500;\nvar multiParams = false;\nvar useRowStyleFunction = false;\nvar styleObj = {};\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 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 = 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 }\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 += ' [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 += ' [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}", + "controllerScript": "var requestTimeout = 500;\nvar multiParams = false;\nvar useRowStyleFunction = false;\nvar styleObj = {};\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 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 += ' [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 += ' [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}", "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}", "dataKeySettingsSchema": "{}\n", "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\":{}}" diff --git a/application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MServerSecurityInfoRepository.java b/application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MServerSecurityInfoRepository.java index 06190cdf70..e3b09ef044 100644 --- a/application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MServerSecurityInfoRepository.java +++ b/application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MServerSecurityInfoRepository.java @@ -66,18 +66,18 @@ public class LwM2MServerSecurityInfoRepository { bsServ.setServerId(serverConfig.getId()); switch (securityMode) { case NO_SEC: - bsServ.setHost(serverConfig.getHost()); + bsServ.setHost(serverConfig.getHostRequests()); bsServ.setPort(serverConfig.getPort()); bsServ.setServerPublicKey(""); break; case PSK: - bsServ.setHost(serverConfig.getSecureHost()); + bsServ.setHost(serverConfig.getSecureHostRequests()); bsServ.setPort(serverConfig.getSecurePort()); bsServ.setServerPublicKey(""); break; case RPK: case X509: - bsServ.setHost(serverConfig.getSecureHost()); + bsServ.setHost(serverConfig.getSecureHostRequests()); bsServ.setPort(serverConfig.getSecurePort()); bsServ.setServerPublicKey(getPublicKey(serverConfig.getCertificateAlias(), this.serverConfig.getPublicX(), this.serverConfig.getPublicY())); break; diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 78658fe8fd..7925f97e89 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -639,9 +639,13 @@ transport: server: id: "${LWM2M_SERVER_ID:123}" bind_address: "${LWM2M_BIND_ADDRESS:0.0.0.0}" + # the host to receive requests to the server + bind_address_requests: "${LWM2M_BIND_ADDRESS_REQUESTS:0.0.0.0}" bind_port: "${LWM2M_BIND_PORT:5685}" security: bind_address: "${LWM2M_BIND_ADDRESS_SECURITY:0.0.0.0}" + # the security host to receive requests to the server + bind_address_requests: "${LWM2M_BIND_ADDRESS_SECURITY_REQUESTS:0.0.0.0}" bind_port: "${LWM2M_BIND_PORT_SECURITY:5686}" # Only for RPK: Public & Private Key. If the keystore file is missing or not working public_x: "${LWM2M_SERVER_PUBLIC_X:05064b9e6762dd8d8b8a52355d7b4d8b9a3d64e6d2ee277d76c248861353f358}" @@ -654,9 +658,13 @@ transport: enable: "${LWM2M_ENABLED_BS:true}" id: "${LWM2M_SERVER_ID_BS:111}" bind_address: "${LWM2M_BIND_ADDRESS_BS:0.0.0.0}" + # the host to receive requests to the server + bind_address_requests: "${LWM2M_BIND_ADDRESS_REQUESTS_BS:0.0.0.0}" bind_port: "${LWM2M_BIND_PORT_BS:5687}" security: - bind_address: "${LWM2M_BIND_ADDRESS_BS:0.0.0.0}" + bind_address: "${LWM2M_BIND_ADDRESS_SECURITY_BS:0.0.0.0}" + # the security host to receive requests to the server + bind_address_requests: "${LWM2M_BIND_ADDRESS_SECURITY_REQUESTS_BS:0.0.0.0}" bind_port: "${LWM2M_BIND_PORT_SECURITY_BS:5688}" # Only for RPK: Public & Private Key. If the keystore file is missing or not working public_x: "${LWM2M_SERVER_PUBLIC_X_BS:5017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f91}" @@ -675,6 +683,8 @@ transport: root_alias: "${LWM2M_SERVER_ROOT_CA:rootca}" enable_gen_new_key_psk_rpk: "${ENABLE_GEN_NEW_KEY_PSK_RPK:false}" timeout: "${LWM2M_TIMEOUT:120000}" + blockwise_lifetime: "${BLOCKWISE_LIFETIME:300000}" + block2_option_enable: "${BLOCK2_OPTION_ENABLED:true}" recommended_ciphers: "${LWM2M_RECOMMENDED_CIPHERS:false}" recommended_supported_groups: "${LWM2M_RECOMMENDED_SUPPORTED_GROUPS:true}" response_pool_size: "${LWM2M_RESPONSE_POOL_SIZE:100}" diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java index 9348cb31a5..04c2fd62fb 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java @@ -102,7 +102,7 @@ public class LwM2MTransportBootstrapService { builder.setLocalSecureAddress(bootstrapConfig.getSecureHost(), bootstrapConfig.getSecurePort()); /** Create CoAP Config */ - builder.setCoapConfig(getCoapConfig(bootstrapConfig.getPort(), bootstrapConfig.getSecurePort())); + builder.setCoapConfig(getCoapConfig(bootstrapConfig.getPort(), bootstrapConfig.getSecurePort(), serverConfig)); /** Define model provider (Create Models )*/ diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MSecureServerConfig.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MSecureServerConfig.java index fcca9fb975..e30cc01456 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MSecureServerConfig.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MSecureServerConfig.java @@ -21,10 +21,14 @@ public interface LwM2MSecureServerConfig { String getHost(); + String getHostRequests(); + Integer getPort(); String getSecureHost(); + String getSecureHostRequests(); + Integer getSecurePort(); String getPublicX(); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportBootstrapConfig.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportBootstrapConfig.java index c0379f9cee..45b6aa796b 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportBootstrapConfig.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportBootstrapConfig.java @@ -34,6 +34,10 @@ public class LwM2MTransportBootstrapConfig implements LwM2MSecureServerConfig { @Value("${transport.lwm2m.bootstrap.bind_address:}") private String host; + @Getter + @Value("${transport.lwm2m.bootstrap.bind_address_requests:}") + private String hostRequests; + @Getter @Value("${transport.lwm2m.bootstrap.bind_port:}") private Integer port; @@ -42,6 +46,9 @@ public class LwM2MTransportBootstrapConfig implements LwM2MSecureServerConfig { @Value("${transport.lwm2m.bootstrap.security.bind_address:}") private String secureHost; + @Getter + @Value("${transport.lwm2m.bootstrap.security.bind_address_requests:}") + private String secureHostRequests; @Getter @Value("${transport.lwm2m.bootstrap.security.bind_port:}") private Integer securePort; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java index 25c7766895..83601f4047 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java @@ -44,6 +44,14 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig { @Value("${transport.lwm2m.timeout:}") private Long timeout; + @Getter + @Value("${transport.lwm2m.blockwise_lifetime:}") + private Long blockwiseLifetime; + + @Getter + @Value("${transport.lwm2m.block2_option_enable:}") + private boolean block2OptionEnable; + @Getter @Value("${transport.sessions.report_timeout}") private long sessionReportTimeout; @@ -112,6 +120,10 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig { @Value("${transport.lwm2m.server.bind_address:}") private String host; + @Getter + @Value("${transport.lwm2m.server.bind_address_requests:}") + private String hostRequests; + @Getter @Value("${transport.lwm2m.server.bind_port:}") private Integer port; @@ -120,6 +132,10 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig { @Value("${transport.lwm2m.server.security.bind_address:}") private String secureHost; + @Getter + @Value("${transport.lwm2m.server.security.bind_address_requests:}") + private String secureHostRequests; + @Getter @Value("${transport.lwm2m.server.security.bind_port:}") private Integer securePort; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/AbstractLwm2mTransportResource.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/AbstractLwM2mTransportResource.java similarity index 95% rename from common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/AbstractLwm2mTransportResource.java rename to common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/AbstractLwM2mTransportResource.java index 50eb468b17..2c82facd23 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/AbstractLwm2mTransportResource.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/AbstractLwM2mTransportResource.java @@ -23,9 +23,9 @@ import org.eclipse.leshan.core.californium.LwM2mCoapResource; import org.thingsboard.server.common.transport.TransportServiceCallback; @Slf4j -public abstract class AbstractLwm2mTransportResource extends LwM2mCoapResource { +public abstract class AbstractLwM2mTransportResource extends LwM2mCoapResource { - public AbstractLwm2mTransportResource(String name) { + public AbstractLwM2mTransportResource(String name) { super(name); } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2MTransportMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2MTransportMsgHandler.java index 8dc1bd64c9..d82dbcbf08 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2MTransportMsgHandler.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2MTransportMsgHandler.java @@ -61,8 +61,8 @@ import org.thingsboard.server.transport.lwm2m.server.adaptors.LwM2MJsonAdaptor; import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile; +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientRpcRequest; import org.thingsboard.server.transport.lwm2m.server.client.LwM2mFwSwUpdate; -import org.thingsboard.server.transport.lwm2m.server.client.Lwm2mClientRpcRequest; import org.thingsboard.server.transport.lwm2m.server.client.ResourceValue; import org.thingsboard.server.transport.lwm2m.server.client.ResultsAddKeyValueProto; import org.thingsboard.server.transport.lwm2m.server.client.ResultsAnalyzerParameters; @@ -89,18 +89,17 @@ import java.util.stream.Collectors; import static org.eclipse.californium.core.coap.CoAP.ResponseCode.BAD_REQUEST; import static org.eclipse.leshan.core.attributes.Attribute.OBJECT_VERSION; import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH; -import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.DOWNLOADED; -import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDATING; +import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.FAILED; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper.getValueFromKvProto; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.CLIENT_NOT_AUTHORIZED; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.DEVICE_ATTRIBUTES_REQUEST; -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_ID; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_5_ID; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_RESULT_ID; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_STATE_ID; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_ERROR; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_INFO; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_TELEMETRY; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_VALUE; -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LWM2M_STRATEGY_2; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.DISCOVER; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.EXECUTE; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE; @@ -110,8 +109,8 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.L import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_ATTRIBUTES; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_REPLACE; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_ID; -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_RESULT_ID; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertJsonArrayToSet; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertOtaUpdateValueToString; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromIdVerToObjectId; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.getAckCallback; @@ -186,7 +185,9 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler public void onRegistered(Registration registration, Collection previousObservations) { registrationExecutor.submit(() -> { try { - log.warn("[{}] [{{}] Client: create after Registration", registration.getEndpoint(), registration.getId()); + String msgReg = previousObservations != null ? String.format("%s %s Client: create after Registration", registration.getEndpoint(), registration.getId()) : + String.format("%s %s Client: create after UpdateRegistration", registration.getEndpoint(), registration.getId()); + log.warn(msgReg); LwM2mClient lwM2MClient = this.clientContext.registerOrUpdate(registration); if (lwM2MClient != null) { SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(lwM2MClient); @@ -204,7 +205,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler this.getInfoFirmwareUpdate(lwM2MClient, null); this.getInfoSoftwareUpdate(lwM2MClient, null); this.initLwM2mFromClientValue(registration, lwM2MClient); - this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client create after Registration", registration.getId()); + this.sendLogsToThingsboard(LOG_LW2M_INFO + ": " + msgReg, registration.getId()); } else { log.error("Client: [{}] onRegistered [{}] name [{}] sessionInfo ", registration.getId(), registration.getEndpoint(), null); } @@ -223,28 +224,33 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler * @param registration - Registration LwM2M Client */ public void updatedReg(Registration registration) { - updateRegistrationExecutor.submit(() -> { - try { - LwM2mClient client = clientContext.getOrRegister(registration); - if (client != null && client.getSession() != null) { - SessionInfoProto sessionInfo = client.getSession(); - this.reportActivityAndRegister(sessionInfo); - if (registration.getBindingMode().useQueueMode()) { - LwM2mQueuedRequest request; - while ((request = client.getQueuedRequests().poll()) != null) { - request.send(); + try { + LwM2mClient client = clientContext.getOrRegister(registration); + if (client != null) { + updateRegistrationExecutor.submit(() -> { + if (client != null && client.getSession() != null) { + SessionInfoProto sessionInfo = client.getSession(); + this.reportActivityAndRegister(sessionInfo); + if (registration.getBindingMode().useQueueMode()) { + LwM2mQueuedRequest request; + while ((request = client.getQueuedRequests().poll()) != null) { + request.send(); + } } + this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client update Registration", registration.getId()); + } else { + log.error("Client: [{}] updatedReg [{}] name [{}] sessionInfo ", registration.getId(), registration.getEndpoint(), null); + this.sendLogsToThingsboard(LOG_LW2M_ERROR + ": Client update Registration", registration.getId()); } - this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client update Registration", registration.getId()); - } else { - log.error("Client: [{}] updatedReg [{}] name [{}] sessionInfo ", registration.getId(), registration.getEndpoint(), null); - this.sendLogsToThingsboard(LOG_LW2M_ERROR + ": Client update Registration", registration.getId()); - } - } catch (Throwable t) { - log.error("[{}] endpoint [{}] error Unable update registration.", registration.getEndpoint(), t); - this.sendLogsToThingsboard(LOG_LW2M_ERROR + String.format(": Client update Registration, %s", t.getMessage()), registration.getId()); + }); } - }); + else { + this.onRegistered(registration, null); + } + } catch (Throwable t) { + log.error("[{}] endpoint [{}] error Unable update registration.", registration.getEndpoint(), t); + this.sendLogsToThingsboard(LOG_LW2M_ERROR + String.format(": Client update Registration, %s", t.getMessage()), registration.getId()); + } } /** @@ -304,7 +310,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler * @param response - observe */ @Override - public void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response, Lwm2mClientRpcRequest rpcRequest) { + public void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response, LwM2mClientRpcRequest rpcRequest) { if (response.getContent() != null) { LwM2mClient lwM2MClient = clientContext.getOrRegister(registration); ObjectModel objectModelVersion = lwM2MClient.getObjectModel(path, this.config.getModelProvider()); @@ -327,7 +333,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler } private void sendRpcRequestAfterReadResponse(Registration registration, LwM2mClient lwM2MClient, String pathIdVer, ReadResponse response, - Lwm2mClientRpcRequest rpcRequest) { + LwM2mClientRpcRequest rpcRequest) { Object value = null; if (response.getContent() instanceof LwM2mObject) { value = lwM2MClient.objectToString((LwM2mObject) response.getContent(), this.converter, pathIdVer); @@ -457,10 +463,10 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler LwM2mTypeOper lwM2mTypeOper = setValidTypeOper(toDeviceRpcRequestMsg.getMethodName()); if (!this.rpcSubscriptions.containsKey(requestUUID)) { this.rpcSubscriptions.put(requestUUID, toDeviceRpcRequestMsg.getExpirationTime()); - Lwm2mClientRpcRequest lwm2mClientRpcRequest = null; + LwM2mClientRpcRequest lwm2mClientRpcRequest = null; try { Registration registration = clientContext.getClient(sessionInfo).getRegistration(); - lwm2mClientRpcRequest = new Lwm2mClientRpcRequest(lwM2mTypeOper, bodyParams, toDeviceRpcRequestMsg.getRequestId(), sessionInfo, registration, this); + lwm2mClientRpcRequest = new LwM2mClientRpcRequest(lwM2mTypeOper, bodyParams, toDeviceRpcRequestMsg.getRequestId(), sessionInfo, registration, this); if (lwm2mClientRpcRequest.getErrorMsg() != null) { lwm2mClientRpcRequest.setResponseCode(BAD_REQUEST.name()); this.onToDeviceRpcResponse(lwm2mClientRpcRequest.getDeviceRpcResponseResultMsg(), sessionInfo); @@ -472,7 +478,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler } } catch (Exception e) { if (lwm2mClientRpcRequest == null) { - lwm2mClientRpcRequest = new Lwm2mClientRpcRequest(); + lwm2mClientRpcRequest = new LwM2mClientRpcRequest(); } lwm2mClientRpcRequest.setResponseCode(BAD_REQUEST.name()); if (lwm2mClientRpcRequest.getErrorMsg() == null) { @@ -494,7 +500,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler log.warn("4.4) after rpcSubscriptions.size(): [{}]", rpcSubscriptions.size()); } - public void sentRpcResponse(Lwm2mClientRpcRequest rpcRequest, String requestCode, String msg, String typeMsg) { + public void sentRpcResponse(LwM2mClientRpcRequest rpcRequest, String requestCode, String msg, String typeMsg) { rpcRequest.setResponseCode(requestCode); if (LOG_LW2M_ERROR.equals(typeMsg)) { rpcRequest.setInfoMsg(null); @@ -604,7 +610,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler LwM2mClientProfile lwM2MClientProfile = clientContext.getProfile(registration); Set clientObjects = clientContext.getSupportedIdVerInClient(registration); if (clientObjects != null && clientObjects.size() > 0) { - if (LWM2M_STRATEGY_2 == LwM2mTransportUtil.getClientOnlyObserveAfterConnect(lwM2MClientProfile)) { + if (LwM2mTransportUtil.LwM2MClientStrategy.CLIENT_STRATEGY_2.code == lwM2MClientProfile.getClientStrategy()) { // #2 lwM2MClient.getPendingReadRequests().addAll(clientObjects); clientObjects.forEach(path -> lwM2mTransportRequest.sendAllRequest(registration, path, READ, ContentFormat.TLV.getName(), @@ -668,53 +674,11 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler lwM2MClient.getSwUpdate().initReadValue(this, this.lwM2mTransportRequest, path); } - /** - * Before operation Execute (FwUpdate) inspection Update Result : - * - after finished operation Write result: success (FwUpdate): fw_state = DOWNLOADED - * - before start operation Execute (FwUpdate) Update Result = 0 - Initial value - * - start Execute (FwUpdate) - * After finished operation Execute (FwUpdate) inspection Update Result : - * - after start operation Execute (FwUpdate): fw_state = UPDATING - * - after success finished operation Execute (FwUpdate) Update Result == 1 ("Firmware updated successfully") - * - finished operation Execute (FwUpdate) - */ - if (lwM2MClient.getFwUpdate() != null - && (convertPathFromObjectIdToIdVer(FW_RESULT_ID, registration).equals(path))) { - if (DOWNLOADED.name().equals(lwM2MClient.getFwUpdate().getStateUpdate()) - && lwM2MClient.getFwUpdate().conditionalFwExecuteStart()) { - lwM2MClient.getFwUpdate().executeFwSwWare(this, this.lwM2mTransportRequest); - } else if (UPDATING.name().equals(lwM2MClient.getFwUpdate().getStateUpdate()) - && lwM2MClient.getFwUpdate().conditionalFwExecuteAfterSuccess()) { - lwM2MClient.getFwUpdate().finishFwSwUpdate(this, true); - } else if (UPDATING.name().equals(lwM2MClient.getFwUpdate().getStateUpdate()) - && lwM2MClient.getFwUpdate().conditionalFwExecuteAfterError()) { - lwM2MClient.getFwUpdate().finishFwSwUpdate(this, false); - } - } - - /** - * Before operation Execute (SwUpdate) inspection Update Result : - * - after finished operation Write result: success (SwUpdate): fw_state = DOWNLOADED - * - before operation Execute (SwUpdate) Update Result = 3 - Successfully Downloaded and package integrity verified - * - start Execute (SwUpdate) - * After finished operation Execute (SwUpdate) inspection Update Result : - * - after start operation Execute (SwUpdate): fw_state = UPDATING - * - after success finished operation Execute (SwUpdate) Update Result == 2 "Software successfully installed."" - * - after success finished operation Execute (SwUpdate) Update Result == 2 "Software successfully installed."" - * - finished operation Execute (SwUpdate) - */ - if (lwM2MClient.getSwUpdate() != null - && (convertPathFromObjectIdToIdVer(SW_RESULT_ID, registration).equals(path))) { - if (DOWNLOADED.name().equals(lwM2MClient.getSwUpdate().getStateUpdate()) - && lwM2MClient.getSwUpdate().conditionalSwUpdateExecute()) { - lwM2MClient.getSwUpdate().executeFwSwWare(this, this.lwM2mTransportRequest); - } else if (UPDATING.name().equals(lwM2MClient.getSwUpdate().getStateUpdate()) - && lwM2MClient.getSwUpdate().conditionalSwExecuteAfterSuccess()) { - lwM2MClient.getSwUpdate().finishFwSwUpdate(this, true); - } else if (UPDATING.name().equals(lwM2MClient.getSwUpdate().getStateUpdate()) - && lwM2MClient.getSwUpdate().conditionalSwExecuteAfterError()) { - lwM2MClient.getSwUpdate().finishFwSwUpdate(this, false); - } + if ((convertPathFromObjectIdToIdVer(FW_RESULT_ID, registration).equals(path)) || + (convertPathFromObjectIdToIdVer(FW_STATE_ID, registration).equals(path))) { + LwM2mFwSwUpdate fwUpdate = lwM2MClient.getFwUpdate(clientContext); + log.warn("93) path: [{}] value: [{}]", path, lwM2mResource.getValue()); + fwUpdate.updateStateOta(this, lwM2mTransportRequest, registration, path, ((Long) lwM2mResource.getValue()).intValue()); } Set paths = new HashSet<>(); paths.add(path); @@ -722,6 +686,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler } else { log.error("Fail update Resource [{}]", lwM2mResource); } + } @@ -869,8 +834,9 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler valueKvProto = new JsonObject(); Object finalvalueKvProto = valueKvProto; Gson gson = new GsonBuilder().create(); + ResourceModel.Type finalCurrentType = currentType; resourceValue.getValues().forEach((k, v) -> { - Object val = this.converter.convertValue(v, currentType, expectedType, + Object val = this.converter.convertValue(v, finalCurrentType, expectedType, new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer))); JsonElement element = gson.toJsonTree(val, val.getClass()); ((JsonObject) finalvalueKvProto).add(String.valueOf(k), element); @@ -880,6 +846,9 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler valueKvProto = this.converter.convertValue(resourceValue.getValue(), currentType, expectedType, new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer))); } + LwM2mOtaConvert lwM2mOtaConvert = convertOtaUpdateValueToString (pathIdVer, valueKvProto, currentType); + valueKvProto = lwM2mOtaConvert.getValue(); + currentType = lwM2mOtaConvert.getCurrentType(); return valueKvProto != null ? this.helper.getKvAttrTelemetryToThingsboard(currentType, resourceName, valueKvProto, resourceValue.isMultiInstances()) : null; } } catch (Exception e) { @@ -1072,7 +1041,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler * @param parametersNew - * @return ResultsAnalyzerParameters: add && new */ - private ResultsAnalyzerParameters getAnalyzerParameters(Set parametersOld, Set parametersNew) { + private ResultsAnalyzerParameters getAnalyzerParameters + (Set parametersOld, Set parametersNew) { ResultsAnalyzerParameters analyzerParameters = null; if (!parametersOld.equals(parametersNew)) { analyzerParameters = new ResultsAnalyzerParameters(); @@ -1084,7 +1054,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler return analyzerParameters; } - private ResultsAnalyzerParameters getAnalyzerParametersIn(Set parametersObserve, Set parameters) { + private ResultsAnalyzerParameters getAnalyzerParametersIn + (Set parametersObserve, Set parameters) { ResultsAnalyzerParameters analyzerParameters = new ResultsAnalyzerParameters(); analyzerParameters.setPathPostParametersAdd(parametersObserve .stream().filter(parameters::contains).collect(Collectors.toSet())); @@ -1113,7 +1084,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler }); } - private ResultsAnalyzerParameters getAnalyzerKeyName(ConcurrentHashMap keyNameOld, ConcurrentHashMap keyNameNew) { + private ResultsAnalyzerParameters getAnalyzerKeyName + (ConcurrentHashMap keyNameOld, ConcurrentHashMap keyNameNew) { ResultsAnalyzerParameters analyzerParameters = new ResultsAnalyzerParameters(); Set paths = keyNameNew.entrySet() .stream() @@ -1133,7 +1105,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler * @param attributeLwm2mNew - * @return */ - private void getAnalyzerAttributeLwm2m(Set registrationIds, JsonObject attributeLwm2mOld, JsonObject attributeLwm2mNew) { + private void getAnalyzerAttributeLwm2m(Set registrationIds, JsonObject attributeLwm2mOld, JsonObject + attributeLwm2mNew) { ResultsAnalyzerParameters analyzerParameters = new ResultsAnalyzerParameters(); ConcurrentHashMap lwm2mAttributesOld = new Gson().fromJson(attributeLwm2mOld.toString(), new TypeToken>() { @@ -1199,7 +1172,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler ); } - private void updateResourcesValueToClient(LwM2mClient lwM2MClient, Object valueOld, Object valueNew, String path) { + private void updateResourcesValueToClient(LwM2mClient lwM2MClient, Object valueOld, Object valueNew, String + path) { if (valueNew != null && (valueOld == null || !valueNew.toString().equals(valueOld.toString()))) { lwM2mTransportRequest.sendAllRequest(lwM2MClient.getRegistration(), path, WRITE_REPLACE, ContentFormat.TLV.getName(), valueNew, @@ -1245,7 +1219,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler * @param attributesResponse - * @param sessionInfo - */ - public void onGetAttributesResponse(TransportProtos.GetAttributeResponseMsg attributesResponse, TransportProtos.SessionInfoProto sessionInfo) { + public void onGetAttributesResponse(TransportProtos.GetAttributeResponseMsg + attributesResponse, TransportProtos.SessionInfoProto sessionInfo) { try { List tsKvProtos = attributesResponse.getSharedAttributeListList(); this.updateAttributeFromThingsboard(tsKvProtos, sessionInfo); @@ -1264,7 +1239,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler * @param tsKvProtos * @param sessionInfo */ - public void updateAttributeFromThingsboard(List tsKvProtos, TransportProtos.SessionInfoProto sessionInfo) { + public void updateAttributeFromThingsboard + (List tsKvProtos, TransportProtos.SessionInfoProto sessionInfo) { LwM2mClient lwM2MClient = clientContext.getClient(sessionInfo); if (lwM2MClient != null) { log.warn("1) UpdateAttributeFromThingsboard, tsKvProtos [{}]", tsKvProtos); @@ -1327,8 +1303,10 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler * @param sessionInfo - */ private void reportActivityAndRegister(SessionInfoProto sessionInfo) { - if (sessionInfo != null && transportService.reportActivity(sessionInfo) == null) { - transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(this, sessionInfo)); + if (sessionInfo != null) { + if (transportService.reportActivity(sessionInfo) == null) { + transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(this, sessionInfo)); + } this.reportActivitySubscription(sessionInfo); } } @@ -1365,8 +1343,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler } } - public void getInfoFirmwareUpdate(LwM2mClient lwM2MClient, Lwm2mClientRpcRequest rpcRequest) { - if (lwM2MClient.getRegistration().getSupportedVersion(FW_ID) != null) { + public void getInfoFirmwareUpdate(LwM2mClient lwM2MClient, LwM2mClientRpcRequest rpcRequest) { + if (lwM2MClient.getRegistration().getSupportedVersion(FW_5_ID) != null) { SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(lwM2MClient); if (sessionInfo != null) { DefaultLwM2MTransportMsgHandler handler = this; @@ -1376,20 +1354,21 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler public void onSuccess(TransportProtos.GetOtaPackageResponseMsg response) { if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus()) && response.getType().equals(OtaPackageType.FIRMWARE.name())) { - log.warn("7) firmware start with ver: [{}]", response.getVersion()); - lwM2MClient.setFwUpdate(new LwM2mFwSwUpdate(lwM2MClient, OtaPackageType.FIRMWARE)); -// clientContext.getProfile(lwM2MClient.getProfileId()).getPostAttributeLwm2mProfile(); - lwM2MClient.getFwUpdate().setTypeUpdateByURL(true); - lwM2MClient.getFwUpdate().setRpcRequest(rpcRequest); - lwM2MClient.getFwUpdate().setCurrentVersion(response.getVersion()); - lwM2MClient.getFwUpdate().setCurrentTitle(response.getTitle()); - log.warn("11) OtaPackageIdMSB: [{}] OtaPackageIdLSB: [{}]", response.getOtaPackageIdMSB(), response.getOtaPackageIdLSB()); - lwM2MClient.getFwUpdate().setCurrentId(new UUID(response.getOtaPackageIdMSB(), response.getOtaPackageIdLSB())); - - if (rpcRequest == null) { - lwM2MClient.getFwUpdate().sendReadObserveInfo(lwM2mTransportRequest); - } else { - lwM2MClient.getFwUpdate().writeFwSwWare(handler, lwM2mTransportRequest); + LwM2mFwSwUpdate fwUpdate = lwM2MClient.getFwUpdate(clientContext); + if (!FAILED.name().equals(fwUpdate.getStateUpdate())) { + log.warn("7) firmware start with ver: [{}]", response.getVersion()); + fwUpdate.setRpcRequest(rpcRequest); + fwUpdate.setCurrentVersion(response.getVersion()); + fwUpdate.setCurrentTitle(response.getTitle()); + fwUpdate.setCurrentId(new UUID(response.getOtaPackageIdMSB(), response.getOtaPackageIdLSB())); + if (rpcRequest == null) { + fwUpdate.sendReadObserveInfo(lwM2mTransportRequest); + } else { + fwUpdate.writeFwSwWare(handler, lwM2mTransportRequest); + } + } + else { + log.warn("7_1) OtaPackage [{}] [{}] [{}]", lwM2MClient.getDeviceName(), response.getVersion(), fwUpdate.getStateUpdate()); } } else { log.trace("OtaPackage [{}] [{}]", lwM2MClient.getDeviceName(), response.getResponseStatus().toString()); @@ -1405,7 +1384,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler } } - public void getInfoSoftwareUpdate(LwM2mClient lwM2MClient, Lwm2mClientRpcRequest rpcRequest) { + public void getInfoSoftwareUpdate(LwM2mClient lwM2MClient, LwM2mClientRpcRequest rpcRequest) { if (lwM2MClient.getRegistration().getSupportedVersion(SW_ID) != null) { SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(lwM2MClient); if (sessionInfo != null) { @@ -1416,18 +1395,16 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler public void onSuccess(TransportProtos.GetOtaPackageResponseMsg response) { if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus()) && response.getType().equals(OtaPackageType.SOFTWARE.name())) { - lwM2MClient.setSwUpdate(new LwM2mFwSwUpdate(lwM2MClient, OtaPackageType.SOFTWARE)); -// clientContext.getProfile(lwM2MClient.getProfileId()).getPostAttributeLwm2mProfile(); - lwM2MClient.getSwUpdate().setTypeUpdateByURL(false); - lwM2MClient.getSwUpdate().setRpcRequest(rpcRequest); - lwM2MClient.getSwUpdate().setCurrentVersion(response.getVersion()); - lwM2MClient.getSwUpdate().setCurrentTitle(response.getTitle()); - lwM2MClient.getSwUpdate().setCurrentId(new OtaPackageId(new UUID(response.getOtaPackageIdMSB(), response.getOtaPackageIdLSB())).getId()); - lwM2MClient.getSwUpdate().sendReadObserveInfo(lwM2mTransportRequest); + LwM2mFwSwUpdate swUpdate = lwM2MClient.getSwUpdate(clientContext); + swUpdate.setRpcRequest(rpcRequest); + swUpdate.setCurrentVersion(response.getVersion()); + swUpdate.setCurrentTitle(response.getTitle()); + swUpdate.setCurrentId(new OtaPackageId(new UUID(response.getOtaPackageIdMSB(), response.getOtaPackageIdLSB())).getId()); + swUpdate.sendReadObserveInfo(lwM2mTransportRequest); if (rpcRequest == null) { - lwM2MClient.getSwUpdate().sendReadObserveInfo(lwM2mTransportRequest); + swUpdate.sendReadObserveInfo(lwM2mTransportRequest); } else { - lwM2MClient.getSwUpdate().writeFwSwWare(handler, lwM2mTransportRequest); + swUpdate.writeFwSwWare(handler, lwM2mTransportRequest); } } else { log.trace("Software [{}] [{}]", lwM2MClient.getDeviceName(), response.getResponseStatus().toString()); @@ -1443,7 +1420,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler } } - private TransportProtos.GetOtaPackageRequestMsg createOtaPackageRequestMsg(SessionInfoProto sessionInfo, String nameFwSW) { + private TransportProtos.GetOtaPackageRequestMsg createOtaPackageRequestMsg(SessionInfoProto sessionInfo, String + nameFwSW) { return TransportProtos.GetOtaPackageRequestMsg.newBuilder() .setDeviceIdMSB(sessionInfo.getDeviceIdMSB()) .setDeviceIdLSB(sessionInfo.getDeviceIdLSB()) diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java index 688ab88eeb..c0afe4fa81 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java @@ -63,8 +63,7 @@ import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256; import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CCM_8; import static org.thingsboard.server.transport.lwm2m.server.LwM2mNetworkConfig.getCoapConfig; -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_COAP_RESOURCE; -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_COAP_RESOURCE; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.OTA_COAP_RESOURCE; @Slf4j @Component @@ -104,10 +103,8 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService { */ - LwM2mTransportCoapResource fwCoapResource = new LwM2mTransportCoapResource(handler, FW_COAP_RESOURCE); - LwM2mTransportCoapResource swCoapResource = new LwM2mTransportCoapResource(handler, SW_COAP_RESOURCE); - this.server.coap().getServer().add(fwCoapResource); - this.server.coap().getServer().add(swCoapResource); + LwM2mTransportCoapResource otaCoapResource = new LwM2mTransportCoapResource(handler, OTA_COAP_RESOURCE); + this.server.coap().getServer().add(otaCoapResource); this.startLhServer(); this.context.setServer(server); } @@ -138,7 +135,7 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService { builder.setEncoder(new DefaultLwM2mNodeEncoder(LwM2mValueConverterImpl.getInstance())); /* Create CoAP Config */ - builder.setCoapConfig(getCoapConfig(config.getPort(), config.getSecurePort())); + builder.setCoapConfig(getCoapConfig(config.getPort(), config.getSecurePort(), config)); /* Define model provider (Create Models )*/ LwM2mModelProvider modelProvider = new LwM2mVersionedModelProvider(this.lwM2mClientContext, this.helper, this.context); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mNetworkConfig.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mNetworkConfig.java index 280cb7dde4..9e07b0b6db 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mNetworkConfig.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mNetworkConfig.java @@ -16,10 +16,12 @@ package org.thingsboard.server.transport.lwm2m.server; import org.eclipse.californium.core.network.config.NetworkConfig; +import org.eclipse.californium.core.network.config.NetworkConfigDefaults; +import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; public class LwM2mNetworkConfig { - public static NetworkConfig getCoapConfig(Integer serverPortNoSec, Integer serverSecurePort) { + public static NetworkConfig getCoapConfig(Integer serverPortNoSec, Integer serverSecurePort, LwM2MTransportServerConfig config) { NetworkConfig coapConfig = new NetworkConfig(); coapConfig.setInt(NetworkConfig.Keys.COAP_PORT,serverPortNoSec); coapConfig.setInt(NetworkConfig.Keys.COAP_SECURE_PORT,serverSecurePort); @@ -41,7 +43,7 @@ public class LwM2mNetworkConfig { CoAP client will try to use block mode or adapt the block size when receiving a 4.13 Entity too large response code */ - coapConfig.setBoolean(NetworkConfig.Keys.BLOCKWISE_STRICT_BLOCK2_OPTION, true); + coapConfig.setBoolean(NetworkConfig.Keys.BLOCKWISE_STRICT_BLOCK2_OPTION, config.isBlock2OptionEnable()); /** Property to indicate if the response should always include the Block2 option \ when client request early blockwise negociation but the response can be sent on one packet. @@ -49,8 +51,15 @@ public class LwM2mNetworkConfig { - value of true indicate that the server will response with block2 option event if no further blocks are required. */ coapConfig.setBoolean(NetworkConfig.Keys.BLOCKWISE_ENTITY_TOO_LARGE_AUTO_FAILOVER, true); - - coapConfig.setInt(NetworkConfig.Keys.BLOCKWISE_STATUS_LIFETIME, 300000); + /** + * The maximum amount of time (in milliseconds) allowed between + * transfers of individual blocks in a blockwise transfer before the + * blockwise transfer state is discarded. + *

+ * The default value of this property is + * {@link NetworkConfigDefaults#DEFAULT_BLOCKWISE_STATUS_LIFETIME} = 5 * 60 * 1000; // 5 mins [ms]. + */ + coapConfig.setLong(NetworkConfig.Keys.BLOCKWISE_STATUS_LIFETIME, config.getBlockwiseLifetime()); /** !!! REQUEST_ENTITY_TOO_LARGE CODE=4.13 The maximum size of a resource body (in bytes) that will be accepted diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mOtaConvert.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mOtaConvert.java new file mode 100644 index 0000000000..7b7c56adb3 --- /dev/null +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mOtaConvert.java @@ -0,0 +1,25 @@ +/** + * Copyright © 2016-2021 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.transport.lwm2m.server; + +import lombok.Data; +import org.eclipse.leshan.core.model.ResourceModel; + +@Data +public class LwM2mOtaConvert { + private ResourceModel.Type currentType; + private Object value; +} diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportCoapResource.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportCoapResource.java index f2aa4dbf24..7ba491d6d1 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportCoapResource.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportCoapResource.java @@ -30,11 +30,10 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicInteger; -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_COAP_RESOURCE; -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_COAP_RESOURCE; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.OTA_COAP_RESOURCE; @Slf4j -public class LwM2mTransportCoapResource extends AbstractLwm2mTransportResource { +public class LwM2mTransportCoapResource extends AbstractLwM2mTransportResource { private final ConcurrentMap tokenToObserveRelationMap = new ConcurrentHashMap<>(); private final ConcurrentMap tokenToObserveNotificationSeqMap = new ConcurrentHashMap<>(); private final LwM2mTransportMsgHandler handler; @@ -68,52 +67,11 @@ public class LwM2mTransportCoapResource extends AbstractLwm2mTransportResource { @Override protected void processHandleGet(CoapExchange exchange) { - log.warn("1) processHandleGet [{}]", exchange); - // exchange.respond(CoAP.ResponseCode.BAD_REQUEST); - int ver = 10; -// int ver = 9; - UUID currentId; - if (ver == 10) { - long mSB = 4951557297924280811L; - long lSb = -8451242882176289074L; - currentId = new UUID(mSB, lSb); - } else { - long mSB = 9085827945869414891L; - long lSb = -9086716326447629319L; - currentId = new UUID(mSB, lSb); + log.warn("90) processHandleGet [{}]", exchange); + if (exchange.getRequestOptions().getUriPath().size() == 2 && + OTA_COAP_RESOURCE.equals(exchange.getRequestOptions().getUriPath().get(0))) { + this.sentOtaData(exchange); } - - String coapResource = exchange.getRequestOptions().getUriPath().get(0); - String token = exchange.getRequestOptions().getUriPath().get(1); - if (exchange.getRequestOptions().getBlock2() != null) { - int chunkSize = exchange.getRequestOptions().getBlock2().getSzx(); - int chunk = 0; - Response response = new Response(CoAP.ResponseCode.CONTENT); - byte[] fwData = this.getFwData(currentId); - if (fwData != null && fwData.length > 0) { - response.setPayload(fwData); - boolean moreFlag = fwData.length > chunkSize; - response.getOptions().setBlock2(chunkSize, moreFlag, chunk); - exchange.respond(response); - } - - } -// List options = exchange.advanced().getRequest().getOptions().getUriPath(); -// options.stream() -// .filter(o -> FW_COAP_RESOURCE.equals(o)) -// .findFirst() -// .ifPresent(o -> System.err.println(o.getNumber() + " " + o.getStringValue())); - - if (FW_COAP_RESOURCE.equals(coapResource)) { - - } - else if (SW_COAP_RESOURCE.equals(coapResource)) { - - } - - - - } @Override @@ -169,7 +127,26 @@ public class LwM2mTransportCoapResource extends AbstractLwm2mTransportResource { } } - private byte[] getFwData(UUID currentId) { + private void sentOtaData (CoapExchange exchange) { + String idStr = exchange.getRequestOptions().getUriPath().get(1); + UUID currentId = UUID.fromString(idStr); + if (exchange.getRequestOptions().getBlock2() != null) { + int chunkSize = exchange.getRequestOptions().getBlock2().getSzx(); + int chunk = 0; + Response response = new Response(CoAP.ResponseCode.CONTENT); + byte[] fwData = this.getOtaData(currentId); + if (fwData != null && fwData.length > 0) { + response.setPayload(fwData); + boolean moreFlag = fwData.length > chunkSize; + response.getOptions().setBlock2(chunkSize, moreFlag, chunk); + log.warn("91) Send currentId: [{}], length: [{}], chunkSize [{}], moreFlag [{}]", currentId.toString(), fwData.length, chunkSize, moreFlag); + exchange.respond(response); + } + + } + } + + private byte[] getOtaData(UUID currentId) { return ((DefaultLwM2MTransportMsgHandler) handler).otaPackageDataCache.get(currentId.toString()); } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportMsgHandler.java index 794df65db5..0ce018303c 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportMsgHandler.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportMsgHandler.java @@ -22,7 +22,7 @@ import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; -import org.thingsboard.server.transport.lwm2m.server.client.Lwm2mClientRpcRequest; +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientRpcRequest; import java.util.Collection; import java.util.Optional; @@ -39,7 +39,7 @@ public interface LwM2mTransportMsgHandler { void setCancelObservationsAll(Registration registration); - void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response, Lwm2mClientRpcRequest rpcRequest); + void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response, LwM2mClientRpcRequest rpcRequest); void onAttributeUpdate(TransportProtos.AttributeUpdateNotificationMsg msg, TransportProtos.SessionInfoProto sessionInfo); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java index 98b40e74fc..f0484d521c 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportRequest.java @@ -55,7 +55,7 @@ import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; -import org.thingsboard.server.transport.lwm2m.server.client.Lwm2mClientRpcRequest; +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientRpcRequest; import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; import javax.annotation.PostConstruct; @@ -75,7 +75,7 @@ import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.DOWN import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.FAILED; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper.getContentFormatByResourceModelType; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.DEFAULT_TIMEOUT; -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_ID; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_5_ID; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_UPDATE_ID; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_ERROR; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_INFO; @@ -126,7 +126,7 @@ public class LwM2mTransportRequest { */ public void sendAllRequest(Registration registration, String targetIdVer, LwM2mTypeOper typeOper, - String contentFormatName, Object params, long timeoutInMs, Lwm2mClientRpcRequest lwm2mClientRpcRequest) { + String contentFormatName, Object params, long timeoutInMs, LwM2mClientRpcRequest lwm2mClientRpcRequest) { try { String target = convertPathFromIdVerToObjectId(targetIdVer); ContentFormat contentFormat = contentFormatName != null ? ContentFormat.fromName(contentFormatName.toUpperCase()) : ContentFormat.DEFAULT; @@ -143,7 +143,7 @@ public class LwM2mTransportRequest { } catch (ClientSleepingException e) { DownlinkRequest finalRequest = request; long finalTimeoutInMs = timeoutInMs; - Lwm2mClientRpcRequest finalRpcRequest = lwm2mClientRpcRequest; + LwM2mClientRpcRequest finalRpcRequest = lwm2mClientRpcRequest; lwM2MClient.getQueuedRequests().add(() -> sendRequest(registration, lwM2MClient, finalRequest, finalTimeoutInMs, finalRpcRequest)); } catch (Exception e) { log.error("[{}] [{}] [{}] Failed to send downlink.", registration.getEndpoint(), targetIdVer, typeOper.name(), e); @@ -225,7 +225,7 @@ public class LwM2mTransportRequest { private DownlinkRequest createRequest(Registration registration, LwM2mClient lwM2MClient, LwM2mTypeOper typeOper, ContentFormat contentFormat, String target, String targetIdVer, - LwM2mPath resultIds, Object params, Lwm2mClientRpcRequest rpcRequest) { + LwM2mPath resultIds, Object params, LwM2mClientRpcRequest rpcRequest) { DownlinkRequest request = null; switch (typeOper) { case READ: @@ -330,7 +330,7 @@ public class LwM2mTransportRequest { @SuppressWarnings({"error sendRequest"}) private void sendRequest(Registration registration, LwM2mClient lwM2MClient, DownlinkRequest request, - long timeoutInMs, Lwm2mClientRpcRequest rpcRequest) { + long timeoutInMs, LwM2mClientRpcRequest rpcRequest) { context.getServer().send(registration, request, timeoutInMs, (ResponseCallback) response -> { if (!lwM2MClient.isInit()) { @@ -354,13 +354,13 @@ public class LwM2mTransportRequest { /** Not Found set setClient_fw_info... = empty **/ - if (lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) { + if (lwM2MClient.getFwUpdate() != null && lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) { lwM2MClient.getFwUpdate().initReadValue(handler, this, request.getPath().toString()); } - if (lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) { + if (lwM2MClient.getSwUpdate() != null && lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) { lwM2MClient.getSwUpdate().initReadValue(handler, this, request.getPath().toString()); } - if (request.getPath().toString().equals(FW_PACKAGE_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) { + if (request.getPath().toString().equals(FW_PACKAGE_5_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) { this.afterWriteFwSWUpdateError(registration, request, response.getErrorMessage()); } if (request.getPath().toString().equals(FW_UPDATE_ID) || request.getPath().toString().equals(SW_INSTALL_ID)) { @@ -371,13 +371,13 @@ public class LwM2mTransportRequest { /** version == null set setClient_fw_info... = empty **/ - if (lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) { + if (lwM2MClient.getFwUpdate() != null && lwM2MClient.getFwUpdate().isInfoFwSwUpdate()) { lwM2MClient.getFwUpdate().initReadValue(handler, this, request.getPath().toString()); } - if (lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) { + if (lwM2MClient.getSwUpdate() != null && lwM2MClient.getSwUpdate().isInfoFwSwUpdate()) { lwM2MClient.getSwUpdate().initReadValue(handler, this, request.getPath().toString()); } - if (request.getPath().toString().equals(FW_PACKAGE_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) { + if (request.getPath().toString().equals(FW_PACKAGE_5_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) { this.afterWriteFwSWUpdateError(registration, request, e.getMessage()); } if (request.getPath().toString().equals(FW_UPDATE_ID) || request.getPath().toString().equals(SW_INSTALL_ID)) { @@ -389,7 +389,7 @@ public class LwM2mTransportRequest { String msg = String.format("%s: SendRequest %s: Resource path - %s msg error - %s", LOG_LW2M_ERROR, request.getClass().getName().toString(), request.getPath().toString(), e.getMessage()); handler.sendLogsToThingsboard(msg, registration.getId()); - log.error("[{}] [{}] - [{}] error SendRequest", request.getClass().getName().toString(), request.getPath().toString(), e.toString()); + log.error(" [{}] [{}] - [{}] error SendRequest", request.getClass().getName().toString(), request.getPath().toString(), e.toString()); if (rpcRequest != null) { handler.sentRpcResponse(rpcRequest, CoAP.CodeClass.ERROR_RESPONSE.name(), e.getMessage(), LOG_LW2M_ERROR); } @@ -398,7 +398,7 @@ public class LwM2mTransportRequest { private WriteRequest getWriteRequestSingleResource(ContentFormat contentFormat, Integer objectId, Integer instanceId, Integer resourceId, Object value, ResourceModel.Type type, - Registration registration, Lwm2mClientRpcRequest rpcRequest) { + Registration registration, LwM2mClientRpcRequest rpcRequest) { try { if (type != null) { switch (type) { @@ -444,7 +444,7 @@ public class LwM2mTransportRequest { } private void handleResponse(Registration registration, final String path, LwM2mResponse response, - DownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) { + DownlinkRequest request, LwM2mClientRpcRequest rpcRequest) { responseRequestExecutor.submit(() -> { try { this.sendResponse(registration, path, response, request, rpcRequest); @@ -462,7 +462,7 @@ public class LwM2mTransportRequest { * @param response - */ private void sendResponse(Registration registration, String path, LwM2mResponse response, - DownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) { + DownlinkRequest request, LwM2mClientRpcRequest rpcRequest) { String pathIdVer = convertPathFromObjectIdToIdVer(path, registration); String msgLog = ""; if (response instanceof ReadResponse) { @@ -509,7 +509,7 @@ public class LwM2mTransportRequest { } } - private void infoWriteResponse(Registration registration, LwM2mResponse response, DownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) { + private void infoWriteResponse(Registration registration, LwM2mResponse response, DownlinkRequest request, LwM2mClientRpcRequest rpcRequest) { try { LwM2mNode node = ((WriteRequest) request).getNode(); String msg = null; @@ -546,7 +546,7 @@ public class LwM2mTransportRequest { } if (msg != null) { handler.sendLogsToThingsboard(msg, registration.getId()); - if (request.getPath().toString().equals(FW_PACKAGE_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) { + if (request.getPath().toString().equals(FW_PACKAGE_5_ID) || request.getPath().toString().equals(SW_PACKAGE_ID)) { this.afterWriteSuccessFwSwUpdate(registration, request); if (rpcRequest != null) { rpcRequest.setInfoMsg(msg); @@ -568,7 +568,7 @@ public class LwM2mTransportRequest { */ private void afterWriteSuccessFwSwUpdate(Registration registration, DownlinkRequest request) { LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId()); - if (request.getPath().toString().equals(FW_PACKAGE_ID) && lwM2MClient.getFwUpdate() != null) { + if (request.getPath().toString().equals(FW_PACKAGE_5_ID) && lwM2MClient.getFwUpdate() != null) { lwM2MClient.getFwUpdate().setStateUpdate(DOWNLOADED.name()); lwM2MClient.getFwUpdate().sendLogs(this.handler, WRITE_REPLACE.name(), LOG_LW2M_INFO, null); } @@ -583,7 +583,7 @@ public class LwM2mTransportRequest { */ private void afterWriteFwSWUpdateError(Registration registration, DownlinkRequest request, String msgError) { LwM2mClient lwM2MClient = this.lwM2mClientContext.getClientByRegistrationId(registration.getId()); - if (request.getPath().toString().equals(FW_PACKAGE_ID) && lwM2MClient.getFwUpdate() != null) { + if (request.getPath().toString().equals(FW_PACKAGE_5_ID) && lwM2MClient.getFwUpdate() != null) { lwM2MClient.getFwUpdate().setStateUpdate(FAILED.name()); lwM2MClient.getFwUpdate().sendLogs(this.handler, WRITE_REPLACE.name(), LOG_LW2M_ERROR, msgError); } @@ -603,7 +603,7 @@ public class LwM2mTransportRequest { } } - private void afterObserveCancel(Registration registration, int observeCancelCnt, String observeCancelMsg, Lwm2mClientRpcRequest rpcRequest) { + private void afterObserveCancel(Registration registration, int observeCancelCnt, String observeCancelMsg, LwM2mClientRpcRequest rpcRequest) { handler.sendLogsToThingsboard(observeCancelMsg, registration.getId()); log.warn("[{}]", observeCancelMsg); if (rpcRequest != null) { diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportUtil.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportUtil.java index 2e7681250a..9be2c24053 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportUtil.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportUtil.java @@ -89,6 +89,11 @@ import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.VERI @Slf4j public class LwM2mTransportUtil { + public static final String EVENT_AWAKE = "AWAKE"; + public static final String RESPONSE_REQUEST_CHANNEL = "RESP_REQ"; + public static final String RESPONSE_CHANNEL = "RESP"; + public static final String OBSERVE_CHANNEL = "OBSERVE"; + public static final String TRANSPORT_DEFAULT_LWM2M_VERSION = "1.0"; public static final String CLIENT_LWM2M_SETTINGS = "clientLwM2mSettings"; public static final String BOOTSTRAP = "bootstrap"; @@ -116,9 +121,6 @@ public class LwM2mTransportUtil { public static final String LOG_LW2M_WARN = "warn"; public static final String LOG_LW2M_VALUE = "value"; - public static final int LWM2M_STRATEGY_1 = 1; - public static final int LWM2M_STRATEGY_2 = 2; - public static final String CLIENT_NOT_AUTHORIZED = "Client not authorized"; public static final String LWM2M_VERSION_DEFAULT = "1.0"; @@ -132,19 +134,22 @@ public class LwM2mTransportUtil { public static final String FINISH_VALUE_KEY = ","; public static final String START_JSON_KEY = "{"; public static final String FINISH_JSON_KEY = "}"; - // public static final String contentFormatNameKey = "contentFormatName"; public static final String INFO_KEY = "info"; - // public static final String TIME_OUT_IN_MS = "timeOutInMs"; public static final String RESULT_KEY = "result"; public static final String ERROR_KEY = "error"; public static final String METHOD_KEY = "methodName"; + public static final String OTA_COAP_RESOURCE = "firmwarePackage"; // Firmware - public static final String FW_COAP_RESOURCE = "fw"; public static final String FW_UPDATE = "Firmware update"; - public static final Integer FW_ID = 5; + public static final Integer FW_5_ID = 5; + public static final Integer FW_19_ID = 19; + // Package W - public static final String FW_PACKAGE_ID = "/5/0/0"; + public static final String FW_PACKAGE_5_ID = "/5/0/0"; + public static final String FW_PACKAGE_19_ID = "/19/0/0"; + // Package URI + public static final String FW_PACKAGE_URI_ID = "/5/0/1"; // State R public static final String FW_STATE_ID = "/5/0/3"; // Update Result R @@ -152,16 +157,27 @@ public class LwM2mTransportUtil { // PkgName R public static final String FW_NAME_ID = "/5/0/6"; // PkgVersion R - public static final String FW_VER_ID = "/5/0/7"; + public static final String FW_5_VER_ID = "/5/0/7"; + /** + * Quectel@Hi15RM1-HLB_V1.0@BC68JAR01A10,V150R100C20B300SP7,V150R100C20B300SP7@8 + * BC68JAR01A10 + * # Request prodct type number + * ATI + * Quectel + * BC68 + * Revision:BC68JAR01A10 + */ + public static final String FW_3_VER_ID = "/3/0/3"; // Update E public static final String FW_UPDATE_ID = "/5/0/2"; // Software - public static final String SW_COAP_RESOURCE = "sw"; public static final String SW_UPDATE = "Software update"; public static final Integer SW_ID = 9; // Package W public static final String SW_PACKAGE_ID = "/9/0/2"; + // Package URI + public static final String SW_PACKAGE_URI_ID = "/9/0/3"; // Update State R public static final String SW_UPDATE_STATE_ID = "/9/0/7"; // Update Result R @@ -234,7 +250,7 @@ public class LwM2mTransportUtil { DELETE(11, "Delete"), // only for RPC - FW_UPDATE(12,"FirmwareUpdate"); + FW_UPDATE(12, "FirmwareUpdate"); // FW_READ_INFO(12, "FirmwareReadInfo"), // SW_READ_INFO(15, "SoftwareReadInfo"), @@ -357,20 +373,11 @@ public class LwM2mTransportUtil { * FirmwareUpdateStatus { * DOWNLOADING, DOWNLOADED, VERIFIED, UPDATING, UPDATED, FAILED */ - public static OtaPackageUpdateStatus EqualsFwSateToFirmwareUpdateStatus(StateFw stateFw, UpdateResultFw updateResultFw) { + public static OtaPackageUpdateStatus equalsFwSateFwResultToFirmwareUpdateStatus(StateFw stateFw, UpdateResultFw updateResultFw) { switch (updateResultFw) { case INITIAL: - switch (stateFw) { - case IDLE: - return VERIFIED; - case DOWNLOADING: - return DOWNLOADING; - case DOWNLOADED: - return DOWNLOADED; - case UPDATING: - return UPDATING; - } - case UPDATE_SUCCESSFULLY: + return equalsFwSateToFirmwareUpdateStatus(stateFw); + case UPDATE_SUCCESSFULLY: return UPDATED; case NOT_ENOUGH: case OUT_OFF_MEMORY: @@ -386,6 +393,41 @@ public class LwM2mTransportUtil { } } + public static OtaPackageUpdateStatus equalsFwResultToFirmwareUpdateStatus(UpdateResultFw updateResultFw) { + switch (updateResultFw) { + case INITIAL: + return VERIFIED; + case UPDATE_SUCCESSFULLY: + return UPDATED; + case NOT_ENOUGH: + case OUT_OFF_MEMORY: + case CONNECTION_LOST: + case INTEGRITY_CHECK_FAILURE: + case UNSUPPORTED_TYPE: + case INVALID_URI: + case UPDATE_FAILED: + case UNSUPPORTED_PROTOCOL: + return FAILED; + default: + throw new CodecException("Invalid value stateFw %s for FirmwareUpdateStatus.", updateResultFw.name()); + } + } + + public static OtaPackageUpdateStatus equalsFwSateToFirmwareUpdateStatus(StateFw stateFw) { + switch (stateFw) { + case IDLE: + return VERIFIED; + case DOWNLOADING: + return DOWNLOADING; + case DOWNLOADED: + return DOWNLOADED; + case UPDATING: + return UPDATING; + default: + throw new CodecException("Invalid value stateFw %d for FirmwareUpdateStatus.", stateFw); + } + } + /** * SW Update State R * 0: INITIAL Before downloading. (see 5.1.2.1) @@ -499,6 +541,101 @@ public class LwM2mTransportUtil { } } + public enum LwM2MClientStrategy { + CLIENT_STRATEGY_1(1, "Read only resources marked as observation"), + CLIENT_STRATEGY_2(2, "Read all client resources"); + + public int code; + public String type; + + LwM2MClientStrategy(int code, String type) { + this.code = code; + this.type = type; + } + + public static LwM2MClientStrategy fromStrategyClientByType(String type) { + for (LwM2MClientStrategy to : LwM2MClientStrategy.values()) { + if (to.type.equals(type)) { + return to; + } + } + throw new IllegalArgumentException(String.format("Unsupported Client Strategy type : %s", type)); + } + + public static LwM2MClientStrategy fromStrategyClientByCode(int code) { + for (LwM2MClientStrategy to : LwM2MClientStrategy.values()) { + if (to.code == code) { + return to; + } + } + throw new IllegalArgumentException(String.format("Unsupported Client Strategy code : %s", code)); + } + } + + public enum LwM2MFirmwareUpdateStrategy { + OBJ_5_BINARY(1, "ObjectId 5, Binary"), + OBJ_5_TEMP_URL(2, "ObjectId 5, URI"), + OBJ_19_BINARY(3, "ObjectId 19, Binary"); + + public int code; + public String type; + + LwM2MFirmwareUpdateStrategy(int code, String type) { + this.code = code; + this.type = type; + } + + public static LwM2MFirmwareUpdateStrategy fromStrategyFwByType(String type) { + for (LwM2MFirmwareUpdateStrategy to : LwM2MFirmwareUpdateStrategy.values()) { + if (to.type.equals(type)) { + return to; + } + } + throw new IllegalArgumentException(String.format("Unsupported FW State type : %s", type)); + } + + public static LwM2MFirmwareUpdateStrategy fromStrategyFwByCode(int code) { + for (LwM2MFirmwareUpdateStrategy to : LwM2MFirmwareUpdateStrategy.values()) { + if (to.code == code) { + return to; + } + } + throw new IllegalArgumentException(String.format("Unsupported FW Strategy code : %s", code)); + } + } + + public enum LwM2MSoftwareUpdateStrategy { + BINARY(1, "ObjectId 9, Binary"), + TEMP_URL(2, "ObjectId 9, URI"); + + public int code; + public String type; + + LwM2MSoftwareUpdateStrategy(int code, String type) { + this.code = code; + this.type = type; + } + + public static LwM2MSoftwareUpdateStrategy fromStrategySwByType(String type) { + for (LwM2MSoftwareUpdateStrategy to : LwM2MSoftwareUpdateStrategy.values()) { + if (to.type.equals(type)) { + return to; + } + } + throw new IllegalArgumentException(String.format("Unsupported SW Strategy type : %s", type)); + } + + public static LwM2MSoftwareUpdateStrategy fromStrategySwByCode(int code) { + for (LwM2MSoftwareUpdateStrategy to : LwM2MSoftwareUpdateStrategy.values()) { + if (to.code == code) { + return to; + } + } + throw new IllegalArgumentException(String.format("Unsupported SW Strategy code : %s", code)); + } + + } + /** * FirmwareUpdateStatus { * DOWNLOADING, DOWNLOADED, VERIFIED, UPDATING, UPDATED, FAILED @@ -536,10 +673,6 @@ public class LwM2mTransportUtil { } } - public static final String EVENT_AWAKE = "AWAKE"; - public static final String RESPONSE_REQUEST_CHANNEL = "RESP_REQ"; - public static final String RESPONSE_CHANNEL = "RESP"; - public static final String OBSERVE_CHANNEL = "OBSERVE"; public static boolean equalsResourceValue(Object valueOld, Object valueNew, ResourceModel.Type type, LwM2mPath resourcePath) throws CodecException { @@ -560,6 +693,36 @@ public class LwM2mTransportUtil { } } + public static LwM2mOtaConvert convertOtaUpdateValueToString (String pathIdVer, Object value, ResourceModel.Type currentType) { + String path = convertPathFromIdVerToObjectId(pathIdVer); + LwM2mOtaConvert lwM2mOtaConvert = new LwM2mOtaConvert(); + if (path != null) { + if (FW_STATE_ID.equals(path)) { + lwM2mOtaConvert.setCurrentType(STRING); + lwM2mOtaConvert.setValue(StateFw.fromStateFwByCode(((Long) value).intValue()).type); + return lwM2mOtaConvert; + } + else if (FW_RESULT_ID.equals(path)) { + lwM2mOtaConvert.setCurrentType(STRING); + lwM2mOtaConvert.setValue(UpdateResultFw.fromUpdateResultFwByCode(((Long) value).intValue()).type); + return lwM2mOtaConvert; + } + else if (SW_UPDATE_STATE_ID.equals(path)) { + lwM2mOtaConvert.setCurrentType(STRING); + lwM2mOtaConvert.setValue(UpdateStateSw.fromUpdateStateSwByCode(((Long) value).intValue()).type); + return lwM2mOtaConvert; + } + else if (SW_RESULT_ID.equals(path)) { + lwM2mOtaConvert.setCurrentType(STRING); + lwM2mOtaConvert.setValue(UpdateResultSw.fromUpdateResultSwByCode(((Long) value).intValue()).type); + return lwM2mOtaConvert; + } + } + lwM2mOtaConvert.setCurrentType(currentType); + lwM2mOtaConvert.setValue(value); + return lwM2mOtaConvert; + } + public static LwM2mNode getLvM2mNodeToObject(LwM2mNode content) { if (content instanceof LwM2mObject) { return (LwM2mObject) content; @@ -635,11 +798,6 @@ public class LwM2mTransportUtil { return null; } - public static int getClientOnlyObserveAfterConnect(LwM2mClientProfile profile) { - return profile.getPostClientLwM2mSettings().getAsJsonObject().has("clientOnlyObserveAfterConnect") ? - profile.getPostClientLwM2mSettings().getAsJsonObject().get("clientOnlyObserveAfterConnect").getAsInt() : 1; - } - private static boolean getValidateCredentialsBodyFromThingsboard(JsonObject objectMsg) { return (objectMsg != null && !objectMsg.isJsonNull() && @@ -916,7 +1074,7 @@ public class LwM2mTransportUtil { case GREATER_THAN: case LESSER_THAN: case STEP: - if (value.getClass().getSimpleName().equals("String") ) { + if (value.getClass().getSimpleName().equals("String")) { value = Double.valueOf((String) value); } return serviceImpl.converter.convertValue(value, equalsResourceTypeGetSimpleName(value), FLOAT, new LwM2mPath(target)); @@ -930,11 +1088,11 @@ public class LwM2mTransportUtil { return new Attribute(key, attrValue); } catch (Exception e) { log.error("CreateAttribute, not valid parameter key: [{}], attrValue: [{}], error: [{}]", key, attrValue, e.getMessage()); - return null; + return null; } } - public static boolean isFwSwWords (String pathName) { + public static boolean isFwSwWords(String pathName) { return OtaPackageUtil.getAttributeKey(OtaPackageType.FIRMWARE, OtaPackageKey.VERSION).equals(pathName) || OtaPackageUtil.getAttributeKey(OtaPackageType.FIRMWARE, OtaPackageKey.TITLE).equals(pathName) || OtaPackageUtil.getAttributeKey(OtaPackageType.FIRMWARE, OtaPackageKey.CHECKSUM).equals(pathName) diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java index 602596ed2b..1ebc9ac66e 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClient.java @@ -31,6 +31,7 @@ import org.eclipse.leshan.server.registration.Registration; import org.eclipse.leshan.server.security.SecurityInfo; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; +import org.thingsboard.server.common.data.ota.OtaPackageType; import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto; @@ -361,5 +362,21 @@ public class LwM2mClient implements Cloneable { } } + public LwM2mFwSwUpdate getFwUpdate (LwM2mClientContext clientContext) { + if (this.fwUpdate == null) { + LwM2mClientProfile lwM2mClientProfile = clientContext.getProfile(this.getProfileId()); + this.fwUpdate = new LwM2mFwSwUpdate(this, OtaPackageType.FIRMWARE, lwM2mClientProfile.getFwUpdateStrategy()); + } + return this.fwUpdate; + } + + public LwM2mFwSwUpdate getSwUpdate (LwM2mClientContext clientContext) { + if (this.swUpdate == null) { + LwM2mClientProfile lwM2mClientProfile = clientContext.getProfile(this.getProfileId()); + this.swUpdate = new LwM2mFwSwUpdate(this, OtaPackageType.SOFTWARE, lwM2mClientProfile.getSwUpdateStrategy()); + } + return this.fwUpdate; + } + } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientProfile.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientProfile.java index 19af453f3c..67edbf2747 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientProfile.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientProfile.java @@ -20,15 +20,23 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; import lombok.Data; import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2MClientStrategy; +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy; +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2MSoftwareUpdateStrategy; @Data public class LwM2mClientProfile { + private final String clientStrategyStr = "clientStrategy"; + private final String fwUpdateStrategyStr = "fwUpdateStrategy"; + private final String swUpdateStrategyStr = "swUpdateStrategy"; private TenantId tenantId; /** - * {"clientLwM2mSettings": { - * clientUpdateValueAfterConnect: false; - * } + * "clientLwM2mSettings": { + * "fwUpdateStrategy": "1", + * "swUpdateStrategy": "1", + * "clientStrategy": "1" + * } **/ private JsonObject postClientLwM2mSettings; @@ -85,5 +93,21 @@ public class LwM2mClientProfile { } } + public int getClientStrategy() { + return this.postClientLwM2mSettings.getAsJsonObject().has(this.clientStrategyStr) ? + Integer.parseInt(this.postClientLwM2mSettings.getAsJsonObject().get(this.clientStrategyStr).getAsString()) : + LwM2MClientStrategy.CLIENT_STRATEGY_1.code; + } + public int getFwUpdateStrategy() { + return this.postClientLwM2mSettings.getAsJsonObject().has(this.fwUpdateStrategyStr) ? + Integer.parseInt(this.postClientLwM2mSettings.getAsJsonObject().get(this.fwUpdateStrategyStr).getAsString()) : + LwM2MFirmwareUpdateStrategy.OBJ_5_BINARY.code; + } + + public int getSwUpdateStrategy() { + return this.postClientLwM2mSettings.getAsJsonObject().has(this.swUpdateStrategyStr) ? + Integer.parseInt(this.postClientLwM2mSettings.getAsJsonObject().get(this.swUpdateStrategyStr).getAsString()) : + LwM2MSoftwareUpdateStrategy.BINARY.code; + } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/Lwm2mClientRpcRequest.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientRpcRequest.java similarity index 98% rename from common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/Lwm2mClientRpcRequest.java rename to common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientRpcRequest.java index d71c6b27f6..ca831b1413 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/Lwm2mClientRpcRequest.java +++ b/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 @Slf4j @Data -public class Lwm2mClientRpcRequest { +public class LwM2mClientRpcRequest { private Registration registration; private TransportProtos.SessionInfoProto sessionInfo; @@ -75,10 +75,10 @@ public class Lwm2mClientRpcRequest { private String infoMsg; private String responseCode; - public Lwm2mClientRpcRequest() { + public LwM2mClientRpcRequest() { } - public Lwm2mClientRpcRequest(LwM2mTypeOper lwM2mTypeOper, String bodyParams, int requestId, + public LwM2mClientRpcRequest(LwM2mTypeOper lwM2mTypeOper, String bodyParams, int requestId, TransportProtos.SessionInfoProto sessionInfo, Registration registration, DefaultLwM2MTransportMsgHandler handler) { this.registration = registration; this.sessionInfo = sessionInfo; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mFwSwUpdate.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mFwSwUpdate.java index 9cafc8f792..97496b91ce 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mFwSwUpdate.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mFwSwUpdate.java @@ -20,6 +20,7 @@ import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.eclipse.leshan.core.request.ContentFormat; +import org.eclipse.leshan.server.registration.Registration; import org.thingsboard.server.common.data.ota.OtaPackageType; import org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus; import org.thingsboard.server.gen.transport.TransportProtos; @@ -36,20 +37,31 @@ import static org.eclipse.californium.core.coap.CoAP.ResponseCode.CONTENT; import static org.thingsboard.server.common.data.ota.OtaPackageKey.STATE; import static org.thingsboard.server.common.data.ota.OtaPackageType.FIRMWARE; import static org.thingsboard.server.common.data.ota.OtaPackageType.SOFTWARE; +import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.DOWNLOADED; +import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.FAILED; +import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.INITIATED; +import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDATED; import static org.thingsboard.server.common.data.ota.OtaPackageUpdateStatus.UPDATING; import static org.thingsboard.server.common.data.ota.OtaPackageUtil.getAttributeKey; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_3_VER_ID; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_5_VER_ID; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_NAME_ID; -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_ID; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_19_ID; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_5_ID; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_PACKAGE_URI_ID; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_RESULT_ID; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_STATE_ID; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_UPDATE; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_UPDATE_ID; -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FW_VER_ID; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_ERROR; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LOG_LW2M_INFO; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_19_BINARY; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_5_BINARY; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_5_TEMP_URL; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.EXECUTE; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.OBSERVE; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_REPLACE; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.OTA_COAP_RESOURCE; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_INSTALL_ID; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_NAME_ID; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_PACKAGE_ID; @@ -59,6 +71,7 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.S import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_UPDATE_STATE_ID; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SW_VER_ID; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer; +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.equalsFwSateToFirmwareUpdateStatus; import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.splitCamelCaseString; @Slf4j @@ -106,27 +119,29 @@ public class LwM2mFwSwUpdate { private final List pendingInfoRequestsStart; @Getter @Setter - private volatile Lwm2mClientRpcRequest rpcRequest; + private volatile LwM2mClientRpcRequest rpcRequest; @Getter @Setter - private volatile boolean typeUpdateByURL; + private volatile int updateStrategy; - public LwM2mFwSwUpdate(LwM2mClient lwM2MClient, OtaPackageType type) { + public LwM2mFwSwUpdate(LwM2mClient lwM2MClient, OtaPackageType type, int updateStrategy) { this.lwM2MClient = lwM2MClient; this.pendingInfoRequestsStart = new CopyOnWriteArrayList<>(); this.type = type; this.stateUpdate = null; - this.typeUpdateByURL = false; + this.updateStrategy = updateStrategy; this.initPathId(); } private void initPathId() { if (FIRMWARE.equals(this.type)) { - this.pathPackageId = FW_PACKAGE_ID; + this.pathPackageId = LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_5_BINARY.code == this.updateStrategy ? + FW_PACKAGE_5_ID : LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_5_TEMP_URL.code == this.updateStrategy ? + FW_PACKAGE_URI_ID : FW_PACKAGE_19_ID; this.pathStateId = FW_STATE_ID; this.pathResultId = FW_RESULT_ID; this.pathNameId = FW_NAME_ID; - this.pathVerId = FW_VER_ID; + this.pathVerId = FW_5_VER_ID; this.pathInstallId = FW_UPDATE_ID; this.wUpdate = FW_UPDATE; } else if (SOFTWARE.equals(this.type)) { @@ -147,13 +162,13 @@ public class LwM2mFwSwUpdate { } if (this.pendingInfoRequestsStart.size() == 0) { this.infoFwSwUpdate = false; - if (!OtaPackageUpdateStatus.DOWNLOADING.name().equals(this.stateUpdate)) { - boolean conditionalStart = this.type.equals(FIRMWARE) ? this.conditionalFwUpdateStart() : - this.conditionalSwUpdateStart(); - if (conditionalStart) { - this.writeFwSwWare(handler, request); - } +// if (!FAILED.name().equals(this.stateUpdate)) { + boolean conditionalStart = this.type.equals(FIRMWARE) ? this.conditionalFwUpdateStart(handler) : + this.conditionalSwUpdateStart(handler); + if (conditionalStart) { + this.writeFwSwWare(handler, request); } +// } } } @@ -163,31 +178,42 @@ public class LwM2mFwSwUpdate { */ public void writeFwSwWare(DefaultLwM2MTransportMsgHandler handler, LwM2mTransportRequest request) { if (this.currentId != null) { - this.stateUpdate = OtaPackageUpdateStatus.DOWNLOADING.name(); + this.stateUpdate = OtaPackageUpdateStatus.INITIATED.name(); this.sendLogs(handler, WRITE_REPLACE.name(), LOG_LW2M_INFO, null); - int chunkSize = 0; - int chunk = 0; - byte[] firmwareChunk = handler.otaPackageDataCache.get(this.currentId.toString(), chunkSize, chunk); String targetIdVer = convertPathFromObjectIdToIdVer(this.pathPackageId, this.lwM2MClient.getRegistration()); String fwMsg = String.format("%s: Start type operation %s paths: %s", LOG_LW2M_INFO, - LwM2mTransportUtil.LwM2mTypeOper.FW_UPDATE.name(), FW_PACKAGE_ID); + LwM2mTransportUtil.LwM2mTypeOper.FW_UPDATE.name(), this.pathPackageId); handler.sendLogsToThingsboard(fwMsg, lwM2MClient.getRegistration().getId()); log.warn("8) Start firmware Update. Send save to: [{}] ver: [{}] path: [{}]", this.lwM2MClient.getDeviceName(), this.currentVersion, targetIdVer); - request.sendAllRequest(this.lwM2MClient.getRegistration(), targetIdVer, WRITE_REPLACE, ContentFormat.OPAQUE.getName(), - firmwareChunk, handler.config.getTimeout(), this.rpcRequest); + if (LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_5_BINARY.code == this.updateStrategy) { + int chunkSize = 0; + int chunk = 0; + byte[] firmwareChunk = handler.otaPackageDataCache.get(this.currentId.toString(), chunkSize, chunk); + request.sendAllRequest(this.lwM2MClient.getRegistration(), targetIdVer, WRITE_REPLACE, ContentFormat.OPAQUE.getName(), + firmwareChunk, handler.config.getTimeout(), this.rpcRequest); + } else if (LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_5_TEMP_URL.code == this.updateStrategy) { + Registration registration = this.getLwM2MClient().getRegistration(); + String api = handler.config.getHostRequests(); + int port = registration.getIdentity().isSecure() ? handler.config.getSecurePort() : handler.config.getPort(); + String uri = "coap://" + api + ":" + Integer.valueOf(port) + "/" + OTA_COAP_RESOURCE + "/" + this.currentId.toString(); + request.sendAllRequest(this.lwM2MClient.getRegistration(), targetIdVer, WRITE_REPLACE, null, + uri, handler.config.getTimeout(), this.rpcRequest); + } else if (LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_19_BINARY.code == this.updateStrategy) { + + } } else { String msgError = "FirmWareId is null."; log.warn("6) [{}]", msgError); if (this.rpcRequest != null) { handler.sentRpcResponse(this.rpcRequest, CONTENT.name(), msgError, LOG_LW2M_ERROR); } - log.error (msgError); + log.error(msgError); this.sendLogs(handler, WRITE_REPLACE.name(), LOG_LW2M_ERROR, msgError); } } public void sendLogs(DefaultLwM2MTransportMsgHandler handler, String typeOper, String typeInfo, String msgError) { - this.sendSateOnThingsBoard(handler); +// this.sendSateOnThingsBoard(handler); String msg = String.format("%s: %s, %s, pkgVer: %s: pkgName - %s state - %s.", typeInfo, this.wUpdate, typeOper, this.currentVersion, this.currentTitle, this.stateUpdate); if (LOG_LW2M_ERROR.equals(typeInfo)) { @@ -203,32 +229,50 @@ public class LwM2mFwSwUpdate { * send execute */ public void executeFwSwWare(DefaultLwM2MTransportMsgHandler handler, LwM2mTransportRequest request) { - this.setStateUpdate(UPDATING.name()); this.sendLogs(handler, EXECUTE.name(), LOG_LW2M_INFO, null); request.sendAllRequest(this.lwM2MClient.getRegistration(), this.pathInstallId, EXECUTE, ContentFormat.TLV.getName(), null, 0, this.rpcRequest); } /** - * Firmware start: + * Firmware start: Check if the version has changed and launch a new update. + * -ObjectId 5, Binary or ObjectId 5, URI * -- If the result of the update - errors (more than 1) - This means that the previous. the update failed. * - We launch the update regardless of the state of the firmware and its version. - * -- 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. - * -- If the result of the update is not errors and is empty - This means that there has not been an update yet. - * - Check if the version has changed and launch a new update. + * -- If the result of the update - errors (more than 1) - This means that the previous. the update failed. + * * ObjectId 5, Binary + * -- 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. + * Compare current versions by equals. + * * ObjectId 5, URI + * -- 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. + * Compare current versions by contains. */ - private boolean conditionalFwUpdateStart() { + private boolean conditionalFwUpdateStart(DefaultLwM2MTransportMsgHandler handler) { Long updateResultFw = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId); + String ver5 = (String) this.lwM2MClient.getResourceValue(null, this.pathVerId); + String pathName = (String) this.lwM2MClient.getResourceValue(null, this.pathNameId); + String ver3 = (String) this.lwM2MClient.getResourceValue(null, FW_3_VER_ID); // #1/#2 - return updateResultFw > LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.code || - ( - (updateResultFw <= LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.code - ) && - ( - (this.currentVersion != null && !this.currentVersion.equals(this.lwM2MClient.getResourceValue(null, this.pathVerId))) || - (this.currentTitle != null && !this.currentTitle.equals(this.lwM2MClient.getResourceValue(null, this.pathNameId))) - ) - ); + String fwMsg = null; + if ((this.currentVersion != null && ( + ver5 != null && ver5.equals(this.currentVersion) || + ver3 != null && ver3.contains(this.currentVersion) + )) || + (this.currentTitle != null && pathName != null && this.currentTitle.equals(pathName))) { + fwMsg = String.format("%s: The update was interrupted. The device has the same version: %s.", LOG_LW2M_ERROR, + this.currentVersion); + } + else if (updateResultFw != null && updateResultFw > LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.code) { + fwMsg = String.format("%s: The update was interrupted. The device has the status UpdateResult: error (%d).", LOG_LW2M_ERROR, + updateResultFw); + } + if (fwMsg != null) { + handler.sendLogsToThingsboard(fwMsg, lwM2MClient.getRegistration().getId()); + return false; + } + else { + return true; + } } @@ -252,7 +296,7 @@ public class LwM2mFwSwUpdate { /** * After operation Execute success inspection Update Result : - * > 1 error: "Firmware updated successfully" + * > 1 error: "Firmware updated successfully" */ public boolean conditionalFwExecuteAfterError() { Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId); @@ -268,7 +312,7 @@ public class LwM2mFwSwUpdate { * - If Update Result is not errors and ver is not empty - This means that before unInstall update * * - Check if the version has changed and launch a new update. */ - private boolean conditionalSwUpdateStart() { + private boolean conditionalSwUpdateStart(DefaultLwM2MTransportMsgHandler handler) { Long updateResultSw = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId); // #1/#2 return updateResultSw >= LwM2mTransportUtil.UpdateResultSw.NOT_ENOUGH_STORAGE.code || @@ -296,7 +340,7 @@ public class LwM2mFwSwUpdate { * -- inspection Update Result: * ---- FW если Update Result == 1 ("Firmware updated successfully") или SW если Update Result == 2 ("Software successfully installed.") * -- fw_state/sw_state = UPDATED - * + *

* After finish operation Execute (error): * -- inspection updateResult and send to thingsboard info about error * --- send to telemetry ( key - this is name Update Result in model) ( @@ -329,7 +373,7 @@ public class LwM2mFwSwUpdate { /** * After operation Execute success inspection Update Result : - * >= 50 - error "NOT_ENOUGH_STORAGE" + * >= 50 - error "NOT_ENOUGH_STORAGE" */ public boolean conditionalSwExecuteAfterError() { Long updateResult = (Long) this.lwM2MClient.getResourceValue(null, this.pathResultId); @@ -358,18 +402,75 @@ public class LwM2mFwSwUpdate { public void sendReadObserveInfo(LwM2mTransportRequest request) { this.infoFwSwUpdate = true; - this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer( - this.pathVerId, this.lwM2MClient.getRegistration())); - this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer( - this.pathNameId, this.lwM2MClient.getRegistration())); this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer( this.pathStateId, this.lwM2MClient.getRegistration())); this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer( this.pathResultId, this.lwM2MClient.getRegistration())); + this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer( + FW_3_VER_ID, this.lwM2MClient.getRegistration())); + if (LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_5_BINARY.code == this.updateStrategy || + LwM2mTransportUtil.LwM2MFirmwareUpdateStrategy.OBJ_19_BINARY.code == this.updateStrategy || + SOFTWARE.equals(this.type)) { + this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer( + this.pathVerId, this.lwM2MClient.getRegistration())); + this.pendingInfoRequestsStart.add(convertPathFromObjectIdToIdVer( + this.pathNameId, this.lwM2MClient.getRegistration())); + } this.pendingInfoRequestsStart.forEach(pathIdVer -> { request.sendAllRequest(this.lwM2MClient.getRegistration(), pathIdVer, OBSERVE, ContentFormat.TLV.getName(), null, 0, this.rpcRequest); }); } + + /** + * Before operation Execute (FwUpdate) inspection Update Result : + * - after finished operation Write result: success (FwUpdate): fw_state = DOWNLOADED + * - before start operation Execute (FwUpdate) Update Result = 0 - Initial value + * - start Execute (FwUpdate) + * After finished operation Execute (FwUpdate) inspection Update Result : + * - after start operation Execute (FwUpdate): fw_state = UPDATING + * - after success finished operation Execute (FwUpdate) Update Result == 1 ("Firmware updated successfully") + * - finished operation Execute (FwUpdate) + */ + public void updateStateOta(DefaultLwM2MTransportMsgHandler handler, LwM2mTransportRequest request, + Registration registration, String path, int value) { + if (OBJ_5_BINARY.code == this.getUpdateStrategy()) { + if ((convertPathFromObjectIdToIdVer(FW_RESULT_ID, registration).equals(path))) { + if (DOWNLOADED.name().equals(this.getStateUpdate()) + && this.conditionalFwExecuteStart()) { + this.executeFwSwWare(handler, request); + } else if (UPDATING.name().equals(this.getStateUpdate()) + && this.conditionalFwExecuteAfterSuccess()) { + this.finishFwSwUpdate(handler, true); + } else if (UPDATING.name().equals(this.getStateUpdate()) + && this.conditionalFwExecuteAfterError()) { + this.finishFwSwUpdate(handler, false); + } + } + } else if (OBJ_5_TEMP_URL.code == this.getUpdateStrategy()) { + if ((convertPathFromObjectIdToIdVer(FW_STATE_ID, registration).equals(path))) { + String state = equalsFwSateToFirmwareUpdateStatus(LwM2mTransportUtil.StateFw.fromStateFwByCode(value)).name(); + if (!FAILED.name().equals(this.stateUpdate) && StringUtils.isNotEmpty(state) && !state.equals(this.stateUpdate)) { + this.stateUpdate = state; + this.sendSateOnThingsBoard(handler); + } + if (value == LwM2mTransportUtil.StateFw.DOWNLOADED.code) { + this.executeFwSwWare(handler, request); + } + } + if ((convertPathFromObjectIdToIdVer(FW_RESULT_ID, registration).equals(path))) { + if (value == LwM2mTransportUtil.UpdateResultFw.INITIAL.code) { + this.setStateUpdate(INITIATED.name()); + } else if (value == LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.code) { + this.setStateUpdate(UPDATED.name()); + } else if (value > LwM2mTransportUtil.UpdateResultFw.UPDATE_SUCCESSFULLY.code) { + this.setStateUpdate(FAILED.name()); + } + this.sendSateOnThingsBoard(handler); + } + } else if (OBJ_19_BINARY.code == this.getUpdateStrategy()) { + + } + } } diff --git a/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml b/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml index 39acda4590..261d1c79f1 100644 --- a/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml +++ b/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml @@ -104,9 +104,13 @@ transport: server: id: "${LWM2M_SERVER_ID:123}" bind_address: "${LWM2M_BIND_ADDRESS:0.0.0.0}" + # the host to receive requests to the server + bind_address_requests: "${LWM2M_BIND_ADDRESS_REQUESTS:0.0.0.0}" bind_port: "${LWM2M_BIND_PORT:5685}" security: bind_address: "${LWM2M_BIND_ADDRESS_SECURITY:0.0.0.0}" + # the security host to receive requests to the server + bind_address_requests: "${LWM2M_BIND_ADDRESS_SECURITY_REQUESTS:0.0.0.0}" bind_port: "${LWM2M_BIND_PORT_SECURITY:5686}" # Only for RPK: Public & Private Key. If the keystore file is missing or not working public_x: "${LWM2M_SERVER_PUBLIC_X:05064b9e6762dd8d8b8a52355d7b4d8b9a3d64e6d2ee277d76c248861353f358}" @@ -114,13 +118,18 @@ transport: private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED:308193020100301306072a8648ce3d020106082a8648ce3d030107047930770201010420dc774b309e547ceb48fee547e104ce201a9c48c449dc5414cd04e7f5cf05f67ba00a06082a8648ce3d030107a1440342000405064b9e6762dd8d8b8a52355d7b4d8b9a3d64e6d2ee277d76c248861353f3585eeb1838e4f9e37b31fa347aef5ce3431eb54e0a2506910c5e0298817445721b}" # Only Certificate_x509: alias: "${LWM2M_KEYSTORE_ALIAS_SERVER:server}" + skip_validity_check_for_client_cert: "${TB_LWM2M_SERVER_SECURITY_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}" bootstrap: enable: "${LWM2M_ENABLED_BS:true}" id: "${LWM2M_SERVER_ID_BS:111}" bind_address: "${LWM2M_BIND_ADDRESS_BS:0.0.0.0}" + # the host to receive requests to the server + bind_address_requests: "${LWM2M_BIND_ADDRESS_REQUESTS_BS:0.0.0.0}" bind_port: "${LWM2M_BIND_PORT_BS:5687}" security: - bind_address: "${LWM2M_BIND_ADDRESS_BS:0.0.0.0}" + bind_address: "${LWM2M_BIND_ADDRESS_SECURITY_BS:0.0.0.0}" + # the security host to receive requests to the server + bind_address_requests: "${LWM2M_BIND_ADDRESS_SECURITY_REQUESTS_BS:0.0.0.0}" bind_port: "${LWM2M_BIND_PORT_SECURITY_BS:5688}" # Only for RPK: Public & Private Key. If the keystore file is missing or not working public_x: "${LWM2M_SERVER_PUBLIC_X_BS:5017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f91}" @@ -139,6 +148,8 @@ transport: root_alias: "${LWM2M_SERVER_ROOT_CA:rootca}" enable_gen_new_key_psk_rpk: "${ENABLE_GEN_NEW_KEY_PSK_RPK:false}" timeout: "${LWM2M_TIMEOUT:120000}" + blockwise_lifetime: "${BLOCKWISE_LIFETIME:300000}" + block2_option_enable: "${BLOCK2_OPTION_ENABLED:true}" recommended_ciphers: "${LWM2M_RECOMMENDED_CIPHERS:false}" recommended_supported_groups: "${LWM2M_RECOMMENDED_SUPPORTED_GROUPS:true}" response_pool_size: "${LWM2M_RESPONSE_POOL_SIZE:100}" @@ -150,6 +161,13 @@ transport: log_max_length: "${LWM2M_LOG_MAX_LENGTH:100}" # Use redis for Security and Registration stores redis.enabled: "${LWM2M_REDIS_ENABLED:false}" + snmp: + enabled: "${SNMP_ENABLED:true}" + response_processing: + # parallelism level for executor (workStealingPool) that is responsible for handling responses from SNMP devices + parallelism_level: "${SNMP_RESPONSE_PROCESSING_PARALLELISM_LEVEL:20}" + # to configure SNMP to work over UDP or TCP + underlying_protocol: "${SNMP_UNDERLYING_PROTOCOL:udp}" queue: type: "${TB_QUEUE_TYPE:kafka}" # kafka (Apache Kafka) or aws-sqs (AWS SQS) or pubsub (PubSub) or service-bus (Azure Service Bus) or rabbitmq (RabbitMQ) diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.html b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.html index 7c3ec6cacf..b164e168cf 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.html @@ -144,36 +144,36 @@

- {{ 'device-profile.lwm2m.client-only-observe-after-connect-label' | translate }} - {{ 'device-profile.lwm2m.client-strategy-label' | translate }} + - {{ 'device-profile.lwm2m.client-only-observe-after-connect' | translate: + {{ 'device-profile.lwm2m.client-strategy' | translate: {count: 1} }} - {{ 'device-profile.lwm2m.client-only-observe-after-connect' | translate: + {{ 'device-profile.lwm2m.client-strategy' | translate: {count: 2} }}
- {{ 'device-profile.lwm2m.fw-update-url-label' | translate }} - - {{ 'device-profile.lwm2m.fw-update-url' | translate: + {{ 'device-profile.lwm2m.fw-update-strategy-label' | translate }} + + {{ 'device-profile.lwm2m.fw-update-strategy' | translate: {count: 1} }} - {{ 'device-profile.lwm2m.fw-update-url' | translate: + {{ 'device-profile.lwm2m.fw-update-strategy' | translate: {count: 2} }} - {{ 'device-profile.lwm2m.fw-update-url' | translate: + {{ 'device-profile.lwm2m.fw-update-strategy' | translate: {count: 3} }} - {{ 'device-profile.lwm2m.sw-update-url-label' | translate }} - - {{ 'device-profile.lwm2m.sw-update-url' | translate: + {{ 'device-profile.lwm2m.sw-update-strategy-label' | translate }} + + {{ 'device-profile.lwm2m.sw-update-strategy' | translate: {count: 1} }} - {{ 'device-profile.lwm2m.sw-update-url' | translate: + {{ 'device-profile.lwm2m.sw-update-strategy' | translate: {count: 2} }} diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.ts index 3342d24791..886ed12c47 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.ts @@ -89,9 +89,9 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro binding:[], bootstrapServer: [null, Validators.required], lwm2mServer: [null, Validators.required], - clientOnlyObserveAfterConnect: [1, []], - fwUpdateUrl: [1, []], - swUpdateUrl: [1, []], + clientStrategy: [1, []], + fwUpdateStrategy: [1, []], + swUpdateStrategy: [1, []], }); this.lwm2mDeviceConfigFormGroup = this.fb.group({ configurationJson: [null, Validators.required] @@ -161,9 +161,9 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro binding: this.configurationValue.bootstrap.servers.binding, bootstrapServer: this.configurationValue.bootstrap.bootstrapServer, lwm2mServer: this.configurationValue.bootstrap.lwm2mServer, - clientOnlyObserveAfterConnect: this.configurationValue.clientLwM2mSettings.clientOnlyObserveAfterConnect, - fwUpdateUrl: this.configurationValue.clientLwM2mSettings.fwUpdateUrl, - swUpdateUrl: this.configurationValue.clientLwM2mSettings.swUpdateUrl + clientStrategy: this.configurationValue.clientLwM2mSettings.clientStrategy, + fwUpdateStrategy: this.configurationValue.clientLwM2mSettings.fwUpdateStrategy, + swUpdateStrategy: this.configurationValue.clientLwM2mSettings.swUpdateStrategy }, {emitEvent: false}); } @@ -194,9 +194,9 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro bootstrapServers.defaultMinPeriod = config.defaultMinPeriod; bootstrapServers.notifIfDisabled = config.notifIfDisabled; bootstrapServers.binding = config.binding; - this.configurationValue.clientLwM2mSettings.clientOnlyObserveAfterConnect = config.clientOnlyObserveAfterConnect; - this.configurationValue.clientLwM2mSettings.fwUpdateUrl = config.fwUpdateUrl; - this.configurationValue.clientLwM2mSettings.swUpdateUrl = config.swUpdateUrl; + this.configurationValue.clientLwM2mSettings.clientStrategy = config.clientStrategy; + this.configurationValue.clientLwM2mSettings.fwUpdateStrategy = config.fwUpdateStrategy; + this.configurationValue.clientLwM2mSettings.swUpdateStrategy = config.swUpdateStrategy; this.upDateJsonAllConfig(); this.updateModel(); } diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-config.models.ts b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-config.models.ts index af4bdc79b0..48613f58de 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-config.models.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-config.models.ts @@ -166,9 +166,9 @@ export interface Lwm2mProfileConfigModels { } export interface ClientLwM2mSettings { - clientOnlyObserveAfterConnect: string; - fwUpdateUrl: string; - swUpdateUrl: string; + clientStrategy: string; + fwUpdateStrategy: string; + swUpdateStrategy: string; } export interface ObservableAttributes { @@ -238,9 +238,9 @@ export function getDefaultProfileConfig(hostname?: any): Lwm2mProfileConfigModel function getDefaultProfileClientLwM2mSettingsConfig(): ClientLwM2mSettings { return { - clientOnlyObserveAfterConnect: "1", - fwUpdateUrl: "1", - swUpdateUrl: "1" + clientStrategy: "1", + fwUpdateStrategy: "1", + swUpdateStrategy: "1" }; } diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index d0209301fa..f6d86e4e84 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -1247,13 +1247,13 @@ "bootstrap-server-account-timeout": "Account after the timeout", "bootstrap-server-account-timeout-tip": "Bootstrap-Server Account after the timeout value given by this resource.", "others-tab": "Other settings...", - "client-only-observe-after-connect-label": "Strategy", - "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} }", - "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.} }", - "fw-update-url-label": "Firmware update strategy", - "fw-update-url": "{ count, plural, 1 {Push firmware update as binary file using Object 5 and Resource 0 (Package).} 2 {Push firmware update as binary file using Object 5 and Resource 0 (Package).} other {Push firmware update as binary file using Object 19 and Resource 0 (Data).} }", - "sw-update-url-label": "Software update strategy", - "sw-update-url": "{ 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).} }", + "client-strategy-label": "Strategy", + "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} }", + "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.} }", + "fw-update-strategy-label": "Firmware update strategy", + "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).} }", + "sw-update-strategy-label": "Software update strategy", + "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).} }", "config-json-tab": "Json Config Profile Device" } },