Commit 4bc417456b04e08f988a0db718a619a931a842b2

Authored by nickAS21
Committed by GitHub
1 parent ad7c314b

lwm2m: back transport newKey start (#4278)

* lwm2m: back transport newKey start

* lwm2m: back transport newKey start1

* lwm2m: back transport newKey fix bug save

* lwm2m: back transport newKey test All security - ok

* lwm2m: back transport newKey fix bug updateAttrShared
  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.common.data.lwm2m;
  17 +
  18 +public interface LwM2mConstants {
  19 +
  20 + String LWM2M_SEPARATOR_PATH = "/";
  21 + String LWM2M_SEPARATOR_KEY = "_";
  22 + String LWM2M_SEPARATOR_SEARCH_TEXT = ":";
  23 +}
@@ -41,6 +41,10 @@ @@ -41,6 +41,10 @@
41 <artifactId>transport-api</artifactId> 41 <artifactId>transport-api</artifactId>
42 </dependency> 42 </dependency>
43 <dependency> 43 <dependency>
  44 + <groupId>org.thingsboard.common</groupId>
  45 + <artifactId>data</artifactId>
  46 + </dependency>
  47 + <dependency>
44 <groupId>org.springframework</groupId> 48 <groupId>org.springframework</groupId>
45 <artifactId>spring-context-support</artifactId> 49 <artifactId>spring-context-support</artifactId>
46 </dependency> 50 </dependency>
@@ -26,6 +26,8 @@ import org.eclipse.leshan.server.registration.RegistrationUpdate; @@ -26,6 +26,8 @@ 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.convertToIdVerFromObjectId;
  30 +
29 @Slf4j 31 @Slf4j
30 public class LwM2mServerListener { 32 public class LwM2mServerListener {
31 33
@@ -90,7 +92,7 @@ public class LwM2mServerListener { @@ -90,7 +92,7 @@ public class LwM2mServerListener {
90 public void onResponse(Observation observation, Registration registration, ObserveResponse response) { 92 public void onResponse(Observation observation, Registration registration, ObserveResponse response) {
91 if (registration != null) { 93 if (registration != null) {
92 try { 94 try {
93 - service.onObservationResponse(registration, observation.getPath().toString(), response); 95 + service.onObservationResponse(registration, convertToIdVerFromObjectId(observation.getPath().toString(), registration), response);
94 } catch (Exception e) { 96 } catch (Exception e) {
95 log.error("[{}] onResponse", e.toString()); 97 log.error("[{}] onResponse", e.toString());
96 98
@@ -22,6 +22,7 @@ import com.google.gson.JsonSyntaxException; @@ -22,6 +22,7 @@ import com.google.gson.JsonSyntaxException;
22 import lombok.extern.slf4j.Slf4j; 22 import lombok.extern.slf4j.Slf4j;
23 import org.apache.commons.lang3.StringUtils; 23 import org.apache.commons.lang3.StringUtils;
24 import org.eclipse.californium.core.network.config.NetworkConfig; 24 import org.eclipse.californium.core.network.config.NetworkConfig;
  25 +import org.eclipse.leshan.core.model.ObjectModel;
25 import org.eclipse.leshan.core.model.ResourceModel; 26 import org.eclipse.leshan.core.model.ResourceModel;
26 import org.eclipse.leshan.core.node.LwM2mMultipleResource; 27 import org.eclipse.leshan.core.node.LwM2mMultipleResource;
27 import org.eclipse.leshan.core.node.LwM2mNode; 28 import org.eclipse.leshan.core.node.LwM2mNode;
@@ -32,6 +33,7 @@ import org.eclipse.leshan.core.node.LwM2mSingleResource; @@ -32,6 +33,7 @@ import org.eclipse.leshan.core.node.LwM2mSingleResource;
32 import org.eclipse.leshan.core.node.codec.CodecException; 33 import org.eclipse.leshan.core.node.codec.CodecException;
33 import org.eclipse.leshan.core.util.Hex; 34 import org.eclipse.leshan.core.util.Hex;
34 import org.eclipse.leshan.server.californium.LeshanServerBuilder; 35 import org.eclipse.leshan.server.californium.LeshanServerBuilder;
  36 +import org.eclipse.leshan.server.registration.Registration;
35 import org.nustaq.serialization.FSTConfiguration; 37 import org.nustaq.serialization.FSTConfiguration;
36 import org.thingsboard.server.common.data.DeviceProfile; 38 import org.thingsboard.server.common.data.DeviceProfile;
37 import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; 39 import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration;
@@ -47,14 +49,12 @@ import java.util.Date; @@ -47,14 +49,12 @@ import java.util.Date;
47 import java.util.LinkedList; 49 import java.util.LinkedList;
48 import java.util.Optional; 50 import java.util.Optional;
49 51
  52 +import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY;
  53 +import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH;
  54 +
50 @Slf4j 55 @Slf4j
51 -//@Component("LwM2MTransportHandler")  
52 -//@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' )|| ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')")  
53 public class LwM2mTransportHandler { 56 public class LwM2mTransportHandler {
54 57
55 - // We choose a default timeout a bit higher to the MAX_TRANSMIT_WAIT(62-93s) which is the time from starting to  
56 - // send a Confirmable message to the time when an acknowledgement is no longer expected.  
57 -  
58 public static final String BASE_DEVICE_API_TOPIC = "v1/devices/me"; 58 public static final String BASE_DEVICE_API_TOPIC = "v1/devices/me";
59 public static final String ATTRIBUTE = "attribute"; 59 public static final String ATTRIBUTE = "attribute";
60 public static final String TELEMETRY = "telemetry"; 60 public static final String TELEMETRY = "telemetry";
@@ -84,6 +84,8 @@ public class LwM2mTransportHandler { @@ -84,6 +84,8 @@ public class LwM2mTransportHandler {
84 public static final String LOG_LW2M_ERROR = "error"; 84 public static final String LOG_LW2M_ERROR = "error";
85 public static final String LOG_LW2M_WARN = "warn"; 85 public static final String LOG_LW2M_WARN = "warn";
86 86
  87 + public static final int LWM2M_STRATEGY_1 = 1;
  88 + public static final int LWM2M_STRATEGY_2 = 2;
87 89
88 public static final String CLIENT_NOT_AUTHORIZED = "Client not authorized"; 90 public static final String CLIENT_NOT_AUTHORIZED = "Client not authorized";
89 91
@@ -110,39 +112,6 @@ public class LwM2mTransportHandler { @@ -110,39 +112,6 @@ public class LwM2mTransportHandler {
110 public static final String SERVICE_CHANNEL = "SERVICE"; 112 public static final String SERVICE_CHANNEL = "SERVICE";
111 public static final String RESPONSE_CHANNEL = "RESP"; 113 public static final String RESPONSE_CHANNEL = "RESP";
112 114
113 -// @Autowired  
114 -// @Qualifier("LeshanServerCert")  
115 -// private LeshanServer lhServerCert;  
116 -//  
117 -// @Autowired  
118 -// @Qualifier("LeshanServerNoSecPskRpk")  
119 -// private LeshanServer lhServerNoSecPskRpk;  
120 -  
121 -// @Autowired  
122 -// @Qualifier("ServerListenerCert")  
123 -// private LwM2mServerListener serverListenerCert;  
124 -//  
125 -// @Autowired  
126 -// @Qualifier("ServerListenerNoSecPskRpk")  
127 -// private LwM2mServerListener serverListenerNoSecPskRpk;  
128 -  
129 -  
130 -// @PostConstruct  
131 -// public void init() {  
132 -// try {  
133 -// serverListenerCert.init(lhServerCert);  
134 -// this.lhServerCert.getRegistrationService().addListener(serverListenerCert.registrationListener);  
135 -// this.lhServerCert.getPresenceService().addListener(serverListenerCert.presenceListener);  
136 -// this.lhServerCert.getObservationService().addListener(serverListenerCert.observationListener);  
137 -// serverListenerNoSecPskRpk.init(lhServerNoSecPskRpk);  
138 -// this.lhServerNoSecPskRpk.getRegistrationService().addListener(serverListenerNoSecPskRpk.registrationListener);  
139 -// this.lhServerNoSecPskRpk.getPresenceService().addListener(serverListenerNoSecPskRpk.presenceListener);  
140 -// this.lhServerNoSecPskRpk.getObservationService().addListener(serverListenerNoSecPskRpk.observationListener);  
141 -// } catch (Exception e) {  
142 -// log.error("init [{}]", e.toString());  
143 -// }  
144 -// }  
145 -  
146 public static NetworkConfig getCoapConfig(Integer serverPortNoSec, Integer serverSecurePort) { 115 public static NetworkConfig getCoapConfig(Integer serverPortNoSec, Integer serverSecurePort) {
147 NetworkConfig coapConfig; 116 NetworkConfig coapConfig;
148 File configFile = new File(NetworkConfig.DEFAULT_FILE_NAME); 117 File configFile = new File(NetworkConfig.DEFAULT_FILE_NAME);
@@ -202,10 +171,10 @@ public class LwM2mTransportHandler { @@ -202,10 +171,10 @@ public class LwM2mTransportHandler {
202 171
203 /** 172 /**
204 * @return deviceProfileBody with Observe&Attribute&Telemetry From Thingsboard 173 * @return deviceProfileBody with Observe&Attribute&Telemetry From Thingsboard
205 - * Example: 174 + * Example:
206 * property: {"clientLwM2mSettings": { 175 * property: {"clientLwM2mSettings": {
207 - * clientUpdateValueAfterConnect: false;  
208 - * } 176 + * clientUpdateValueAfterConnect: false;
  177 + * }
209 * property: "observeAttr" 178 * property: "observeAttr"
210 * {"keyName": { 179 * {"keyName": {
211 * "/3/0/1": "modelNumber", 180 * "/3/0/1": "modelNumber",
@@ -222,7 +191,7 @@ public class LwM2mTransportHandler { @@ -222,7 +191,7 @@ public class LwM2mTransportHandler {
222 try { 191 try {
223 ObjectMapper mapper = new ObjectMapper(); 192 ObjectMapper mapper = new ObjectMapper();
224 String profileStr = mapper.writeValueAsString(profile); 193 String profileStr = mapper.writeValueAsString(profile);
225 - JsonObject profileJson = (profileStr != null) ? validateJson(profileStr) : null; 194 + JsonObject profileJson = (profileStr != null) ? validateJson(profileStr) : null;
226 return (getValidateCredentialsBodyFromThingsboard(profileJson)) ? LwM2mTransportHandler.getNewProfileParameters(profileJson, deviceProfile.getTenantId()) : null; 195 return (getValidateCredentialsBodyFromThingsboard(profileJson)) ? LwM2mTransportHandler.getNewProfileParameters(profileJson, deviceProfile.getTenantId()) : null;
227 } catch (IOException e) { 196 } catch (IOException e) {
228 log.error("", e); 197 log.error("", e);
@@ -246,9 +215,9 @@ public class LwM2mTransportHandler { @@ -246,9 +215,9 @@ public class LwM2mTransportHandler {
246 return null; 215 return null;
247 } 216 }
248 217
249 - public static boolean getClientOnlyObserveAfterConnect (LwM2mClientProfile profile) {  
250 - return profile.getPostClientLwM2mSettings().getAsJsonObject().has("clientOnlyObserveAfterConnect") &&  
251 - profile.getPostClientLwM2mSettings().getAsJsonObject().get("clientOnlyObserveAfterConnect").getAsBoolean(); 218 + public static int getClientOnlyObserveAfterConnect(LwM2mClientProfile profile) {
  219 + return profile.getPostClientLwM2mSettings().getAsJsonObject().has("clientOnlyObserveAfterConnect") ?
  220 + profile.getPostClientLwM2mSettings().getAsJsonObject().get("clientOnlyObserveAfterConnect").getAsInt() : 1;
252 } 221 }
253 222
254 private static boolean getValidateCredentialsBodyFromThingsboard(JsonObject objectMsg) { 223 private static boolean getValidateCredentialsBodyFromThingsboard(JsonObject objectMsg) {
@@ -346,4 +315,49 @@ public class LwM2mTransportHandler { @@ -346,4 +315,49 @@ public class LwM2mTransportHandler {
346 } 315 }
347 }; 316 };
348 } 317 }
  318 +
  319 + public static String convertToObjectIdFromIdVer(String key) {
  320 + try {
  321 + String[] keyArray = key.split(LWM2M_SEPARATOR_PATH);
  322 + if (keyArray.length > 1 && keyArray[1].split(LWM2M_SEPARATOR_KEY).length == 2) {
  323 + keyArray[1] = keyArray[1].split(LWM2M_SEPARATOR_KEY)[0];
  324 + return StringUtils.join(keyArray, LWM2M_SEPARATOR_PATH);
  325 + } else {
  326 + return key;
  327 + }
  328 + } catch (Exception e) {
  329 + return null;
  330 + }
  331 + }
  332 +
  333 + public static String convertToIdVerFromObjectId(String path, Registration registration) {
  334 + String ver = registration.getSupportedObject().get(new LwM2mPath(path).getObjectId());
  335 + try {
  336 + String[] keyArray = path.split(LWM2M_SEPARATOR_PATH);
  337 + if (keyArray.length > 1) {
  338 + keyArray[1] = keyArray[1] + LWM2M_SEPARATOR_KEY + ver;
  339 + return StringUtils.join(keyArray, LWM2M_SEPARATOR_PATH);
  340 + } else {
  341 + return path;
  342 + }
  343 + } catch (Exception e) {
  344 + return null;
  345 + }
  346 + }
  347 +
  348 + public static Integer validateObjectIdFromKey(String key) {
  349 + try {
  350 + return Integer.parseInt(key.split(LWM2M_SEPARATOR_PATH)[1].split(LWM2M_SEPARATOR_KEY)[0]);
  351 + } catch (Exception e) {
  352 + return null;
  353 + }
  354 + }
  355 +
  356 + public static String validateObjectVerFromKey(String key) {
  357 + try {
  358 + return (key.split(LWM2M_SEPARATOR_PATH)[1].split(LWM2M_SEPARATOR_KEY)[1]);
  359 + } catch (Exception e) {
  360 + return ObjectModel.DEFAULT_VERSION;
  361 + }
  362 + }
349 } 363 }
@@ -72,6 +72,8 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandle @@ -72,6 +72,8 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandle
72 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.PUT_TYPE_OPER_WRITE_ATTRIBUTES; 72 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.PUT_TYPE_OPER_WRITE_ATTRIBUTES;
73 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.PUT_TYPE_OPER_WRITE_UPDATE; 73 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.PUT_TYPE_OPER_WRITE_UPDATE;
74 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.RESPONSE_CHANNEL; 74 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.RESPONSE_CHANNEL;
  75 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertToIdVerFromObjectId;
  76 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertToObjectIdFromIdVer;
75 77
76 @Slf4j 78 @Slf4j
77 @Service 79 @Service
@@ -114,7 +116,7 @@ public class LwM2mTransportRequest { @@ -114,7 +116,7 @@ public class LwM2mTransportRequest {
114 */ 116 */
115 public void sendAllRequest(Registration registration, String target, String typeOper, 117 public void sendAllRequest(Registration registration, String target, String typeOper,
116 String contentFormatParam, Observation observation, Object params, long timeoutInMs) { 118 String contentFormatParam, Observation observation, Object params, long timeoutInMs) {
117 - LwM2mPath resultIds = new LwM2mPath(target); 119 + LwM2mPath resultIds = new LwM2mPath(convertToObjectIdFromIdVer(target));
118 if (registration != null && resultIds.getObjectId() >= 0) { 120 if (registration != null && resultIds.getObjectId() >= 0) {
119 DownlinkRequest request = null; 121 DownlinkRequest request = null;
120 ContentFormat contentFormat = contentFormatParam != null ? ContentFormat.fromName(contentFormatParam.toUpperCase()) : null; 122 ContentFormat contentFormat = contentFormatParam != null ? ContentFormat.fromName(contentFormatParam.toUpperCase()) : null;
@@ -229,9 +231,8 @@ public class LwM2mTransportRequest { @@ -229,9 +231,8 @@ public class LwM2mTransportRequest {
229 private void sendRequest(Registration registration, DownlinkRequest request, long timeoutInMs) { 231 private void sendRequest(Registration registration, DownlinkRequest request, long timeoutInMs) {
230 LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null); 232 LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null);
231 leshanServer.send(registration, request, timeoutInMs, (ResponseCallback<?>) response -> { 233 leshanServer.send(registration, request, timeoutInMs, (ResponseCallback<?>) response -> {
232 -  
233 if (!lwM2MClient.isInit()) { 234 if (!lwM2MClient.isInit()) {
234 - lwM2MClient.initValue(this.serviceImpl, request.getPath().toString()); 235 + lwM2MClient.initValue(this.serviceImpl, convertToIdVerFromObjectId(request.getPath().toString(), registration));
235 } 236 }
236 if (isSuccess(((Response) response.getCoapResponse()).getCode())) { 237 if (isSuccess(((Response) response.getCoapResponse()).getCode())) {
237 this.handleResponse(registration, request.getPath().toString(), response, request); 238 this.handleResponse(registration, request.getPath().toString(), response, request);
@@ -251,7 +252,7 @@ public class LwM2mTransportRequest { @@ -251,7 +252,7 @@ public class LwM2mTransportRequest {
251 } 252 }
252 }, e -> { 253 }, e -> {
253 if (!lwM2MClient.isInit()) { 254 if (!lwM2MClient.isInit()) {
254 - lwM2MClient.initValue(this.serviceImpl, request.getPath().toString()); 255 + lwM2MClient.initValue(this.serviceImpl, convertToIdVerFromObjectId(request.getPath().toString(), registration));
255 } 256 }
256 String msg = String.format("%s: sendRequest: Resource path - %s msg error - %s SendRequest to Client", 257 String msg = String.format("%s: sendRequest: Resource path - %s msg error - %s SendRequest to Client",
257 LOG_LW2M_ERROR, request.getPath().toString(), e.toString()); 258 LOG_LW2M_ERROR, request.getPath().toString(), e.toString());
@@ -310,21 +311,22 @@ public class LwM2mTransportRequest { @@ -310,21 +311,22 @@ public class LwM2mTransportRequest {
310 * @param response - 311 * @param response -
311 */ 312 */
312 private void sendResponse(Registration registration, String path, LwM2mResponse response, DownlinkRequest request) { 313 private void sendResponse(Registration registration, String path, LwM2mResponse response, DownlinkRequest request) {
  314 + String pathIdVer = convertToIdVerFromObjectId(path, registration);
313 if (response instanceof ReadResponse) { 315 if (response instanceof ReadResponse) {
314 - serviceImpl.onObservationResponse(registration, path, (ReadResponse) response); 316 + serviceImpl.onObservationResponse(registration, pathIdVer, (ReadResponse) response);
315 } else if (response instanceof CancelObservationResponse) { 317 } else if (response instanceof CancelObservationResponse) {
316 - log.info("[{}] Path [{}] CancelObservationResponse 3_Send", path, response); 318 + log.info("[{}] Path [{}] CancelObservationResponse 3_Send", pathIdVer, response);
317 } else if (response instanceof DeleteResponse) { 319 } else if (response instanceof DeleteResponse) {
318 - log.info("[{}] Path [{}] DeleteResponse 5_Send", path, response); 320 + log.info("[{}] Path [{}] DeleteResponse 5_Send", pathIdVer, response);
319 } else if (response instanceof DiscoverResponse) { 321 } else if (response instanceof DiscoverResponse) {
320 - log.info("[{}] Path [{}] DiscoverResponse 6_Send", path, response); 322 + log.info("[{}] Path [{}] DiscoverResponse 6_Send", pathIdVer, response);
321 } else if (response instanceof ExecuteResponse) { 323 } else if (response instanceof ExecuteResponse) {
322 - log.info("[{}] Path [{}] ExecuteResponse 7_Send", path, response); 324 + log.info("[{}] Path [{}] ExecuteResponse 7_Send", pathIdVer, response);
323 } else if (response instanceof WriteAttributesResponse) { 325 } else if (response instanceof WriteAttributesResponse) {
324 - log.info("[{}] Path [{}] WriteAttributesResponse 8_Send", path, response); 326 + log.info("[{}] Path [{}] WriteAttributesResponse 8_Send", pathIdVer, response);
325 } else if (response instanceof WriteResponse) { 327 } else if (response instanceof WriteResponse) {
326 - log.info("[{}] Path [{}] WriteAttributesResponse 9_Send", path, response);  
327 - serviceImpl.onWriteResponseOk(registration, path, (WriteRequest) request); 328 + log.info("[{}] Path [{}] WriteAttributesResponse 9_Send", pathIdVer, response);
  329 + serviceImpl.onWriteResponseOk(registration, pathIdVer, (WriteRequest) request);
328 } 330 }
329 } 331 }
330 } 332 }
@@ -88,10 +88,15 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandle @@ -88,10 +88,15 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandle
88 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;
89 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;
90 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_TELEMETRY; 90 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_TELEMETRY;
  91 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LWM2M_STRATEGY_2;
91 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.POST_TYPE_OPER_EXECUTE; 92 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.POST_TYPE_OPER_EXECUTE;
92 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.POST_TYPE_OPER_WRITE_REPLACE; 93 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.POST_TYPE_OPER_WRITE_REPLACE;
93 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.SERVICE_CHANNEL; 94 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.SERVICE_CHANNEL;
  95 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertToIdVerFromObjectId;
  96 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertToObjectIdFromIdVer;
94 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.getAckCallback; 97 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.getAckCallback;
  98 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.validateObjectIdFromKey;
  99 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.validateObjectVerFromKey;
95 100
96 @Slf4j 101 @Slf4j
97 @Service 102 @Service
@@ -290,19 +295,19 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -290,19 +295,19 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
290 if (msg.getSharedUpdatedCount() > 0) { 295 if (msg.getSharedUpdatedCount() > 0) {
291 JsonElement el = JsonConverter.toJson(msg); 296 JsonElement el = JsonConverter.toJson(msg);
292 el.getAsJsonObject().entrySet().forEach(de -> { 297 el.getAsJsonObject().entrySet().forEach(de -> {
293 - String path = this.getPathAttributeUpdate(sessionInfo, de.getKey()); 298 + String pathIdVer = this.getPathAttributeUpdate(sessionInfo, de.getKey());
294 String value = de.getValue().getAsString(); 299 String value = de.getValue().getAsString();
295 LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())); 300 LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()));
296 LwM2mClientProfile clientProfile = lwM2mClientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB())); 301 LwM2mClientProfile clientProfile = lwM2mClientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB()));
297 - if (path != null && !path.isEmpty() && (this.validatePathInAttrProfile(clientProfile, path) || this.validatePathInTelemetryProfile(clientProfile, path))) {  
298 - ResourceModel resourceModel = lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResourceModel(lwM2MClient.getRegistration(), new LwM2mPath(path)); 302 + if (pathIdVer != null && !pathIdVer.isEmpty() && (this.validatePathInAttrProfile(clientProfile, pathIdVer) || this.validatePathInTelemetryProfile(clientProfile, pathIdVer))) {
  303 + ResourceModel resourceModel = lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResourceModel(lwM2MClient.getRegistration(), new LwM2mPath(convertToObjectIdFromIdVer(pathIdVer)));
299 if (resourceModel != null && resourceModel.operations.isWritable()) { 304 if (resourceModel != null && resourceModel.operations.isWritable()) {
300 - lwM2mTransportRequest.sendAllRequest(lwM2MClient.getRegistration(), path, POST_TYPE_OPER_WRITE_REPLACE, 305 + lwM2mTransportRequest.sendAllRequest(lwM2MClient.getRegistration(), pathIdVer, POST_TYPE_OPER_WRITE_REPLACE,
301 ContentFormat.TLV.getName(), null, value, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout()); 306 ContentFormat.TLV.getName(), null, value, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout());
302 } else { 307 } else {
303 - log.error("Resource path - [{}] value - [{}] is not Writable and cannot be updated", path, value); 308 + log.error("Resource path - [{}] value - [{}] is not Writable and cannot be updated", pathIdVer, value);
304 String logMsg = String.format("%s: attributeUpdate: Resource path - %s value - %s is not Writable and cannot be updated", 309 String logMsg = String.format("%s: attributeUpdate: Resource path - %s value - %s is not Writable and cannot be updated",
305 - LOG_LW2M_ERROR, path, value); 310 + LOG_LW2M_ERROR, pathIdVer, value);
306 this.sentLogsToThingsboard(logMsg, lwM2MClient.getRegistration()); 311 this.sentLogsToThingsboard(logMsg, lwM2MClient.getRegistration());
307 } 312 }
308 } else { 313 } else {
@@ -348,7 +353,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -348,7 +353,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
348 353
349 /** 354 /**
350 * Trigger Server path = "/1/0/8" 355 * Trigger Server path = "/1/0/8"
351 - * 356 + * <p>
352 * Trigger bootStrap path = "/1/0/9" - have to implemented on client 357 * Trigger bootStrap path = "/1/0/9" - have to implemented on client
353 */ 358 */
354 @Override 359 @Override
@@ -458,7 +463,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -458,7 +463,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
458 private void initLwM2mFromClientValue(Registration registration, LwM2mClient lwM2MClient) { 463 private void initLwM2mFromClientValue(Registration registration, LwM2mClient lwM2MClient) {
459 LwM2mClientProfile lwM2MClientProfile = lwM2mClientContext.getProfile(registration); 464 LwM2mClientProfile lwM2MClientProfile = lwM2mClientContext.getProfile(registration);
460 Set<String> clientObjects = this.getAllOjectsInClient(registration); 465 Set<String> clientObjects = this.getAllOjectsInClient(registration);
461 - if (clientObjects != null && !LwM2mTransportHandler.getClientOnlyObserveAfterConnect(lwM2MClientProfile)) { 466 + if (clientObjects != null && LWM2M_STRATEGY_2 == LwM2mTransportHandler.getClientOnlyObserveAfterConnect(lwM2MClientProfile)) {
462 // #2 467 // #2
463 lwM2MClient.getPendingRequests().addAll(clientObjects); 468 lwM2MClient.getPendingRequests().addAll(clientObjects);
464 clientObjects.forEach(path -> lwM2mTransportRequest.sendAllRequest(registration, path, GET_TYPE_OPER_READ, ContentFormat.TLV.getName(), 469 clientObjects.forEach(path -> lwM2mTransportRequest.sendAllRequest(registration, path, GET_TYPE_OPER_READ, ContentFormat.TLV.getName(),
@@ -499,9 +504,9 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -499,9 +504,9 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
499 * #1 Return old Value Resource from LwM2MClient 504 * #1 Return old Value Resource from LwM2MClient
500 * #2 Update new Resources (replace old Resource Value on new Resource Value) 505 * #2 Update new Resources (replace old Resource Value on new Resource Value)
501 * 506 *
502 - * @param registration - Registration LwM2M Client 507 + * @param registration - Registration LwM2M Client
503 * @param lwM2mResource - LwM2mSingleResource response.getContent() 508 * @param lwM2mResource - LwM2mSingleResource response.getContent()
504 - * @param path - resource 509 + * @param path - resource
505 */ 510 */
506 private void updateResourcesValue(Registration registration, LwM2mResource lwM2mResource, String path) { 511 private void updateResourcesValue(Registration registration, LwM2mResource lwM2mResource, String path) {
507 LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null); 512 LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null);
@@ -539,7 +544,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -539,7 +544,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
539 544
540 /** 545 /**
541 * @param clientProfile - 546 * @param clientProfile -
542 - * @param path - 547 + * @param path -
543 * @return true if path isPresent in postAttributeProfile 548 * @return true if path isPresent in postAttributeProfile
544 */ 549 */
545 private boolean validatePathInAttrProfile(LwM2mClientProfile clientProfile, String path) { 550 private boolean validatePathInAttrProfile(LwM2mClientProfile clientProfile, String path) {
@@ -555,7 +560,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -555,7 +560,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
555 560
556 /** 561 /**
557 * @param clientProfile - 562 * @param clientProfile -
558 - * @param path - 563 + * @param path -
559 * @return true if path isPresent in postAttributeProfile 564 * @return true if path isPresent in postAttributeProfile
560 */ 565 */
561 private boolean validatePathInTelemetryProfile(LwM2mClientProfile clientProfile, String path) { 566 private boolean validatePathInTelemetryProfile(LwM2mClientProfile clientProfile, String path) {
@@ -581,10 +586,13 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -581,10 +586,13 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
581 Set<String> clientInstances = this.getAllInstancesInClient(registration); 586 Set<String> clientInstances = this.getAllInstancesInClient(registration);
582 Set<String> result; 587 Set<String> result;
583 if (GET_TYPE_OPER_READ.equals(typeOper)) { 588 if (GET_TYPE_OPER_READ.equals(typeOper)) {
584 - result = JacksonUtil.fromString(lwM2MClientProfile.getPostAttributeProfile().toString(), new TypeReference<>() {});  
585 - result.addAll(JacksonUtil.fromString(lwM2MClientProfile.getPostTelemetryProfile().toString(), new TypeReference<>() {})); 589 + result = JacksonUtil.fromString(lwM2MClientProfile.getPostAttributeProfile().toString(), new TypeReference<>() {
  590 + });
  591 + result.addAll(JacksonUtil.fromString(lwM2MClientProfile.getPostTelemetryProfile().toString(), new TypeReference<>() {
  592 + }));
586 } else { 593 } else {
587 - result = JacksonUtil.fromString(lwM2MClientProfile.getPostObserveProfile().toString(), new TypeReference<>() {}); 594 + result = JacksonUtil.fromString(lwM2MClientProfile.getPostObserveProfile().toString(), new TypeReference<>() {
  595 + });
588 } 596 }
589 Set<String> pathSent = ConcurrentHashMap.newKeySet(); 597 Set<String> pathSent = ConcurrentHashMap.newKeySet();
590 result.forEach(target -> { 598 result.forEach(target -> {
@@ -646,7 +654,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -646,7 +654,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
646 Arrays.stream(registration.getObjectLinks()).forEach(url -> { 654 Arrays.stream(registration.getObjectLinks()).forEach(url -> {
647 LwM2mPath pathIds = new LwM2mPath(url.getUrl()); 655 LwM2mPath pathIds = new LwM2mPath(url.getUrl());
648 if (pathIds.isObjectInstance()) { 656 if (pathIds.isObjectInstance()) {
649 - clientInstances.add(url.getUrl()); 657 + clientInstances.add(convertToIdVerFromObjectId(url.getUrl(), registration));
650 } 658 }
651 }); 659 });
652 return (clientInstances.size() > 0) ? clientInstances : null; 660 return (clientInstances.size() > 0) ? clientInstances : null;
@@ -656,26 +664,22 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -656,26 +664,22 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
656 * @param attributes - new JsonObject 664 * @param attributes - new JsonObject
657 * @param telemetry - new JsonObject 665 * @param telemetry - new JsonObject
658 * @param registration - Registration LwM2M Client 666 * @param registration - Registration LwM2M Client
659 - * @param path - 667 + * @param path -
660 */ 668 */
661 private void getParametersFromProfile(JsonObject attributes, JsonObject telemetry, Registration registration, Set<String> path) { 669 private void getParametersFromProfile(JsonObject attributes, JsonObject telemetry, Registration registration, Set<String> path) {
662 - LwM2mClientProfile lwM2MClientProfile = lwM2mClientContext.getProfile(registration);  
663 - lwM2MClientProfile.getPostAttributeProfile().forEach(p -> {  
664 - LwM2mPath pathIds = new LwM2mPath(p.getAsString());  
665 - if (pathIds.isResource()) {  
666 - if (path == null || path.contains(p.getAsString())) {  
667 - this.addParameters(p.getAsString(), attributes, registration); 670 + if (path != null && path.size() > 0) {
  671 + LwM2mClientProfile lwM2MClientProfile = lwM2mClientContext.getProfile(registration);
  672 + lwM2MClientProfile.getPostAttributeProfile().forEach(idVer -> {
  673 + if (path.contains(idVer.getAsString())) {
  674 + this.addParameters(idVer.getAsString(), attributes, registration);
668 } 675 }
669 - }  
670 - });  
671 - lwM2MClientProfile.getPostTelemetryProfile().forEach(p -> {  
672 - LwM2mPath pathIds = new LwM2mPath(p.getAsString());  
673 - if (pathIds.isResource()) {  
674 - if (path == null || path.contains(p.getAsString())) {  
675 - this.addParameters(p.getAsString(), telemetry, registration); 676 + });
  677 + lwM2MClientProfile.getPostTelemetryProfile().forEach(idVer -> {
  678 + if (path.contains(idVer.getAsString())) {
  679 + this.addParameters(idVer.getAsString(), telemetry, registration);
676 } 680 }
677 - }  
678 - }); 681 + });
  682 + }
679 } 683 }
680 684
681 /** 685 /**
@@ -703,22 +707,21 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -703,22 +707,21 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
703 * @return - value of Resource or null 707 * @return - value of Resource or null
704 */ 708 */
705 private String getResourceValueToString(LwM2mClient lwM2MClient, String path) { 709 private String getResourceValueToString(LwM2mClient lwM2MClient, String path) {
706 - LwM2mPath pathIds = new LwM2mPath(path);  
707 - ResourceValue resourceValue = this.returnResourceValueFromLwM2MClient(lwM2MClient, pathIds); 710 + LwM2mPath pathIds =new LwM2mPath(convertToObjectIdFromIdVer(path));
  711 + ResourceValue resourceValue = this.returnResourceValueFromLwM2MClient(lwM2MClient, path);
708 return resourceValue == null ? null : 712 return resourceValue == null ? null :
709 this.converter.convertValue(resourceValue.getResourceValue(), this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResourceModelType(lwM2MClient.getRegistration(), pathIds), ResourceModel.Type.STRING, pathIds).toString(); 713 this.converter.convertValue(resourceValue.getResourceValue(), this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResourceModelType(lwM2MClient.getRegistration(), pathIds), ResourceModel.Type.STRING, pathIds).toString();
710 } 714 }
711 715
712 /** 716 /**
713 - *  
714 * @param lwM2MClient - 717 * @param lwM2MClient -
715 - * @param pathIds - 718 + * @param path -
716 * @return - return value of Resource by idPath 719 * @return - return value of Resource by idPath
717 */ 720 */
718 - private ResourceValue returnResourceValueFromLwM2MClient(LwM2mClient lwM2MClient, LwM2mPath pathIds) { 721 + private ResourceValue returnResourceValueFromLwM2MClient(LwM2mClient lwM2MClient, String path) {
719 ResourceValue resourceValue = null; 722 ResourceValue resourceValue = null;
720 - if (pathIds.isResource()) {  
721 - resourceValue = lwM2MClient.getResources().get(pathIds.toString()); 723 + if (new LwM2mPath(convertToObjectIdFromIdVer(path)).isResource()) {
  724 + resourceValue = lwM2MClient.getResources().get(path);
722 } 725 }
723 return resourceValue; 726 return resourceValue;
724 } 727 }
@@ -818,8 +821,10 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -818,8 +821,10 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
818 821
819 // #5.1 822 // #5.1
820 if (!observeOld.equals(observeNew)) { 823 if (!observeOld.equals(observeNew)) {
821 - Set<String> observeSetOld = new Gson().fromJson(observeOld, new TypeToken<>() {}.getType());  
822 - Set<String> observeSetNew = new Gson().fromJson(observeNew, new TypeToken<>() {}.getType()); 824 + Set<String> observeSetOld = new Gson().fromJson(observeOld, new TypeToken<>() {
  825 + }.getType());
  826 + Set<String> observeSetNew = new Gson().fromJson(observeNew, new TypeToken<>() {
  827 + }.getType());
823 //#5.2 add 828 //#5.2 add
824 // path Attr/Telemetry includes newObserve 829 // path Attr/Telemetry includes newObserve
825 attributeSetOld.addAll(telemetrySetOld); 830 attributeSetOld.addAll(telemetrySetOld);
@@ -840,7 +845,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -840,7 +845,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
840 } 845 }
841 } 846 }
842 847
843 - private Set <String> convertJsonArrayToSet (JsonArray jsonArray) { 848 + private Set<String> convertJsonArrayToSet(JsonArray jsonArray) {
844 List<String> attributeListOld = new Gson().fromJson(jsonArray, new TypeToken<>() { 849 List<String> attributeListOld = new Gson().fromJson(jsonArray, new TypeToken<>() {
845 }.getType()); 850 }.getType());
846 return Sets.newConcurrentHashSet(attributeListOld); 851 return Sets.newConcurrentHashSet(attributeListOld);
@@ -907,7 +912,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -907,7 +912,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
907 private void cancelObserveIsValue(Registration registration, Set<String> paramAnallyzer) { 912 private void cancelObserveIsValue(Registration registration, Set<String> paramAnallyzer) {
908 LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null); 913 LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null);
909 paramAnallyzer.forEach(p -> { 914 paramAnallyzer.forEach(p -> {
910 - if (this.returnResourceValueFromLwM2MClient(lwM2MClient, new LwM2mPath(p)) != null) { 915 + if (this.returnResourceValueFromLwM2MClient(lwM2MClient, p) != null) {
911 this.setCancelObservationRecourse(registration, p); 916 this.setCancelObservationRecourse(registration, p);
912 } 917 }
913 } 918 }
@@ -953,8 +958,9 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -953,8 +958,9 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
953 */ 958 */
954 private String getPathAttributeUpdateProfile(TransportProtos.SessionInfoProto sessionInfo, String name) { 959 private String getPathAttributeUpdateProfile(TransportProtos.SessionInfoProto sessionInfo, String name) {
955 LwM2mClientProfile profile = lwM2mClientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB())); 960 LwM2mClientProfile profile = lwM2mClientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB()));
  961 + Registration registration = lwM2mClientContext.getLwM2MClient(sessionInfo).getRegistration();
956 return profile.getPostKeyNameProfile().getAsJsonObject().entrySet().stream() 962 return profile.getPostKeyNameProfile().getAsJsonObject().entrySet().stream()
957 - .filter(e -> e.getValue().getAsString().equals(name)).findFirst().map(Map.Entry::getKey) 963 + .filter(e -> e.getValue().getAsString().equals(name) && validateResourceInModelByVer(registration, e.getKey())).findFirst().map(Map.Entry::getKey)
958 .orElse(""); 964 .orElse("");
959 } 965 }
960 966
@@ -974,12 +980,14 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -974,12 +980,14 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
974 try { 980 try {
975 LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2MClient(sessionInfo); 981 LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2MClient(sessionInfo);
976 attributesResponse.getSharedAttributeListList().forEach(attr -> { 982 attributesResponse.getSharedAttributeListList().forEach(attr -> {
977 - String path = this.getPathAttributeUpdate(sessionInfo, attr.getKv().getKey());  
978 - // #1.1  
979 - if (lwM2MClient.getDelayedRequests().containsKey(path) && attr.getTs() > lwM2MClient.getDelayedRequests().get(path).getTs()) {  
980 - lwM2MClient.getDelayedRequests().put(path, attr);  
981 - } else {  
982 - lwM2MClient.getDelayedRequests().put(path, attr); 983 + String path =this.getPathAttributeUpdate(sessionInfo, attr.getKv().getKey());
  984 + if (path != null) {
  985 + // #1.1
  986 + if (lwM2MClient.getDelayedRequests().containsKey(path) && attr.getTs() > lwM2MClient.getDelayedRequests().get(path).getTs()) {
  987 + lwM2MClient.getDelayedRequests().put(path, attr);
  988 + } else {
  989 + lwM2MClient.getDelayedRequests().put(path, attr);
  990 + }
983 } 991 }
984 }); 992 });
985 // #2.1 993 // #2.1
@@ -1057,6 +1065,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -1057,6 +1065,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
1057 } 1065 }
1058 1066
1059 /** 1067 /**
  1068 + * !!! sharedAttr === profileAttr !!!
1060 * If there is a difference in values between the current resource values and the shared attribute values 1069 * If there is a difference in values between the current resource values and the shared attribute values
1061 * when the client connects to the server 1070 * when the client connects to the server
1062 * #1 get attributes name from profile include name resources in ModelObject if resource isWritable 1071 * #1 get attributes name from profile include name resources in ModelObject if resource isWritable
@@ -1083,24 +1092,42 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -1083,24 +1092,42 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
1083 1092
1084 1093
1085 /** 1094 /**
1086 - * Get names and keyNames from profile shared!!!! attr resources IsWritable 1095 + * !!! sharedAttr === profileAttr !!!
  1096 + * Get names or keyNames from profile: resources IsWritable
1087 * 1097 *
1088 * @param lwM2MClient - 1098 * @param lwM2MClient -
1089 - * @return ArrayList keyNames from profile attr resources shared!!!! && IsWritable 1099 + * @return ArrayList keyNames from profile profileAttr && IsWritable
1090 */ 1100 */
1091 private List<String> getNamesAttrFromProfileIsWritable(LwM2mClient lwM2MClient) { 1101 private List<String> getNamesAttrFromProfileIsWritable(LwM2mClient lwM2MClient) {
1092 LwM2mClientProfile profile = lwM2mClientContext.getProfile(lwM2MClient.getProfileId()); 1102 LwM2mClientProfile profile = lwM2mClientContext.getProfile(lwM2MClient.getProfileId());
1093 - Set<String> attrSet = new Gson().fromJson(profile.getPostAttributeProfile(), new TypeToken<>() {}.getType());  
1094 - ConcurrentMap<String, String> keyNamesMap = new Gson().fromJson(profile.getPostKeyNameProfile().toString(), new TypeToken<ConcurrentHashMap<String, String>>() {}.getType()); 1103 + Set<String> attrSet = new Gson().fromJson(profile.getPostAttributeProfile(),
  1104 + new TypeToken<HashSet<String>>() {
  1105 + }.getType());
  1106 + ConcurrentMap<String, String> keyNamesMap = new Gson().fromJson(profile.getPostKeyNameProfile().toString(),
  1107 + new TypeToken<ConcurrentHashMap<String, String>>() {
  1108 + }.getType());
1095 1109
1096 ConcurrentMap<String, String> keyNamesIsWritable = keyNamesMap.entrySet() 1110 ConcurrentMap<String, String> keyNamesIsWritable = keyNamesMap.entrySet()
1097 .stream() 1111 .stream()
1098 - .filter(e -> (attrSet.contains(e.getKey()) && lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResourceModel(lwM2MClient.getRegistration(), new LwM2mPath(e.getKey())) != null &&  
1099 - lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResourceModel(lwM2MClient.getRegistration(), new LwM2mPath(e.getKey())).operations.isWritable())) 1112 + .filter(e -> (attrSet.contains(e.getKey()) && resourceIsWritable(lwM2MClient.getRegistration(), e.getKey())))
1100 .collect(Collectors.toConcurrentMap(Map.Entry::getKey, Map.Entry::getValue)); 1113 .collect(Collectors.toConcurrentMap(Map.Entry::getKey, Map.Entry::getValue));
1101 1114
1102 Set<String> namesIsWritable = ConcurrentHashMap.newKeySet(); 1115 Set<String> namesIsWritable = ConcurrentHashMap.newKeySet();
1103 namesIsWritable.addAll(new HashSet<>(keyNamesIsWritable.values())); 1116 namesIsWritable.addAll(new HashSet<>(keyNamesIsWritable.values()));
1104 return new ArrayList<>(namesIsWritable); 1117 return new ArrayList<>(namesIsWritable);
1105 } 1118 }
  1119 +
  1120 + private boolean resourceIsWritable(Registration registration, String pathKey) {
  1121 + return validateResourceInModelByVer(registration, pathKey) &&
  1122 + lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResourceModel(registration,
  1123 + new LwM2mPath(convertToObjectIdFromIdVer(pathKey))).operations.isWritable();
  1124 + }
  1125 +
  1126 + private boolean validateResourceInModelByVer(Registration registration, String pathKey) {
  1127 + Integer objectId = validateObjectIdFromKey(pathKey);
  1128 + String objectVer = validateObjectVerFromKey(pathKey);
  1129 + LwM2mPath lwM2mPath = new LwM2mPath(convertToObjectIdFromIdVer(pathKey));
  1130 + return objectId != null && objectVer != null && objectVer.equals(registration.getSupportedVersion(objectId)) &&
  1131 + lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResourceModel(registration, lwM2mPath) != null;
  1132 + }
1106 } 1133 }
@@ -32,6 +32,7 @@ import java.util.Iterator; @@ -32,6 +32,7 @@ import java.util.Iterator;
32 import java.util.Map; 32 import java.util.Map;
33 33
34 import static org.thingsboard.server.common.data.ResourceType.LWM2M_MODEL; 34 import static org.thingsboard.server.common.data.ResourceType.LWM2M_MODEL;
  35 +import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY;
35 36
36 @Slf4j 37 @Slf4j
37 public class LwM2mVersionedModelProvider implements LwM2mModelProvider { 38 public class LwM2mVersionedModelProvider implements LwM2mModelProvider {
@@ -49,12 +50,9 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider { @@ -49,12 +50,9 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider {
49 this.lwM2mClientContext = lwM2mClientContext; 50 this.lwM2mClientContext = lwM2mClientContext;
50 this.lwM2mTransportContextServer = lwM2mTransportContextServer; 51 this.lwM2mTransportContextServer = lwM2mTransportContextServer;
51 } 52 }
52 - private String getIdVer(ObjectModel objectModel) {  
53 - return objectModel.id + "##" + ((objectModel.getVersion() == null || objectModel.getVersion().isEmpty()) ? ObjectModel.DEFAULT_VERSION : objectModel.getVersion());  
54 - }  
55 53
56 - private String getIdVer(Integer objectId, String version) {  
57 - return objectId != null ? objectId + "##" + ((version == null || version.isEmpty()) ? ObjectModel.DEFAULT_VERSION : version) : null; 54 + private String getKeyIdVer(Integer objectId, String version) {
  55 + return objectId != null ? objectId + LWM2M_SEPARATOR_KEY + ((version == null || version.isEmpty()) ? ObjectModel.DEFAULT_VERSION : version) : null;
58 } 56 }
59 57
60 /** 58 /**
@@ -65,8 +63,7 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider { @@ -65,8 +63,7 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider {
65 */ 63 */
66 @Override 64 @Override
67 public LwM2mModel getObjectModel(Registration registration) { 65 public LwM2mModel getObjectModel(Registration registration) {
68 - return new DynamicModel(registration  
69 - ); 66 + return new DynamicModel(registration);
70 } 67 }
71 68
72 private class DynamicModel implements LwM2mModel { 69 private class DynamicModel implements LwM2mModel {
@@ -107,7 +104,6 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider { @@ -107,7 +104,6 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider {
107 Map<Integer, String> supportedObjects = this.registration.getSupportedObject(); 104 Map<Integer, String> supportedObjects = this.registration.getSupportedObject();
108 Collection<ObjectModel> result = new ArrayList<>(supportedObjects.size()); 105 Collection<ObjectModel> result = new ArrayList<>(supportedObjects.size());
109 Iterator<Map.Entry<Integer, String>> i$ = supportedObjects.entrySet().iterator(); 106 Iterator<Map.Entry<Integer, String>> i$ = supportedObjects.entrySet().iterator();
110 -  
111 while (i$.hasNext()) { 107 while (i$.hasNext()) {
112 Map.Entry<Integer, String> supportedObject = i$.next(); 108 Map.Entry<Integer, String> supportedObject = i$.next();
113 ObjectModel objectModel = this.getObjectModelDynamic(supportedObject.getKey(), supportedObject.getValue()); 109 ObjectModel objectModel = this.getObjectModelDynamic(supportedObject.getKey(), supportedObject.getValue());
@@ -119,7 +115,7 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider { @@ -119,7 +115,7 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider {
119 } 115 }
120 116
121 private ObjectModel getObjectModelDynamic(Integer objectId, String version) { 117 private ObjectModel getObjectModelDynamic(Integer objectId, String version) {
122 - String key = getIdVer(objectId, version); 118 + String key = getKeyIdVer(objectId, version);
123 String xmlB64 = lwM2mTransportContextServer.getTransportResourceCache().get( 119 String xmlB64 = lwM2mTransportContextServer.getTransportResourceCache().get(
124 this.tenantId, 120 this.tenantId,
125 LWM2M_MODEL, 121 LWM2M_MODEL,
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.store;  
17 -  
18 -import lombok.extern.slf4j.Slf4j;  
19 -import org.eclipse.leshan.core.util.Hex;  
20 -import org.eclipse.leshan.server.registration.Registration;  
21 -import org.eclipse.leshan.server.security.InMemorySecurityStore;  
22 -import org.eclipse.leshan.server.security.SecurityInfo;  
23 -import org.eclipse.leshan.server.security.SecurityStoreListener;  
24 -import org.springframework.beans.factory.annotation.Autowired;  
25 -import org.thingsboard.server.common.data.DeviceProfile;  
26 -import org.thingsboard.server.gen.transport.TransportProtos;  
27 -import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode;  
28 -import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator;  
29 -import org.thingsboard.server.transport.lwm2m.secure.ReadResultSecurityStore;  
30 -import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler;  
31 -import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;  
32 -import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile;  
33 -import org.thingsboard.server.transport.lwm2m.utils.TypeServer;  
34 -  
35 -import java.util.Collection;  
36 -import java.util.List;  
37 -import java.util.Map;  
38 -import java.util.UUID;  
39 -import java.util.concurrent.ConcurrentHashMap;  
40 -import java.util.concurrent.locks.Lock;  
41 -import java.util.concurrent.locks.ReadWriteLock;  
42 -import java.util.concurrent.locks.ReentrantReadWriteLock;  
43 -import java.util.stream.Collectors;  
44 -  
45 -import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.NO_SEC;  
46 -  
47 -@Slf4j  
48 -//@Service("LwM2mInMemorySecurityStore")  
49 -//@TbLwM2mTransportComponent  
50 -@Deprecated  
51 -public class LwM2mInMemorySecurityStore extends InMemorySecurityStore {  
52 - private static final boolean INFOS_ARE_COMPROMISED = false;  
53 -  
54 - // lock for the two maps  
55 - private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();  
56 - private final Lock readLock = readWriteLock.readLock();  
57 - private final Lock writeLock = readWriteLock.writeLock();  
58 - private final Map<String /** registrationId */, LwM2mClient> sessions = new ConcurrentHashMap<>();  
59 - private Map<UUID /** profileUUid */, LwM2mClientProfile> profiles = new ConcurrentHashMap<>();  
60 - private SecurityStoreListener listener;  
61 -  
62 - @Autowired  
63 - LwM2mCredentialsSecurityInfoValidator lwM2MCredentialsSecurityInfoValidator;  
64 -  
65 - /**  
66 - * Start after DefaultAuthorizer or LwM2mPskStore  
67 - * @param endPoint -  
68 - * @return SecurityInfo  
69 - */  
70 - @Override  
71 - public SecurityInfo getByEndpoint(String endPoint) {  
72 - readLock.lock();  
73 - try {  
74 - String registrationId = this.getRegistrationId(endPoint, null);  
75 - return (registrationId != null && sessions.size() > 0 && sessions.get(registrationId) != null) ?  
76 - sessions.get(registrationId).getSecurityInfo() : this.addLwM2MClientToSession(endPoint);  
77 - } finally {  
78 - readLock.unlock();  
79 - }  
80 - }  
81 -  
82 - /**  
83 - * Start after LwM2mPskStore  
84 - * @param identity -  
85 - * @return SecurityInfo  
86 - */  
87 - @Override  
88 - public SecurityInfo getByIdentity(String identity) {  
89 - readLock.lock();  
90 - try {  
91 - String integrationId = this.getRegistrationId(null, identity);  
92 - return (integrationId != null) ? sessions.get(integrationId).getSecurityInfo() : this.addLwM2MClientToSession(identity);  
93 - } finally {  
94 - readLock.unlock();  
95 - }  
96 - }  
97 -  
98 - @Override  
99 - public Collection<SecurityInfo> getAll() {  
100 - readLock.lock();  
101 - try {  
102 - return this.sessions.values().stream().map(LwM2mClient::getSecurityInfo).collect(Collectors.toUnmodifiableList());  
103 - } finally {  
104 - readLock.unlock();  
105 - }  
106 - }  
107 -  
108 - /**  
109 - * Removed registration Client from sessions and listener  
110 - * @param registrationId if Client  
111 - */  
112 - public void delRemoveSessionAndListener(String registrationId) {  
113 - writeLock.lock();  
114 - try {  
115 - LwM2mClient lwM2MClient = (sessions.get(registrationId) != null) ? sessions.get(registrationId) : null;  
116 - if (lwM2MClient != null) {  
117 - if (listener != null) {  
118 - listener.securityInfoRemoved(INFOS_ARE_COMPROMISED, lwM2MClient.getSecurityInfo());  
119 - }  
120 - sessions.remove(registrationId);  
121 - }  
122 - } finally {  
123 - writeLock.unlock();  
124 - }  
125 - }  
126 -  
127 - @Override  
128 - public void setListener(SecurityStoreListener listener) {  
129 - this.listener = listener;  
130 - }  
131 -  
132 - public LwM2mClient getLwM2MClient(String endPoint, String identity) {  
133 - Map.Entry<String, LwM2mClient> modelClients = endPoint != null ?  
134 - this.sessions.entrySet().stream().filter(model -> endPoint.equals(model.getValue().getEndpoint())).findAny().orElse(null) :  
135 - this.sessions.entrySet().stream().filter(model -> identity.equals(model.getValue().getIdentity())).findAny().orElse(null);  
136 - return modelClients != null ? modelClients.getValue() : null;  
137 - }  
138 -  
139 - public LwM2mClient getLwM2MClientWithReg(Registration registration, String registrationId) {  
140 - return registrationId != null ?  
141 - this.sessions.get(registrationId) :  
142 - this.sessions.containsKey(registration.getId()) ?  
143 - this.sessions.get(registration.getId()) :  
144 - this.sessions.get(registration.getEndpoint());  
145 - }  
146 -  
147 - public LwM2mClient getLwM2MClient(TransportProtos.SessionInfoProto sessionInfo) {  
148 - return this.getSession(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())).entrySet().iterator().next().getValue();  
149 - }  
150 -  
151 - /**  
152 - * Update in sessions (LwM2MClient for key registration_Id) after starting registration LwM2MClient in LwM2MTransportServiceImpl  
153 - * Remove from sessions LwM2MClient with key registration_Endpoint  
154 - * @param registration -  
155 - * @return LwM2MClient after adding it to session  
156 - */  
157 - public LwM2mClient updateInSessionsLwM2MClient(Registration registration) {  
158 - writeLock.lock();  
159 - try {  
160 - if (this.sessions.get(registration.getEndpoint()) == null) {  
161 - this.addLwM2MClientToSession(registration.getEndpoint());  
162 - }  
163 - LwM2mClient lwM2MClient = this.sessions.get(registration.getEndpoint());  
164 - lwM2MClient.setRegistration(registration);  
165 -// lwM2MClient.getAttributes().putAll(registration.getAdditionalRegistrationAttributes());  
166 - this.sessions.remove(registration.getEndpoint());  
167 - this.sessions.put(registration.getId(), lwM2MClient);  
168 - return lwM2MClient;  
169 - } finally {  
170 - writeLock.unlock();  
171 - }  
172 - }  
173 -  
174 - private String getRegistrationId(String endPoint, String identity) {  
175 - List<String> registrationIds = (endPoint != null) ?  
176 - this.sessions.entrySet().stream().filter(model -> endPoint.equals(model.getValue().getEndpoint())).map(Map.Entry::getKey).collect(Collectors.toList()) :  
177 - this.sessions.entrySet().stream().filter(model -> identity.equals(model.getValue().getIdentity())).map(Map.Entry::getKey).collect(Collectors.toList());  
178 - return (registrationIds != null && registrationIds.size() > 0) ? registrationIds.get(0) : null;  
179 - }  
180 -  
181 - public Registration getByRegistration(String registrationId) {  
182 - return this.sessions.get(registrationId).getRegistration();  
183 - }  
184 -  
185 - /**  
186 - * Add new LwM2MClient to session  
187 - * @param identity-  
188 - * @return SecurityInfo. If error - SecurityInfoError  
189 - * and log:  
190 - * - FORBIDDEN - if there is no authorization  
191 - * - profileUuid - if the device does not have a profile  
192 - * - device - if the thingsboard does not have a device with a name equal to the identity  
193 - */  
194 - private SecurityInfo addLwM2MClientToSession(String identity) {  
195 - ReadResultSecurityStore store = lwM2MCredentialsSecurityInfoValidator.createAndValidateCredentialsSecurityInfo(identity, TypeServer.CLIENT);  
196 - if (store.getSecurityMode() < LwM2MSecurityMode.DEFAULT_MODE.code) {  
197 - UUID profileUuid = (store.getDeviceProfile() != null && addUpdateProfileParameters(store.getDeviceProfile())) ? store.getDeviceProfile().getUuidId() : null;  
198 - if (store.getSecurityInfo() != null && profileUuid != null) {  
199 - String endpoint = store.getSecurityInfo().getEndpoint();  
200 - sessions.put(endpoint, new LwM2mClient(endpoint, store.getSecurityInfo().getIdentity(), store.getSecurityInfo(), store.getMsg(), profileUuid, UUID.randomUUID()));  
201 - } else if (store.getSecurityMode() == NO_SEC.code && profileUuid != null) {  
202 - sessions.put(identity, new LwM2mClient(identity, null, null, store.getMsg(), profileUuid, UUID.randomUUID()));  
203 - } else {  
204 - log.error("Registration failed: FORBIDDEN/profileUuid/device [{}] , endpointId: [{}]", profileUuid, identity);  
205 - /**  
206 - * Return Error securityInfo  
207 - */  
208 - byte[] preSharedKey = Hex.decodeHex("0A0B".toCharArray());  
209 - SecurityInfo infoError = SecurityInfo.newPreSharedKeyInfo("error", "error_identity", preSharedKey);  
210 - return infoError;  
211 - }  
212 - }  
213 - return store.getSecurityInfo();  
214 - }  
215 -  
216 - public Map<String, LwM2mClient> getSession(UUID sessionUuId) {  
217 - return this.sessions.entrySet().stream()  
218 - .filter(e -> e.getValue().getSessionId().equals(sessionUuId))  
219 - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));  
220 - }  
221 -  
222 - public Map<String, LwM2mClient> getSessions() {  
223 - return this.sessions;  
224 - }  
225 -  
226 - public Map<UUID, LwM2mClientProfile> getProfiles() {  
227 - return this.profiles;  
228 - }  
229 -  
230 - public LwM2mClientProfile getProfile(UUID profileUuId) {  
231 - return this.profiles.get(profileUuId);  
232 - }  
233 -  
234 - public LwM2mClientProfile getProfile(String registrationId) {  
235 - UUID profileUUid = this.getSessions().get(registrationId).getProfileId();  
236 - return this.getProfiles().get(profileUUid);  
237 - }  
238 -  
239 - public Map<UUID, LwM2mClientProfile> setProfiles(Map<UUID, LwM2mClientProfile> profiles) {  
240 - return this.profiles = profiles;  
241 - }  
242 -  
243 - public boolean addUpdateProfileParameters(DeviceProfile deviceProfile) {  
244 - LwM2mClientProfile lwM2MClientProfile = LwM2mTransportHandler.getLwM2MClientProfileFromThingsboard(deviceProfile);  
245 - if (lwM2MClientProfile != null) {  
246 - profiles.put(deviceProfile.getUuidId(), lwM2MClientProfile);  
247 - return true;  
248 - }  
249 - return false;  
250 - }  
251 -}  
@@ -29,6 +29,7 @@ import org.springframework.context.annotation.Lazy; @@ -29,6 +29,7 @@ import org.springframework.context.annotation.Lazy;
29 import org.springframework.stereotype.Service; 29 import org.springframework.stereotype.Service;
30 import org.thingsboard.server.cache.TBRedisCacheConfiguration; 30 import org.thingsboard.server.cache.TBRedisCacheConfiguration;
31 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; 31 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
  32 +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
32 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; 33 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
33 34
34 import java.util.Collection; 35 import java.util.Collection;
@@ -89,10 +90,14 @@ public class TbLwM2mStoreConfiguration { @@ -89,10 +90,14 @@ public class TbLwM2mStoreConfiguration {
89 } 90 }
90 91
91 @Override 92 @Override
92 - public SecurityInfo getByEndpoint(String endpoint) {  
93 - SecurityInfo securityInfo = securityStore.getByEndpoint(endpoint); 93 + public SecurityInfo getByEndpoint(String endPoint) {
  94 + SecurityInfo securityInfo = securityStore.getByEndpoint(endPoint);
94 if (securityInfo == null) { 95 if (securityInfo == null) {
95 - securityInfo = clientContext.addLwM2mClientToSession(endpoint).getSecurityInfo(); 96 + LwM2mClient lwM2mClient = clientContext.getLwM2MClient(endPoint, null);
  97 + if (lwM2mClient != null && !lwM2mClient.getRegistration().getIdentity().isSecure()){
  98 + return null;
  99 + }
  100 + securityInfo = clientContext.addLwM2mClientToSession(endPoint).getSecurityInfo();
96 try { 101 try {
97 if (securityInfo != null) { 102 if (securityInfo != null) {
98 add(securityInfo); 103 add(securityInfo);
@@ -466,7 +466,6 @@ public class ModelConstants { @@ -466,7 +466,6 @@ public class ModelConstants {
466 public static final String RESOURCE_TITLE_COLUMN = TITLE_PROPERTY; 466 public static final String RESOURCE_TITLE_COLUMN = TITLE_PROPERTY;
467 public static final String RESOURCE_DATA_COLUMN = "data"; 467 public static final String RESOURCE_DATA_COLUMN = "data";
468 468
469 -  
470 /** 469 /**
471 * Cassandra attributes and timeseries constants. 470 * Cassandra attributes and timeseries constants.
472 */ 471 */
@@ -65,7 +65,8 @@ public class TbResourceEntity extends BaseSqlEntity<TbResource> implements Searc @@ -65,7 +65,8 @@ public class TbResourceEntity extends BaseSqlEntity<TbResource> implements Searc
65 } 65 }
66 66
67 public TbResourceEntity(TbResource resource) { 67 public TbResourceEntity(TbResource resource) {
68 - this.setUuid(resource.getId().getId()); 68 + this.id = resource.getUuidId();
  69 + this.createdTime = resource.getCreatedTime();
69 this.tenantId = resource.getTenantId().getId(); 70 this.tenantId = resource.getTenantId().getId();
70 this.title = resource.getTitle(); 71 this.title = resource.getTitle();
71 this.resourceType = resource.getResourceType().name(); 72 this.resourceType = resource.getResourceType().name();
@@ -43,6 +43,8 @@ import java.util.Comparator; @@ -43,6 +43,8 @@ import java.util.Comparator;
43 import java.util.List; 43 import java.util.List;
44 import java.util.stream.Collectors; 44 import java.util.stream.Collectors;
45 45
  46 +import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY;
  47 +import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_SEARCH_TEXT;
46 import static org.thingsboard.server.dao.device.DeviceServiceImpl.INCORRECT_TENANT_ID; 48 import static org.thingsboard.server.dao.device.DeviceServiceImpl.INCORRECT_TENANT_ID;
47 import static org.thingsboard.server.dao.service.Validator.validateId; 49 import static org.thingsboard.server.dao.service.Validator.validateId;
48 50
@@ -62,26 +64,24 @@ public class BaseTbResourceService implements TbResourceService { @@ -62,26 +64,24 @@ public class BaseTbResourceService implements TbResourceService {
62 } 64 }
63 65
64 @Override 66 @Override
65 - public TbResource saveResource(TbResource resource) throws InvalidDDFFileException, IOException {  
66 - log.trace("Executing saveResource [{}]", resource);  
67 -  
68 - if (resource.getId() == null && ResourceType.LWM2M_MODEL.equals(resource.getResourceType())) { 67 + public TbResource saveResource(TbResource tbResource) throws InvalidDDFFileException, IOException {
  68 + log.trace("Executing saveResource [{}]", tbResource);
  69 + if (ResourceType.LWM2M_MODEL.equals(tbResource.getResourceType())) {
69 List<ObjectModel> objectModels = 70 List<ObjectModel> objectModels =
70 - ddfFileParser.parseEx(new ByteArrayInputStream(Base64.getDecoder().decode(resource.getData())), resource.getSearchText()); 71 + ddfFileParser.parseEx(new ByteArrayInputStream(Base64.getDecoder().decode(tbResource.getData())), tbResource.getSearchText());
71 if (!objectModels.isEmpty()) { 72 if (!objectModels.isEmpty()) {
72 ObjectModel objectModel = objectModels.get(0); 73 ObjectModel objectModel = objectModels.get(0);
73 -  
74 - String resourceKey = objectModel.id + "_" + objectModel.getVersion(); 74 + String resourceKey = objectModel.id + LWM2M_SEPARATOR_KEY + objectModel.getVersion();
75 String name = objectModel.name; 75 String name = objectModel.name;
76 - resource.setResourceKey(resourceKey);  
77 - resource.setTitle(name);  
78 - resource.setSearchText(resourceKey + ":" + name); 76 + tbResource.setResourceKey(resourceKey);
  77 + tbResource.setTitle(name);
  78 + tbResource.setSearchText(resourceKey + LWM2M_SEPARATOR_SEARCH_TEXT + name);
  79 + } else {
  80 + throw new DataValidationException(String.format("Could not parse the XML of objectModel with name %s", tbResource.getSearchText()));
79 } 81 }
80 } 82 }
81 -  
82 - validate(resource);  
83 -  
84 - return resourceDao.saveResource(resource); 83 + validate(tbResource);
  84 + return resourceDao.save(tbResource.getTenantId(), tbResource);
85 } 85 }
86 86
87 @Override 87 @Override
@@ -162,9 +162,6 @@ public class BaseTbResourceService implements TbResourceService { @@ -162,9 +162,6 @@ public class BaseTbResourceService implements TbResourceService {
162 throw new DataValidationException("Resource value should be specified!"); 162 throw new DataValidationException("Resource value should be specified!");
163 } 163 }
164 validate(resource.getTenantId(), resource.getResourceType(), resource.getResourceKey()); 164 validate(resource.getTenantId(), resource.getResourceType(), resource.getResourceKey());
165 - if (resource.getResourceType().equals(ResourceType.LWM2M_MODEL) && this.toLwM2mObject(resource) == null) {  
166 - throw new DataValidationException(String.format("Could not parse the XML of objectModel with name %s", resource.getSearchText()));  
167 - }  
168 } 165 }
169 166
170 protected void validate(TenantId tenantId, ResourceType resourceType, String resourceId) { 167 protected void validate(TenantId tenantId, ResourceType resourceType, String resourceId) {
@@ -26,8 +26,6 @@ import java.util.List; @@ -26,8 +26,6 @@ import java.util.List;
26 26
27 public interface TbResourceDao extends Dao<TbResource> { 27 public interface TbResourceDao extends Dao<TbResource> {
28 28
29 - TbResource saveResource(TbResource resource);  
30 -  
31 TbResource getResource(TenantId tenantId, ResourceType resourceType, String resourceId); 29 TbResource getResource(TenantId tenantId, ResourceType resourceType, String resourceId);
32 30
33 PageData<TbResource> findAllByTenantId(TenantId tenantId, PageLink pageLink); 31 PageData<TbResource> findAllByTenantId(TenantId tenantId, PageLink pageLink);
@@ -18,7 +18,6 @@ package org.thingsboard.server.dao.sql.resource; @@ -18,7 +18,6 @@ package org.thingsboard.server.dao.sql.resource;
18 import lombok.extern.slf4j.Slf4j; 18 import lombok.extern.slf4j.Slf4j;
19 import org.springframework.data.repository.CrudRepository; 19 import org.springframework.data.repository.CrudRepository;
20 import org.springframework.stereotype.Component; 20 import org.springframework.stereotype.Component;
21 -import org.springframework.transaction.annotation.Transactional;  
22 import org.thingsboard.server.common.data.ResourceType; 21 import org.thingsboard.server.common.data.ResourceType;
23 import org.thingsboard.server.common.data.TbResource; 22 import org.thingsboard.server.common.data.TbResource;
24 import org.thingsboard.server.common.data.id.TenantId; 23 import org.thingsboard.server.common.data.id.TenantId;
@@ -54,12 +53,6 @@ public class JpaTbResourceDao extends JpaAbstractSearchTextDao<TbResourceEntity, @@ -54,12 +53,6 @@ public class JpaTbResourceDao extends JpaAbstractSearchTextDao<TbResourceEntity,
54 } 53 }
55 54
56 @Override 55 @Override
57 - @Transactional  
58 - public TbResource saveResource(TbResource resource) {  
59 - return DaoUtil.getData(resourceRepository.save(new TbResourceEntity(resource)));  
60 - }  
61 -  
62 - @Override  
63 public TbResource getResource(TenantId tenantId, ResourceType resourceType, String resourceKey) { 56 public TbResource getResource(TenantId tenantId, ResourceType resourceType, String resourceKey) {
64 57
65 return DaoUtil.getData(resourceRepository.findByTenantIdAndResourceTypeAndResourceKey(tenantId.getId(), resourceType.name(), resourceKey)); 58 return DaoUtil.getData(resourceRepository.findByTenantIdAndResourceTypeAndResourceKey(tenantId.getId(), resourceType.name(), resourceKey));