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