Commit e33420d3a89264b3df099654eea8b3671ca0fbec

Authored by nickAS21
Committed by GitHub
1 parent 9dcb7b9b

Lwm2m: firmwareUpdate (#4516)

* Lwm2m: firmwareUpdate

* Lwm2m: firmwareUpdate with merge master

* Lwm2m: firmwareUpdate cleaned

* Lwm2m: delete Californium.properties

* Lwm2m: merge with master
Showing 17 changed files with 435 additions and 208 deletions
@@ -185,7 +185,7 @@ public class DefaultTbResourceService implements TbResourceService { @@ -185,7 +185,7 @@ public class DefaultTbResourceService implements TbResourceService {
185 instance.setId(0); 185 instance.setId(0);
186 List<LwM2mResourceObserve> resources = new ArrayList<>(); 186 List<LwM2mResourceObserve> resources = new ArrayList<>();
187 obj.resources.forEach((k, v) -> { 187 obj.resources.forEach((k, v) -> {
188 - if (!v.operations.isExecutable()) { 188 + if (v.operations.isReadable()) {
189 LwM2mResourceObserve lwM2MResourceObserve = new LwM2mResourceObserve(k, v.name, false, false, false); 189 LwM2mResourceObserve lwM2MResourceObserve = new LwM2mResourceObserve(k, v.name, false, false, false);
190 resources.add(lwM2MResourceObserve); 190 resources.add(lwM2MResourceObserve);
191 } 191 }
@@ -95,8 +95,8 @@ public class DataConstants { @@ -95,8 +95,8 @@ public class DataConstants {
95 95
96 //firmware 96 //firmware
97 //telemetry 97 //telemetry
98 - public static final String CURRENT_FIRMWARE_TITLE = "cur_fw_title";  
99 - public static final String CURRENT_FIRMWARE_VERSION = "cur_fw_version"; 98 + public static final String CURRENT_FIRMWARE_TITLE = "current_fw_title";
  99 + public static final String CURRENT_FIRMWARE_VERSION = "current_fw_version";
100 public static final String TARGET_FIRMWARE_TITLE = "target_fw_title"; 100 public static final String TARGET_FIRMWARE_TITLE = "target_fw_title";
101 public static final String TARGET_FIRMWARE_VERSION = "target_fw_version"; 101 public static final String TARGET_FIRMWARE_VERSION = "target_fw_version";
102 public static final String TARGET_FIRMWARE_TS = "target_fw_ts"; 102 public static final String TARGET_FIRMWARE_TS = "target_fw_ts";
@@ -55,7 +55,7 @@ import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE @@ -55,7 +55,7 @@ import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE
55 import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8; 55 import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
56 import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256; 56 import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256;
57 import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CCM_8; 57 import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CCM_8;
58 -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.getCoapConfig; 58 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mNetworkConfig.getCoapConfig;
59 59
60 @Slf4j 60 @Slf4j
61 @Component 61 @Component
@@ -93,7 +93,6 @@ public class LwM2MTransportBootstrapServerConfiguration { @@ -93,7 +93,6 @@ public class LwM2MTransportBootstrapServerConfiguration {
93 builder.setCoapConfig(getCoapConfig(bootstrapPortNoSec, bootstrapSecurePort)); 93 builder.setCoapConfig(getCoapConfig(bootstrapPortNoSec, bootstrapSecurePort));
94 94
95 /** Define model provider (Create Models )*/ 95 /** Define model provider (Create Models )*/
96 -// builder.setModel(new StaticModel(contextS.getLwM2MTransportConfigServer().getModelsValueCommon()));  
97 96
98 /** Create credentials */ 97 /** Create credentials */
99 this.setServerWithCredentials(builder); 98 this.setServerWithCredentials(builder);
  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 org.eclipse.californium.core.network.config.NetworkConfig;
  19 +
  20 +public class LwM2mNetworkConfig {
  21 +
  22 + public static NetworkConfig getCoapConfig(Integer serverPortNoSec, Integer serverSecurePort) {
  23 + NetworkConfig coapConfig = new NetworkConfig();
  24 + coapConfig.setInt(NetworkConfig.Keys.COAP_PORT,serverPortNoSec);
  25 + coapConfig.setInt(NetworkConfig.Keys.COAP_SECURE_PORT,serverSecurePort);
  26 + /**
  27 + * Example:Property for large packet:
  28 + * #NetworkConfig config = new NetworkConfig();
  29 + * #config.setInt(NetworkConfig.Keys.MAX_MESSAGE_SIZE,32);
  30 + * #config.setInt(NetworkConfig.Keys.PREFERRED_BLOCK_SIZE,32);
  31 + * #config.setInt(NetworkConfig.Keys.MAX_RESOURCE_BODY_SIZE,2048);
  32 + * #config.setInt(NetworkConfig.Keys.MAX_RETRANSMIT,3);
  33 + * #config.setInt(NetworkConfig.Keys.MAX_TRANSMIT_WAIT,120000);
  34 + */
  35 +
  36 + /**
  37 + * Property to indicate if the response should always include the Block2 option \
  38 + * when client request early blockwise negociation but the response can be sent on one packet.
  39 + * - value of false indicate that the server will respond without block2 option if no further blocks are required.
  40 + * - value of true indicate that the server will response with block2 option event if no further blocks are required.
  41 + * CoAP client will try to use block mode
  42 + * or adapt the block size when receiving a 4.13 Entity too large response code
  43 + */
  44 + coapConfig.setBoolean(NetworkConfig.Keys.BLOCKWISE_STRICT_BLOCK2_OPTION, true);
  45 + /***
  46 + * Property to indicate if the response should always include the Block2 option \
  47 + * when client request early blockwise negociation but the response can be sent on one packet.
  48 + * - value of false indicate that the server will respond without block2 option if no further blocks are required.
  49 + * - value of true indicate that the server will response with block2 option event if no further blocks are required.
  50 + */
  51 + coapConfig.setBoolean(NetworkConfig.Keys.BLOCKWISE_ENTITY_TOO_LARGE_AUTO_FAILOVER, true);
  52 +
  53 + coapConfig.setInt(NetworkConfig.Keys.BLOCKWISE_STATUS_LIFETIME, 300000);
  54 + /**
  55 + * !!! REQUEST_ENTITY_TOO_LARGE CODE=4.13
  56 + * The maximum size of a resource body (in bytes) that will be accepted
  57 + * as the payload of a POST/PUT or the response to a GET request in a
  58 + * transparent> blockwise transfer.
  59 + * This option serves as a safeguard against excessive memory
  60 + * consumption when many resources contain large bodies that cannot be
  61 + * transferred in a single CoAP message. This option has no impact on
  62 + * *manually* managed blockwise transfers in which the blocks are handled individually.
  63 + * Note that this option does not prevent local clients or resource
  64 + * implementations from sending large bodies as part of a request or response to a peer.
  65 + * The default value of this property is DEFAULT_MAX_RESOURCE_BODY_SIZE = 8192
  66 + * A value of {@code 0} turns off transparent handling of blockwise transfers altogether.
  67 + */
  68 +// coapConfig.setInt(NetworkConfig.Keys.MAX_RESOURCE_BODY_SIZE, 8192);
  69 + coapConfig.setInt(NetworkConfig.Keys.MAX_RESOURCE_BODY_SIZE, 16384);
  70 + /**
  71 + * The default DTLS response matcher.
  72 + * Supported values are STRICT, RELAXED, or PRINCIPAL.
  73 + * The default value is STRICT.
  74 + * Create new instance of udp endpoint context matcher.
  75 + * Params:
  76 + * checkAddress
  77 + * – true with address check, (STRICT, UDP)
  78 + * - false, without
  79 + */
  80 + coapConfig.setString(NetworkConfig.Keys.RESPONSE_MATCHING, "STRICT");
  81 + /**
  82 + * https://tools.ietf.org/html/rfc7959#section-2.9.3
  83 + * The block size (number of bytes) to use when doing a blockwise transfer. \
  84 + * This value serves as the upper limit for block size in blockwise transfers
  85 + */
  86 + coapConfig.setInt(NetworkConfig.Keys.PREFERRED_BLOCK_SIZE, 512);
  87 + /**
  88 + * The maximum payload size (in bytes) that can be transferred in a
  89 + * single message, i.e. without requiring a blockwise transfer.
  90 + * NB: this value MUST be adapted to the maximum message size supported by the transport layer.
  91 + * In particular, this value cannot exceed the network's MTU if UDP is used as the transport protocol
  92 + * DEFAULT_VALUE = 1024
  93 + */
  94 + coapConfig.setInt(NetworkConfig.Keys.MAX_MESSAGE_SIZE, 512);
  95 +
  96 + coapConfig.setInt(NetworkConfig.Keys.MAX_RETRANSMIT, 4);
  97 +
  98 + return coapConfig;
  99 + }
  100 +}
@@ -26,6 +26,7 @@ import org.eclipse.leshan.server.registration.RegistrationUpdate; @@ -26,6 +26,7 @@ import org.eclipse.leshan.server.registration.RegistrationUpdate;
26 26
27 import java.util.Collection; 27 import java.util.Collection;
28 28
  29 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_INFO;
29 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertPathFromObjectIdToIdVer; 30 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertPathFromObjectIdToIdVer;
30 31
31 @Slf4j 32 @Slf4j
@@ -85,17 +86,19 @@ public class LwM2mServerListener { @@ -85,17 +86,19 @@ public class LwM2mServerListener {
85 86
86 @Override 87 @Override
87 public void cancelled(Observation observation) { 88 public void cancelled(Observation observation) {
88 - log.info("Received notification cancelled from [{}] ", observation.getPath()); 89 + String msg = String.format("%s: Cancel Observation %s.", LOG_LW2M_INFO, observation.getPath());
  90 + service.sendLogsToThingsboard(msg, observation.getRegistrationId());
  91 + log.trace(msg);
89 } 92 }
90 93
91 @Override 94 @Override
92 public void onResponse(Observation observation, Registration registration, ObserveResponse response) { 95 public void onResponse(Observation observation, Registration registration, ObserveResponse response) {
93 if (registration != null) { 96 if (registration != null) {
94 try { 97 try {
95 - service.onObservationResponse(registration, convertPathFromObjectIdToIdVer(observation.getPath().toString(), 98 + service.onUpdateValueAfterReadResponse(registration, convertPathFromObjectIdToIdVer(observation.getPath().toString(),
96 registration), response, null); 99 registration), response, null);
97 } catch (Exception e) { 100 } catch (Exception e) {
98 - log.error("[{}] onResponse", e.toString()); 101 + log.error("Observation/Read onResponse", e);
99 102
100 } 103 }
101 } 104 }
@@ -108,7 +111,10 @@ public class LwM2mServerListener { @@ -108,7 +111,10 @@ public class LwM2mServerListener {
108 111
109 @Override 112 @Override
110 public void newObservation(Observation observation, Registration registration) { 113 public void newObservation(Observation observation, Registration registration) {
111 - log.info("Received newObservation from [{}] endpoint [{}] ", observation.getPath(), registration.getEndpoint()); 114 + String msg = String.format("%s: Successful start newObservation %s.", LOG_LW2M_INFO,
  115 + observation.getPath());
  116 + service.sendLogsToThingsboard(msg, registration.getId());
  117 + log.trace(msg);
112 } 118 }
113 }; 119 };
114 120
@@ -25,7 +25,6 @@ import com.google.gson.JsonSyntaxException; @@ -25,7 +25,6 @@ import com.google.gson.JsonSyntaxException;
25 import com.google.gson.reflect.TypeToken; 25 import com.google.gson.reflect.TypeToken;
26 import lombok.extern.slf4j.Slf4j; 26 import lombok.extern.slf4j.Slf4j;
27 import org.apache.commons.lang3.StringUtils; 27 import org.apache.commons.lang3.StringUtils;
28 -import org.eclipse.californium.core.network.config.NetworkConfig;  
29 import org.eclipse.leshan.core.attributes.Attribute; 28 import org.eclipse.leshan.core.attributes.Attribute;
30 import org.eclipse.leshan.core.attributes.AttributeSet; 29 import org.eclipse.leshan.core.attributes.AttributeSet;
31 import org.eclipse.leshan.core.model.ObjectModel; 30 import org.eclipse.leshan.core.model.ObjectModel;
@@ -40,7 +39,6 @@ import org.eclipse.leshan.core.node.codec.CodecException; @@ -40,7 +39,6 @@ import org.eclipse.leshan.core.node.codec.CodecException;
40 import org.eclipse.leshan.core.request.DownlinkRequest; 39 import org.eclipse.leshan.core.request.DownlinkRequest;
41 import org.eclipse.leshan.core.request.WriteAttributesRequest; 40 import org.eclipse.leshan.core.request.WriteAttributesRequest;
42 import org.eclipse.leshan.core.util.Hex; 41 import org.eclipse.leshan.core.util.Hex;
43 -import org.eclipse.leshan.server.californium.LeshanServerBuilder;  
44 import org.eclipse.leshan.server.registration.Registration; 42 import org.eclipse.leshan.server.registration.Registration;
45 import org.nustaq.serialization.FSTConfiguration; 43 import org.nustaq.serialization.FSTConfiguration;
46 import org.thingsboard.server.common.data.DeviceProfile; 44 import org.thingsboard.server.common.data.DeviceProfile;
@@ -50,7 +48,6 @@ import org.thingsboard.server.common.transport.TransportServiceCallback; @@ -50,7 +48,6 @@ import org.thingsboard.server.common.transport.TransportServiceCallback;
50 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; 48 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
51 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile; 49 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile;
52 50
53 -import java.io.File;  
54 import java.io.IOException; 51 import java.io.IOException;
55 import java.util.ArrayList; 52 import java.util.ArrayList;
56 import java.util.Arrays; 53 import java.util.Arrays;
@@ -72,7 +69,6 @@ import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPA @@ -72,7 +69,6 @@ import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPA
72 @Slf4j 69 @Slf4j
73 public class LwM2mTransportHandler { 70 public class LwM2mTransportHandler {
74 71
75 - // public static final String BASE_DEVICE_API_TOPIC = "v1/devices/me";  
76 public static final String TRANSPORT_DEFAULT_LWM2M_VERSION = "1.0"; 72 public static final String TRANSPORT_DEFAULT_LWM2M_VERSION = "1.0";
77 public static final String CLIENT_LWM2M_SETTINGS = "clientLwM2mSettings"; 73 public static final String CLIENT_LWM2M_SETTINGS = "clientLwM2mSettings";
78 public static final String BOOTSTRAP = "bootstrap"; 74 public static final String BOOTSTRAP = "bootstrap";
@@ -85,19 +81,12 @@ public class LwM2mTransportHandler { @@ -85,19 +81,12 @@ public class LwM2mTransportHandler {
85 public static final String KEY_NAME = "keyName"; 81 public static final String KEY_NAME = "keyName";
86 public static final String OBSERVE_LWM2M = "observe"; 82 public static final String OBSERVE_LWM2M = "observe";
87 public static final String ATTRIBUTE_LWM2M = "attributeLwm2m"; 83 public static final String ATTRIBUTE_LWM2M = "attributeLwm2m";
88 -// public static final String RESOURCE_VALUE = "resValue";  
89 -// public static final String RESOURCE_TYPE = "resType";  
90 84
91 private static final String REQUEST = "/request"; 85 private static final String REQUEST = "/request";
92 - // private static final String RESPONSE = "/response";  
93 private static final String ATTRIBUTES = "/" + ATTRIBUTE; 86 private static final String ATTRIBUTES = "/" + ATTRIBUTE;
94 public static final String TELEMETRIES = "/" + TELEMETRY; 87 public static final String TELEMETRIES = "/" + TELEMETRY;
95 - // public static final String ATTRIBUTES_RESPONSE = ATTRIBUTES + RESPONSE;  
96 public static final String ATTRIBUTES_REQUEST = ATTRIBUTES + REQUEST; 88 public static final String ATTRIBUTES_REQUEST = ATTRIBUTES + REQUEST;
97 - // public static final String DEVICE_ATTRIBUTES_RESPONSE = ATTRIBUTES_RESPONSE + "/";  
98 public static final String DEVICE_ATTRIBUTES_REQUEST = ATTRIBUTES_REQUEST + "/"; 89 public static final String DEVICE_ATTRIBUTES_REQUEST = ATTRIBUTES_REQUEST + "/";
99 -// public static final String DEVICE_ATTRIBUTES_TOPIC = BASE_DEVICE_API_TOPIC + ATTRIBUTES;  
100 -// public static final String DEVICE_TELEMETRY_TOPIC = BASE_DEVICE_API_TOPIC + TELEMETRIES;  
101 90
102 public static final long DEFAULT_TIMEOUT = 2 * 60 * 1000L; // 2min in ms 91 public static final long DEFAULT_TIMEOUT = 2 * 60 * 1000L; // 2min in ms
103 92
@@ -112,6 +101,11 @@ public class LwM2mTransportHandler { @@ -112,6 +101,11 @@ public class LwM2mTransportHandler {
112 101
113 public static final String CLIENT_NOT_AUTHORIZED = "Client not authorized"; 102 public static final String CLIENT_NOT_AUTHORIZED = "Client not authorized";
114 103
  104 + public static final Integer FR_OBJECT_ID = 5;
  105 + public static final Integer FR_RESOURCE_VER_ID = 7;
  106 + public static final String FR_PATH_RESOURCE_VER_ID = LWM2M_SEPARATOR_PATH + FR_OBJECT_ID + LWM2M_SEPARATOR_PATH
  107 + + "0" + LWM2M_SEPARATOR_PATH + FR_RESOURCE_VER_ID;
  108 +
115 public enum LwM2mTypeServer { 109 public enum LwM2mTypeServer {
116 BOOTSTRAP(0, "bootstrap"), 110 BOOTSTRAP(0, "bootstrap"),
117 CLIENT(1, "client"); 111 CLIENT(1, "client");
@@ -168,6 +162,8 @@ public class LwM2mTransportHandler { @@ -168,6 +162,8 @@ public class LwM2mTransportHandler {
168 WRITE_ATTRIBUTES(8, "WriteAttributes"), 162 WRITE_ATTRIBUTES(8, "WriteAttributes"),
169 DELETE(9, "Delete"); 163 DELETE(9, "Delete");
170 164
  165 +// READ_INFO_FW(10, "ReadInfoFirmware");
  166 +
171 public int code; 167 public int code;
172 public String type; 168 public String type;
173 169
@@ -190,21 +186,6 @@ public class LwM2mTransportHandler { @@ -190,21 +186,6 @@ public class LwM2mTransportHandler {
190 public static final String SERVICE_CHANNEL = "SERVICE"; 186 public static final String SERVICE_CHANNEL = "SERVICE";
191 public static final String RESPONSE_CHANNEL = "RESP"; 187 public static final String RESPONSE_CHANNEL = "RESP";
192 188
193 - public static NetworkConfig getCoapConfig(Integer serverPortNoSec, Integer serverSecurePort) {  
194 - NetworkConfig coapConfig;  
195 - File configFile = new File(NetworkConfig.DEFAULT_FILE_NAME);  
196 - if (configFile.isFile()) {  
197 - coapConfig = new NetworkConfig();  
198 - coapConfig.load(configFile);  
199 - } else {  
200 - coapConfig = LeshanServerBuilder.createDefaultNetworkConfig();  
201 - coapConfig.store(configFile);  
202 - }  
203 - coapConfig.setString("COAP_PORT", Integer.toString(serverPortNoSec));  
204 - coapConfig.setString("COAP_SECURE_PORT", Integer.toString(serverSecurePort));  
205 - return coapConfig;  
206 - }  
207 -  
208 public static boolean equalsResourceValue(Object valueOld, Object valueNew, ResourceModel.Type type, LwM2mPath resourcePath) throws CodecException { 189 public static boolean equalsResourceValue(Object valueOld, Object valueNew, ResourceModel.Type type, LwM2mPath resourcePath) throws CodecException {
209 switch (type) { 190 switch (type) {
210 case BOOLEAN: 191 case BOOLEAN:
@@ -67,6 +67,7 @@ import static org.eclipse.californium.core.coap.CoAP.ResponseCode.CONTENT; @@ -67,6 +67,7 @@ import static org.eclipse.californium.core.coap.CoAP.ResponseCode.CONTENT;
67 import static org.eclipse.leshan.core.ResponseCode.BAD_REQUEST; 67 import static org.eclipse.leshan.core.ResponseCode.BAD_REQUEST;
68 import static org.eclipse.leshan.core.ResponseCode.NOT_FOUND; 68 import static org.eclipse.leshan.core.ResponseCode.NOT_FOUND;
69 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.DEFAULT_TIMEOUT; 69 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.DEFAULT_TIMEOUT;
  70 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.FR_PATH_RESOURCE_VER_ID;
70 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_ERROR; 71 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_ERROR;
71 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_INFO; 72 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_INFO;
72 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_VALUE; 73 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_VALUE;
@@ -125,7 +126,6 @@ public class LwM2mTransportRequest { @@ -125,7 +126,6 @@ public class LwM2mTransportRequest {
125 public void sendAllRequest(Registration registration, String targetIdVer, LwM2mTypeOper typeOper, 126 public void sendAllRequest(Registration registration, String targetIdVer, LwM2mTypeOper typeOper,
126 String contentFormatName, Object params, long timeoutInMs, Lwm2mClientRpcRequest rpcRequest) { 127 String contentFormatName, Object params, long timeoutInMs, Lwm2mClientRpcRequest rpcRequest) {
127 try { 128 try {
128 -  
129 String target = convertPathFromIdVerToObjectId(targetIdVer); 129 String target = convertPathFromIdVerToObjectId(targetIdVer);
130 DownlinkRequest request = null; 130 DownlinkRequest request = null;
131 ContentFormat contentFormat = contentFormatName != null ? ContentFormat.fromName(contentFormatName.toUpperCase()) : ContentFormat.DEFAULT; 131 ContentFormat contentFormat = contentFormatName != null ? ContentFormat.fromName(contentFormatName.toUpperCase()) : ContentFormat.DEFAULT;
@@ -145,11 +145,11 @@ public class LwM2mTransportRequest { @@ -145,11 +145,11 @@ public class LwM2mTransportRequest {
145 break; 145 break;
146 case OBSERVE: 146 case OBSERVE:
147 if (resultIds.isResource()) { 147 if (resultIds.isResource()) {
148 - request = new ObserveRequest(resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId()); 148 + request = new ObserveRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId());
149 } else if (resultIds.isObjectInstance()) { 149 } else if (resultIds.isObjectInstance()) {
150 - request = new ObserveRequest(resultIds.getObjectId(), resultIds.getObjectInstanceId()); 150 + request = new ObserveRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId());
151 } else if (resultIds.getObjectId() >= 0) { 151 } else if (resultIds.getObjectId() >= 0) {
152 - request = new ObserveRequest(resultIds.getObjectId()); 152 + request = new ObserveRequest(contentFormat, resultIds.getObjectId());
153 } 153 }
154 break; 154 break;
155 case OBSERVE_CANCEL: 155 case OBSERVE_CANCEL:
@@ -171,8 +171,6 @@ public class LwM2mTransportRequest { @@ -171,8 +171,6 @@ public class LwM2mTransportRequest {
171 break; 171 break;
172 case WRITE_REPLACE: 172 case WRITE_REPLACE:
173 // Request to write a <b>String Single-Instance Resource</b> using the TLV content format. 173 // Request to write a <b>String Single-Instance Resource</b> using the TLV content format.
174 -// resource = lwM2MClient.getResourceModel(targetIdVer);  
175 -// if (contentFormat.equals(ContentFormat.TLV) && !resource.multiple) {  
176 resourceModel = lwM2MClient.getResourceModel(targetIdVer, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer() 174 resourceModel = lwM2MClient.getResourceModel(targetIdVer, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer()
177 .getModelProvider()); 175 .getModelProvider());
178 if (contentFormat.equals(ContentFormat.TLV)) { 176 if (contentFormat.equals(ContentFormat.TLV)) {
@@ -181,7 +179,6 @@ public class LwM2mTransportRequest { @@ -181,7 +179,6 @@ public class LwM2mTransportRequest {
181 registration, rpcRequest); 179 registration, rpcRequest);
182 } 180 }
183 // Mode.REPLACE && Request to write a <b>String Single-Instance Resource</b> using the given content format (TEXT, TLV, JSON) 181 // Mode.REPLACE && Request to write a <b>String Single-Instance Resource</b> using the given content format (TEXT, TLV, JSON)
184 -// else if (!contentFormat.equals(ContentFormat.TLV) && !resource.multiple) {  
185 else if (!contentFormat.equals(ContentFormat.TLV)) { 182 else if (!contentFormat.equals(ContentFormat.TLV)) {
186 request = this.getWriteRequestSingleResource(contentFormat, resultIds.getObjectId(), 183 request = this.getWriteRequestSingleResource(contentFormat, resultIds.getObjectId(),
187 resultIds.getObjectInstanceId(), resultIds.getResourceId(), params, resourceModel.type, 184 resultIds.getObjectInstanceId(), resultIds.getResourceId(), params, resourceModel.type,
@@ -215,13 +212,16 @@ public class LwM2mTransportRequest { @@ -215,13 +212,16 @@ public class LwM2mTransportRequest {
215 long finalTimeoutInMs = timeoutInMs; 212 long finalTimeoutInMs = timeoutInMs;
216 lwM2MClient.getQueuedRequests().add(() -> sendRequest(registration, lwM2MClient, finalRequest, finalTimeoutInMs, rpcRequest)); 213 lwM2MClient.getQueuedRequests().add(() -> sendRequest(registration, lwM2MClient, finalRequest, finalTimeoutInMs, rpcRequest));
217 } catch (Exception e) { 214 } catch (Exception e) {
218 - log.error("[{}] [{}] [{}] Failed to send downlink.", registration.getEndpoint(), targetIdVer, typeOper, e); 215 + log.error("[{}] [{}] [{}] Failed to send downlink.", registration.getEndpoint(), targetIdVer, typeOper.name(), e);
  216 + }
  217 + } else if (OBSERVE_CANCEL == typeOper) {
  218 + log.trace("[{}], [{}] - [{}] SendRequest", registration.getEndpoint(), typeOper.name(), targetIdVer);
  219 + if (rpcRequest != null) {
  220 + rpcRequest.setInfoMsg(null);
  221 + serviceImpl.sentRpcRequest(rpcRequest, CONTENT.name(), null, null);
219 } 222 }
220 - } else if (OBSERVE_CANCEL == typeOper && rpcRequest != null) {  
221 - rpcRequest.setInfoMsg(null);  
222 - serviceImpl.sentRpcRequest(rpcRequest, CONTENT.name(), null, null);  
223 } else { 223 } else {
224 - log.error("[{}], [{}] - [{}] error SendRequest", registration.getEndpoint(), typeOper, targetIdVer); 224 + log.error("[{}], [{}] - [{}] error SendRequest", registration.getEndpoint(), typeOper.name(), targetIdVer);
225 if (rpcRequest != null) { 225 if (rpcRequest != null) {
226 String errorMsg = resourceModel == null ? String.format("Path %s not found in object version", targetIdVer) : "SendRequest - null"; 226 String errorMsg = resourceModel == null ? String.format("Path %s not found in object version", targetIdVer) : "SendRequest - null";
227 serviceImpl.sentRpcRequest(rpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR); 227 serviceImpl.sentRpcRequest(rpcRequest, NOT_FOUND.getName(), errorMsg, LOG_LW2M_ERROR);
@@ -236,8 +236,8 @@ public class LwM2mTransportRequest { @@ -236,8 +236,8 @@ public class LwM2mTransportRequest {
236 Set<String> observationPaths = observations.stream().map(observation -> observation.getPath().toString()).collect(Collectors.toUnmodifiableSet()); 236 Set<String> observationPaths = observations.stream().map(observation -> observation.getPath().toString()).collect(Collectors.toUnmodifiableSet());
237 String msg = String.format("%s: type operation %s observation paths - %s", LOG_LW2M_INFO, 237 String msg = String.format("%s: type operation %s observation paths - %s", LOG_LW2M_INFO,
238 OBSERVE_READ_ALL.type, observationPaths); 238 OBSERVE_READ_ALL.type, observationPaths);
239 - serviceImpl.sendLogsToThingsboard(msg, registration);  
240 - log.info("[{}], [{}]", registration.getEndpoint(), msg); 239 + serviceImpl.sendLogsToThingsboard(msg, registration.getId());
  240 + log.trace("[{}] [{}], [{}]", typeOper.name(), registration.getEndpoint(), msg);
241 if (rpcRequest != null) { 241 if (rpcRequest != null) {
242 String valueMsg = String.format("Observation paths - %s", observationPaths); 242 String valueMsg = String.format("Observation paths - %s", observationPaths);
243 serviceImpl.sentRpcRequest(rpcRequest, CONTENT.name(), valueMsg, LOG_LW2M_VALUE); 243 serviceImpl.sentRpcRequest(rpcRequest, CONTENT.name(), valueMsg, LOG_LW2M_VALUE);
@@ -246,7 +246,7 @@ public class LwM2mTransportRequest { @@ -246,7 +246,7 @@ public class LwM2mTransportRequest {
246 } catch (Exception e) { 246 } catch (Exception e) {
247 String msg = String.format("%s: type operation %s %s", LOG_LW2M_ERROR, 247 String msg = String.format("%s: type operation %s %s", LOG_LW2M_ERROR,
248 typeOper.name(), e.getMessage()); 248 typeOper.name(), e.getMessage());
249 - serviceImpl.sendLogsToThingsboard(msg, registration); 249 + serviceImpl.sendLogsToThingsboard(msg, registration.getId());
250 throw new Exception(e); 250 throw new Exception(e);
251 } 251 }
252 } 252 }
@@ -261,45 +261,53 @@ public class LwM2mTransportRequest { @@ -261,45 +261,53 @@ public class LwM2mTransportRequest {
261 private void sendRequest(Registration registration, LwM2mClient lwM2MClient, DownlinkRequest request, long timeoutInMs, Lwm2mClientRpcRequest rpcRequest) { 261 private void sendRequest(Registration registration, LwM2mClient lwM2MClient, DownlinkRequest request, long timeoutInMs, Lwm2mClientRpcRequest rpcRequest) {
262 leshanServer.send(registration, request, timeoutInMs, (ResponseCallback<?>) response -> { 262 leshanServer.send(registration, request, timeoutInMs, (ResponseCallback<?>) response -> {
263 if (!lwM2MClient.isInit()) { 263 if (!lwM2MClient.isInit()) {
264 - lwM2MClient.initValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration)); 264 + lwM2MClient.initReadValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration));
265 } 265 }
266 if (CoAP.ResponseCode.isSuccess(((Response) response.getCoapResponse()).getCode())) { 266 if (CoAP.ResponseCode.isSuccess(((Response) response.getCoapResponse()).getCode())) {
267 this.handleResponse(registration, request.getPath().toString(), response, request, rpcRequest); 267 this.handleResponse(registration, request.getPath().toString(), response, request, rpcRequest);
268 - if (request instanceof WriteRequest && ((WriteRequest) request).isReplaceRequest()) {  
269 - LwM2mNode node = ((WriteRequest) request).getNode();  
270 - Object value = this.converter.convertValue(((LwM2mSingleResource) node).getValue(),  
271 - ((LwM2mSingleResource) node).getType(), ResourceModel.Type.STRING, request.getPath());  
272 - String msg = String.format("%s: sendRequest Replace: CoapCde - %s Lwm2m code - %d name - %s Resource path - %s value - %s SendRequest to Client",  
273 - LOG_LW2M_INFO, ((Response) response.getCoapResponse()).getCode(), response.getCode().getCode(),  
274 - response.getCode().getName(), request.getPath().toString(), value);  
275 - serviceImpl.sendLogsToThingsboard(msg, registration);  
276 - log.info("[{}] [{}] - [{}] [{}] Update SendRequest[{}]", registration.getEndpoint(),  
277 - ((Response) response.getCoapResponse()).getCode(), response.getCode(),  
278 - request.getPath().toString(), value);  
279 - serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), null, LOG_LW2M_INFO);  
280 - }  
281 } else { 268 } else {
282 - String msg = String.format("%s: sendRequest: CoapCode - %s Lwm2m code - %d name - %s Resource path - %s SendRequest to Client", LOG_LW2M_ERROR, 269 + String msg = String.format("%s: SendRequest %s: CoapCode - %s Lwm2m code - %d name - %s Resource path - %s", LOG_LW2M_ERROR, request.getClass().getName().toString(),
283 ((Response) response.getCoapResponse()).getCode(), response.getCode().getCode(), response.getCode().getName(), request.getPath().toString()); 270 ((Response) response.getCoapResponse()).getCode(), response.getCode().getCode(), response.getCode().getName(), request.getPath().toString());
284 - serviceImpl.sendLogsToThingsboard(msg, registration);  
285 - log.error("[{}], [{}] - [{}] [{}] error SendRequest", registration.getEndpoint(), ((Response) response.getCoapResponse()).getCode(), response.getCode(), request.getPath().toString()); 271 + serviceImpl.sendLogsToThingsboard(msg, registration.getId());
  272 + log.error("[{}] [{}], [{}] - [{}] [{}] error SendRequest", request.getClass().getName().toString(), registration.getEndpoint(),
  273 + ((Response) response.getCoapResponse()).getCode(), response.getCode(), request.getPath().toString());
  274 + if (!lwM2MClient.isInit()) {
  275 + lwM2MClient.initReadValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration));
  276 + }
286 if (rpcRequest != null) { 277 if (rpcRequest != null) {
287 serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), response.getErrorMessage(), LOG_LW2M_ERROR); 278 serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), response.getErrorMessage(), LOG_LW2M_ERROR);
288 } 279 }
  280 + /** Not Found
  281 + * set setClient_fw_version = empty
  282 + **/
  283 + if (FR_PATH_RESOURCE_VER_ID.equals(request.getPath().toString()) && lwM2MClient.isUpdateFw()) {
  284 + lwM2MClient.setUpdateFw(false);
  285 + lwM2MClient.getFrUpdate().setClientFwVersion("");
  286 + log.warn("updateFirmwareClient1");
  287 + serviceImpl.updateFirmwareClient(lwM2MClient);
  288 + }
289 } 289 }
290 }, e -> { 290 }, e -> {
  291 + /** version == null
  292 + * set setClient_fw_version = empty
  293 + **/
  294 + if (FR_PATH_RESOURCE_VER_ID.equals(request.getPath().toString()) && lwM2MClient.isUpdateFw()) {
  295 + lwM2MClient.setUpdateFw(false);
  296 + lwM2MClient.getFrUpdate().setClientFwVersion("");
  297 + log.warn("updateFirmwareClient2");
  298 + serviceImpl.updateFirmwareClient(lwM2MClient);
  299 + }
291 if (!lwM2MClient.isInit()) { 300 if (!lwM2MClient.isInit()) {
292 - lwM2MClient.initValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration)); 301 + lwM2MClient.initReadValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration));
293 } 302 }
294 - String msg = String.format("%s: sendRequest: Resource path - %s msg error - %s SendRequest to Client",  
295 - LOG_LW2M_ERROR, request.getPath().toString(), e.getMessage());  
296 - serviceImpl.sendLogsToThingsboard(msg, registration);  
297 - log.error("[{}] - [{}] error SendRequest", request.getPath().toString(), e.toString()); 303 + String msg = String.format("%s: SendRequest %s: Resource path - %s msg error - %s",
  304 + LOG_LW2M_ERROR, request.getClass().getName().toString(), request.getPath().toString(), e.getMessage());
  305 + serviceImpl.sendLogsToThingsboard(msg, registration.getId());
  306 + log.error("[{}] [{}] - [{}] error SendRequest", request.getClass().getName().toString(), request.getPath().toString(), e.toString());
298 if (rpcRequest != null) { 307 if (rpcRequest != null) {
299 serviceImpl.sentRpcRequest(rpcRequest, CoAP.CodeClass.ERROR_RESPONSE.name(), e.getMessage(), LOG_LW2M_ERROR); 308 serviceImpl.sentRpcRequest(rpcRequest, CoAP.CodeClass.ERROR_RESPONSE.name(), e.getMessage(), LOG_LW2M_ERROR);
300 } 309 }
301 }); 310 });
302 -  
303 } 311 }
304 312
305 private WriteRequest getWriteRequestSingleResource(ContentFormat contentFormat, Integer objectId, Integer instanceId, 313 private WriteRequest getWriteRequestSingleResource(ContentFormat contentFormat, Integer objectId, Integer instanceId,
@@ -323,7 +331,9 @@ public class LwM2mTransportRequest { @@ -323,7 +331,9 @@ public class LwM2mTransportRequest {
323 Date date = new Date(Long.decode(value.toString())); 331 Date date = new Date(Long.decode(value.toString()));
324 return (contentFormat == null) ? new WriteRequest(objectId, instanceId, resourceId, date) : new WriteRequest(contentFormat, objectId, instanceId, resourceId, date); 332 return (contentFormat == null) ? new WriteRequest(objectId, instanceId, resourceId, date) : new WriteRequest(contentFormat, objectId, instanceId, resourceId, date);
325 case OPAQUE: // byte[] value, base64 333 case OPAQUE: // byte[] value, base64
326 - return (contentFormat == null) ? new WriteRequest(objectId, instanceId, resourceId, Hex.decodeHex(value.toString().toCharArray())) : new WriteRequest(contentFormat, objectId, instanceId, resourceId, Hex.decodeHex(value.toString().toCharArray())); 334 + byte[] valueRequest = value instanceof byte[] ? (byte[]) value : Hex.decodeHex(value.toString().toCharArray());
  335 + return (contentFormat == null) ? new WriteRequest(objectId, instanceId, resourceId, valueRequest) :
  336 + new WriteRequest(contentFormat, objectId, instanceId, resourceId, valueRequest);
327 default: 337 default:
328 } 338 }
329 } 339 }
@@ -337,7 +347,7 @@ public class LwM2mTransportRequest { @@ -337,7 +347,7 @@ public class LwM2mTransportRequest {
337 String patn = "/" + objectId + "/" + instanceId + "/" + resourceId; 347 String patn = "/" + objectId + "/" + instanceId + "/" + resourceId;
338 String msg = String.format(LOG_LW2M_ERROR + ": NumberFormatException: Resource path - %s type - %s value - %s msg error - %s SendRequest to Client", 348 String msg = String.format(LOG_LW2M_ERROR + ": NumberFormatException: Resource path - %s type - %s value - %s msg error - %s SendRequest to Client",
339 patn, type, value, e.toString()); 349 patn, type, value, e.toString());
340 - serviceImpl.sendLogsToThingsboard(msg, registration); 350 + serviceImpl.sendLogsToThingsboard(msg, registration.getId());
341 log.error("Path: [{}] type: [{}] value: [{}] errorMsg: [{}]]", patn, type, value, e.toString()); 351 log.error("Path: [{}] type: [{}] value: [{}] errorMsg: [{}]]", patn, type, value, e.toString());
342 if (rpcRequest != null) { 352 if (rpcRequest != null) {
343 String errorMsg = String.format("NumberFormatException: Resource path - %s type - %s value - %s", patn, type, value); 353 String errorMsg = String.format("NumberFormatException: Resource path - %s type - %s value - %s", patn, type, value);
@@ -369,7 +379,7 @@ public class LwM2mTransportRequest { @@ -369,7 +379,7 @@ public class LwM2mTransportRequest {
369 DownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) { 379 DownlinkRequest request, Lwm2mClientRpcRequest rpcRequest) {
370 String pathIdVer = convertPathFromObjectIdToIdVer(path, registration); 380 String pathIdVer = convertPathFromObjectIdToIdVer(path, registration);
371 if (response instanceof ReadResponse) { 381 if (response instanceof ReadResponse) {
372 - serviceImpl.onObservationResponse(registration, pathIdVer, (ReadResponse) response, rpcRequest); 382 + serviceImpl.onUpdateValueAfterReadResponse(registration, pathIdVer, (ReadResponse) response, rpcRequest);
373 } else if (response instanceof CancelObservationResponse) { 383 } else if (response instanceof CancelObservationResponse) {
374 log.info("[{}] Path [{}] CancelObservationResponse 3_Send", pathIdVer, response); 384 log.info("[{}] Path [{}] CancelObservationResponse 3_Send", pathIdVer, response);
375 385
@@ -389,14 +399,33 @@ public class LwM2mTransportRequest { @@ -389,14 +399,33 @@ public class LwM2mTransportRequest {
389 } else if (response instanceof WriteAttributesResponse) { 399 } else if (response instanceof WriteAttributesResponse) {
390 log.info("[{}] Path [{}] WriteAttributesResponse 8_Send", pathIdVer, response); 400 log.info("[{}] Path [{}] WriteAttributesResponse 8_Send", pathIdVer, response);
391 } else if (response instanceof WriteResponse) { 401 } else if (response instanceof WriteResponse) {
392 - log.info("[{}] Path [{}] WriteAttributesResponse 9_Send", pathIdVer, response); 402 + log.info("[{}] Path [{}] WriteResponse 9_Send", pathIdVer, response);
  403 + this.infoWriteResponse(registration, response, request);
393 serviceImpl.onWriteResponseOk(registration, pathIdVer, (WriteRequest) request); 404 serviceImpl.onWriteResponseOk(registration, pathIdVer, (WriteRequest) request);
394 } 405 }
395 - if (rpcRequest != null && (response instanceof ExecuteResponse  
396 - || response instanceof WriteAttributesResponse  
397 - || response instanceof DeleteResponse)) {  
398 - rpcRequest.setInfoMsg(null);  
399 - serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), null, null); 406 + if (rpcRequest != null) {
  407 + if (response instanceof ExecuteResponse
  408 + || response instanceof WriteAttributesResponse
  409 + || response instanceof DeleteResponse) {
  410 + rpcRequest.setInfoMsg(null);
  411 + serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), null, null);
  412 + } else if (response instanceof WriteResponse) {
  413 + serviceImpl.sentRpcRequest(rpcRequest, response.getCode().getName(), null, LOG_LW2M_INFO);
  414 + }
400 } 415 }
401 } 416 }
  417 +
  418 + private void infoWriteResponse(Registration registration, LwM2mResponse response,
  419 + DownlinkRequest request) {
  420 + LwM2mNode node = ((WriteRequest) request).getNode();
  421 + Object value = this.converter.convertValue(((LwM2mSingleResource) node).getValue(),
  422 + ((LwM2mSingleResource) node).getType(), ResourceModel.Type.STRING, request.getPath());
  423 + String msg = String.format("%s: Update finished successfully: CoapCde - %s Lwm2m code - %d name - %s Resource path - %s value - %s",
  424 + LOG_LW2M_INFO, ((Response) response.getCoapResponse()).getCode(), response.getCode().getCode(),
  425 + response.getCode().getName(), request.getPath().toString(), value);
  426 + serviceImpl.sendLogsToThingsboard(msg, registration.getId());
  427 + log.warn("[{}] [{}] [{}] - [{}] [{}] Update finished successfully: [{}]", request.getClass().getName().toString(), registration.getEndpoint(),
  428 + ((Response) response.getCoapResponse()).getCode(), response.getCode(),
  429 + request.getPath().toString(), value);
  430 + }
402 } 431 }
@@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
16 package org.thingsboard.server.transport.lwm2m.server; 16 package org.thingsboard.server.transport.lwm2m.server;
17 17
18 import lombok.extern.slf4j.Slf4j; 18 import lombok.extern.slf4j.Slf4j;
  19 +import org.eclipse.californium.core.network.config.NetworkConfig;
  20 +import org.eclipse.californium.core.network.stack.BlockwiseLayer;
19 import org.eclipse.californium.scandium.config.DtlsConnectorConfig; 21 import org.eclipse.californium.scandium.config.DtlsConnectorConfig;
20 import org.eclipse.leshan.core.node.codec.DefaultLwM2mNodeDecoder; 22 import org.eclipse.leshan.core.node.codec.DefaultLwM2mNodeDecoder;
21 import org.eclipse.leshan.core.node.codec.DefaultLwM2mNodeEncoder; 23 import org.eclipse.leshan.core.node.codec.DefaultLwM2mNodeEncoder;
@@ -57,7 +59,7 @@ import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE @@ -57,7 +59,7 @@ import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE
57 import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8; 59 import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
58 import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256; 60 import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256;
59 import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CCM_8; 61 import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CCM_8;
60 -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.getCoapConfig; 62 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mNetworkConfig.getCoapConfig;
61 63
62 @Slf4j 64 @Slf4j
63 @Component 65 @Component
@@ -92,7 +94,10 @@ public class LwM2mTransportServerConfiguration { @@ -92,7 +94,10 @@ public class LwM2mTransportServerConfiguration {
92 /** Use a magic converter to support bad type send by the UI. */ 94 /** Use a magic converter to support bad type send by the UI. */
93 builder.setEncoder(new DefaultLwM2mNodeEncoder(LwM2mValueConverterImpl.getInstance())); 95 builder.setEncoder(new DefaultLwM2mNodeEncoder(LwM2mValueConverterImpl.getInstance()));
94 96
  97 +
95 /** Create CoAP Config */ 98 /** Create CoAP Config */
  99 + NetworkConfig networkConfig = getCoapConfig(serverPortNoSec, serverSecurePort);
  100 + BlockwiseLayer blockwiseLayer = new BlockwiseLayer(networkConfig);
96 builder.setCoapConfig(getCoapConfig(serverPortNoSec, serverSecurePort)); 101 builder.setCoapConfig(getCoapConfig(serverPortNoSec, serverSecurePort));
97 102
98 /** Define model provider (Create Models )*/ 103 /** Define model provider (Create Models )*/
@@ -110,6 +115,7 @@ public class LwM2mTransportServerConfiguration { @@ -110,6 +115,7 @@ public class LwM2mTransportServerConfiguration {
110 115
111 /** Create DTLS Config */ 116 /** Create DTLS Config */
112 DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder(); 117 DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder();
  118 + dtlsConfig.setServerOnly(true);
113 dtlsConfig.setRecommendedSupportedGroupsOnly(this.context.getLwM2MTransportConfigServer().isRecommendedSupportedGroups()); 119 dtlsConfig.setRecommendedSupportedGroupsOnly(this.context.getLwM2MTransportConfigServer().isRecommendedSupportedGroups());
114 dtlsConfig.setRecommendedCipherSuitesOnly(this.context.getLwM2MTransportConfigServer().isRecommendedCiphers()); 120 dtlsConfig.setRecommendedCipherSuitesOnly(this.context.getLwM2MTransportConfigServer().isRecommendedCiphers());
115 if (this.pskMode) { 121 if (this.pskMode) {
@@ -39,7 +39,7 @@ public interface LwM2mTransportService extends TbTransportService { @@ -39,7 +39,7 @@ public interface LwM2mTransportService extends TbTransportService {
39 39
40 void setCancelObservations(Registration registration); 40 void setCancelObservations(Registration registration);
41 41
42 - void onObservationResponse(Registration registration, String path, ReadResponse response, Lwm2mClientRpcRequest rpcRequest); 42 + void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response, Lwm2mClientRpcRequest rpcRequest);
43 43
44 void onAttributeUpdate(TransportProtos.AttributeUpdateNotificationMsg msg, TransportProtos.SessionInfoProto sessionInfo); 44 void onAttributeUpdate(TransportProtos.AttributeUpdateNotificationMsg msg, TransportProtos.SessionInfoProto sessionInfo);
45 45
@@ -60,6 +60,4 @@ public interface LwM2mTransportService extends TbTransportService { @@ -60,6 +60,4 @@ public interface LwM2mTransportService extends TbTransportService {
60 void doTrigger(Registration registration, String path); 60 void doTrigger(Registration registration, String path);
61 61
62 void doDisconnect(TransportProtos.SessionInfoProto sessionInfo); 62 void doDisconnect(TransportProtos.SessionInfoProto sessionInfo);
63 -  
64 -  
65 } 63 }
@@ -38,10 +38,12 @@ import org.eclipse.leshan.server.registration.Registration; @@ -38,10 +38,12 @@ import org.eclipse.leshan.server.registration.Registration;
38 import org.springframework.context.annotation.Lazy; 38 import org.springframework.context.annotation.Lazy;
39 import org.springframework.stereotype.Service; 39 import org.springframework.stereotype.Service;
40 import org.thingsboard.common.util.JacksonUtil; 40 import org.thingsboard.common.util.JacksonUtil;
  41 +import org.thingsboard.server.cache.firmware.FirmwareDataCache;
41 import org.thingsboard.server.common.data.Device; 42 import org.thingsboard.server.common.data.Device;
42 import org.thingsboard.server.common.data.DeviceProfile; 43 import org.thingsboard.server.common.data.DeviceProfile;
43 -import org.thingsboard.server.common.data.DeviceTransportType; 44 +import org.thingsboard.server.common.data.id.FirmwareId;
44 import org.thingsboard.server.common.transport.TransportService; 45 import org.thingsboard.server.common.transport.TransportService;
  46 +import org.thingsboard.server.common.transport.TransportServiceCallback;
45 import org.thingsboard.server.common.transport.adaptor.AdaptorException; 47 import org.thingsboard.server.common.transport.adaptor.AdaptorException;
46 import org.thingsboard.server.common.transport.service.DefaultTransportService; 48 import org.thingsboard.server.common.transport.service.DefaultTransportService;
47 import org.thingsboard.server.gen.transport.TransportProtos; 49 import org.thingsboard.server.gen.transport.TransportProtos;
@@ -77,9 +79,12 @@ import java.util.stream.Collectors; @@ -77,9 +79,12 @@ import java.util.stream.Collectors;
77 79
78 import static org.eclipse.californium.core.coap.CoAP.ResponseCode.BAD_REQUEST; 80 import static org.eclipse.californium.core.coap.CoAP.ResponseCode.BAD_REQUEST;
79 import static org.eclipse.leshan.core.attributes.Attribute.OBJECT_VERSION; 81 import static org.eclipse.leshan.core.attributes.Attribute.OBJECT_VERSION;
  82 +import static org.thingsboard.server.common.data.DataConstants.FIRMWARE_VERSION;
  83 +import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY;
80 import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH; 84 import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH;
81 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.CLIENT_NOT_AUTHORIZED; 85 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.CLIENT_NOT_AUTHORIZED;
82 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.DEVICE_ATTRIBUTES_REQUEST; 86 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.DEVICE_ATTRIBUTES_REQUEST;
  87 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.FR_PATH_RESOURCE_VER_ID;
83 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_ERROR; 88 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_ERROR;
84 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_INFO; 89 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_INFO;
85 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_VALUE; 90 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_VALUE;
@@ -110,6 +115,8 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -110,6 +115,8 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
110 private ExecutorService executorUpdateRegistered; 115 private ExecutorService executorUpdateRegistered;
111 private ExecutorService executorUnRegistered; 116 private ExecutorService executorUnRegistered;
112 private LwM2mValueConverterImpl converter; 117 private LwM2mValueConverterImpl converter;
  118 + private FirmwareDataCache firmwareDataCache;
  119 +
113 120
114 private final TransportService transportService; 121 private final TransportService transportService;
115 122
@@ -121,12 +128,15 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -121,12 +128,15 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
121 128
122 private final LwM2mTransportRequest lwM2mTransportRequest; 129 private final LwM2mTransportRequest lwM2mTransportRequest;
123 130
124 - public LwM2mTransportServiceImpl(TransportService transportService, LwM2mTransportContextServer lwM2mTransportContextServer, LwM2mClientContext lwM2mClientContext, LeshanServer leshanServer, @Lazy LwM2mTransportRequest lwM2mTransportRequest) { 131 + public LwM2mTransportServiceImpl(TransportService transportService, LwM2mTransportContextServer lwM2mTransportContextServer,
  132 + LwM2mClientContext lwM2mClientContext, LeshanServer leshanServer,
  133 + @Lazy LwM2mTransportRequest lwM2mTransportRequest, FirmwareDataCache firmwareDataCache) {
125 this.transportService = transportService; 134 this.transportService = transportService;
126 this.lwM2mTransportContextServer = lwM2mTransportContextServer; 135 this.lwM2mTransportContextServer = lwM2mTransportContextServer;
127 this.lwM2mClientContext = lwM2mClientContext; 136 this.lwM2mClientContext = lwM2mClientContext;
128 this.leshanServer = leshanServer; 137 this.leshanServer = leshanServer;
129 this.lwM2mTransportRequest = lwM2mTransportRequest; 138 this.lwM2mTransportRequest = lwM2mTransportRequest;
  139 + this.firmwareDataCache = firmwareDataCache;
130 } 140 }
131 141
132 @PostConstruct 142 @PostConstruct
@@ -168,8 +178,9 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -168,8 +178,9 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
168 transportService.process(sessionInfo, DefaultTransportService.getSessionEventMsg(SessionEvent.OPEN), null); 178 transportService.process(sessionInfo, DefaultTransportService.getSessionEventMsg(SessionEvent.OPEN), null);
169 transportService.process(sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build(), null); 179 transportService.process(sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build(), null);
170 transportService.process(sessionInfo, TransportProtos.SubscribeToRPCMsg.newBuilder().build(), null); 180 transportService.process(sessionInfo, TransportProtos.SubscribeToRPCMsg.newBuilder().build(), null);
  181 + this.getInfoFirmwareUpdate(lwM2MClient);
171 this.initLwM2mFromClientValue(registration, lwM2MClient); 182 this.initLwM2mFromClientValue(registration, lwM2MClient);
172 - this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client create after Registration", registration); 183 + this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client create after Registration", registration.getId());
173 } else { 184 } else {
174 log.error("Client: [{}] onRegistered [{}] name [{}] sessionInfo ", registration.getId(), registration.getEndpoint(), null); 185 log.error("Client: [{}] onRegistered [{}] name [{}] sessionInfo ", registration.getId(), registration.getEndpoint(), null);
175 } 186 }
@@ -224,7 +235,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -224,7 +235,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
224 executorUnRegistered.submit(() -> { 235 executorUnRegistered.submit(() -> {
225 try { 236 try {
226 this.setCancelObservations(registration); 237 this.setCancelObservations(registration);
227 - this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client unRegistration", registration); 238 + this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client unRegistration", registration.getId());
228 this.closeClientSession(registration); 239 this.closeClientSession(registration);
229 } catch (Throwable t) { 240 } catch (Throwable t) {
230 log.error("[{}] endpoint [{}] error Unable un registration.", registration.getEndpoint(), t); 241 log.error("[{}] endpoint [{}] error Unable un registration.", registration.getEndpoint(), t);
@@ -257,7 +268,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -257,7 +268,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
257 @Override 268 @Override
258 public void onSleepingDev(Registration registration) { 269 public void onSleepingDev(Registration registration) {
259 log.info("[{}] [{}] Received endpoint Sleeping version event", registration.getId(), registration.getEndpoint()); 270 log.info("[{}] [{}] Received endpoint Sleeping version event", registration.getId(), registration.getEndpoint());
260 - this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client is sleeping!", registration); 271 + this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client is sleeping!", registration.getId());
261 272
262 //TODO: associate endpointId with device information. 273 //TODO: associate endpointId with device information.
263 } 274 }
@@ -280,7 +291,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -280,7 +291,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
280 * @param response - observe 291 * @param response - observe
281 */ 292 */
282 @Override 293 @Override
283 - public void onObservationResponse(Registration registration, String path, ReadResponse response, Lwm2mClientRpcRequest rpcRequest) { 294 + public void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response, Lwm2mClientRpcRequest rpcRequest) {
284 if (response.getContent() != null) { 295 if (response.getContent() != null) {
285 if (response.getContent() instanceof LwM2mObject) { 296 if (response.getContent() instanceof LwM2mObject) {
286 LwM2mObject lwM2mObject = (LwM2mObject) response.getContent(); 297 LwM2mObject lwM2mObject = (LwM2mObject) response.getContent();
@@ -304,20 +315,26 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -304,20 +315,26 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
304 315
305 /** 316 /**
306 * Update - send request in change value resources in Client 317 * Update - send request in change value resources in Client
307 - * Path to resources from profile equal keyName or from ModelObject equal name  
308 - * Only for resources: isWritable && isPresent as attribute in profile -> LwM2MClientProfile (format: CamelCase)  
309 - * Delete - nothing * 318 + * 1. FirmwareUpdate:
  319 + * - If msg.getSharedUpdatedList().forEach(tsKvProto -> {tsKvProto.getKv().getKey().indexOf(FIRMWARE_UPDATE_PREFIX, 0) == 0
  320 + * 2. Shared Other AttributeUpdate
  321 + * -- Path to resources from profile equal keyName or from ModelObject equal name
  322 + * -- Only for resources: isWritable && isPresent as attribute in profile -> LwM2MClientProfile (format: CamelCase)
  323 + * 3. Delete - nothing
310 * 324 *
311 * @param msg - 325 * @param msg -
312 */ 326 */
313 @Override 327 @Override
314 public void onAttributeUpdate(AttributeUpdateNotificationMsg msg, TransportProtos.SessionInfoProto sessionInfo) { 328 public void onAttributeUpdate(AttributeUpdateNotificationMsg msg, TransportProtos.SessionInfoProto sessionInfo) {
  329 + LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()));
315 if (msg.getSharedUpdatedCount() > 0) { 330 if (msg.getSharedUpdatedCount() > 0) {
316 msg.getSharedUpdatedList().forEach(tsKvProto -> { 331 msg.getSharedUpdatedList().forEach(tsKvProto -> {
317 String pathName = tsKvProto.getKv().getKey(); 332 String pathName = tsKvProto.getKv().getKey();
318 String pathIdVer = this.getPresentPathIntoProfile(sessionInfo, pathName); 333 String pathIdVer = this.getPresentPathIntoProfile(sessionInfo, pathName);
319 Object valueNew = this.lwM2mTransportContextServer.getValueFromKvProto(tsKvProto.getKv()); 334 Object valueNew = this.lwM2mTransportContextServer.getValueFromKvProto(tsKvProto.getKv());
320 - LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())); 335 + if (FIRMWARE_VERSION.equals(pathName) && !valueNew.equals(lwM2MClient.getFrUpdate().getCurrentFwVersion())) {
  336 + this.getInfoFirmwareUpdate(lwM2MClient);
  337 + }
321 if (pathIdVer != null) { 338 if (pathIdVer != null) {
322 ResourceModel resourceModel = lwM2MClient.getResourceModel(pathIdVer, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer() 339 ResourceModel resourceModel = lwM2MClient.getResourceModel(pathIdVer, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer()
323 .getModelProvider()); 340 .getModelProvider());
@@ -327,19 +344,26 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -327,19 +344,26 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
327 log.error("Resource path - [{}] value - [{}] is not Writable and cannot be updated", pathIdVer, valueNew); 344 log.error("Resource path - [{}] value - [{}] is not Writable and cannot be updated", pathIdVer, valueNew);
328 String logMsg = String.format("%s: attributeUpdate: Resource path - %s value - %s is not Writable and cannot be updated", 345 String logMsg = String.format("%s: attributeUpdate: Resource path - %s value - %s is not Writable and cannot be updated",
329 LOG_LW2M_ERROR, pathIdVer, valueNew); 346 LOG_LW2M_ERROR, pathIdVer, valueNew);
330 - this.sendLogsToThingsboard(logMsg, lwM2MClient.getRegistration()); 347 + this.sendLogsToThingsboard(logMsg, lwM2MClient.getRegistration().getId());
331 } 348 }
332 } else { 349 } else {
333 log.error("Resource name name - [{}] value - [{}] is not present as attribute/telemetry in profile and cannot be updated", pathName, valueNew); 350 log.error("Resource name name - [{}] value - [{}] is not present as attribute/telemetry in profile and cannot be updated", pathName, valueNew);
334 String logMsg = String.format("%s: attributeUpdate: attribute name - %s value - %s is not present as attribute in profile and cannot be updated", 351 String logMsg = String.format("%s: attributeUpdate: attribute name - %s value - %s is not present as attribute in profile and cannot be updated",
335 LOG_LW2M_ERROR, pathName, valueNew); 352 LOG_LW2M_ERROR, pathName, valueNew);
336 - this.sendLogsToThingsboard(logMsg, lwM2MClient.getRegistration()); 353 + this.sendLogsToThingsboard(logMsg, lwM2MClient.getRegistration().getId());
337 } 354 }
  355 +
338 }); 356 });
339 } else if (msg.getSharedDeletedCount() > 0) { 357 } else if (msg.getSharedDeletedCount() > 0) {
  358 + msg.getSharedUpdatedList().forEach(tsKvProto -> {
  359 + String pathName = tsKvProto.getKv().getKey();
  360 + Object valueNew = this.lwM2mTransportContextServer.getValueFromKvProto(tsKvProto.getKv());
  361 + if (FIRMWARE_VERSION.equals(pathName) && !valueNew.equals(lwM2MClient.getFrUpdate().getCurrentFwVersion())) {
  362 + lwM2MClient.getFrUpdate().setCurrentFwVersion((String) valueNew);
  363 + }
  364 + });
340 log.info("[{}] delete [{}] onAttributeUpdate", msg.getSharedDeletedList(), sessionInfo); 365 log.info("[{}] delete [{}] onAttributeUpdate", msg.getSharedDeletedList(), sessionInfo);
341 } 366 }
342 -  
343 } 367 }
344 368
345 /** 369 /**
@@ -455,23 +479,21 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -455,23 +479,21 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
455 } 479 }
456 if (rpcRequest.has(lwm2mClientRpcRequest.paramsKey) && rpcRequest.get(lwm2mClientRpcRequest.paramsKey).isJsonObject()) { 480 if (rpcRequest.has(lwm2mClientRpcRequest.paramsKey) && rpcRequest.get(lwm2mClientRpcRequest.paramsKey).isJsonObject()) {
457 lwm2mClientRpcRequest.setParams(new Gson().fromJson(rpcRequest.get(lwm2mClientRpcRequest.paramsKey) 481 lwm2mClientRpcRequest.setParams(new Gson().fromJson(rpcRequest.get(lwm2mClientRpcRequest.paramsKey)
458 - .getAsJsonObject().toString(), new TypeToken<ConcurrentHashMap<String, Object>>() {  
459 - }.getType())); 482 + .getAsJsonObject().toString(), new TypeToken<ConcurrentHashMap<String, Object>>() {
  483 + }.getType()));
460 } 484 }
461 lwm2mClientRpcRequest.setSessionInfo(sessionInfo); 485 lwm2mClientRpcRequest.setSessionInfo(sessionInfo);
462 if (OBSERVE_READ_ALL != lwm2mClientRpcRequest.getTypeOper() && lwm2mClientRpcRequest.getTargetIdVer() == null) { 486 if (OBSERVE_READ_ALL != lwm2mClientRpcRequest.getTypeOper() && lwm2mClientRpcRequest.getTargetIdVer() == null) {
463 lwm2mClientRpcRequest.setErrorMsg(lwm2mClientRpcRequest.targetIdVerKey + " and " + 487 lwm2mClientRpcRequest.setErrorMsg(lwm2mClientRpcRequest.targetIdVerKey + " and " +
464 lwm2mClientRpcRequest.keyNameKey + " is null or bad format"); 488 lwm2mClientRpcRequest.keyNameKey + " is null or bad format");
465 - }  
466 - else if ((EXECUTE == lwm2mClientRpcRequest.getTypeOper() 489 + } else if ((EXECUTE == lwm2mClientRpcRequest.getTypeOper()
467 || WRITE_REPLACE == lwm2mClientRpcRequest.getTypeOper()) 490 || WRITE_REPLACE == lwm2mClientRpcRequest.getTypeOper())
468 - && lwm2mClientRpcRequest.getTargetIdVer() !=null 491 + && lwm2mClientRpcRequest.getTargetIdVer() != null
469 && !(new LwM2mPath(convertPathFromIdVerToObjectId(lwm2mClientRpcRequest.getTargetIdVer())).isResource() 492 && !(new LwM2mPath(convertPathFromIdVerToObjectId(lwm2mClientRpcRequest.getTargetIdVer())).isResource()
470 || new LwM2mPath(convertPathFromIdVerToObjectId(lwm2mClientRpcRequest.getTargetIdVer())).isResourceInstance())) { 493 || new LwM2mPath(convertPathFromIdVerToObjectId(lwm2mClientRpcRequest.getTargetIdVer())).isResourceInstance())) {
471 - lwm2mClientRpcRequest.setErrorMsg("Invalid parameter " + lwm2mClientRpcRequest.targetIdVerKey 494 + lwm2mClientRpcRequest.setErrorMsg("Invalid parameter " + lwm2mClientRpcRequest.targetIdVerKey
472 + ". Only Resource or ResourceInstance can be this operation"); 495 + ". Only Resource or ResourceInstance can be this operation");
473 - }  
474 - else if (WRITE_UPDATE == lwm2mClientRpcRequest.getTypeOper()){ 496 + } else if (WRITE_UPDATE == lwm2mClientRpcRequest.getTypeOper()) {
475 lwm2mClientRpcRequest.setErrorMsg("Procedures In Development..."); 497 lwm2mClientRpcRequest.setErrorMsg("Procedures In Development...");
476 } 498 }
477 } else { 499 } else {
@@ -483,23 +505,23 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -483,23 +505,23 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
483 return lwm2mClientRpcRequest; 505 return lwm2mClientRpcRequest;
484 } 506 }
485 507
486 - public void sentRpcRequest (Lwm2mClientRpcRequest rpcRequest, String requestCode, String msg, String typeMsg) { 508 + public void sentRpcRequest(Lwm2mClientRpcRequest rpcRequest, String requestCode, String msg, String typeMsg) {
487 rpcRequest.setResponseCode(requestCode); 509 rpcRequest.setResponseCode(requestCode);
488 - if (LOG_LW2M_ERROR.equals(typeMsg)) {  
489 - rpcRequest.setInfoMsg(null);  
490 - rpcRequest.setValueMsg(null);  
491 - if (rpcRequest.getErrorMsg() == null) {  
492 - msg = msg.isEmpty() ? null : msg;  
493 - rpcRequest.setErrorMsg(msg);  
494 - }  
495 - } else if (LOG_LW2M_INFO.equals(typeMsg)) {  
496 - if (rpcRequest.getInfoMsg() == null) {  
497 - rpcRequest.setInfoMsg(msg);  
498 - }  
499 - } else if (LOG_LW2M_VALUE.equals(typeMsg)) {  
500 - if (rpcRequest.getValueMsg() == null) {  
501 - rpcRequest.setValueMsg(msg);  
502 - } 510 + if (LOG_LW2M_ERROR.equals(typeMsg)) {
  511 + rpcRequest.setInfoMsg(null);
  512 + rpcRequest.setValueMsg(null);
  513 + if (rpcRequest.getErrorMsg() == null) {
  514 + msg = msg.isEmpty() ? null : msg;
  515 + rpcRequest.setErrorMsg(msg);
  516 + }
  517 + } else if (LOG_LW2M_INFO.equals(typeMsg)) {
  518 + if (rpcRequest.getInfoMsg() == null) {
  519 + rpcRequest.setInfoMsg(msg);
  520 + }
  521 + } else if (LOG_LW2M_VALUE.equals(typeMsg)) {
  522 + if (rpcRequest.getValueMsg() == null) {
  523 + rpcRequest.setValueMsg(msg);
  524 + }
503 } 525 }
504 this.onToDeviceRpcResponse(rpcRequest.getDeviceRpcResponseResultMsg(), rpcRequest.getSessionInfo()); 526 this.onToDeviceRpcResponse(rpcRequest.getDeviceRpcResponseResultMsg(), rpcRequest.getSessionInfo());
505 } 527 }
@@ -556,7 +578,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -556,7 +578,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
556 */ 578 */
557 protected void onAwakeDev(Registration registration) { 579 protected void onAwakeDev(Registration registration) {
558 log.info("[{}] [{}] Received endpoint Awake version event", registration.getId(), registration.getEndpoint()); 580 log.info("[{}] [{}] Received endpoint Awake version event", registration.getId(), registration.getEndpoint());
559 - this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client is awake!", registration); 581 + this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client is awake!", registration.getId());
560 //TODO: associate endpointId with device information. 582 //TODO: associate endpointId with device information.
561 } 583 }
562 584
@@ -583,10 +605,10 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -583,10 +605,10 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
583 605
584 /** 606 /**
585 * @param logMsg - text msg 607 * @param logMsg - text msg
586 - * @param registration - Id of Registration LwM2M Client 608 + * @param registrationId - Id of Registration LwM2M Client
587 */ 609 */
588 - public void sendLogsToThingsboard(String logMsg, Registration registration) {  
589 - SessionInfoProto sessionInfo = this.getValidateSessionInfo(registration); 610 + public void sendLogsToThingsboard(String logMsg, String registrationId) {
  611 + SessionInfoProto sessionInfo = this.getValidateSessionInfo(registrationId);
590 if (logMsg != null && sessionInfo != null) { 612 if (logMsg != null && sessionInfo != null) {
591 this.lwM2mTransportContextServer.sendParametersOnThingsboardTelemetry(this.lwM2mTransportContextServer.getKvLogyToThingsboard(logMsg), sessionInfo); 613 this.lwM2mTransportContextServer.sendParametersOnThingsboardTelemetry(this.lwM2mTransportContextServer.getKvLogyToThingsboard(logMsg), sessionInfo);
592 } 614 }
@@ -610,7 +632,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -610,7 +632,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
610 if (clientObjects != null && clientObjects.size() > 0) { 632 if (clientObjects != null && clientObjects.size() > 0) {
611 if (LWM2M_STRATEGY_2 == LwM2mTransportHandler.getClientOnlyObserveAfterConnect(lwM2MClientProfile)) { 633 if (LWM2M_STRATEGY_2 == LwM2mTransportHandler.getClientOnlyObserveAfterConnect(lwM2MClientProfile)) {
612 // #2 634 // #2
613 - lwM2MClient.getPendingRequests().addAll(clientObjects); 635 + lwM2MClient.getPendingReadRequests().addAll(clientObjects);
614 clientObjects.forEach(path -> lwM2mTransportRequest.sendAllRequest(registration, path, READ, ContentFormat.TLV.getName(), 636 clientObjects.forEach(path -> lwM2mTransportRequest.sendAllRequest(registration, path, READ, ContentFormat.TLV.getName(),
615 null, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout(), null)); 637 null, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout(), null));
616 } 638 }
@@ -652,6 +674,8 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -652,6 +674,8 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
652 * Sending observe value of resources to thingsboard 674 * Sending observe value of resources to thingsboard
653 * #1 Return old Value Resource from LwM2MClient 675 * #1 Return old Value Resource from LwM2MClient
654 * #2 Update new Resources (replace old Resource Value on new Resource Value) 676 * #2 Update new Resources (replace old Resource Value on new Resource Value)
  677 + * #3 If fr_update -> UpdateFirmware
  678 + * #4 updateAttrTelemetry
655 * 679 *
656 * @param registration - Registration LwM2M Client 680 * @param registration - Registration LwM2M Client
657 * @param lwM2mResource - LwM2mSingleResource response.getContent() 681 * @param lwM2mResource - LwM2mSingleResource response.getContent()
@@ -661,6 +685,19 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -661,6 +685,19 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
661 LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null); 685 LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null);
662 if (lwM2MClient.saveResourceValue(path, lwM2mResource, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer() 686 if (lwM2MClient.saveResourceValue(path, lwM2mResource, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer()
663 .getModelProvider())) { 687 .getModelProvider())) {
  688 + if (FR_PATH_RESOURCE_VER_ID.equals(convertPathFromIdVerToObjectId(path)) &&
  689 + lwM2MClient.getFrUpdate().getCurrentFwVersion() != null
  690 + && !lwM2MClient.getFrUpdate().getCurrentFwVersion().equals(lwM2MClient.getFrUpdate().getClientFwVersion())
  691 + && lwM2MClient.isUpdateFw()) {
  692 +
  693 + /** version != null
  694 + * set setClient_fw_version = value
  695 + **/
  696 + lwM2MClient.setUpdateFw(false);
  697 + lwM2MClient.getFrUpdate().setClientFwVersion(lwM2mResource.getValue().toString());
  698 + log.warn("updateFirmwareClient3");
  699 + this.updateFirmwareClient(lwM2MClient);
  700 + }
664 Set<String> paths = new HashSet<>(); 701 Set<String> paths = new HashSet<>();
665 paths.add(path); 702 paths.add(path);
666 this.updateAttrTelemetry(registration, paths); 703 this.updateAttrTelemetry(registration, paths);
@@ -669,6 +706,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -669,6 +706,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
669 } 706 }
670 } 707 }
671 708
  709 +
672 /** 710 /**
673 * send Attribute and Telemetry to Thingsboard 711 * send Attribute and Telemetry to Thingsboard
674 * #1 - get AttrName/TelemetryName with value from LwM2MClient: 712 * #1 - get AttrName/TelemetryName with value from LwM2MClient:
@@ -723,22 +761,23 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -723,22 +761,23 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
723 params = this.getPathForWriteAttributes(lwM2MClientProfile.getPostAttributeLwm2mProfile()); 761 params = this.getPathForWriteAttributes(lwM2MClientProfile.getPostAttributeLwm2mProfile());
724 result = params.keySet(); 762 result = params.keySet();
725 } 763 }
726 - if (!result.isEmpty()) { 764 + if (result != null && !result.isEmpty()) {
727 // #1 765 // #1
728 Set<String> pathSend = result.stream().filter(target -> { 766 Set<String> pathSend = result.stream().filter(target -> {
729 return target.split(LWM2M_SEPARATOR_PATH).length < 3 ? 767 return target.split(LWM2M_SEPARATOR_PATH).length < 3 ?
730 clientObjects.contains("/" + target.split(LWM2M_SEPARATOR_PATH)[1]) : 768 clientObjects.contains("/" + target.split(LWM2M_SEPARATOR_PATH)[1]) :
731 clientObjects.contains("/" + target.split(LWM2M_SEPARATOR_PATH)[1] + "/" + target.split(LWM2M_SEPARATOR_PATH)[2]); 769 clientObjects.contains("/" + target.split(LWM2M_SEPARATOR_PATH)[1] + "/" + target.split(LWM2M_SEPARATOR_PATH)[2]);
732 } 770 }
733 - )  
734 - .collect(Collectors.toUnmodifiableSet()); 771 + ).collect(Collectors.toUnmodifiableSet());
735 if (!pathSend.isEmpty()) { 772 if (!pathSend.isEmpty()) {
736 - lwM2MClient.getPendingRequests().addAll(pathSend); 773 + lwM2MClient.getPendingReadRequests().addAll(pathSend);
737 ConcurrentHashMap<String, Object> finalParams = params; 774 ConcurrentHashMap<String, Object> finalParams = params;
738 - pathSend.forEach(target -> lwM2mTransportRequest.sendAllRequest(registration, target, typeOper, ContentFormat.TLV.getName(),  
739 - finalParams != null ? finalParams.get(target) : null, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout(), null)); 775 + pathSend.forEach(target -> {
  776 + lwM2mTransportRequest.sendAllRequest(registration, target, typeOper, ContentFormat.TLV.getName(),
  777 + finalParams != null ? finalParams.get(target) : null, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout(), null);
  778 + });
740 if (OBSERVE.equals(typeOper)) { 779 if (OBSERVE.equals(typeOper)) {
741 - lwM2MClient.initValue(this, null); 780 + lwM2MClient.initReadValue(this, null);
742 } 781 }
743 } 782 }
744 } 783 }
@@ -969,7 +1008,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -969,7 +1008,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
969 // update value in Resources 1008 // update value in Resources
970 registrationIds.forEach(registrationId -> { 1009 registrationIds.forEach(registrationId -> {
971 Registration registration = lwM2mClientContext.getRegistration(registrationId); 1010 Registration registration = lwM2mClientContext.getRegistration(registrationId);
972 - this.readResourceValueObserve(registration, sendAttrToThingsboard.getPathPostParametersAdd(), READ); 1011 + this.readObserveFromProfile(registration, sendAttrToThingsboard.getPathPostParametersAdd(), READ);
973 // send attr/telemetry to tingsboard for new path 1012 // send attr/telemetry to tingsboard for new path
974 this.updateAttrTelemetry(registration, sendAttrToThingsboard.getPathPostParametersAdd()); 1013 this.updateAttrTelemetry(registration, sendAttrToThingsboard.getPathPostParametersAdd());
975 }); 1014 });
@@ -998,12 +1037,12 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -998,12 +1037,12 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
998 registrationIds.forEach(registrationId -> { 1037 registrationIds.forEach(registrationId -> {
999 Registration registration = lwM2mClientContext.getRegistration(registrationId); 1038 Registration registration = lwM2mClientContext.getRegistration(registrationId);
1000 if (postObserveAnalyzer.getPathPostParametersAdd().size() > 0) { 1039 if (postObserveAnalyzer.getPathPostParametersAdd().size() > 0) {
1001 - this.readResourceValueObserve(registration, postObserveAnalyzer.getPathPostParametersAdd(), OBSERVE); 1040 + this.readObserveFromProfile(registration, postObserveAnalyzer.getPathPostParametersAdd(), OBSERVE);
1002 } 1041 }
1003 // 5.3 del 1042 // 5.3 del
1004 // send Request cancel observe to Client 1043 // send Request cancel observe to Client
1005 if (postObserveAnalyzer.getPathPostParametersDel().size() > 0) { 1044 if (postObserveAnalyzer.getPathPostParametersDel().size() > 0) {
1006 - this.cancelObserveIsValue(registration, postObserveAnalyzer.getPathPostParametersDel()); 1045 + this.cancelObserveFromProfile(registration, postObserveAnalyzer.getPathPostParametersDel());
1007 } 1046 }
1008 }); 1047 });
1009 } 1048 }
@@ -1043,7 +1082,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -1043,7 +1082,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
1043 * @param registration - Registration LwM2M Client 1082 * @param registration - Registration LwM2M Client
1044 * @param targets - path Resources == [ "/2/0/0", "/2/0/1"] 1083 * @param targets - path Resources == [ "/2/0/0", "/2/0/1"]
1045 */ 1084 */
1046 - private void readResourceValueObserve(Registration registration, Set<String> targets, LwM2mTypeOper typeOper) { 1085 + private void readObserveFromProfile(Registration registration, Set<String> targets, LwM2mTypeOper typeOper) {
1047 targets.forEach(target -> { 1086 targets.forEach(target -> {
1048 LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(target)); 1087 LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(target));
1049 if (pathIds.isResource()) { 1088 if (pathIds.isResource()) {
@@ -1133,7 +1172,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -1133,7 +1172,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
1133 1172
1134 } 1173 }
1135 1174
1136 - private void cancelObserveIsValue(Registration registration, Set<String> paramAnallyzer) { 1175 + private void cancelObserveFromProfile(Registration registration, Set<String> paramAnallyzer) {
1137 LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null); 1176 LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null);
1138 paramAnallyzer.forEach(pathIdVer -> { 1177 paramAnallyzer.forEach(pathIdVer -> {
1139 if (this.getResourceValueFromLwM2MClient(lwM2MClient, pathIdVer) != null) { 1178 if (this.getResourceValueFromLwM2MClient(lwM2MClient, pathIdVer) != null) {
@@ -1153,7 +1192,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -1153,7 +1192,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
1153 log.error("Failed update resource [{}] [{}]", path, valueNew); 1192 log.error("Failed update resource [{}] [{}]", path, valueNew);
1154 String logMsg = String.format("%s: Failed update resource path - %s value - %s. Value is not changed or bad", 1193 String logMsg = String.format("%s: Failed update resource path - %s value - %s. Value is not changed or bad",
1155 LOG_LW2M_ERROR, path, valueNew); 1194 LOG_LW2M_ERROR, path, valueNew);
1156 - this.sendLogsToThingsboard(logMsg, lwM2MClient.getRegistration()); 1195 + this.sendLogsToThingsboard(logMsg, lwM2MClient.getRegistration().getId());
1157 log.info("Failed update resource [{}] [{}]", path, valueNew); 1196 log.info("Failed update resource [{}] [{}]", path, valueNew);
1158 } 1197 }
1159 } 1198 }
@@ -1182,8 +1221,10 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -1182,8 +1221,10 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
1182 } 1221 }
1183 1222
1184 /** 1223 /**
1185 - * Update resource value on client: if there is a difference in values between the current resource values and the shared attribute values  
1186 - * #1 Get path resource by result attributesResponse 1224 + * 1. FirmwareUpdate:
  1225 + * - msg.getSharedUpdatedList().forEach(tsKvProto -> {tsKvProto.getKv().getKey().indexOf(FIRMWARE_UPDATE_PREFIX, 0) == 0
  1226 + * 2. Update resource value on client: if there is a difference in values between the current resource values and the shared attribute values
  1227 + * - Get path resource by result attributesResponse
1187 * 1228 *
1188 * @param attributesResponse - 1229 * @param attributesResponse -
1189 * @param sessionInfo - 1230 * @param sessionInfo -
@@ -1191,6 +1232,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -1191,6 +1232,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
1191 public void onGetAttributesResponse(TransportProtos.GetAttributeResponseMsg attributesResponse, TransportProtos.SessionInfoProto sessionInfo) { 1232 public void onGetAttributesResponse(TransportProtos.GetAttributeResponseMsg attributesResponse, TransportProtos.SessionInfoProto sessionInfo) {
1192 try { 1233 try {
1193 List<TransportProtos.TsKvProto> tsKvProtos = attributesResponse.getSharedAttributeListList(); 1234 List<TransportProtos.TsKvProto> tsKvProtos = attributesResponse.getSharedAttributeListList();
  1235 +
1194 this.updateAttriuteFromThingsboard(tsKvProtos, sessionInfo); 1236 this.updateAttriuteFromThingsboard(tsKvProtos, sessionInfo);
1195 } catch (Exception e) { 1237 } catch (Exception e) {
1196 log.error(String.valueOf(e)); 1238 log.error(String.valueOf(e));
@@ -1274,7 +1316,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -1274,7 +1316,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
1274 */ 1316 */
1275 private SessionInfoProto getValidateSessionInfo(String registrationId) { 1317 private SessionInfoProto getValidateSessionInfo(String registrationId) {
1276 LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(null, registrationId); 1318 LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(null, registrationId);
1277 - return getNewSessionInfoProto(lwM2MClient); 1319 + return lwM2MClient != null ? this.getNewSessionInfoProto(lwM2MClient) : null;
1278 } 1320 }
1279 1321
1280 /** 1322 /**
@@ -1293,28 +1335,88 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -1293,28 +1335,88 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
1293 } 1335 }
1294 1336
1295 /** 1337 /**
1296 - * !!! sharedAttr === profileAttr !!!  
1297 - * If there is a difference in values between the current resource values and the shared attribute values  
1298 - * when the client connects to the server  
1299 - * #1 get attributes name from profile include name resources in ModelObject if resource isWritable  
1300 - * #2.1 #1 size > 0 => send Request getAttributes to thingsboard 1338 + * #1. !!! sharedAttr === profileAttr !!!
  1339 + * - If there is a difference in values between the current resource values and the shared attribute values
  1340 + * - when the client connects to the server
  1341 + * #1.1 get attributes name from profile include name resources in ModelObject if resource isWritable
  1342 + * #1.2 #1 size > 0 => send Request getAttributes to thingsboard
  1343 + * #2. FirmwareAttribute subscribe:
1301 * 1344 *
1302 * @param lwM2MClient - LwM2M Client 1345 * @param lwM2MClient - LwM2M Client
1303 */ 1346 */
1304 public void putDelayedUpdateResourcesThingsboard(LwM2mClient lwM2MClient) { 1347 public void putDelayedUpdateResourcesThingsboard(LwM2mClient lwM2MClient) {
1305 SessionInfoProto sessionInfo = this.getValidateSessionInfo(lwM2MClient.getRegistration()); 1348 SessionInfoProto sessionInfo = this.getValidateSessionInfo(lwM2MClient.getRegistration());
1306 if (sessionInfo != null) { 1349 if (sessionInfo != null) {
1307 - //#1.1 + #1.2  
1308 - List<String> attrSharedNames = this.getNamesAttrFromProfileIsWritable(lwM2MClient);  
1309 - if (attrSharedNames.size() > 0) {  
1310 - //#2.1 1350 + //#1.1
  1351 + ConcurrentMap<String, String> keyNamesMap = this.getNamesFromProfileForSharedAttributes(lwM2MClient);
  1352 + if (keyNamesMap.values().size() > 0) {
1311 try { 1353 try {
1312 - TransportProtos.GetAttributeRequestMsg getAttributeMsg = lwM2mTransportContextServer.getAdaptor().convertToGetAttributes(null, attrSharedNames); 1354 + //#1.2
  1355 + TransportProtos.GetAttributeRequestMsg getAttributeMsg = lwM2mTransportContextServer.getAdaptor().convertToGetAttributes(null, keyNamesMap.values());
1313 transportService.process(sessionInfo, getAttributeMsg, getAckCallback(lwM2MClient, getAttributeMsg.getRequestId(), DEVICE_ATTRIBUTES_REQUEST)); 1356 transportService.process(sessionInfo, getAttributeMsg, getAckCallback(lwM2MClient, getAttributeMsg.getRequestId(), DEVICE_ATTRIBUTES_REQUEST));
1314 } catch (AdaptorException e) { 1357 } catch (AdaptorException e) {
1315 log.warn("Failed to decode get attributes request", e); 1358 log.warn("Failed to decode get attributes request", e);
1316 } 1359 }
1317 } 1360 }
  1361 +
  1362 + }
  1363 + }
  1364 +
  1365 + public void getInfoFirmwareUpdate(LwM2mClient lwM2MClient) {
  1366 + SessionInfoProto sessionInfo = this.getValidateSessionInfo(lwM2MClient.getRegistration());
  1367 + if (sessionInfo != null) {
  1368 + TransportProtos.GetFirmwareRequestMsg getFirmwareRequestMsg = TransportProtos.GetFirmwareRequestMsg.newBuilder()
  1369 + .setDeviceIdMSB(sessionInfo.getDeviceIdMSB())
  1370 + .setDeviceIdLSB(sessionInfo.getDeviceIdLSB())
  1371 + .setTenantIdMSB(sessionInfo.getTenantIdMSB())
  1372 + .setTenantIdLSB(sessionInfo.getTenantIdLSB())
  1373 + .build();
  1374 + transportService.process(sessionInfo, getFirmwareRequestMsg,
  1375 + new TransportServiceCallback<>() {
  1376 + @Override
  1377 + public void onSuccess(TransportProtos.GetFirmwareResponseMsg response) {
  1378 + if (TransportProtos.ResponseStatus.SUCCESS.equals(response.getResponseStatus())) {
  1379 + lwM2MClient.getFrUpdate().setCurrentFwVersion(response.getVersion());
  1380 + lwM2MClient.getFrUpdate().setCurrentFwId(new FirmwareId(new UUID(response.getFirmwareIdMSB(), response.getFirmwareIdLSB())).getId());
  1381 + lwM2MClient.setUpdateFw(true);
  1382 + readRequestToClientFirmwareVer(lwM2MClient.getRegistration());
  1383 + } else {
  1384 + log.trace("Firmware [{}] [{}]", lwM2MClient.getDeviceName(), response.getResponseStatus().toString());
  1385 + }
  1386 + }
  1387 +
  1388 + @Override
  1389 + public void onError(Throwable e) {
  1390 + log.trace("Failed to process credentials ", e);
  1391 + }
  1392 + });
  1393 + }
  1394 + }
  1395 +
  1396 + /**
  1397 + * @param registration
  1398 + */
  1399 + public void readRequestToClientFirmwareVer(Registration registration) {
  1400 + String pathIdVer = convertPathFromObjectIdToIdVer(FR_PATH_RESOURCE_VER_ID, registration);
  1401 + lwM2mTransportRequest.sendAllRequest(registration, pathIdVer, READ, ContentFormat.TLV.getName(),
  1402 + null, lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout(), null);
  1403 + }
  1404 +
  1405 + /**
  1406 + *
  1407 + * @param lwM2MClient -
  1408 + */
  1409 + public void updateFirmwareClient(LwM2mClient lwM2MClient) {
  1410 + if (!lwM2MClient.getFrUpdate().getCurrentFwVersion().equals(lwM2MClient.getFrUpdate().getClientFwVersion())) {
  1411 + int chunkSize = 0;
  1412 + int chunk = 0;
  1413 + byte[] firmwareChunk = firmwareDataCache.get(lwM2MClient.getFrUpdate().getCurrentFwId().toString(), chunkSize, chunk);
  1414 + Integer objectId = 5;
  1415 + String verSupportedObject = lwM2MClient.getRegistration().getSupportedObject().get(objectId);
  1416 + String targetIdVer = LWM2M_SEPARATOR_PATH + objectId + LWM2M_SEPARATOR_KEY + verSupportedObject + LWM2M_SEPARATOR_PATH + 0 + LWM2M_SEPARATOR_PATH + 0;
  1417 + lwM2mTransportRequest.sendAllRequest(lwM2MClient.getRegistration(), targetIdVer, WRITE_REPLACE, ContentFormat.TLV.getName(),
  1418 + firmwareChunk, lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout(), null);
  1419 + log.warn("updateFirmwareClient [{}] [{}]", lwM2MClient.getFrUpdate().getCurrentFwVersion(), lwM2MClient.getFrUpdate().getClientFwVersion());
1318 } 1420 }
1319 } 1421 }
1320 1422
@@ -1326,23 +1428,12 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -1326,23 +1428,12 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
1326 * @param lwM2MClient - 1428 * @param lwM2MClient -
1327 * @return ArrayList keyNames from profile profileAttr && IsWritable 1429 * @return ArrayList keyNames from profile profileAttr && IsWritable
1328 */ 1430 */
1329 - private List<String> getNamesAttrFromProfileIsWritable(LwM2mClient lwM2MClient) { 1431 + private ConcurrentMap<String, String> getNamesFromProfileForSharedAttributes(LwM2mClient lwM2MClient) {
  1432 +
1330 LwM2mClientProfile profile = lwM2mClientContext.getProfile(lwM2MClient.getProfileId()); 1433 LwM2mClientProfile profile = lwM2mClientContext.getProfile(lwM2MClient.getProfileId());
1331 - Set<String> attrSet = new Gson().fromJson(profile.getPostAttributeProfile(),  
1332 - new TypeToken<HashSet<String>>() {  
1333 - }.getType());  
1334 - ConcurrentMap<String, String> keyNamesMap = new Gson().fromJson(profile.getPostKeyNameProfile().toString(), 1434 + return new Gson().fromJson(profile.getPostKeyNameProfile().toString(),
1335 new TypeToken<ConcurrentHashMap<String, String>>() { 1435 new TypeToken<ConcurrentHashMap<String, String>>() {
1336 }.getType()); 1436 }.getType());
1337 -  
1338 - ConcurrentMap<String, String> keyNamesIsWritable = keyNamesMap.entrySet()  
1339 - .stream()  
1340 - .filter(e -> (attrSet.contains(e.getKey()) && validateResourceInModel(lwM2MClient, e.getKey(), true)))  
1341 - .collect(Collectors.toConcurrentMap(Map.Entry::getKey, Map.Entry::getValue));  
1342 -  
1343 - Set<String> namesIsWritable = ConcurrentHashMap.newKeySet();  
1344 - namesIsWritable.addAll(new HashSet<>(keyNamesIsWritable.values()));  
1345 - return new ArrayList<>(namesIsWritable);  
1346 } 1437 }
1347 1438
1348 private boolean validateResourceInModel(LwM2mClient lwM2mClient, String pathIdVer, boolean isWritableNotOptional) { 1439 private boolean validateResourceInModel(LwM2mClient lwM2mClient, String pathIdVer, boolean isWritableNotOptional) {
@@ -24,11 +24,8 @@ import org.thingsboard.server.common.transport.adaptor.AdaptorException; @@ -24,11 +24,8 @@ import org.thingsboard.server.common.transport.adaptor.AdaptorException;
24 import org.thingsboard.server.common.transport.adaptor.JsonConverter; 24 import org.thingsboard.server.common.transport.adaptor.JsonConverter;
25 import org.thingsboard.server.gen.transport.TransportProtos; 25 import org.thingsboard.server.gen.transport.TransportProtos;
26 26
27 -import java.util.Arrays;  
28 -import java.util.HashSet;  
29 -import java.util.List; 27 +import java.util.Collection;
30 import java.util.Random; 28 import java.util.Random;
31 -import java.util.Set;  
32 29
33 @Slf4j 30 @Slf4j
34 @Component("LwM2MJsonAdaptor") 31 @Component("LwM2MJsonAdaptor")
@@ -54,11 +51,7 @@ public class LwM2MJsonAdaptor implements LwM2MTransportAdaptor { @@ -54,11 +51,7 @@ public class LwM2MJsonAdaptor implements LwM2MTransportAdaptor {
54 } 51 }
55 52
56 @Override 53 @Override
57 - public TransportProtos.GetAttributeRequestMsg convertToGetAttributes(List<String> clientKeys, List<String> sharedKeys) throws AdaptorException {  
58 - return processGetAttributeRequestMsg(clientKeys, sharedKeys);  
59 - }  
60 -  
61 - protected TransportProtos.GetAttributeRequestMsg processGetAttributeRequestMsg(List<String> clientKeys, List<String> sharedKeys) throws AdaptorException { 54 + public TransportProtos.GetAttributeRequestMsg convertToGetAttributes(Collection<String> clientKeys, Collection<String> sharedKeys) throws AdaptorException {
62 try { 55 try {
63 TransportProtos.GetAttributeRequestMsg.Builder result = TransportProtos.GetAttributeRequestMsg.newBuilder(); 56 TransportProtos.GetAttributeRequestMsg.Builder result = TransportProtos.GetAttributeRequestMsg.newBuilder();
64 Random random = new Random(); 57 Random random = new Random();
@@ -75,14 +68,4 @@ public class LwM2MJsonAdaptor implements LwM2MTransportAdaptor { @@ -75,14 +68,4 @@ public class LwM2MJsonAdaptor implements LwM2MTransportAdaptor {
75 throw new AdaptorException(e); 68 throw new AdaptorException(e);
76 } 69 }
77 } 70 }
78 -  
79 - private Set<String> toStringSet(JsonElement requestBody, String name) {  
80 - JsonElement element = requestBody.getAsJsonObject().get(name);  
81 - if (element != null) {  
82 - return new HashSet<>(Arrays.asList(element.getAsString().split(",")));  
83 - } else {  
84 - return null;  
85 - }  
86 - }  
87 -  
88 } 71 }
@@ -19,7 +19,7 @@ import com.google.gson.JsonElement; @@ -19,7 +19,7 @@ import com.google.gson.JsonElement;
19 import org.thingsboard.server.common.transport.adaptor.AdaptorException; 19 import org.thingsboard.server.common.transport.adaptor.AdaptorException;
20 import org.thingsboard.server.gen.transport.TransportProtos; 20 import org.thingsboard.server.gen.transport.TransportProtos;
21 21
22 -import java.util.List; 22 +import java.util.Collection;
23 23
24 public interface LwM2MTransportAdaptor { 24 public interface LwM2MTransportAdaptor {
25 25
@@ -27,5 +27,5 @@ public interface LwM2MTransportAdaptor { @@ -27,5 +27,5 @@ public interface LwM2MTransportAdaptor {
27 27
28 TransportProtos.PostAttributeMsg convertToPostAttributes(JsonElement jsonElement) throws AdaptorException; 28 TransportProtos.PostAttributeMsg convertToPostAttributes(JsonElement jsonElement) throws AdaptorException;
29 29
30 - TransportProtos.GetAttributeRequestMsg convertToGetAttributes(List<String> clientKeys, List<String> sharedKeys) throws AdaptorException; 30 + TransportProtos.GetAttributeRequestMsg convertToGetAttributes(Collection<String> clientKeys, Collection<String> sharedKeys) throws AdaptorException;
31 } 31 }
@@ -57,13 +57,15 @@ public class LwM2mClient implements Cloneable { @@ -57,13 +57,15 @@ public class LwM2mClient implements Cloneable {
57 private UUID deviceId; 57 private UUID deviceId;
58 private UUID sessionId; 58 private UUID sessionId;
59 private UUID profileId; 59 private UUID profileId;
  60 + private volatile LwM2mFirmwareUpdate frUpdate;
60 private Registration registration; 61 private Registration registration;
61 private ValidateDeviceCredentialsResponseMsg credentialsResponse; 62 private ValidateDeviceCredentialsResponseMsg credentialsResponse;
62 private final Map<String, ResourceValue> resources; 63 private final Map<String, ResourceValue> resources;
63 private final Map<String, TransportProtos.TsKvProto> delayedRequests; 64 private final Map<String, TransportProtos.TsKvProto> delayedRequests;
64 - private final List<String> pendingRequests; 65 + private final List<String> pendingReadRequests;
65 private final Queue<LwM2mQueuedRequest> queuedRequests; 66 private final Queue<LwM2mQueuedRequest> queuedRequests;
66 private boolean init; 67 private boolean init;
  68 + private volatile boolean updateFw;
67 69
68 public Object clone() throws CloneNotSupportedException { 70 public Object clone() throws CloneNotSupportedException {
69 return super.clone(); 71 return super.clone();
@@ -75,12 +77,14 @@ public class LwM2mClient implements Cloneable { @@ -75,12 +77,14 @@ public class LwM2mClient implements Cloneable {
75 this.securityInfo = securityInfo; 77 this.securityInfo = securityInfo;
76 this.credentialsResponse = credentialsResponse; 78 this.credentialsResponse = credentialsResponse;
77 this.delayedRequests = new ConcurrentHashMap<>(); 79 this.delayedRequests = new ConcurrentHashMap<>();
78 - this.pendingRequests = new CopyOnWriteArrayList<>(); 80 + this.pendingReadRequests = new CopyOnWriteArrayList<>();
79 this.resources = new ConcurrentHashMap<>(); 81 this.resources = new ConcurrentHashMap<>();
80 this.profileId = profileId; 82 this.profileId = profileId;
81 this.sessionId = sessionId; 83 this.sessionId = sessionId;
82 this.init = false; 84 this.init = false;
  85 + this.updateFw = false;
83 this.queuedRequests = new ConcurrentLinkedQueue<>(); 86 this.queuedRequests = new ConcurrentLinkedQueue<>();
  87 + this.frUpdate = new LwM2mFirmwareUpdate();
84 } 88 }
85 89
86 public boolean saveResourceValue(String pathRez, LwM2mResource rez, LwM2mModelProvider modelProvider) { 90 public boolean saveResourceValue(String pathRez, LwM2mResource rez, LwM2mModelProvider modelProvider) {
@@ -103,15 +107,13 @@ public class LwM2mClient implements Cloneable { @@ -103,15 +107,13 @@ public class LwM2mClient implements Cloneable {
103 LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRez)); 107 LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRez));
104 String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId()); 108 String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId());
105 String verRez = getVerFromPathIdVerOrId(pathRez); 109 String verRez = getVerFromPathIdVerOrId(pathRez);
106 - return (verRez == null || verSupportedObject.equals(verRez)) ? modelProvider.getObjectModel(registration) 110 + return verRez == null || verRez.equals(verSupportedObject) ? modelProvider.getObjectModel(registration)
107 .getResourceModel(pathIds.getObjectId(), pathIds.getResourceId()) : null; 111 .getResourceModel(pathIds.getObjectId(), pathIds.getResourceId()) : null;
108 } 112 }
109 113
110 public Collection<LwM2mResource> getNewResourcesForInstance(String pathRezIdVer, LwM2mModelProvider modelProvider, 114 public Collection<LwM2mResource> getNewResourcesForInstance(String pathRezIdVer, LwM2mModelProvider modelProvider,
111 LwM2mValueConverterImpl converter) { 115 LwM2mValueConverterImpl converter) {
112 LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRezIdVer)); 116 LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRezIdVer));
113 - String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId());  
114 - String verRez = getVerFromPathIdVerOrId(pathRezIdVer);  
115 Collection<LwM2mResource> resources = ConcurrentHashMap.newKeySet(); 117 Collection<LwM2mResource> resources = ConcurrentHashMap.newKeySet();
116 Map<Integer, ResourceModel> resourceModels = modelProvider.getObjectModel(registration) 118 Map<Integer, ResourceModel> resourceModels = modelProvider.getObjectModel(registration)
117 .getObjectModel(pathIds.getObjectId()).resources; 119 .getObjectModel(pathIds.getObjectId()).resources;
@@ -170,11 +172,11 @@ public class LwM2mClient implements Cloneable { @@ -170,11 +172,11 @@ public class LwM2mClient implements Cloneable {
170 .collect(Collectors.toSet()); 172 .collect(Collectors.toSet());
171 } 173 }
172 174
173 - public void initValue(LwM2mTransportServiceImpl serviceImpl, String path) { 175 + public void initReadValue(LwM2mTransportServiceImpl serviceImpl, String path) {
174 if (path != null) { 176 if (path != null) {
175 - this.pendingRequests.remove(path); 177 + this.pendingReadRequests.remove(path);
176 } 178 }
177 - if (this.pendingRequests.size() == 0) { 179 + if (this.pendingReadRequests.size() == 0) {
178 this.init = true; 180 this.init = true;
179 serviceImpl.putDelayedUpdateResourcesThingsboard(this); 181 serviceImpl.putDelayedUpdateResourcesThingsboard(this);
180 } 182 }
@@ -82,12 +82,12 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { @@ -82,12 +82,12 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
82 82
83 @Override 83 @Override
84 public LwM2mClient getLwM2mClientWithReg(Registration registration, String registrationId) { 84 public LwM2mClient getLwM2mClientWithReg(Registration registration, String registrationId) {
85 - LwM2mClient client = registrationId != null ? 85 + LwM2mClient client = registrationId != null && this.lwM2mClients.containsKey(registrationId) ?
86 this.lwM2mClients.get(registrationId) : 86 this.lwM2mClients.get(registrationId) :
87 - this.lwM2mClients.containsKey(registration.getId()) ?  
88 - this.lwM2mClients.get(registration.getId()) :  
89 - this.lwM2mClients.get(registration.getEndpoint());  
90 - return client != null ? client : updateInSessionsLwM2MClient(registration); 87 + registration !=null && this.lwM2mClients.containsKey(registration.getId()) ?
  88 + this.lwM2mClients.get(registration.getId()) : registration !=null && this.lwM2mClients.containsKey(registration) ?
  89 + this.lwM2mClients.get(registration.getEndpoint()) : null;
  90 + return client != null ? client : registration!= null ? updateInSessionsLwM2MClient(registration) : null;
91 } 91 }
92 92
93 @Override 93 @Override
  1 +/**
  2 + * Copyright © 2016-2021 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.transport.lwm2m.server.client;
  17 +
  18 +import lombok.Data;
  19 +
  20 +import java.util.UUID;
  21 +
  22 +@Data
  23 +public class LwM2mFirmwareUpdate {
  24 + private volatile String clientFwVersion;
  25 + private volatile String currentFwVersion;
  26 + private volatile UUID currentFwId;
  27 +}
@@ -24,6 +24,8 @@ import { @@ -24,6 +24,8 @@ import {
24 NG_VALUE_ACCESSOR, 24 NG_VALUE_ACCESSOR,
25 Validators 25 Validators
26 } from '@angular/forms'; 26 } from '@angular/forms';
  27 +import { Store } from '@ngrx/store';
  28 +import { AppState } from '@core/core.state';
27 import { coerceBooleanProperty } from '@angular/cdk/coercion'; 29 import { coerceBooleanProperty } from '@angular/cdk/coercion';
28 import { 30 import {
29 ATTRIBUTE, 31 ATTRIBUTE,
@@ -38,6 +40,7 @@ import { @@ -38,6 +40,7 @@ import {
38 } from './lwm2m-profile-config.models'; 40 } from './lwm2m-profile-config.models';
39 import { deepClone, isDefinedAndNotNull, isEqual, isUndefined } from '@core/utils'; 41 import { deepClone, isDefinedAndNotNull, isEqual, isUndefined } from '@core/utils';
40 import { MatDialog } from '@angular/material/dialog'; 42 import { MatDialog } from '@angular/material/dialog';
  43 +import { TranslateService } from '@ngx-translate/core';
41 import { 44 import {
42 Lwm2mObjectAddInstancesData, 45 Lwm2mObjectAddInstancesData,
43 Lwm2mObjectAddInstancesDialogComponent 46 Lwm2mObjectAddInstancesDialogComponent
@@ -80,8 +83,10 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor @@ -80,8 +83,10 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor
80 @Input() 83 @Input()
81 disabled: boolean; 84 disabled: boolean;
82 85
83 - constructor(private fb: FormBuilder,  
84 - private dialog: MatDialog) { 86 + constructor(private store: Store<AppState>,
  87 + private fb: FormBuilder,
  88 + private dialog: MatDialog,
  89 + public translate: TranslateService) {
85 this.observeAttrTelemetryFormGroup = this.fb.group({ 90 this.observeAttrTelemetryFormGroup = this.fb.group({
86 [CLIENT_LWM2M]: this.fb.array([]) 91 [CLIENT_LWM2M]: this.fb.array([])
87 }); 92 });
@@ -93,7 +98,7 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor @@ -93,7 +98,7 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor
93 } 98 }
94 99
95 private propagateChange = (v: any) => { 100 private propagateChange = (v: any) => {
96 - } 101 + };
97 102
98 registerOnChange(fn: any): void { 103 registerOnChange(fn: any): void {
99 this.propagateChange = fn; 104 this.propagateChange = fn;
@@ -184,7 +189,7 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor @@ -184,7 +189,7 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor
184 this.observeAttrTelemetryFormGroup.get(CLIENT_LWM2M).updateValueAndValidity(); 189 this.observeAttrTelemetryFormGroup.get(CLIENT_LWM2M).updateValueAndValidity();
185 } 190 }
186 191
187 - trackByParams = (index: number): number => { 192 + trackByParams = (index: number, element: any): number => {
188 return index; 193 return index;
189 } 194 }
190 195
@@ -312,7 +317,7 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor @@ -312,7 +317,7 @@ export class Lwm2mObserveAttrTelemetryComponent implements ControlValueAccessor
312 return objectName + ' <' + idVerObj + '>'; 317 return objectName + ' <' + idVerObj + '>';
313 } 318 }
314 getNameInstanceLwm2m = (instance: Instance, idVerObj: string): string => { 319 getNameInstanceLwm2m = (instance: Instance, idVerObj: string): string => {
315 - return ` instance <${idVerObj}/${instance.id}>`; 320 + return ' instance <' + idVerObj + '/' + instance.id +'>';
316 } 321 }
317 322
318 updateAttributeLwm2mObject = (event: Event, objectKeyId: number): void => { 323 updateAttributeLwm2mObject = (event: Event, objectKeyId: number): void => {
@@ -1205,7 +1205,7 @@ @@ -1205,7 +1205,7 @@
1205 "telemetry-label": "Telemetry", 1205 "telemetry-label": "Telemetry",
1206 "key-name-label": "Key Name", 1206 "key-name-label": "Key Name",
1207 "attribute-lwm2m-label": "AttrLwm2m", 1207 "attribute-lwm2m-label": "AttrLwm2m",
1208 - "resource-tip": "ID & Original Name of the Resource", 1208 + "resource-tip": "ID & Original Name of the Resource (only Operations isReadable)",
1209 "is-observe-tip": "Is Observe", 1209 "is-observe-tip": "Is Observe",
1210 "not-observe-tip": "To observe select telemetry or attributes first", 1210 "not-observe-tip": "To observe select telemetry or attributes first",
1211 "is-attr-tip": "Is Attribute", 1211 "is-attr-tip": "Is Attribute",