Commit 247941bcf74d936c4479bd2c8e383a5716640360

Authored by YevhenBondarenko
Committed by Andrew Shvayka
1 parent 118a0671

fixed ObjectModel extra parsing and refactoring

@@ -15,24 +15,16 @@ @@ -15,24 +15,16 @@
15 */ 15 */
16 package org.thingsboard.server.transport.lwm2m.config; 16 package org.thingsboard.server.transport.lwm2m.config;
17 17
18 -import com.google.common.io.Resources;  
19 import lombok.Getter; 18 import lombok.Getter;
20 import lombok.Setter; 19 import lombok.Setter;
21 import lombok.extern.slf4j.Slf4j; 20 import lombok.extern.slf4j.Slf4j;
22 -import org.eclipse.leshan.server.model.LwM2mModelProvider;  
23 -import org.jetbrains.annotations.NotNull;  
24 import org.springframework.beans.factory.annotation.Value; 21 import org.springframework.beans.factory.annotation.Value;
25 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; 22 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
26 import org.springframework.stereotype.Component; 23 import org.springframework.stereotype.Component;
27 import org.thingsboard.server.common.data.ResourceUtils; 24 import org.thingsboard.server.common.data.ResourceUtils;
28 25
29 import javax.annotation.PostConstruct; 26 import javax.annotation.PostConstruct;
30 -import java.io.File;  
31 -import java.io.FileInputStream;  
32 -import java.io.FileNotFoundException;  
33 import java.io.InputStream; 27 import java.io.InputStream;
34 -import java.net.URI;  
35 -import java.net.URISyntaxException;  
36 import java.security.KeyStore; 28 import java.security.KeyStore;
37 29
38 @Slf4j 30 @Slf4j
@@ -41,10 +33,6 @@ import java.security.KeyStore; @@ -41,10 +33,6 @@ import java.security.KeyStore;
41 public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig { 33 public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig {
42 34
43 @Getter 35 @Getter
44 - @Setter  
45 - private LwM2mModelProvider modelProvider;  
46 -  
47 - @Getter  
48 @Value("${transport.lwm2m.timeout:}") 36 @Value("${transport.lwm2m.timeout:}")
49 private Long timeout; 37 private Long timeout;
50 38
@@ -147,6 +135,4 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig { @@ -147,6 +135,4 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig {
147 } 135 }
148 } 136 }
149 137
150 -  
151 -  
152 } 138 }
@@ -62,14 +62,13 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService { @@ -62,14 +62,13 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
62 62
63 private final LwM2mTransportContext context; 63 private final LwM2mTransportContext context;
64 private final LwM2MTransportServerConfig config; 64 private final LwM2MTransportServerConfig config;
65 - private final LwM2mTransportServerHelper helper;  
66 private final OtaPackageDataCache otaPackageDataCache; 65 private final OtaPackageDataCache otaPackageDataCache;
67 private final DefaultLwM2MUplinkMsgHandler handler; 66 private final DefaultLwM2MUplinkMsgHandler handler;
68 private final CaliforniumRegistrationStore registrationStore; 67 private final CaliforniumRegistrationStore registrationStore;
69 private final TbSecurityStore securityStore; 68 private final TbSecurityStore securityStore;
70 - private final LwM2mClientContext lwM2mClientContext;  
71 private final TbLwM2MDtlsCertificateVerifier certificateVerifier; 69 private final TbLwM2MDtlsCertificateVerifier certificateVerifier;
72 private final TbLwM2MAuthorizer authorizer; 70 private final TbLwM2MAuthorizer authorizer;
  71 + private final LwM2mVersionedModelProvider modelProvider;
73 72
74 private LeshanServer server; 73 private LeshanServer server;
75 74
@@ -118,8 +117,6 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService { @@ -118,8 +117,6 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
118 builder.setCoapConfig(getCoapConfig(config.getPort(), config.getSecurePort(), config)); 117 builder.setCoapConfig(getCoapConfig(config.getPort(), config.getSecurePort(), config));
119 118
120 /* Define model provider (Create Models )*/ 119 /* Define model provider (Create Models )*/
121 - LwM2mModelProvider modelProvider = new LwM2mVersionedModelProvider(this.lwM2mClientContext, this.helper, this.context);  
122 - config.setModelProvider(modelProvider);  
123 builder.setObjectModelProvider(modelProvider); 120 builder.setObjectModelProvider(modelProvider);
124 121
125 /* Set securityStore with new registrationStore */ 122 /* Set securityStore with new registrationStore */
@@ -97,15 +97,15 @@ public class LwM2mSessionMsgListener implements GenericFutureListener<Future<? s @@ -97,15 +97,15 @@ public class LwM2mSessionMsgListener implements GenericFutureListener<Future<? s
97 } 97 }
98 98
99 @Override 99 @Override
100 - public void onResourceUpdate(@NotNull Optional<TransportProtos.ResourceUpdateMsg> resourceUpdateMsgOpt) {  
101 - if (ResourceType.LWM2M_MODEL.name().equals(resourceUpdateMsgOpt.get().getResourceType())) { 100 + public void onResourceUpdate(TransportProtos.ResourceUpdateMsg resourceUpdateMsgOpt) {
  101 + if (ResourceType.LWM2M_MODEL.name().equals(resourceUpdateMsgOpt.getResourceType())) {
102 this.handler.onResourceUpdate(resourceUpdateMsgOpt); 102 this.handler.onResourceUpdate(resourceUpdateMsgOpt);
103 } 103 }
104 } 104 }
105 105
106 @Override 106 @Override
107 - public void onResourceDelete(@NotNull Optional<TransportProtos.ResourceDeleteMsg> resourceDeleteMsgOpt) {  
108 - if (ResourceType.LWM2M_MODEL.name().equals(resourceDeleteMsgOpt.get().getResourceType())) { 107 + public void onResourceDelete(TransportProtos.ResourceDeleteMsg resourceDeleteMsgOpt) {
  108 + if (ResourceType.LWM2M_MODEL.name().equals(resourceDeleteMsgOpt.getResourceType())) {
109 this.handler.onResourceDelete(resourceDeleteMsgOpt); 109 this.handler.onResourceDelete(resourceDeleteMsgOpt);
110 } 110 }
111 } 111 }
@@ -15,7 +15,6 @@ @@ -15,7 +15,6 @@
15 */ 15 */
16 package org.thingsboard.server.transport.lwm2m.server; 16 package org.thingsboard.server.transport.lwm2m.server;
17 17
18 -import lombok.RequiredArgsConstructor;  
19 import lombok.extern.slf4j.Slf4j; 18 import lombok.extern.slf4j.Slf4j;
20 import org.eclipse.leshan.core.model.DefaultDDFFileValidator; 19 import org.eclipse.leshan.core.model.DefaultDDFFileValidator;
21 import org.eclipse.leshan.core.model.LwM2mModel; 20 import org.eclipse.leshan.core.model.LwM2mModel;
@@ -23,8 +22,11 @@ import org.eclipse.leshan.core.model.ObjectModel; @@ -23,8 +22,11 @@ import org.eclipse.leshan.core.model.ObjectModel;
23 import org.eclipse.leshan.core.model.ResourceModel; 22 import org.eclipse.leshan.core.model.ResourceModel;
24 import org.eclipse.leshan.server.model.LwM2mModelProvider; 23 import org.eclipse.leshan.server.model.LwM2mModelProvider;
25 import org.eclipse.leshan.server.registration.Registration; 24 import org.eclipse.leshan.server.registration.Registration;
  25 +import org.springframework.context.annotation.Lazy;
  26 +import org.springframework.stereotype.Service;
26 import org.thingsboard.server.common.data.TbResource; 27 import org.thingsboard.server.common.data.TbResource;
27 import org.thingsboard.server.common.data.id.TenantId; 28 import org.thingsboard.server.common.data.id.TenantId;
  29 +import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
28 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; 30 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
29 31
30 import java.util.ArrayList; 32 import java.util.ArrayList;
@@ -32,47 +34,58 @@ import java.util.Base64; @@ -32,47 +34,58 @@ import java.util.Base64;
32 import java.util.Collection; 34 import java.util.Collection;
33 import java.util.Map; 35 import java.util.Map;
34 import java.util.Optional; 36 import java.util.Optional;
  37 +import java.util.concurrent.ConcurrentHashMap;
  38 +import java.util.concurrent.ConcurrentMap;
  39 +import java.util.concurrent.locks.Lock;
  40 +import java.util.concurrent.locks.ReentrantLock;
35 41
36 import static org.thingsboard.server.common.data.ResourceType.LWM2M_MODEL; 42 import static org.thingsboard.server.common.data.ResourceType.LWM2M_MODEL;
37 import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY; 43 import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY;
38 44
39 @Slf4j 45 @Slf4j
40 -@RequiredArgsConstructor 46 +@Service
  47 +@TbLwM2mTransportComponent
41 public class LwM2mVersionedModelProvider implements LwM2mModelProvider { 48 public class LwM2mVersionedModelProvider implements LwM2mModelProvider {
42 49
43 - /**  
44 - * int objectId  
45 - * String version ("1.01")  
46 - * Key = objectId + "##" + version  
47 - * Value = TenantId  
48 - */  
49 private final LwM2mClientContext lwM2mClientContext; 50 private final LwM2mClientContext lwM2mClientContext;
50 private final LwM2mTransportServerHelper helper; 51 private final LwM2mTransportServerHelper helper;
51 private final LwM2mTransportContext context; 52 private final LwM2mTransportContext context;
  53 + private final ConcurrentMap<TenantId, ConcurrentMap<String, ObjectModel>> models;
  54 +
  55 + public LwM2mVersionedModelProvider(@Lazy LwM2mClientContext lwM2mClientContext, LwM2mTransportServerHelper helper, LwM2mTransportContext context) {
  56 + this.lwM2mClientContext = lwM2mClientContext;
  57 + this.helper = helper;
  58 + this.context = context;
  59 + this.models = new ConcurrentHashMap<>();
  60 + }
52 61
53 private String getKeyIdVer(Integer objectId, String version) { 62 private String getKeyIdVer(Integer objectId, String version) {
54 return objectId != null ? objectId + LWM2M_SEPARATOR_KEY + ((version == null || version.isEmpty()) ? ObjectModel.DEFAULT_VERSION : version) : null; 63 return objectId != null ? objectId + LWM2M_SEPARATOR_KEY + ((version == null || version.isEmpty()) ? ObjectModel.DEFAULT_VERSION : version) : null;
55 } 64 }
56 65
57 - /**  
58 - * Update repository if need  
59 - *  
60 - * @param registration  
61 - * @return  
62 - */  
63 @Override 66 @Override
64 public LwM2mModel getObjectModel(Registration registration) { 67 public LwM2mModel getObjectModel(Registration registration) {
65 return new DynamicModel(registration); 68 return new DynamicModel(registration);
66 } 69 }
67 70
68 - private class DynamicModel implements LwM2mModel { 71 + public void evict(TenantId tenantId, String key) {
  72 + if (tenantId.isNullUid()) {
  73 + models.values().forEach(m -> m.remove(key));
  74 + } else {
  75 + models.get(tenantId).remove(key);
  76 + }
  77 + }
69 78
  79 + private class DynamicModel implements LwM2mModel {
70 private final Registration registration; 80 private final Registration registration;
71 private final TenantId tenantId; 81 private final TenantId tenantId;
  82 + private final Lock modelsLock;
72 83
73 public DynamicModel(Registration registration) { 84 public DynamicModel(Registration registration) {
74 this.registration = registration; 85 this.registration = registration;
75 this.tenantId = lwM2mClientContext.getClientByEndpoint(registration.getEndpoint()).getTenantId(); 86 this.tenantId = lwM2mClientContext.getClientByEndpoint(registration.getEndpoint()).getTenantId();
  87 + this.modelsLock = new ReentrantLock();
  88 + models.computeIfAbsent(tenantId, t -> new ConcurrentHashMap<>());
76 } 89 }
77 90
78 @Override 91 @Override
@@ -114,6 +127,25 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider { @@ -114,6 +127,25 @@ public class LwM2mVersionedModelProvider implements LwM2mModelProvider {
114 127
115 private ObjectModel getObjectModelDynamic(Integer objectId, String version) { 128 private ObjectModel getObjectModelDynamic(Integer objectId, String version) {
116 String key = getKeyIdVer(objectId, version); 129 String key = getKeyIdVer(objectId, version);
  130 + ObjectModel objectModel = models.get(tenantId).get(key);
  131 +
  132 + if (objectModel == null) {
  133 + modelsLock.lock();
  134 + try {
  135 + objectModel = models.get(tenantId).get(key);
  136 + if (objectModel == null) {
  137 + objectModel = getObjectModel(key);
  138 + models.get(tenantId).put(key, objectModel);
  139 + }
  140 + } finally {
  141 + modelsLock.unlock();
  142 + }
  143 + }
  144 +
  145 + return objectModel;
  146 + }
  147 +
  148 + private ObjectModel getObjectModel(String key) {
117 Optional<TbResource> tbResource = context.getTransportResourceCache().get(this.tenantId, LWM2M_MODEL, key); 149 Optional<TbResource> tbResource = context.getTransportResourceCache().get(this.tenantId, LWM2M_MODEL, key);
118 return tbResource.map(resource -> helper.parseFromXmlToObjectModel( 150 return tbResource.map(resource -> helper.parseFromXmlToObjectModel(
119 Base64.getDecoder().decode(resource.getData()), 151 Base64.getDecoder().decode(resource.getData()),
@@ -21,13 +21,11 @@ import lombok.Setter; @@ -21,13 +21,11 @@ import lombok.Setter;
21 import lombok.extern.slf4j.Slf4j; 21 import lombok.extern.slf4j.Slf4j;
22 import org.eclipse.leshan.core.model.ObjectModel; 22 import org.eclipse.leshan.core.model.ObjectModel;
23 import org.eclipse.leshan.core.model.ResourceModel; 23 import org.eclipse.leshan.core.model.ResourceModel;
24 -import org.eclipse.leshan.core.node.LwM2mMultipleResource;  
25 import org.eclipse.leshan.core.node.LwM2mPath; 24 import org.eclipse.leshan.core.node.LwM2mPath;
26 import org.eclipse.leshan.core.node.LwM2mResource; 25 import org.eclipse.leshan.core.node.LwM2mResource;
27 import org.eclipse.leshan.core.node.LwM2mSingleResource; 26 import org.eclipse.leshan.core.node.LwM2mSingleResource;
28 import org.eclipse.leshan.core.node.codec.LwM2mValueConverter; 27 import org.eclipse.leshan.core.node.codec.LwM2mValueConverter;
29 import org.eclipse.leshan.core.request.ContentFormat; 28 import org.eclipse.leshan.core.request.ContentFormat;
30 -import org.eclipse.leshan.core.util.Hex;  
31 import org.eclipse.leshan.server.model.LwM2mModelProvider; 29 import org.eclipse.leshan.server.model.LwM2mModelProvider;
32 import org.eclipse.leshan.server.registration.Registration; 30 import org.eclipse.leshan.server.registration.Registration;
33 import org.thingsboard.server.common.data.Device; 31 import org.thingsboard.server.common.data.Device;
@@ -44,7 +42,6 @@ import java.io.IOException; @@ -44,7 +42,6 @@ import java.io.IOException;
44 import java.io.ObjectInputStream; 42 import java.io.ObjectInputStream;
45 import java.io.Serializable; 43 import java.io.Serializable;
46 import java.util.Collection; 44 import java.util.Collection;
47 -import java.util.HashMap;  
48 import java.util.Map; 45 import java.util.Map;
49 import java.util.Optional; 46 import java.util.Optional;
50 import java.util.Set; 47 import java.util.Set;
@@ -58,7 +55,6 @@ import java.util.concurrent.locks.Lock; @@ -58,7 +55,6 @@ import java.util.concurrent.locks.Lock;
58 import java.util.concurrent.locks.ReentrantLock; 55 import java.util.concurrent.locks.ReentrantLock;
59 import java.util.stream.Collectors; 56 import java.util.stream.Collectors;
60 57
61 -import static org.eclipse.leshan.core.model.ResourceModel.Type.OPAQUE;  
62 import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH; 58 import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH;
63 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LWM2M_OBJECT_VERSION_DEFAULT; 59 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LWM2M_OBJECT_VERSION_DEFAULT;
64 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertObjectIdToVersionedId; 60 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertObjectIdToVersionedId;
@@ -281,8 +277,6 @@ public class LwM2mClient implements Serializable { @@ -281,8 +277,6 @@ public class LwM2mClient implements Serializable {
281 .getObjectModel(pathIds.getObjectId()) : null; 277 .getObjectModel(pathIds.getObjectId()) : null;
282 } 278 }
283 279
284 -  
285 -  
286 public Collection<LwM2mResource> getNewResourceForInstance(String pathRezIdVer, Object params, LwM2mModelProvider modelProvider, 280 public Collection<LwM2mResource> getNewResourceForInstance(String pathRezIdVer, Object params, LwM2mModelProvider modelProvider,
287 LwM2mValueConverter converter) { 281 LwM2mValueConverter converter) {
288 LwM2mPath pathIds = new LwM2mPath(fromVersionedIdToObjectId(pathRezIdVer)); 282 LwM2mPath pathIds = new LwM2mPath(fromVersionedIdToObjectId(pathRezIdVer));
@@ -378,7 +372,7 @@ public class LwM2mClient implements Serializable { @@ -378,7 +372,7 @@ public class LwM2mClient implements Serializable {
378 this.lock = new ReentrantLock(); 372 this.lock = new ReentrantLock();
379 } 373 }
380 374
381 - public long updateLastUplinkTime(){ 375 + public long updateLastUplinkTime() {
382 this.lastUplinkTime = System.currentTimeMillis(); 376 this.lastUplinkTime = System.currentTimeMillis();
383 this.firstEdrxDownlink = true; 377 this.firstEdrxDownlink = true;
384 return lastUplinkTime; 378 return lastUplinkTime;
@@ -40,6 +40,7 @@ import org.thingsboard.server.transport.lwm2m.config.LwM2mVersion; @@ -40,6 +40,7 @@ import org.thingsboard.server.transport.lwm2m.config.LwM2mVersion;
40 import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo; 40 import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo;
41 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext; 41 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext;
42 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil; 42 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil;
  43 +import org.thingsboard.server.transport.lwm2m.server.LwM2mVersionedModelProvider;
43 import org.thingsboard.server.transport.lwm2m.server.ota.LwM2MOtaUpdateService; 44 import org.thingsboard.server.transport.lwm2m.server.ota.LwM2MOtaUpdateService;
44 import org.thingsboard.server.transport.lwm2m.server.session.LwM2MSessionManager; 45 import org.thingsboard.server.transport.lwm2m.server.session.LwM2MSessionManager;
45 import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MClientStore; 46 import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MClientStore;
@@ -74,6 +75,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { @@ -74,6 +75,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
74 private final TbLwM2MClientStore clientStore; 75 private final TbLwM2MClientStore clientStore;
75 private final LwM2MSessionManager sessionManager; 76 private final LwM2MSessionManager sessionManager;
76 private final TransportDeviceProfileCache deviceProfileCache; 77 private final TransportDeviceProfileCache deviceProfileCache;
  78 + private final LwM2mVersionedModelProvider modelProvider;
77 79
78 @Autowired 80 @Autowired
79 @Lazy 81 @Lazy
@@ -543,8 +545,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { @@ -543,8 +545,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
543 } 545 }
544 546
545 private boolean validateResourceInModel(LwM2mClient lwM2mClient, String pathIdVer, boolean isWritableNotOptional) { 547 private boolean validateResourceInModel(LwM2mClient lwM2mClient, String pathIdVer, boolean isWritableNotOptional) {
546 - ResourceModel resourceModel = lwM2mClient.getResourceModel(pathIdVer, this.config  
547 - .getModelProvider()); 548 + ResourceModel resourceModel = lwM2mClient.getResourceModel(pathIdVer, modelProvider);
548 Integer objectId = new LwM2mPath(fromVersionedIdToObjectId(pathIdVer)).getObjectId(); 549 Integer objectId = new LwM2mPath(fromVersionedIdToObjectId(pathIdVer)).getObjectId();
549 String objectVer = validateObjectVerFromKey(pathIdVer); 550 String objectVer = validateObjectVerFromKey(pathIdVer);
550 return resourceModel != null && (isWritableNotOptional ? 551 return resourceModel != null && (isWritableNotOptional ?
@@ -60,6 +60,7 @@ import org.thingsboard.server.common.data.device.data.lwm2m.ObjectAttributes; @@ -60,6 +60,7 @@ import org.thingsboard.server.common.data.device.data.lwm2m.ObjectAttributes;
60 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; 60 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
61 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; 61 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
62 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext; 62 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext;
  63 +import org.thingsboard.server.transport.lwm2m.server.LwM2mVersionedModelProvider;
63 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; 64 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
64 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; 65 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
65 import org.thingsboard.server.transport.lwm2m.server.common.LwM2MExecutorAwareService; 66 import org.thingsboard.server.transport.lwm2m.server.common.LwM2MExecutorAwareService;
@@ -99,6 +100,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im @@ -99,6 +100,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
99 private final LwM2MTransportServerConfig config; 100 private final LwM2MTransportServerConfig config;
100 private final LwM2MTelemetryLogService logService; 101 private final LwM2MTelemetryLogService logService;
101 private final LwM2mClientContext clientContext; 102 private final LwM2mClientContext clientContext;
  103 + private final LwM2mVersionedModelProvider modelProvider;
102 104
103 @PostConstruct 105 @PostConstruct
104 public void init() { 106 public void init() {
@@ -124,7 +126,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im @@ -124,7 +126,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
124 @Override 126 @Override
125 public void sendReadRequest(LwM2mClient client, TbLwM2MReadRequest request, DownlinkRequestCallback<ReadRequest, ReadResponse> callback) { 127 public void sendReadRequest(LwM2mClient client, TbLwM2MReadRequest request, DownlinkRequestCallback<ReadRequest, ReadResponse> callback) {
126 validateVersionedId(client, request); 128 validateVersionedId(client, request);
127 - ReadRequest downlink = new ReadRequest(getRequestContentFormat(client, request, this.config.getModelProvider()), request.getObjectId()); 129 + ReadRequest downlink = new ReadRequest(getRequestContentFormat(client, request, modelProvider), request.getObjectId());
128 sendSimpleRequest(client, downlink, request.getTimeout(), callback); 130 sendSimpleRequest(client, downlink, request.getTimeout(), callback);
129 } 131 }
130 132
@@ -145,7 +147,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im @@ -145,7 +147,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
145 Set<Observation> observations = context.getServer().getObservationService().getObservations(client.getRegistration()); 147 Set<Observation> observations = context.getServer().getObservationService().getObservations(client.getRegistration());
146 if (observations.stream().noneMatch(observation -> observation.getPath().equals(resultIds))) { 148 if (observations.stream().noneMatch(observation -> observation.getPath().equals(resultIds))) {
147 ObserveRequest downlink; 149 ObserveRequest downlink;
148 - ContentFormat contentFormat = getRequestContentFormat(client, request, this.config.getModelProvider()); 150 + ContentFormat contentFormat = getRequestContentFormat(client, request, modelProvider);
149 if (resultIds.isResource()) { 151 if (resultIds.isResource()) {
150 downlink = new ObserveRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId()); 152 downlink = new ObserveRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId());
151 } else if (resultIds.isObjectInstance()) { 153 } else if (resultIds.isObjectInstance()) {
@@ -174,7 +176,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im @@ -174,7 +176,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
174 176
175 @Override 177 @Override
176 public void sendExecuteRequest(LwM2mClient client, TbLwM2MExecuteRequest request, DownlinkRequestCallback<ExecuteRequest, ExecuteResponse> callback) { 178 public void sendExecuteRequest(LwM2mClient client, TbLwM2MExecuteRequest request, DownlinkRequestCallback<ExecuteRequest, ExecuteResponse> callback) {
177 - ResourceModel resourceModelExecute = client.getResourceModel(request.getVersionedId(), this.config.getModelProvider()); 179 + ResourceModel resourceModelExecute = client.getResourceModel(request.getVersionedId(), modelProvider);
178 if (resourceModelExecute != null) { 180 if (resourceModelExecute != null) {
179 ExecuteRequest downlink; 181 ExecuteRequest downlink;
180 if (request.getParams() != null && !resourceModelExecute.multiple) { 182 if (request.getParams() != null && !resourceModelExecute.multiple) {
@@ -231,7 +233,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im @@ -231,7 +233,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
231 233
232 @Override 234 @Override
233 public void sendWriteReplaceRequest(LwM2mClient client, TbLwM2MWriteReplaceRequest request, DownlinkRequestCallback<WriteRequest, WriteResponse> callback) { 235 public void sendWriteReplaceRequest(LwM2mClient client, TbLwM2MWriteReplaceRequest request, DownlinkRequestCallback<WriteRequest, WriteResponse> callback) {
234 - ResourceModel resourceModelWrite = client.getResourceModel(request.getVersionedId(), this.config.getModelProvider()); 236 + ResourceModel resourceModelWrite = client.getResourceModel(request.getVersionedId(), modelProvider);
235 if (resourceModelWrite != null) { 237 if (resourceModelWrite != null) {
236 ContentFormat contentFormat = convertResourceModelTypeToContentFormat(client, resourceModelWrite.type); 238 ContentFormat contentFormat = convertResourceModelTypeToContentFormat(client, resourceModelWrite.type);
237 try { 239 try {
@@ -267,8 +269,8 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im @@ -267,8 +269,8 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
267 * send request: path = '/3/0' node == wM2mObjectInstance 269 * send request: path = '/3/0' node == wM2mObjectInstance
268 * with params == "\"resources\": {15: resource:{id:15. value:'+01'...}} 270 * with params == "\"resources\": {15: resource:{id:15. value:'+01'...}}
269 **/ 271 **/
270 - Collection<LwM2mResource> resources = client.getNewResourceForInstance(request.getVersionedId(), request.getValue(), this.config.getModelProvider(), this.converter);  
271 - ResourceModel resourceModelWrite = client.getResourceModel(request.getVersionedId(), this.config.getModelProvider()); 272 + Collection<LwM2mResource> resources = client.getNewResourceForInstance(request.getVersionedId(), request.getValue(), modelProvider, this.converter);
  273 + ResourceModel resourceModelWrite = client.getResourceModel(request.getVersionedId(), modelProvider);
272 ContentFormat contentFormat = request.getObjectContentFormat() != null ? request.getObjectContentFormat() : convertResourceModelTypeToContentFormat(client, resourceModelWrite.type); 274 ContentFormat contentFormat = request.getObjectContentFormat() != null ? request.getObjectContentFormat() : convertResourceModelTypeToContentFormat(client, resourceModelWrite.type);
273 WriteRequest downlink = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(), 275 WriteRequest downlink = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(),
274 resultIds.getObjectInstanceId(), resources); 276 resultIds.getObjectInstanceId(), resources);
@@ -279,7 +281,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im @@ -279,7 +281,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
279 * int rscId = resultIds.getObjectInstanceId(); 281 * int rscId = resultIds.getObjectInstanceId();
280 * contentFormat – Format of the payload (TLV or JSON). 282 * contentFormat – Format of the payload (TLV or JSON).
281 */ 283 */
282 - Collection<LwM2mResource> resources = client.getNewResourcesForInstance(request.getVersionedId(), request.getValue(), this.config.getModelProvider(), this.converter); 284 + Collection<LwM2mResource> resources = client.getNewResourcesForInstance(request.getVersionedId(), request.getValue(), modelProvider, this.converter);
283 if (resources.size() > 0) { 285 if (resources.size() > 0) {
284 ContentFormat contentFormat = request.getObjectContentFormat() != null ? request.getObjectContentFormat() : ContentFormat.DEFAULT; 286 ContentFormat contentFormat = request.getObjectContentFormat() != null ? request.getObjectContentFormat() : ContentFormat.DEFAULT;
285 WriteRequest downlink = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resources); 287 WriteRequest downlink = new WriteRequest(WriteRequest.Mode.UPDATE, contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resources);
@@ -46,6 +46,7 @@ import org.thingsboard.server.common.data.device.data.lwm2m.ObjectAttributes; @@ -46,6 +46,7 @@ import org.thingsboard.server.common.data.device.data.lwm2m.ObjectAttributes;
46 import org.thingsboard.server.common.data.device.data.lwm2m.OtherConfiguration; 46 import org.thingsboard.server.common.data.device.data.lwm2m.OtherConfiguration;
47 import org.thingsboard.server.common.data.device.data.lwm2m.TelemetryMappingConfiguration; 47 import org.thingsboard.server.common.data.device.data.lwm2m.TelemetryMappingConfiguration;
48 import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; 48 import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration;
  49 +import org.thingsboard.server.common.data.id.TenantId;
49 import org.thingsboard.server.common.data.ota.OtaPackageUtil; 50 import org.thingsboard.server.common.data.ota.OtaPackageUtil;
50 import org.thingsboard.server.common.transport.TransportService; 51 import org.thingsboard.server.common.transport.TransportService;
51 import org.thingsboard.server.common.transport.TransportServiceCallback; 52 import org.thingsboard.server.common.transport.TransportServiceCallback;
@@ -57,6 +58,7 @@ import org.thingsboard.server.transport.lwm2m.server.LwM2mOtaConvert; @@ -57,6 +58,7 @@ import org.thingsboard.server.transport.lwm2m.server.LwM2mOtaConvert;
57 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext; 58 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext;
58 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper; 59 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper;
59 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil; 60 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil;
  61 +import org.thingsboard.server.transport.lwm2m.server.LwM2mVersionedModelProvider;
60 import org.thingsboard.server.transport.lwm2m.server.attributes.LwM2MAttributesService; 62 import org.thingsboard.server.transport.lwm2m.server.attributes.LwM2MAttributesService;
61 import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClientState; 63 import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClientState;
62 import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClientStateException; 64 import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClientStateException;
@@ -139,8 +141,8 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl @@ -139,8 +141,8 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
139 private final LwM2mTransportServerHelper helper; 141 private final LwM2mTransportServerHelper helper;
140 private final TbLwM2MDtlsSessionStore sessionStore; 142 private final TbLwM2MDtlsSessionStore sessionStore;
141 private final LwM2mClientContext clientContext; 143 private final LwM2mClientContext clientContext;
142 - private final LwM2MRpcRequestHandler rpcHandler;  
143 private final LwM2mDownlinkMsgHandler defaultLwM2MDownlinkMsgHandler; 144 private final LwM2mDownlinkMsgHandler defaultLwM2MDownlinkMsgHandler;
  145 + private final LwM2mVersionedModelProvider modelProvider;
144 146
145 public DefaultLwM2MUplinkMsgHandler(TransportService transportService, 147 public DefaultLwM2MUplinkMsgHandler(TransportService transportService,
146 LwM2MTransportServerConfig config, 148 LwM2MTransportServerConfig config,
@@ -150,9 +152,10 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl @@ -150,9 +152,10 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
150 LwM2MSessionManager sessionManager, 152 LwM2MSessionManager sessionManager,
151 @Lazy LwM2MOtaUpdateService otaService, 153 @Lazy LwM2MOtaUpdateService otaService,
152 @Lazy LwM2MAttributesService attributesService, 154 @Lazy LwM2MAttributesService attributesService,
153 - @Lazy LwM2MRpcRequestHandler rpcHandler,  
154 @Lazy LwM2mDownlinkMsgHandler defaultLwM2MDownlinkMsgHandler, 155 @Lazy LwM2mDownlinkMsgHandler defaultLwM2MDownlinkMsgHandler,
155 - LwM2mTransportContext context, TbLwM2MDtlsSessionStore sessionStore) { 156 + LwM2mTransportContext context,
  157 + TbLwM2MDtlsSessionStore sessionStore,
  158 + LwM2mVersionedModelProvider modelProvider) {
156 this.transportService = transportService; 159 this.transportService = transportService;
157 this.sessionManager = sessionManager; 160 this.sessionManager = sessionManager;
158 this.attributesService = attributesService; 161 this.attributesService = attributesService;
@@ -161,10 +164,10 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl @@ -161,10 +164,10 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
161 this.helper = helper; 164 this.helper = helper;
162 this.clientContext = clientContext; 165 this.clientContext = clientContext;
163 this.logService = logService; 166 this.logService = logService;
164 - this.rpcHandler = rpcHandler;  
165 this.defaultLwM2MDownlinkMsgHandler = defaultLwM2MDownlinkMsgHandler; 167 this.defaultLwM2MDownlinkMsgHandler = defaultLwM2MDownlinkMsgHandler;
166 this.context = context; 168 this.context = context;
167 this.sessionStore = sessionStore; 169 this.sessionStore = sessionStore;
  170 + this.modelProvider = modelProvider;
168 } 171 }
169 172
170 @PostConstruct 173 @PostConstruct
@@ -309,7 +312,7 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl @@ -309,7 +312,7 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
309 public void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response) { 312 public void onUpdateValueAfterReadResponse(Registration registration, String path, ReadResponse response) {
310 if (response.getContent() != null) { 313 if (response.getContent() != null) {
311 LwM2mClient lwM2MClient = clientContext.getClientByEndpoint(registration.getEndpoint()); 314 LwM2mClient lwM2MClient = clientContext.getClientByEndpoint(registration.getEndpoint());
312 - ObjectModel objectModelVersion = lwM2MClient.getObjectModel(path, this.config.getModelProvider()); 315 + ObjectModel objectModelVersion = lwM2MClient.getObjectModel(path, modelProvider);
313 if (objectModelVersion != null) { 316 if (objectModelVersion != null) {
314 if (response.getContent() instanceof LwM2mObject) { 317 if (response.getContent() instanceof LwM2mObject) {
315 LwM2mObject lwM2mObject = (LwM2mObject) response.getContent(); 318 LwM2mObject lwM2mObject = (LwM2mObject) response.getContent();
@@ -388,15 +391,19 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl @@ -388,15 +391,19 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
388 } 391 }
389 392
390 @Override 393 @Override
391 - public void onResourceUpdate(Optional<TransportProtos.ResourceUpdateMsg> resourceUpdateMsgOpt) {  
392 - String idVer = resourceUpdateMsgOpt.get().getResourceKey();  
393 - clientContext.getLwM2mClients().forEach(e -> e.updateResourceModel(idVer, this.config.getModelProvider())); 394 + public void onResourceUpdate(TransportProtos.ResourceUpdateMsg resourceUpdateMsgOpt) {
  395 + String idVer = resourceUpdateMsgOpt.getResourceKey();
  396 + TenantId tenantId = new TenantId(new UUID(resourceUpdateMsgOpt.getTenantIdMSB(), resourceUpdateMsgOpt.getTenantIdLSB()));
  397 + modelProvider.evict(tenantId, idVer);
  398 + clientContext.getLwM2mClients().forEach(e -> e.updateResourceModel(idVer, modelProvider));
394 } 399 }
395 400
396 @Override 401 @Override
397 - public void onResourceDelete(Optional<TransportProtos.ResourceDeleteMsg> resourceDeleteMsgOpt) {  
398 - String pathIdVer = resourceDeleteMsgOpt.get().getResourceKey();  
399 - clientContext.getLwM2mClients().forEach(e -> e.deleteResources(pathIdVer, this.config.getModelProvider())); 402 + public void onResourceDelete(TransportProtos.ResourceDeleteMsg resourceDeleteMsgOpt) {
  403 + String pathIdVer = resourceDeleteMsgOpt.getResourceKey();
  404 + TenantId tenantId = new TenantId(new UUID(resourceDeleteMsgOpt.getTenantIdMSB(), resourceDeleteMsgOpt.getTenantIdLSB()));
  405 + modelProvider.evict(tenantId, pathIdVer);
  406 + clientContext.getLwM2mClients().forEach(e -> e.deleteResources(pathIdVer, modelProvider));
400 } 407 }
401 408
402 /** 409 /**
@@ -544,7 +551,7 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl @@ -544,7 +551,7 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
544 */ 551 */
545 private void updateResourcesValue(LwM2mClient lwM2MClient, LwM2mResource lwM2mResource, String path) { 552 private void updateResourcesValue(LwM2mClient lwM2MClient, LwM2mResource lwM2mResource, String path) {
546 Registration registration = lwM2MClient.getRegistration(); 553 Registration registration = lwM2MClient.getRegistration();
547 - if (lwM2MClient.saveResourceValue(path, lwM2mResource, this.config.getModelProvider())) { 554 + if (lwM2MClient.saveResourceValue(path, lwM2mResource, modelProvider)) {
548 if (path.equals(convertObjectIdToVersionedId(FW_NAME_ID, registration))) { 555 if (path.equals(convertObjectIdToVersionedId(FW_NAME_ID, registration))) {
549 otaService.onCurrentFirmwareNameUpdate(lwM2MClient, (String) lwM2mResource.getValue()); 556 otaService.onCurrentFirmwareNameUpdate(lwM2MClient, (String) lwM2mResource.getValue());
550 } else if (path.equals(convertObjectIdToVersionedId(FW_3_VER_ID, registration))) { 557 } else if (path.equals(convertObjectIdToVersionedId(FW_3_VER_ID, registration))) {
@@ -48,9 +48,9 @@ public interface LwM2mUplinkMsgHandler { @@ -48,9 +48,9 @@ public interface LwM2mUplinkMsgHandler {
48 48
49 void onDeviceUpdate(TransportProtos.SessionInfoProto sessionInfo, Device device, Optional<DeviceProfile> deviceProfileOpt); 49 void onDeviceUpdate(TransportProtos.SessionInfoProto sessionInfo, Device device, Optional<DeviceProfile> deviceProfileOpt);
50 50
51 - void onResourceUpdate(Optional<TransportProtos.ResourceUpdateMsg> resourceUpdateMsgOpt); 51 + void onResourceUpdate(TransportProtos.ResourceUpdateMsg resourceUpdateMsgOpt);
52 52
53 - void onResourceDelete(Optional<TransportProtos.ResourceDeleteMsg> resourceDeleteMsgOpt); 53 + void onResourceDelete(TransportProtos.ResourceDeleteMsg resourceDeleteMsgOpt);
54 54
55 void onAwakeDev(Registration registration); 55 void onAwakeDev(Registration registration);
56 56
@@ -56,7 +56,7 @@ public interface SessionMsgListener { @@ -56,7 +56,7 @@ public interface SessionMsgListener {
56 56
57 default void onDeviceDeleted(DeviceId deviceId) {} 57 default void onDeviceDeleted(DeviceId deviceId) {}
58 58
59 - default void onResourceUpdate(Optional<TransportProtos.ResourceUpdateMsg> resourceUpdateMsgOpt) {} 59 + default void onResourceUpdate(TransportProtos.ResourceUpdateMsg resourceUpdateMsgOpt) {}
60 60
61 - default void onResourceDelete(Optional<TransportProtos.ResourceDeleteMsg> resourceUpdateMsgOpt) {} 61 + default void onResourceDelete(TransportProtos.ResourceDeleteMsg resourceUpdateMsgOpt) {}
62 } 62 }
@@ -908,7 +908,7 @@ public class DefaultTransportService implements TransportService { @@ -908,7 +908,7 @@ public class DefaultTransportService implements TransportService {
908 transportResourceCache.update(tenantId, resourceType, resourceId); 908 transportResourceCache.update(tenantId, resourceType, resourceId);
909 sessions.forEach((id, mdRez) -> { 909 sessions.forEach((id, mdRez) -> {
910 log.warn("ResourceUpdate - [{}] [{}]", id, mdRez); 910 log.warn("ResourceUpdate - [{}] [{}]", id, mdRez);
911 - transportCallbackExecutor.submit(() -> mdRez.getListener().onResourceUpdate(Optional.ofNullable(msg))); 911 + transportCallbackExecutor.submit(() -> mdRez.getListener().onResourceUpdate(msg));
912 }); 912 });
913 913
914 } else if (toSessionMsg.hasResourceDeleteMsg()) { 914 } else if (toSessionMsg.hasResourceDeleteMsg()) {
@@ -919,7 +919,7 @@ public class DefaultTransportService implements TransportService { @@ -919,7 +919,7 @@ public class DefaultTransportService implements TransportService {
919 transportResourceCache.evict(tenantId, resourceType, resourceId); 919 transportResourceCache.evict(tenantId, resourceType, resourceId);
920 sessions.forEach((id, mdRez) -> { 920 sessions.forEach((id, mdRez) -> {
921 log.warn("ResourceDelete - [{}] [{}]", id, mdRez); 921 log.warn("ResourceDelete - [{}] [{}]", id, mdRez);
922 - transportCallbackExecutor.submit(() -> mdRez.getListener().onResourceDelete(Optional.ofNullable(msg))); 922 + transportCallbackExecutor.submit(() -> mdRez.getListener().onResourceDelete(msg));
923 }); 923 });
924 } else { 924 } else {
925 //TODO: should we notify the device actor about missed session? 925 //TODO: should we notify the device actor about missed session?