Commit af57637dc5ec4490b0c6c68701ec829dd9e4d488

Authored by nickAS21
1 parent 8369429f

lwm2m: notification in transport, add, update, del models

Showing 14 changed files with 186 additions and 98 deletions
@@ -20,6 +20,6 @@ import lombok.Data; @@ -20,6 +20,6 @@ import lombok.Data;
20 @Data 20 @Data
21 public class LwM2mInstance { 21 public class LwM2mInstance {
22 int id; 22 int id;
23 - LwM2mResource [] resources; 23 + LwM2mResourceObserve[] resources;
24 24
25 } 25 }
common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/LwM2mResourceObserve.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/LwM2mResource.java
@@ -22,7 +22,7 @@ import java.util.stream.Stream; @@ -22,7 +22,7 @@ import java.util.stream.Stream;
22 22
23 @Data 23 @Data
24 @AllArgsConstructor 24 @AllArgsConstructor
25 -public class LwM2mResource { 25 +public class LwM2mResourceObserve {
26 int id; 26 int id;
27 String name; 27 String name;
28 boolean observe; 28 boolean observe;
@@ -30,7 +30,7 @@ public class LwM2mResource { @@ -30,7 +30,7 @@ public class LwM2mResource {
30 boolean telemetry; 30 boolean telemetry;
31 String keyName; 31 String keyName;
32 32
33 - public LwM2mResource(int id, String name, boolean observe, boolean attribute, boolean telemetry) { 33 + public LwM2mResourceObserve(int id, String name, boolean observe, boolean attribute, boolean telemetry) {
34 this.id = id; 34 this.id = id;
35 this.name = name; 35 this.name = name;
36 this.observe = observe; 36 this.observe = observe;
@@ -20,10 +20,11 @@ import io.netty.util.concurrent.GenericFutureListener; @@ -20,10 +20,11 @@ import io.netty.util.concurrent.GenericFutureListener;
20 import lombok.extern.slf4j.Slf4j; 20 import lombok.extern.slf4j.Slf4j;
21 import org.thingsboard.server.common.data.Device; 21 import org.thingsboard.server.common.data.Device;
22 import org.thingsboard.server.common.data.DeviceProfile; 22 import org.thingsboard.server.common.data.DeviceProfile;
  23 +import org.thingsboard.server.common.data.ResourceType;
23 import org.thingsboard.server.common.transport.SessionMsgListener; 24 import org.thingsboard.server.common.transport.SessionMsgListener;
24 import org.thingsboard.server.gen.transport.TransportProtos; 25 import org.thingsboard.server.gen.transport.TransportProtos;
25 -import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponseMsg;  
26 import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg; 26 import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg;
  27 +import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponseMsg;
27 import org.thingsboard.server.gen.transport.TransportProtos.SessionCloseNotificationProto; 28 import org.thingsboard.server.gen.transport.TransportProtos.SessionCloseNotificationProto;
28 import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcRequestMsg; 29 import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcRequestMsg;
29 import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcResponseMsg; 30 import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcResponseMsg;
@@ -85,4 +86,16 @@ public class LwM2mSessionMsgListener implements GenericFutureListener<Future<? s @@ -85,4 +86,16 @@ public class LwM2mSessionMsgListener implements GenericFutureListener<Future<? s
85 public void operationComplete(Future<? super Void> future) throws Exception { 86 public void operationComplete(Future<? super Void> future) throws Exception {
86 log.info("[{}] operationComplete", future); 87 log.info("[{}] operationComplete", future);
87 } 88 }
  89 +
  90 + public void onResourceUpdate(Optional<TransportProtos.ResourceUpdateMsg> resourceUpdateMsgOpt) {
  91 + if (ResourceType.LWM2M_MODEL.name().equals(resourceUpdateMsgOpt.get().getResourceType())) {
  92 + this.service.onResourceUpdate(resourceUpdateMsgOpt);
  93 + }
  94 + }
  95 +
  96 + public void onResourceDelete(Optional<TransportProtos.ResourceDeleteMsg> resourceDeleteMsgOpt) {
  97 + if (ResourceType.LWM2M_MODEL.name().equals(resourceDeleteMsgOpt.get().getResourceType())) {
  98 + this.service.onResourceDelete(resourceDeleteMsgOpt);
  99 + }
  100 + }
88 } 101 }
@@ -83,7 +83,7 @@ public class LwM2mTransportRequest { @@ -83,7 +83,7 @@ public class LwM2mTransportRequest {
83 83
84 private LwM2mValueConverterImpl converter; 84 private LwM2mValueConverterImpl converter;
85 85
86 - private final LwM2mTransportContextServer context; 86 + private final LwM2mTransportContextServer lwM2mTransportContextServer;
87 87
88 private final LwM2mClientContext lwM2mClientContext; 88 private final LwM2mClientContext lwM2mClientContext;
89 89
@@ -91,8 +91,8 @@ public class LwM2mTransportRequest { @@ -91,8 +91,8 @@ public class LwM2mTransportRequest {
91 91
92 private final LwM2mTransportServiceImpl serviceImpl; 92 private final LwM2mTransportServiceImpl serviceImpl;
93 93
94 - public LwM2mTransportRequest(LwM2mTransportContextServer context, LwM2mClientContext lwM2mClientContext, LeshanServer leshanServer, LwM2mTransportServiceImpl serviceImpl) {  
95 - this.context = context; 94 + public LwM2mTransportRequest(LwM2mTransportContextServer lwM2mTransportContextServer, LwM2mClientContext lwM2mClientContext, LeshanServer leshanServer, LwM2mTransportServiceImpl serviceImpl) {
  95 + this.lwM2mTransportContextServer = lwM2mTransportContextServer;
96 this.lwM2mClientContext = lwM2mClientContext; 96 this.lwM2mClientContext = lwM2mClientContext;
97 this.leshanServer = leshanServer; 97 this.leshanServer = leshanServer;
98 this.serviceImpl = serviceImpl; 98 this.serviceImpl = serviceImpl;
@@ -101,7 +101,7 @@ public class LwM2mTransportRequest { @@ -101,7 +101,7 @@ public class LwM2mTransportRequest {
101 @PostConstruct 101 @PostConstruct
102 public void init() { 102 public void init() {
103 this.converter = LwM2mValueConverterImpl.getInstance(); 103 this.converter = LwM2mValueConverterImpl.getInstance();
104 - executorResponse = Executors.newFixedThreadPool(this.context.getLwM2MTransportConfigServer().getRequestPoolSize(), 104 + executorResponse = Executors.newFixedThreadPool(this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getRequestPoolSize(),
105 new NamedThreadFactory(String.format("LwM2M %s channel response", RESPONSE_CHANNEL))); 105 new NamedThreadFactory(String.format("LwM2M %s channel response", RESPONSE_CHANNEL)));
106 } 106 }
107 107
@@ -120,7 +120,8 @@ public class LwM2mTransportRequest { @@ -120,7 +120,8 @@ public class LwM2mTransportRequest {
120 if (registration != null && resultIds.getObjectId() >= 0) { 120 if (registration != null && resultIds.getObjectId() >= 0) {
121 DownlinkRequest request = null; 121 DownlinkRequest request = null;
122 ContentFormat contentFormat = contentFormatParam != null ? ContentFormat.fromName(contentFormatParam.toUpperCase()) : null; 122 ContentFormat contentFormat = contentFormatParam != null ? ContentFormat.fromName(contentFormatParam.toUpperCase()) : null;
123 - ResourceModel resource = serviceImpl.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResourceModel(registration, resultIds); 123 + LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null);
  124 + ResourceModel resource = lwM2MClient.getResourceModel(target);
124 timeoutInMs = timeoutInMs > 0 ? timeoutInMs : DEFAULT_TIMEOUT; 125 timeoutInMs = timeoutInMs > 0 ? timeoutInMs : DEFAULT_TIMEOUT;
125 switch (typeOper) { 126 switch (typeOper) {
126 case GET_TYPE_OPER_READ: 127 case GET_TYPE_OPER_READ:
@@ -217,7 +218,10 @@ public class LwM2mTransportRequest { @@ -217,7 +218,10 @@ public class LwM2mTransportRequest {
217 } 218 }
218 219
219 if (request != null) { 220 if (request != null) {
220 - this.sendRequest(registration, request, timeoutInMs); 221 + this.sendRequest(registration, lwM2MClient, request, timeoutInMs);
  222 + }
  223 + else {
  224 + log.error("[{}], [{}] - [{}] error SendRequest", registration.getEndpoint(), typeOper, target);
221 } 225 }
222 } 226 }
223 } 227 }
@@ -230,8 +234,7 @@ public class LwM2mTransportRequest { @@ -230,8 +234,7 @@ public class LwM2mTransportRequest {
230 */ 234 */
231 235
232 @SuppressWarnings("unchecked") 236 @SuppressWarnings("unchecked")
233 - private void sendRequest(Registration registration, DownlinkRequest request, long timeoutInMs) {  
234 - LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null); 237 + private void sendRequest(Registration registration, LwM2mClient lwM2MClient, DownlinkRequest request, long timeoutInMs) {
235 leshanServer.send(registration, request, timeoutInMs, (ResponseCallback<?>) response -> { 238 leshanServer.send(registration, request, timeoutInMs, (ResponseCallback<?>) response -> {
236 if (!lwM2MClient.isInit()) { 239 if (!lwM2MClient.isInit()) {
237 lwM2MClient.initValue(this.serviceImpl, convertToIdVerFromObjectId(request.getPath().toString(), registration)); 240 lwM2MClient.initValue(this.serviceImpl, convertToIdVerFromObjectId(request.getPath().toString(), registration));
@@ -47,6 +47,10 @@ public interface LwM2mTransportService { @@ -47,6 +47,10 @@ public interface LwM2mTransportService {
47 47
48 void onDeviceUpdate(TransportProtos.SessionInfoProto sessionInfo, Device device, Optional<DeviceProfile> deviceProfileOpt); 48 void onDeviceUpdate(TransportProtos.SessionInfoProto sessionInfo, Device device, Optional<DeviceProfile> deviceProfileOpt);
49 49
  50 + void onResourceUpdate (Optional<TransportProtos.ResourceUpdateMsg> resourceUpdateMsgOpt);
  51 +
  52 + void onResourceDelete(Optional<TransportProtos.ResourceDeleteMsg> resourceDeleteMsgOpt);
  53 +
50 void doTrigger(Registration registration, String path); 54 void doTrigger(Registration registration, String path);
51 55
52 void doDisconnect(TransportProtos.SessionInfoProto sessionInfo); 56 void doDisconnect(TransportProtos.SessionInfoProto sessionInfo);
@@ -52,7 +52,6 @@ import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; @@ -52,7 +52,6 @@ import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
52 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; 52 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
53 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; 53 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
54 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile; 54 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile;
55 -import org.thingsboard.server.transport.lwm2m.server.client.ResourceValue;  
56 import org.thingsboard.server.transport.lwm2m.server.client.ResultsAnalyzerParameters; 55 import org.thingsboard.server.transport.lwm2m.server.client.ResultsAnalyzerParameters;
57 import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; 56 import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;
58 57
@@ -73,9 +72,6 @@ import java.util.concurrent.ConcurrentMap; @@ -73,9 +72,6 @@ import java.util.concurrent.ConcurrentMap;
73 import java.util.concurrent.ExecutorService; 72 import java.util.concurrent.ExecutorService;
74 import java.util.concurrent.Executors; 73 import java.util.concurrent.Executors;
75 import java.util.concurrent.TimeUnit; 74 import java.util.concurrent.TimeUnit;
76 -import java.util.concurrent.locks.Lock;  
77 -import java.util.concurrent.locks.ReadWriteLock;  
78 -import java.util.concurrent.locks.ReentrantReadWriteLock;  
79 import java.util.stream.Collectors; 75 import java.util.stream.Collectors;
80 76
81 import static org.thingsboard.server.common.transport.util.JsonUtils.getJsonObject; 77 import static org.thingsboard.server.common.transport.util.JsonUtils.getJsonObject;
@@ -107,8 +103,6 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -107,8 +103,6 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
107 private ExecutorService executorUpdateRegistered; 103 private ExecutorService executorUpdateRegistered;
108 private ExecutorService executorUnRegistered; 104 private ExecutorService executorUnRegistered;
109 private LwM2mValueConverterImpl converter; 105 private LwM2mValueConverterImpl converter;
110 - protected final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();  
111 - protected final Lock writeLock = readWriteLock.writeLock();  
112 106
113 private final TransportService transportService; 107 private final TransportService transportService;
114 108
@@ -162,7 +156,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -162,7 +156,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
162 if (lwM2MClient != null) { 156 if (lwM2MClient != null) {
163 SessionInfoProto sessionInfo = this.getValidateSessionInfo(registration); 157 SessionInfoProto sessionInfo = this.getValidateSessionInfo(registration);
164 if (sessionInfo != null) { 158 if (sessionInfo != null) {
165 - this.initLwM2mClient (lwM2MClient, sessionInfo); 159 + this.initLwM2mClient(lwM2MClient, sessionInfo);
166 transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(this, sessionInfo)); 160 transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(this, sessionInfo));
167 transportService.process(sessionInfo, DefaultTransportService.getSessionEventMsg(SessionEvent.OPEN), null); 161 transportService.process(sessionInfo, DefaultTransportService.getSessionEventMsg(SessionEvent.OPEN), null);
168 transportService.process(sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build(), null); 162 transportService.process(sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build(), null);
@@ -223,7 +217,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -223,7 +217,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
223 }); 217 });
224 } 218 }
225 219
226 - private void initLwM2mClient (LwM2mClient lwM2MClient, SessionInfoProto sessionInfo) { 220 + private void initLwM2mClient(LwM2mClient lwM2MClient, SessionInfoProto sessionInfo) {
227 lwM2MClient.setDeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB())); 221 lwM2MClient.setDeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB()));
228 lwM2MClient.setProfileId(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB())); 222 lwM2MClient.setProfileId(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB()));
229 lwM2MClient.setDeviceName(sessionInfo.getDeviceName()); 223 lwM2MClient.setDeviceName(sessionInfo.getDeviceName());
@@ -309,7 +303,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -309,7 +303,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
309 LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())); 303 LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()));
310 LwM2mClientProfile clientProfile = lwM2mClientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB())); 304 LwM2mClientProfile clientProfile = lwM2mClientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB()));
311 if (pathIdVer != null && !pathIdVer.isEmpty() && (this.validatePathInAttrProfile(clientProfile, pathIdVer) || this.validatePathInTelemetryProfile(clientProfile, pathIdVer))) { 305 if (pathIdVer != null && !pathIdVer.isEmpty() && (this.validatePathInAttrProfile(clientProfile, pathIdVer) || this.validatePathInTelemetryProfile(clientProfile, pathIdVer))) {
312 - ResourceModel resourceModel = lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResourceModel(lwM2MClient.getRegistration(), new LwM2mPath(convertToObjectIdFromIdVer(pathIdVer))); 306 + ResourceModel resourceModel = lwM2MClient.getResourceModel(pathIdVer);
313 if (resourceModel != null && resourceModel.operations.isWritable()) { 307 if (resourceModel != null && resourceModel.operations.isWritable()) {
314 lwM2mTransportRequest.sendAllRequest(lwM2MClient.getRegistration(), pathIdVer, POST_TYPE_OPER_WRITE_REPLACE, 308 lwM2mTransportRequest.sendAllRequest(lwM2MClient.getRegistration(), pathIdVer, POST_TYPE_OPER_WRITE_REPLACE,
315 ContentFormat.TLV.getName(), null, value, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout()); 309 ContentFormat.TLV.getName(), null, value, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout());
@@ -361,6 +355,26 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -361,6 +355,26 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
361 } 355 }
362 356
363 /** 357 /**
  358 + *
  359 + * @param resourceUpdateMsgOpt -
  360 + */
  361 + @Override
  362 + public void onResourceUpdate (Optional<TransportProtos.ResourceUpdateMsg> resourceUpdateMsgOpt) {
  363 + String idVer = resourceUpdateMsgOpt.get().getResourceKey(); // 19_1.0
  364 + lwM2mClientContext.getLwM2mClients().values().stream().forEach(e -> e.updateResourceModel(idVer, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getModelProvider()));
  365 + }
  366 +
  367 + /**
  368 + *
  369 + * @param resourceDeleteMsgOpt -
  370 + */
  371 + @Override
  372 + public void onResourceDelete(Optional<TransportProtos.ResourceDeleteMsg> resourceDeleteMsgOpt) {
  373 + String pathIdVer = resourceDeleteMsgOpt.get().getResourceKey(); // 19_1.0
  374 + lwM2mClientContext.getLwM2mClients().values().stream().forEach(e -> e.deleteResources(pathIdVer, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getModelProvider()));
  375 + }
  376 +
  377 + /**
364 * Trigger Server path = "/1/0/8" 378 * Trigger Server path = "/1/0/8"
365 * <p> 379 * <p>
366 * Trigger bootStrap path = "/1/0/9" - have to implemented on client 380 * Trigger bootStrap path = "/1/0/9" - have to implemented on client
@@ -519,10 +533,14 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -519,10 +533,14 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
519 */ 533 */
520 private void updateResourcesValue(Registration registration, LwM2mResource lwM2mResource, String path) { 534 private void updateResourcesValue(Registration registration, LwM2mResource lwM2mResource, String path) {
521 LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null); 535 LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null);
522 - lwM2MClient.updateResourceValue(path, lwM2mResource);  
523 - Set<String> paths = new HashSet<>();  
524 - paths.add(path);  
525 - this.updateAttrTelemetry(registration, paths); 536 + if (lwM2MClient.saveResourceValue(path, lwM2mResource, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getModelProvider())) {
  537 + Set<String> paths = new HashSet<>();
  538 + paths.add(path);
  539 + this.updateAttrTelemetry(registration, paths);
  540 + }
  541 + else {
  542 + log.error("Fail update Resource [{}]", lwM2mResource);
  543 + }
526 } 544 }
527 545
528 /** 546 /**
@@ -538,12 +556,9 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -538,12 +556,9 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
538 JsonObject attributes = new JsonObject(); 556 JsonObject attributes = new JsonObject();
539 JsonObject telemetries = new JsonObject(); 557 JsonObject telemetries = new JsonObject();
540 try { 558 try {
541 - writeLock.lock();  
542 this.getParametersFromProfile(attributes, telemetries, registration, paths); 559 this.getParametersFromProfile(attributes, telemetries, registration, paths);
543 } catch (Exception e) { 560 } catch (Exception e) {
544 log.error("UpdateAttrTelemetry", e); 561 log.error("UpdateAttrTelemetry", e);
545 - } finally {  
546 - writeLock.unlock();  
547 } 562 }
548 if (attributes.getAsJsonObject().entrySet().size() > 0) 563 if (attributes.getAsJsonObject().entrySet().size() > 0)
549 this.updateParametersOnThingsboard(attributes, DEVICE_ATTRIBUTES_TOPIC, registration); 564 this.updateParametersOnThingsboard(attributes, DEVICE_ATTRIBUTES_TOPIC, registration);
@@ -558,8 +573,8 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -558,8 +573,8 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
558 */ 573 */
559 private boolean validatePathInAttrProfile(LwM2mClientProfile clientProfile, String path) { 574 private boolean validatePathInAttrProfile(LwM2mClientProfile clientProfile, String path) {
560 try { 575 try {
561 - List<String> attributesSet = new Gson().fromJson(clientProfile.getPostAttributeProfile(), new TypeToken<List<String>>() {  
562 - }.getType()); 576 + List<String> attributesSet = new Gson().fromJson(clientProfile.getPostAttributeProfile(),
  577 + new TypeToken<List<String>>() {}.getType());
563 return attributesSet.stream().anyMatch(p -> p.equals(path)); 578 return attributesSet.stream().anyMatch(p -> p.equals(path));
564 } catch (Exception e) { 579 } catch (Exception e) {
565 log.error("Fail Validate Path [{}] ClientProfile.Attribute", path, e); 580 log.error("Fail Validate Path [{}] ClientProfile.Attribute", path, e);
@@ -717,9 +732,9 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -717,9 +732,9 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
717 */ 732 */
718 private String getResourceValueToString(LwM2mClient lwM2MClient, String path) { 733 private String getResourceValueToString(LwM2mClient lwM2MClient, String path) {
719 LwM2mPath pathIds = new LwM2mPath(convertToObjectIdFromIdVer(path)); 734 LwM2mPath pathIds = new LwM2mPath(convertToObjectIdFromIdVer(path));
720 - ResourceValue resourceValue = this.returnResourceValueFromLwM2MClient(lwM2MClient, path); 735 + LwM2mResource resourceValue = this.returnResourceValueFromLwM2MClient(lwM2MClient, path);
721 return resourceValue == null ? null : 736 return resourceValue == null ? null :
722 - this.converter.convertValue(resourceValue.getResourceValue(), this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResourceModelType(lwM2MClient.getRegistration(), pathIds), ResourceModel.Type.STRING, pathIds).toString(); 737 + this.converter.convertValue(resourceValue.isMultiInstances() ? resourceValue.getValues() : resourceValue.getValue(), resourceValue.getType(), ResourceModel.Type.STRING, pathIds).toString();
723 } 738 }
724 739
725 /** 740 /**
@@ -727,10 +742,10 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -727,10 +742,10 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
727 * @param path - 742 * @param path -
728 * @return - return value of Resource by idPath 743 * @return - return value of Resource by idPath
729 */ 744 */
730 - private ResourceValue returnResourceValueFromLwM2MClient(LwM2mClient lwM2MClient, String path) {  
731 - ResourceValue resourceValue = null; 745 + private LwM2mResource returnResourceValueFromLwM2MClient(LwM2mClient lwM2MClient, String path) {
  746 + LwM2mResource resourceValue = null;
732 if (new LwM2mPath(convertToObjectIdFromIdVer(path)).isResource()) { 747 if (new LwM2mPath(convertToObjectIdFromIdVer(path)).isResource()) {
733 - resourceValue = lwM2MClient.getResources().get(path); 748 + resourceValue = lwM2MClient.getResources().get(path).getLwM2mResource();
734 } 749 }
735 return resourceValue; 750 return resourceValue;
736 } 751 }
@@ -967,9 +982,9 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -967,9 +982,9 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
967 */ 982 */
968 private String getPathAttributeUpdateProfile(TransportProtos.SessionInfoProto sessionInfo, String name) { 983 private String getPathAttributeUpdateProfile(TransportProtos.SessionInfoProto sessionInfo, String name) {
969 LwM2mClientProfile profile = lwM2mClientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB())); 984 LwM2mClientProfile profile = lwM2mClientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB()));
970 - Registration registration = lwM2mClientContext.getLwM2MClient(sessionInfo).getRegistration(); 985 + LwM2mClient lwM2mClient = lwM2mClientContext.getLwM2MClient(sessionInfo);
971 return profile.getPostKeyNameProfile().getAsJsonObject().entrySet().stream() 986 return profile.getPostKeyNameProfile().getAsJsonObject().entrySet().stream()
972 - .filter(e -> e.getValue().getAsString().equals(name) && validateResourceInModel(registration, e.getKey(), false)).findFirst().map(Map.Entry::getKey) 987 + .filter(e -> e.getValue().getAsString().equals(name) && validateResourceInModel(lwM2mClient, e.getKey(), false)).findFirst().map(Map.Entry::getKey)
973 .orElse(""); 988 .orElse("");
974 } 989 }
975 990
@@ -1118,7 +1133,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -1118,7 +1133,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
1118 1133
1119 ConcurrentMap<String, String> keyNamesIsWritable = keyNamesMap.entrySet() 1134 ConcurrentMap<String, String> keyNamesIsWritable = keyNamesMap.entrySet()
1120 .stream() 1135 .stream()
1121 - .filter(e -> (attrSet.contains(e.getKey()) && validateResourceInModel(lwM2MClient.getRegistration(), e.getKey(), true))) 1136 + .filter(e -> (attrSet.contains(e.getKey()) && validateResourceInModel(lwM2MClient, e.getKey(), true)))
1122 .collect(Collectors.toConcurrentMap(Map.Entry::getKey, Map.Entry::getValue)); 1137 .collect(Collectors.toConcurrentMap(Map.Entry::getKey, Map.Entry::getValue));
1123 1138
1124 Set<String> namesIsWritable = ConcurrentHashMap.newKeySet(); 1139 Set<String> namesIsWritable = ConcurrentHashMap.newKeySet();
@@ -1126,13 +1141,12 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { @@ -1126,13 +1141,12 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService {
1126 return new ArrayList<>(namesIsWritable); 1141 return new ArrayList<>(namesIsWritable);
1127 } 1142 }
1128 1143
1129 - private boolean validateResourceInModel(Registration registration, String pathKey, boolean isWritable) {  
1130 - ResourceModel resourceModel = lwM2mTransportContextServer.getLwM2MTransportConfigServer().getResourceModel(registration,  
1131 - new LwM2mPath(convertToObjectIdFromIdVer(pathKey))); 1144 + private boolean validateResourceInModel(LwM2mClient lwM2mClient, String pathKey, boolean isWritable) {
  1145 + ResourceModel resourceModel = lwM2mClient.getResourceModel(pathKey);
1132 Integer objectId = validateObjectIdFromKey(pathKey); 1146 Integer objectId = validateObjectIdFromKey(pathKey);
1133 String objectVer = validateObjectVerFromKey(pathKey); 1147 String objectVer = validateObjectVerFromKey(pathKey);
1134 return resourceModel != null && (isWritable ? 1148 return resourceModel != null && (isWritable ?
1135 - objectId != null && objectVer != null && objectVer.equals(registration.getSupportedVersion(objectId)) && resourceModel.operations.isWritable() :  
1136 - objectId != null && objectVer != null && objectVer.equals(registration.getSupportedVersion(objectId))); 1149 + objectId != null && objectVer != null && objectVer.equals(lwM2mClient.getRegistration().getSupportedVersion(objectId)) && resourceModel.operations.isWritable() :
  1150 + objectId != null && objectVer != null && objectVer.equals(lwM2mClient.getRegistration().getSupportedVersion(objectId)));
1137 } 1151 }
1138 } 1152 }
@@ -85,7 +85,7 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider { @@ -85,7 +85,7 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider {
85 if (objectModel != null) 85 if (objectModel != null)
86 return objectModel.resources.get(resourceId); 86 return objectModel.resources.get(resourceId);
87 else 87 else
88 - log.warn("TbResources (Object model) with id [{}/{}] not found on the server", objectId, resourceId); 88 + log.warn("TbResources (Object model) with id [{}/0/{}] not found on the server", objectId, resourceId);
89 return null; 89 return null;
90 } catch (Exception e) { 90 } catch (Exception e) {
91 log.error("", e); 91 log.error("", e);
@@ -17,9 +17,10 @@ package org.thingsboard.server.transport.lwm2m.server.client; @@ -17,9 +17,10 @@ package org.thingsboard.server.transport.lwm2m.server.client;
17 17
18 import lombok.Data; 18 import lombok.Data;
19 import lombok.extern.slf4j.Slf4j; 19 import lombok.extern.slf4j.Slf4j;
20 -import org.eclipse.leshan.core.node.LwM2mMultipleResource; 20 +import org.eclipse.leshan.core.model.ResourceModel;
  21 +import org.eclipse.leshan.core.node.LwM2mPath;
21 import org.eclipse.leshan.core.node.LwM2mResource; 22 import org.eclipse.leshan.core.node.LwM2mResource;
22 -import org.eclipse.leshan.core.node.LwM2mSingleResource; 23 +import org.eclipse.leshan.server.model.LwM2mModelProvider;
23 import org.eclipse.leshan.server.registration.Registration; 24 import org.eclipse.leshan.server.registration.Registration;
24 import org.eclipse.leshan.server.security.SecurityInfo; 25 import org.eclipse.leshan.server.security.SecurityInfo;
25 import org.thingsboard.server.gen.transport.TransportProtos; 26 import org.thingsboard.server.gen.transport.TransportProtos;
@@ -28,9 +29,14 @@ import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServiceImpl; @@ -28,9 +29,14 @@ import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServiceImpl;
28 29
29 import java.util.List; 30 import java.util.List;
30 import java.util.Map; 31 import java.util.Map;
  32 +import java.util.Set;
31 import java.util.UUID; 33 import java.util.UUID;
32 import java.util.concurrent.ConcurrentHashMap; 34 import java.util.concurrent.ConcurrentHashMap;
33 import java.util.concurrent.CopyOnWriteArrayList; 35 import java.util.concurrent.CopyOnWriteArrayList;
  36 +import java.util.stream.Collectors;
  37 +
  38 +import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH;
  39 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertToObjectIdFromIdVer;
34 40
35 @Slf4j 41 @Slf4j
36 @Data 42 @Data
@@ -67,21 +73,74 @@ public class LwM2mClient implements Cloneable { @@ -67,21 +73,74 @@ public class LwM2mClient implements Cloneable {
67 this.init = false; 73 this.init = false;
68 } 74 }
69 75
70 - public void updateResourceValue(String pathRez, LwM2mResource rez) {  
71 - if (rez instanceof LwM2mMultipleResource) {  
72 - this.resources.put(pathRez, new ResourceValue(rez.getValues(), null, true));  
73 - } else if (rez instanceof LwM2mSingleResource) {  
74 - this.resources.put(pathRez, new ResourceValue(null, rez.getValue(), false)); 76 + public boolean saveResourceValue(String pathRez, LwM2mResource rez, LwM2mModelProvider modelProvider) {
  77 + if (this.resources.get(pathRez) != null && this.resources.get(pathRez).getResourceModel() != null) {
  78 + this.resources.get(pathRez).setLwM2mResource(rez);
  79 + return true;
  80 + } else {
  81 + LwM2mPath pathIds = new LwM2mPath(convertToObjectIdFromIdVer(pathRez));
  82 + ResourceModel resourceModel = modelProvider.getObjectModel(registration).getResourceModel(pathIds.getObjectId(), pathIds.getResourceId());
  83 + if (resourceModel != null) {
  84 + this.resources.put(pathRez, new ResourceValue(rez, resourceModel));
  85 + return true;
  86 + } else {
  87 + return false;
  88 + }
  89 + }
  90 + }
  91 +
  92 + public ResourceModel getResourceModel(String pathRez) {
  93 + if (this.getResources().get(pathRez) != null) {
  94 + return this.getResources().get(pathRez).getResourceModel();
  95 + } else {
  96 + return null;
75 } 97 }
76 } 98 }
77 99
78 - public void initValue(LwM2mTransportServiceImpl lwM2MTransportService, String path) { 100 + /**
  101 + *
  102 + * @param pathIdVer == "3_1.0"
  103 + * @param modelProvider -
  104 + */
  105 + public void deleteResources(String pathIdVer, LwM2mModelProvider modelProvider) {
  106 + Set key = getKeysEqualsIdVer(pathIdVer);
  107 + key.forEach(pathRez -> {
  108 + LwM2mPath pathIds = new LwM2mPath(convertToObjectIdFromIdVer(pathRez.toString()));
  109 + ResourceModel resourceModel = modelProvider.getObjectModel(registration).getResourceModel(pathIds.getObjectId(), pathIds.getResourceId());
  110 + if (resourceModel != null) {
  111 + this.resources.get(pathRez).setResourceModel(resourceModel);
  112 + }
  113 + else {
  114 + this.resources.remove(pathRez);
  115 + }
  116 + });
  117 + }
  118 +
  119 + public void updateResourceModel(String idVer, LwM2mModelProvider modelProvider) {
  120 + Set key = getKeysEqualsIdVer(idVer);
  121 + key.forEach(k -> this.saveResourceModel(k.toString(), modelProvider));
  122 + }
  123 +
  124 + private void saveResourceModel(String pathRez, LwM2mModelProvider modelProvider) {
  125 + LwM2mPath pathIds = new LwM2mPath(convertToObjectIdFromIdVer(pathRez));
  126 + ResourceModel resourceModel = modelProvider.getObjectModel(registration).getResourceModel(pathIds.getObjectId(), pathIds.getResourceId());
  127 + this.resources.get(pathRez).setResourceModel(resourceModel);
  128 + }
  129 +
  130 + private Set getKeysEqualsIdVer(String idVer) {
  131 + return this.resources.keySet()
  132 + .stream()
  133 + .filter(e -> idVer.equals(e.split(LWM2M_SEPARATOR_PATH)[1]))
  134 + .collect(Collectors.toSet());
  135 + }
  136 +
  137 + public void initValue(LwM2mTransportServiceImpl serviceImpl, String path) {
79 if (path != null) { 138 if (path != null) {
80 this.pendingRequests.remove(path); 139 this.pendingRequests.remove(path);
81 } 140 }
82 if (this.pendingRequests.size() == 0) { 141 if (this.pendingRequests.size() == 0) {
83 this.init = true; 142 this.init = true;
84 - lwM2MTransportService.putDelayedUpdateResourcesThingsboard(this); 143 + serviceImpl.putDelayedUpdateResourcesThingsboard(this);
85 } 144 }
86 } 145 }
87 146
@@ -34,25 +34,25 @@ public class LwM2mClientProfile { @@ -34,25 +34,25 @@ public class LwM2mClientProfile {
34 34
35 /** 35 /**
36 * {"keyName": { 36 * {"keyName": {
37 - * "/3/0/1": "modelNumber",  
38 - * "/3/0/0": "manufacturer",  
39 - * "/3/0/2": "serialNumber" 37 + * "/3_1.0/0/1": "modelNumber",
  38 + * "/3_1.0/0/0": "manufacturer",
  39 + * "/3_1.0/0/2": "serialNumber"
40 * } 40 * }
41 **/ 41 **/
42 private JsonObject postKeyNameProfile; 42 private JsonObject postKeyNameProfile;
43 43
44 /** 44 /**
45 - * [ "/2/0/0", "/2/0/1"] 45 + * [ "/3_1.0/0/0", "/3_1.0/0/1"]
46 */ 46 */
47 private JsonArray postAttributeProfile; 47 private JsonArray postAttributeProfile;
48 48
49 /** 49 /**
50 - * [ "/2/0/0", "/2/0/1"] 50 + * [ "/3_1.0/0/0", "/3_1.0/0/2"]
51 */ 51 */
52 private JsonArray postTelemetryProfile; 52 private JsonArray postTelemetryProfile;
53 53
54 /** 54 /**
55 - * [ "/2/0/0", "/2/0/1"] 55 + * [ "/3_1.0/0", "/3_1.0/0/1, "/3_1.0/0/2"]
56 */ 56 */
57 private JsonArray postObserveProfile; 57 private JsonArray postObserveProfile;
58 58
@@ -16,23 +16,16 @@ @@ -16,23 +16,16 @@
16 package org.thingsboard.server.transport.lwm2m.server.client; 16 package org.thingsboard.server.transport.lwm2m.server.client;
17 17
18 import lombok.Data; 18 import lombok.Data;
19 -  
20 -import java.util.Map; 19 +import org.eclipse.leshan.core.model.ResourceModel;
  20 +import org.eclipse.leshan.core.node.LwM2mResource;
21 21
22 @Data 22 @Data
23 public class ResourceValue { 23 public class ResourceValue {
24 - Map<Integer, ?> values;  
25 - Object value;  
26 - boolean multiInstances;  
27 -  
28 - public ResourceValue(Map<Integer, ?> values, Object value, boolean multiInstances) {  
29 - this.values = values;  
30 - this.value = value;  
31 - this.multiInstances = multiInstances;  
32 - } 24 + private LwM2mResource lwM2mResource;
  25 + private ResourceModel resourceModel;
33 26
34 - public Object getResourceValue() {  
35 - return this.multiInstances ? this.values : this.value; 27 + public ResourceValue(LwM2mResource lwM2mResource, ResourceModel resourceModel) {
  28 + this.lwM2mResource = lwM2mResource;
  29 + this.resourceModel = resourceModel;
36 } 30 }
37 -  
38 } 31 }
@@ -18,11 +18,11 @@ package org.thingsboard.server.common.transport; @@ -18,11 +18,11 @@ package org.thingsboard.server.common.transport;
18 import org.thingsboard.server.common.data.Device; 18 import org.thingsboard.server.common.data.Device;
19 import org.thingsboard.server.common.data.DeviceProfile; 19 import org.thingsboard.server.common.data.DeviceProfile;
20 import org.thingsboard.server.gen.transport.TransportProtos; 20 import org.thingsboard.server.gen.transport.TransportProtos;
21 -import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcResponseMsg;  
22 import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg; 21 import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg;
23 import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponseMsg; 22 import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponseMsg;
24 import org.thingsboard.server.gen.transport.TransportProtos.SessionCloseNotificationProto; 23 import org.thingsboard.server.gen.transport.TransportProtos.SessionCloseNotificationProto;
25 import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcRequestMsg; 24 import org.thingsboard.server.gen.transport.TransportProtos.ToDeviceRpcRequestMsg;
  25 +import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcResponseMsg;
26 import org.thingsboard.server.gen.transport.TransportProtos.ToTransportUpdateCredentialsProto; 26 import org.thingsboard.server.gen.transport.TransportProtos.ToTransportUpdateCredentialsProto;
27 27
28 import java.util.Optional; 28 import java.util.Optional;
@@ -44,9 +44,12 @@ public interface SessionMsgListener { @@ -44,9 +44,12 @@ public interface SessionMsgListener {
44 44
45 default void onToTransportUpdateCredentials(ToTransportUpdateCredentialsProto toTransportUpdateCredentials){} 45 default void onToTransportUpdateCredentials(ToTransportUpdateCredentialsProto toTransportUpdateCredentials){}
46 46
47 - default void onDeviceProfileUpdate(TransportProtos.SessionInfoProto newSessionInfo, DeviceProfile deviceProfile) {  
48 - } 47 + default void onDeviceProfileUpdate(TransportProtos.SessionInfoProto newSessionInfo, DeviceProfile deviceProfile) {}
  48 +
  49 + default void onDeviceUpdate(TransportProtos.SessionInfoProto sessionInfo, Device device,
  50 + Optional<DeviceProfile> deviceProfileOpt) {}
  51 +
  52 + default void onResourceUpdate(Optional<TransportProtos.ResourceUpdateMsg> resourceUpdateMsgOpt) {}
49 53
50 - default void onDeviceUpdate(TransportProtos.SessionInfoProto sessionInfo, Device device, Optional<DeviceProfile> deviceProfileOpt) {  
51 - } 54 + default void onResourceDelete(Optional<TransportProtos.ResourceDeleteMsg> resourceUpdateMsgOpt) {}
52 } 55 }
@@ -18,10 +18,7 @@ package org.thingsboard.server.common.transport.lwm2m; @@ -18,10 +18,7 @@ package org.thingsboard.server.common.transport.lwm2m;
18 import lombok.Getter; 18 import lombok.Getter;
19 import lombok.Setter; 19 import lombok.Setter;
20 import lombok.extern.slf4j.Slf4j; 20 import lombok.extern.slf4j.Slf4j;
21 -import org.eclipse.leshan.core.model.ResourceModel;  
22 -import org.eclipse.leshan.core.node.LwM2mPath;  
23 import org.eclipse.leshan.server.model.LwM2mModelProvider; 21 import org.eclipse.leshan.server.model.LwM2mModelProvider;
24 -import org.eclipse.leshan.server.registration.Registration;  
25 import org.springframework.beans.factory.annotation.Value; 22 import org.springframework.beans.factory.annotation.Value;
26 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; 23 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
27 import org.springframework.stereotype.Component; 24 import org.springframework.stereotype.Component;
@@ -219,13 +216,4 @@ public class LwM2MTransportConfigServer { @@ -219,13 +216,4 @@ public class LwM2MTransportConfigServer {
219 } 216 }
220 return FULL_FILE_PATH.toUri().getPath(); 217 return FULL_FILE_PATH.toUri().getPath();
221 } 218 }
222 -  
223 - public ResourceModel getResourceModel(Registration registration, LwM2mPath pathIds) {  
224 - return this.modelProvider.getObjectModel(registration).getResourceModel(pathIds.getObjectId(), pathIds.getResourceId());  
225 - }  
226 -  
227 - public ResourceModel.Type getResourceModelType(Registration registration, LwM2mPath pathIds) {  
228 - ResourceModel resource = this.getResourceModel(registration, pathIds);  
229 - return (resource == null) ? null : resource.type;  
230 - }  
231 } 219 }
@@ -288,7 +288,7 @@ public class DefaultTransportService implements TransportService { @@ -288,7 +288,7 @@ public class DefaultTransportService implements TransportService {
288 } 288 }
289 289
290 @Override 290 @Override
291 - public void process(TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg msg, TransportServiceCallback<TransportProtos.ValidateDeviceCredentialsResponseMsg> callback) { 291 + public void process(TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg msg, TransportServiceCallback<TransportProtos.ValidateDeviceCredentialsResponseMsg> callback) {
292 log.trace("Processing msg: {}", msg); 292 log.trace("Processing msg: {}", msg);
293 TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>(UUID.randomUUID(), TransportApiRequestMsg.newBuilder().setValidateDeviceLwM2MCredentialsRequestMsg(msg).build()); 293 TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>(UUID.randomUUID(), TransportApiRequestMsg.newBuilder().setValidateDeviceLwM2MCredentialsRequestMsg(msg).build());
294 AsyncCallbackTemplate.withCallback(transportApiRequestTemplate.send(protoMsg), 294 AsyncCallbackTemplate.withCallback(transportApiRequestTemplate.send(protoMsg),
@@ -710,12 +710,21 @@ public class DefaultTransportService implements TransportService { @@ -710,12 +710,21 @@ public class DefaultTransportService implements TransportService {
710 ResourceType resourceType = ResourceType.valueOf(msg.getResourceType()); 710 ResourceType resourceType = ResourceType.valueOf(msg.getResourceType());
711 String resourceId = msg.getResourceKey(); 711 String resourceId = msg.getResourceKey();
712 transportResourceCache.update(tenantId, resourceType, resourceId); 712 transportResourceCache.update(tenantId, resourceType, resourceId);
  713 + sessions.forEach((id, mdRez) -> {
  714 + log.warn("ResourceUpdate - [{}] [{}]", id, mdRez);
  715 + transportCallbackExecutor.submit(() -> mdRez.getListener().onResourceUpdate(Optional.ofNullable(msg)));
  716 + });
  717 +
713 } else if (toSessionMsg.hasResourceDeleteMsg()) { 718 } else if (toSessionMsg.hasResourceDeleteMsg()) {
714 TransportProtos.ResourceDeleteMsg msg = toSessionMsg.getResourceDeleteMsg(); 719 TransportProtos.ResourceDeleteMsg msg = toSessionMsg.getResourceDeleteMsg();
715 TenantId tenantId = new TenantId(new UUID(msg.getTenantIdMSB(), msg.getTenantIdLSB())); 720 TenantId tenantId = new TenantId(new UUID(msg.getTenantIdMSB(), msg.getTenantIdLSB()));
716 ResourceType resourceType = ResourceType.valueOf(msg.getResourceType()); 721 ResourceType resourceType = ResourceType.valueOf(msg.getResourceType());
717 String resourceId = msg.getResourceKey(); 722 String resourceId = msg.getResourceKey();
718 transportResourceCache.evict(tenantId, resourceType, resourceId); 723 transportResourceCache.evict(tenantId, resourceType, resourceId);
  724 + sessions.forEach((id, mdRez) -> {
  725 + log.warn("ResourceDelete - [{}] [{}]", id, mdRez);
  726 + transportCallbackExecutor.submit(() -> mdRez.getListener().onResourceDelete(Optional.ofNullable(msg)));
  727 + });
719 } else { 728 } else {
720 //TODO: should we notify the device actor about missed session? 729 //TODO: should we notify the device actor about missed session?
721 log.debug("[{}] Missing session.", sessionId); 730 log.debug("[{}] Missing session.", sessionId);
@@ -827,7 +836,7 @@ public class DefaultTransportService implements TransportService { @@ -827,7 +836,7 @@ public class DefaultTransportService implements TransportService {
827 } 836 }
828 837
829 private void sendToRuleEngine(TenantId tenantId, DeviceId deviceId, TransportProtos.SessionInfoProto sessionInfo, JsonObject json, 838 private void sendToRuleEngine(TenantId tenantId, DeviceId deviceId, TransportProtos.SessionInfoProto sessionInfo, JsonObject json,
830 - TbMsgMetaData metaData, SessionMsgType sessionMsgType, TbQueueCallback callback) { 839 + TbMsgMetaData metaData, SessionMsgType sessionMsgType, TbQueueCallback callback) {
831 DeviceProfileId deviceProfileId = new DeviceProfileId(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB())); 840 DeviceProfileId deviceProfileId = new DeviceProfileId(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB()));
832 DeviceProfile deviceProfile = deviceProfileCache.get(deviceProfileId); 841 DeviceProfile deviceProfile = deviceProfileCache.get(deviceProfileId);
833 RuleChainId ruleChainId; 842 RuleChainId ruleChainId;
@@ -31,7 +31,7 @@ import org.thingsboard.server.common.data.id.TbResourceId; @@ -31,7 +31,7 @@ import org.thingsboard.server.common.data.id.TbResourceId;
31 import org.thingsboard.server.common.data.id.TenantId; 31 import org.thingsboard.server.common.data.id.TenantId;
32 import org.thingsboard.server.common.data.lwm2m.LwM2mInstance; 32 import org.thingsboard.server.common.data.lwm2m.LwM2mInstance;
33 import org.thingsboard.server.common.data.lwm2m.LwM2mObject; 33 import org.thingsboard.server.common.data.lwm2m.LwM2mObject;
34 -import org.thingsboard.server.common.data.lwm2m.LwM2mResource; 34 +import org.thingsboard.server.common.data.lwm2m.LwM2mResourceObserve;
35 import org.thingsboard.server.common.data.page.PageData; 35 import org.thingsboard.server.common.data.page.PageData;
36 import org.thingsboard.server.common.data.page.PageLink; 36 import org.thingsboard.server.common.data.page.PageLink;
37 import org.thingsboard.server.dao.exception.DataValidationException; 37 import org.thingsboard.server.dao.exception.DataValidationException;
@@ -87,7 +87,9 @@ public class BaseTbResourceService implements TbResourceService { @@ -87,7 +87,9 @@ public class BaseTbResourceService implements TbResourceService {
87 String resourceKey = objectModel.id + LWM2M_SEPARATOR_KEY + objectModel.getVersion(); 87 String resourceKey = objectModel.id + LWM2M_SEPARATOR_KEY + objectModel.getVersion();
88 String name = objectModel.name; 88 String name = objectModel.name;
89 resource.setResourceKey(resourceKey); 89 resource.setResourceKey(resourceKey);
90 - resource.setTitle(name + " id=" +objectModel.id + " v" + objectModel.getVersion()); 90 + if (resource.getId() == null) {
  91 + resource.setTitle(name + " id=" + objectModel.id + " v" + objectModel.getVersion());
  92 + }
91 resource.setSearchText(resourceKey + LWM2M_SEPARATOR_SEARCH_TEXT + name); 93 resource.setSearchText(resourceKey + LWM2M_SEPARATOR_SEARCH_TEXT + name);
92 } else { 94 } else {
93 throw new DataValidationException(String.format("Could not parse the XML of objectModel with name %s", resource.getSearchText())); 95 throw new DataValidationException(String.format("Could not parse the XML of objectModel with name %s", resource.getSearchText()));
@@ -205,14 +207,14 @@ public class BaseTbResourceService implements TbResourceService { @@ -205,14 +207,14 @@ public class BaseTbResourceService implements TbResourceService {
205 lwM2mObject.setMandatory(obj.mandatory); 207 lwM2mObject.setMandatory(obj.mandatory);
206 LwM2mInstance instance = new LwM2mInstance(); 208 LwM2mInstance instance = new LwM2mInstance();
207 instance.setId(0); 209 instance.setId(0);
208 - List<LwM2mResource> resources = new ArrayList<>(); 210 + List<LwM2mResourceObserve> resources = new ArrayList<>();
209 obj.resources.forEach((k, v) -> { 211 obj.resources.forEach((k, v) -> {
210 if (!v.operations.isExecutable()) { 212 if (!v.operations.isExecutable()) {
211 - LwM2mResource lwM2mResource = new LwM2mResource(k, v.name, false, false, false);  
212 - resources.add(lwM2mResource); 213 + LwM2mResourceObserve lwM2MResourceObserve = new LwM2mResourceObserve(k, v.name, false, false, false);
  214 + resources.add(lwM2MResourceObserve);
213 } 215 }
214 }); 216 });
215 - instance.setResources(resources.toArray(LwM2mResource[]::new)); 217 + instance.setResources(resources.toArray(LwM2mResourceObserve[]::new));
216 lwM2mObject.setInstances(new LwM2mInstance[]{instance}); 218 lwM2mObject.setInstances(new LwM2mInstance[]{instance});
217 return lwM2mObject; 219 return lwM2mObject;
218 } 220 }