Commit 72382a52e3e4b7d1b550c0d7fdb03a027c77c5a4

Authored by Andrii Shvaika
1 parent dd5195e8

LwM2M Server refactoring

Showing 11 changed files with 423 additions and 398 deletions
... ... @@ -32,7 +32,7 @@ import org.springframework.stereotype.Service;
32 32 import org.thingsboard.server.gen.transport.TransportProtos;
33 33 import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode;
34 34 import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator;
35   -import org.thingsboard.server.transport.lwm2m.secure.ReadResultSecurityStore;
  35 +import org.thingsboard.server.transport.lwm2m.secure.EndpointSecurityInfo;
36 36 import org.thingsboard.server.transport.lwm2m.server.LwM2mSessionMsgListener;
37 37 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext;
38 38 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper;
... ... @@ -72,7 +72,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore {
72 72
73 73 @Override
74 74 public List<SecurityInfo> getAllByEndpoint(String endPoint) {
75   - ReadResultSecurityStore store = lwM2MCredentialsSecurityInfoValidator.createAndValidateCredentialsSecurityInfo(endPoint, LwM2mTransportUtil.LwM2mTypeServer.BOOTSTRAP);
  75 + EndpointSecurityInfo store = lwM2MCredentialsSecurityInfoValidator.getEndpointSecurityInfo(endPoint, LwM2mTransportUtil.LwM2mTypeServer.BOOTSTRAP);
76 76 if (store.getBootstrapJsonCredential() != null && store.getSecurityMode() < LwM2MSecurityMode.DEFAULT_MODE.code) {
77 77 /* add value to store from BootstrapJson */
78 78 this.setBootstrapConfigScurityInfo(store);
... ... @@ -96,7 +96,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore {
96 96
97 97 @Override
98 98 public SecurityInfo getByIdentity(String identity) {
99   - ReadResultSecurityStore store = lwM2MCredentialsSecurityInfoValidator.createAndValidateCredentialsSecurityInfo(identity, LwM2mTransportUtil.LwM2mTypeServer.BOOTSTRAP);
  99 + EndpointSecurityInfo store = lwM2MCredentialsSecurityInfoValidator.getEndpointSecurityInfo(identity, LwM2mTransportUtil.LwM2mTypeServer.BOOTSTRAP);
100 100 if (store.getBootstrapJsonCredential() != null && store.getSecurityMode() < LwM2MSecurityMode.DEFAULT_MODE.code) {
101 101 /* add value to store from BootstrapJson */
102 102 this.setBootstrapConfigScurityInfo(store);
... ... @@ -113,7 +113,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore {
113 113 return null;
114 114 }
115 115
116   - private void setBootstrapConfigScurityInfo(ReadResultSecurityStore store) {
  116 + private void setBootstrapConfigScurityInfo(EndpointSecurityInfo store) {
117 117 /* BootstrapConfig */
118 118 LwM2MBootstrapConfig lwM2MBootstrapConfig = this.getParametersBootstrap(store);
119 119 if (lwM2MBootstrapConfig != null) {
... ... @@ -150,7 +150,7 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore {
150 150 }
151 151 }
152 152
153   - private LwM2MBootstrapConfig getParametersBootstrap(ReadResultSecurityStore store) {
  153 + private LwM2MBootstrapConfig getParametersBootstrap(EndpointSecurityInfo store) {
154 154 try {
155 155 JsonObject bootstrapJsonCredential = store.getBootstrapJsonCredential();
156 156 if (bootstrapJsonCredential != null) {
... ...
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/EndpointSecurityInfo.java renamed from common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/ReadResultSecurityStore.java
... ... @@ -25,7 +25,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCreden
25 25 import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.DEFAULT_MODE;
26 26
27 27 @Data
28   -public class ReadResultSecurityStore {
  28 +public class EndpointSecurityInfo {
29 29 private ValidateDeviceCredentialsResponseMsg msg;
30 30 private SecurityInfo securityInfo;
31 31 private int securityMode = DEFAULT_MODE.code;
... ...
... ... @@ -52,15 +52,10 @@ public class LwM2mCredentialsSecurityInfoValidator {
52 52 private final LwM2mTransportContext context;
53 53 private final LwM2MTransportServerConfig config;
54 54
55   - /**
56   - * Request to thingsboard Response from thingsboard ValidateDeviceLwM2MCredentials
57   - * @param endpoint -
58   - * @param keyValue -
59   - * @return ValidateDeviceCredentialsResponseMsg and SecurityInfo
60   - */
61   - public ReadResultSecurityStore createAndValidateCredentialsSecurityInfo(String endpoint, LwM2mTransportUtil.LwM2mTypeServer keyValue) {
  55 +
  56 + public EndpointSecurityInfo getEndpointSecurityInfo(String endpoint, LwM2mTransportUtil.LwM2mTypeServer keyValue) {
62 57 CountDownLatch latch = new CountDownLatch(1);
63   - final ReadResultSecurityStore[] resultSecurityStore = new ReadResultSecurityStore[1];
  58 + final EndpointSecurityInfo[] resultSecurityStore = new EndpointSecurityInfo[1];
64 59 context.getTransportService().process(ValidateDeviceLwM2MCredentialsRequestMsg.newBuilder().setCredentialsId(endpoint).build(),
65 60 new TransportServiceCallback<>() {
66 61 @Override
... ... @@ -90,27 +85,27 @@ public class LwM2mCredentialsSecurityInfoValidator {
90 85
91 86 /**
92 87 * Create new SecurityInfo
93   - * @param endPoint -
  88 + * @param endpoint -
94 89 * @param jsonStr -
95 90 * @param keyValue -
96 91 * @return SecurityInfo
97 92 */
98   - private ReadResultSecurityStore createSecurityInfo(String endPoint, String jsonStr, LwM2mTransportUtil.LwM2mTypeServer keyValue) {
99   - ReadResultSecurityStore result = new ReadResultSecurityStore();
  93 + private EndpointSecurityInfo createSecurityInfo(String endpoint, String jsonStr, LwM2mTransportUtil.LwM2mTypeServer keyValue) {
  94 + EndpointSecurityInfo result = new EndpointSecurityInfo();
100 95 JsonObject objectMsg = LwM2mTransportUtil.validateJson(jsonStr);
101 96 if (objectMsg != null && !objectMsg.isJsonNull()) {
102 97 JsonObject object = (objectMsg.has(keyValue.type) && !objectMsg.get(keyValue.type).isJsonNull()) ? objectMsg.get(keyValue.type).getAsJsonObject() : null;
103 98 /**
104 99 * Only PSK
105 100 */
106   - String endPointPsk = (objectMsg.has("client")
  101 + String endpointPsk = (objectMsg.has("client")
107 102 && objectMsg.get("client").getAsJsonObject().has("endpoint")
108 103 && objectMsg.get("client").getAsJsonObject().get("endpoint").isJsonPrimitive()) ? objectMsg.get("client").getAsJsonObject().get("endpoint").getAsString() : null;
109   - endPoint = (endPointPsk == null || endPointPsk.isEmpty()) ? endPoint : endPointPsk;
  104 + endpoint = (endpointPsk == null || endpointPsk.isEmpty()) ? endpoint : endpointPsk;
110 105 if (object != null && !object.isJsonNull()) {
111 106 if (keyValue.equals(LwM2mTransportUtil.LwM2mTypeServer.BOOTSTRAP)) {
112 107 result.setBootstrapJsonCredential(object);
113   - result.setEndPoint(endPoint);
  108 + result.setEndPoint(endpoint);
114 109 result.setSecurityMode(LwM2MSecurityMode.fromSecurityMode(object.get("bootstrapServer").getAsJsonObject().get("securityMode").getAsString().toLowerCase()).code);
115 110 } else {
116 111 LwM2MSecurityMode lwM2MSecurityMode = LwM2MSecurityMode.fromSecurityMode(object.get("securityConfigClientMode").getAsString().toLowerCase());
... ... @@ -119,13 +114,13 @@ public class LwM2mCredentialsSecurityInfoValidator {
119 114 createClientSecurityInfoNoSec(result);
120 115 break;
121 116 case PSK:
122   - createClientSecurityInfoPSK(result, endPoint, object);
  117 + createClientSecurityInfoPSK(result, endpoint, object);
123 118 break;
124 119 case RPK:
125   - createClientSecurityInfoRPK(result, endPoint, object);
  120 + createClientSecurityInfoRPK(result, endpoint, object);
126 121 break;
127 122 case X509:
128   - createClientSecurityInfoX509(result, endPoint);
  123 + createClientSecurityInfoX509(result, endpoint);
129 124 break;
130 125 default:
131 126 break;
... ... @@ -136,20 +131,20 @@ public class LwM2mCredentialsSecurityInfoValidator {
136 131 return result;
137 132 }
138 133
139   - private void createClientSecurityInfoNoSec(ReadResultSecurityStore result) {
  134 + private void createClientSecurityInfoNoSec(EndpointSecurityInfo result) {
140 135 result.setSecurityInfo(null);
141 136 result.setSecurityMode(NO_SEC.code);
142 137 }
143 138
144   - private void createClientSecurityInfoPSK(ReadResultSecurityStore result, String endPoint, JsonObject object) {
  139 + private void createClientSecurityInfoPSK(EndpointSecurityInfo result, String endpoint, JsonObject object) {
145 140 /** PSK Deserialization */
146 141 String identity = (object.has("identity") && object.get("identity").isJsonPrimitive()) ? object.get("identity").getAsString() : null;
147 142 if (identity != null && !identity.isEmpty()) {
148 143 try {
149 144 byte[] key = (object.has("key") && object.get("key").isJsonPrimitive()) ? Hex.decodeHex(object.get("key").getAsString().toCharArray()) : null;
150 145 if (key != null && key.length > 0) {
151   - if (endPoint != null && !endPoint.isEmpty()) {
152   - result.setSecurityInfo(SecurityInfo.newPreSharedKeyInfo(endPoint, identity, key));
  146 + if (endpoint != null && !endpoint.isEmpty()) {
  147 + result.setSecurityInfo(SecurityInfo.newPreSharedKeyInfo(endpoint, identity, key));
153 148 result.setSecurityMode(PSK.code);
154 149 }
155 150 }
... ... @@ -161,7 +156,7 @@ public class LwM2mCredentialsSecurityInfoValidator {
161 156 }
162 157 }
163 158
164   - private void createClientSecurityInfoRPK(ReadResultSecurityStore result, String endpoint, JsonObject object) {
  159 + private void createClientSecurityInfoRPK(EndpointSecurityInfo result, String endpoint, JsonObject object) {
165 160 try {
166 161 if (object.has("key") && object.get("key").isJsonPrimitive()) {
167 162 byte[] rpkkey = Hex.decodeHex(object.get("key").getAsString().toLowerCase().toCharArray());
... ... @@ -176,7 +171,7 @@ public class LwM2mCredentialsSecurityInfoValidator {
176 171 }
177 172 }
178 173
179   - private void createClientSecurityInfoX509(ReadResultSecurityStore result, String endpoint) {
  174 + private void createClientSecurityInfoX509(EndpointSecurityInfo result, String endpoint) {
180 175 result.setSecurityInfo(SecurityInfo.newX509CertInfo(endpoint));
181 176 result.setSecurityMode(X509.code);
182 177 }
... ...
... ... @@ -32,11 +32,11 @@ import org.eclipse.leshan.core.observation.Observation;
32 32 import org.eclipse.leshan.core.request.ContentFormat;
33 33 import org.eclipse.leshan.core.request.WriteRequest;
34 34 import org.eclipse.leshan.core.response.ReadResponse;
35   -import org.eclipse.leshan.core.util.NamedThreadFactory;
36 35 import org.eclipse.leshan.server.registration.Registration;
37 36 import org.springframework.context.annotation.Lazy;
38 37 import org.springframework.stereotype.Service;
39 38 import org.thingsboard.common.util.JacksonUtil;
  39 +import org.thingsboard.common.util.ThingsBoardExecutors;
40 40 import org.thingsboard.server.cache.firmware.FirmwareDataCache;
41 41 import org.thingsboard.server.common.data.Device;
42 42 import org.thingsboard.server.common.data.DeviceProfile;
... ... @@ -66,8 +66,8 @@ import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;
66 66 import javax.annotation.PostConstruct;
67 67 import java.util.ArrayList;
68 68 import java.util.Collection;
  69 +import java.util.Collections;
69 70 import java.util.HashSet;
70   -import java.util.LinkedHashSet;
71 71 import java.util.List;
72 72 import java.util.Map;
73 73 import java.util.Optional;
... ... @@ -77,7 +77,6 @@ import java.util.UUID;
77 77 import java.util.concurrent.ConcurrentHashMap;
78 78 import java.util.concurrent.ConcurrentMap;
79 79 import java.util.concurrent.ExecutorService;
80   -import java.util.concurrent.Executors;
81 80 import java.util.concurrent.TimeUnit;
82 81 import java.util.stream.Collectors;
83 82
... ... @@ -85,6 +84,7 @@ import static org.eclipse.californium.core.coap.CoAP.ResponseCode.BAD_REQUEST;
85 84 import static org.eclipse.leshan.core.attributes.Attribute.OBJECT_VERSION;
86 85 import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY;
87 86 import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH;
  87 +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper.getValueFromKvProto;
88 88 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.CLIENT_NOT_AUTHORIZED;
89 89 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.DEVICE_ATTRIBUTES_REQUEST;
90 90 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.FR_OBJECT_ID;
... ... @@ -103,7 +103,6 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.L
103 103 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_ATTRIBUTES;
104 104 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_REPLACE;
105 105 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.LwM2mTypeOper.WRITE_UPDATE;
106   -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.SERVICE_CHANNEL;
107 106 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertJsonArrayToSet;
108 107 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromIdVerToObjectId;
109 108 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer;
... ... @@ -115,9 +114,9 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.v
115 114 @TbLwM2mTransportComponent
116 115 public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler {
117 116
118   - private ExecutorService executorRegistered;
119   - private ExecutorService executorUpdateRegistered;
120   - private ExecutorService executorUnRegistered;
  117 + private ExecutorService registrationExecutor;
  118 + private ExecutorService updateRegistrationExecutor;
  119 + private ExecutorService unregistrationExecutor;
121 120 private LwM2mValueConverterImpl converter;
122 121
123 122 private final TransportService transportService;
... ... @@ -126,18 +125,18 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
126 125 private final FirmwareDataCache firmwareDataCache;
127 126 private final LwM2mTransportServerHelper helper;
128 127 private final LwM2MJsonAdaptor adaptor;
129   - private final LwM2mClientContext lwM2mClientContext;
  128 + private final LwM2mClientContext clientContext;
130 129 private final LwM2mTransportRequest lwM2mTransportRequest;
131 130
132 131 public DefaultLwM2MTransportMsgHandler(TransportService transportService, LwM2MTransportServerConfig config, LwM2mTransportServerHelper helper,
133   - LwM2mClientContext lwM2mClientContext,
  132 + LwM2mClientContext clientContext,
134 133 @Lazy LwM2mTransportRequest lwM2mTransportRequest,
135 134 FirmwareDataCache firmwareDataCache,
136 135 LwM2mTransportContext context, LwM2MJsonAdaptor adaptor) {
137 136 this.transportService = transportService;
138 137 this.config = config;
139 138 this.helper = helper;
140   - this.lwM2mClientContext = lwM2mClientContext;
  139 + this.clientContext = clientContext;
141 140 this.lwM2mTransportRequest = lwM2mTransportRequest;
142 141 this.firmwareDataCache = firmwareDataCache;
143 142 this.context = context;
... ... @@ -146,13 +145,10 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
146 145
147 146 @PostConstruct
148 147 public void init() {
149   - this.context.getScheduler().scheduleAtFixedRate(this::checkInactivityAndReportActivity, new Random().nextInt((int) config.getSessionReportTimeout()), config.getSessionReportTimeout(), TimeUnit.MILLISECONDS);
150   - this.executorRegistered = Executors.newFixedThreadPool(this.config.getRegisteredPoolSize(),
151   - new NamedThreadFactory(String.format("LwM2M %s channel registered", SERVICE_CHANNEL)));
152   - this.executorUpdateRegistered = Executors.newFixedThreadPool(this.config.getUpdateRegisteredPoolSize(),
153   - new NamedThreadFactory(String.format("LwM2M %s channel update registered", SERVICE_CHANNEL)));
154   - this.executorUnRegistered = Executors.newFixedThreadPool(this.config.getUnRegisteredPoolSize(),
155   - new NamedThreadFactory(String.format("LwM2M %s channel un registered", SERVICE_CHANNEL)));
  148 + this.context.getScheduler().scheduleAtFixedRate(this::reportActivity, new Random().nextInt((int) config.getSessionReportTimeout()), config.getSessionReportTimeout(), TimeUnit.MILLISECONDS);
  149 + this.registrationExecutor = ThingsBoardExecutors.newWorkStealingPool(this.config.getRegisteredPoolSize(), "LwM2M registration");
  150 + this.updateRegistrationExecutor = ThingsBoardExecutors.newWorkStealingPool(this.config.getUpdateRegisteredPoolSize(), "LwM2M update registration");
  151 + this.unregistrationExecutor = ThingsBoardExecutors.newWorkStealingPool(this.config.getUnRegisteredPoolSize(), "LwM2M unregistration");
156 152 this.converter = LwM2mValueConverterImpl.getInstance();
157 153 }
158 154
... ... @@ -171,14 +167,13 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
171 167 * @param previousObservations - may be null
172 168 */
173 169 public void onRegistered(Registration registration, Collection<Observation> previousObservations) {
174   - executorRegistered.submit(() -> {
  170 + registrationExecutor.submit(() -> {
175 171 try {
176 172 log.warn("[{}] [{{}] Client: create after Registration", registration.getEndpoint(), registration.getId());
177   - LwM2mClient lwM2MClient = this.lwM2mClientContext.updateInSessionsLwM2MClient(registration);
  173 + LwM2mClient lwM2MClient = this.clientContext.registerOrUpdate(registration);
178 174 if (lwM2MClient != null) {
179   - SessionInfoProto sessionInfo = this.getValidateSessionInfo(registration);
  175 + SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(lwM2MClient);
180 176 if (sessionInfo != null) {
181   - this.initLwM2mClient(lwM2MClient, sessionInfo);
182 177 transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(this, sessionInfo));
183 178 transportService.process(sessionInfo, DefaultTransportService.getSessionEventMsg(SessionEvent.OPEN), null);
184 179 transportService.process(sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build(), null);
... ... @@ -204,24 +199,18 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
204 199 * @param registration - Registration LwM2M Client
205 200 */
206 201 public void updatedReg(Registration registration) {
207   - executorUpdateRegistered.submit(() -> {
  202 + updateRegistrationExecutor.submit(() -> {
208 203 try {
209   - SessionInfoProto sessionInfo = this.getValidateSessionInfo(registration);
210   - if (sessionInfo != null) {
211   - this.checkInactivity(sessionInfo);
212   - LwM2mClient lwM2MClient = this.lwM2mClientContext.getLwM2MClient(sessionInfo);
213   - if (lwM2MClient.getDeviceId() == null && lwM2MClient.getProfileId() == null) {
214   - initLwM2mClient(lwM2MClient, sessionInfo);
215   - } else {
216   - if (registration.getBindingMode().useQueueMode()) {
217   - LwM2mQueuedRequest request;
218   - while ((request = lwM2MClient.getQueuedRequests().poll()) != null) {
219   - request.send();
220   - }
  204 + LwM2mClient client = clientContext.getOrRegister(registration);
  205 + if (client != null && client.getSession() != null) {
  206 + SessionInfoProto sessionInfo = client.getSession();
  207 + this.reportActivityAndRegister(sessionInfo);
  208 + if (registration.getBindingMode().useQueueMode()) {
  209 + LwM2mQueuedRequest request;
  210 + while ((request = client.getQueuedRequests().poll()) != null) {
  211 + request.send();
221 212 }
222 213 }
223   -
224   - log.info("Client: [{}] updatedReg [{}] name [{}] profile ", registration.getId(), registration.getEndpoint(), sessionInfo.getDeviceType());
225 214 } else {
226 215 log.error("Client: [{}] updatedReg [{}] name [{}] sessionInfo ", registration.getId(), registration.getEndpoint(), null);
227 216 }
... ... @@ -237,7 +226,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
237 226 * !!! Warn: if have not finishing unReg, then this operation will be finished on next Client`s connect
238 227 */
239 228 public void unReg(Registration registration, Collection<Observation> observations) {
240   - executorUnRegistered.submit(() -> {
  229 + unregistrationExecutor.submit(() -> {
241 230 try {
242 231 this.setCancelObservations(registration);
243 232 this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client unRegistration", registration.getId());
... ... @@ -248,22 +237,12 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
248 237 });
249 238 }
250 239
251   - private void initLwM2mClient(LwM2mClient lwM2MClient, SessionInfoProto sessionInfo) {
252   - lwM2MClient.setDeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB()));
253   - lwM2MClient.setProfileId(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB()));
254   - lwM2MClient.setDeviceName(sessionInfo.getDeviceName());
255   - lwM2MClient.setDeviceProfileName(sessionInfo.getDeviceType());
256   - }
257   -
258 240 private void closeClientSession(Registration registration) {
259   - SessionInfoProto sessionInfo = this.getValidateSessionInfo(registration);
  241 + SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(registration);
260 242 if (sessionInfo != null) {
261 243 transportService.deregisterSession(sessionInfo);
262 244 this.doCloseSession(sessionInfo);
263   - lwM2mClientContext.delRemoveSessionAndListener(registration.getId());
264   - if (lwM2mClientContext.getProfiles().size() > 0) {
265   - this.syncSessionsAndProfiles();
266   - }
  245 + clientContext.removeClientByRegistrationId(registration.getId());
267 246 log.info("Client close session: [{}] unReg [{}] name [{}] profile ", registration.getId(), registration.getEndpoint(), sessionInfo.getDeviceType());
268 247 } else {
269 248 log.error("Client close session: [{}] unReg [{}] name [{}] sessionInfo ", registration.getId(), registration.getEndpoint(), null);
... ... @@ -331,12 +310,12 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
331 310 */
332 311 @Override
333 312 public void onAttributeUpdate(AttributeUpdateNotificationMsg msg, TransportProtos.SessionInfoProto sessionInfo) {
334   - LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()));
  313 + LwM2mClient lwM2MClient = clientContext.getClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()));
335 314 if (msg.getSharedUpdatedCount() > 0) {
336 315 msg.getSharedUpdatedList().forEach(tsKvProto -> {
337 316 String pathName = tsKvProto.getKv().getKey();
338 317 String pathIdVer = this.getPresentPathIntoProfile(sessionInfo, pathName);
339   - Object valueNew = LwM2mTransportServerHelper.getValueFromKvProto(tsKvProto.getKv());
  318 + Object valueNew = getValueFromKvProto(tsKvProto.getKv());
340 319 //TODO: react on change of the firmware name.
341 320 if (FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.VERSION).equals(pathName) && !valueNew.equals(lwM2MClient.getFrUpdate().getCurrentFwVersion())) {
342 321 this.getInfoFirmwareUpdate(lwM2MClient);
... ... @@ -363,7 +342,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
363 342 } else if (msg.getSharedDeletedCount() > 0) {
364 343 msg.getSharedUpdatedList().forEach(tsKvProto -> {
365 344 String pathName = tsKvProto.getKv().getKey();
366   - Object valueNew = LwM2mTransportServerHelper.getValueFromKvProto(tsKvProto.getKv());
  345 + Object valueNew = getValueFromKvProto(tsKvProto.getKv());
367 346 if (FirmwareUtil.getAttributeKey(FirmwareType.FIRMWARE, FirmwareKey.VERSION).equals(pathName) && !valueNew.equals(lwM2MClient.getFrUpdate().getCurrentFwVersion())) {
368 347 lwM2MClient.getFrUpdate().setCurrentFwVersion((String) valueNew);
369 348 }
... ... @@ -378,45 +357,34 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
378 357 */
379 358 @Override
380 359 public void onDeviceProfileUpdate(SessionInfoProto sessionInfo, DeviceProfile deviceProfile) {
381   - Set<String> registrationIds = lwM2mClientContext.getLwM2mClients().entrySet()
382   - .stream()
383   - .filter(e -> e.getValue().getProfileId().equals(deviceProfile.getUuidId()))
384   - .map(Map.Entry::getKey).sorted().collect(Collectors.toCollection(LinkedHashSet::new));
  360 + Set<LwM2mClient> clients = clientContext.getLwM2mClients()
  361 + .stream().filter(e -> e.getProfileId().equals(deviceProfile.getUuidId())).collect(Collectors.toSet());
  362 + clients.forEach(client -> client.onDeviceProfileUpdate(deviceProfile));
  363 + Set<String> registrationIds = clients.stream().map(LwM2mClient::getRegistration).map(Registration::getId).collect(Collectors.toSet());
385 364 if (registrationIds.size() > 0) {
386   - this.onDeviceUpdateChangeProfile(registrationIds, deviceProfile);
  365 + this.onDeviceProfileUpdate(registrationIds, deviceProfile);
387 366 }
388 367 }
389 368
390   - /**
391   - * @param sessionInfo -
392   - * @param device -
393   - * @param deviceProfileOpt -
394   - */
395 369 @Override
396 370 public void onDeviceUpdate(SessionInfoProto sessionInfo, Device device, Optional<DeviceProfile> deviceProfileOpt) {
397   - Optional<String> registrationIdOpt = lwM2mClientContext.getLwM2mClients().entrySet().stream()
398   - .filter(e -> device.getUuidId().equals(e.getValue().getDeviceId()))
399   - .map(Map.Entry::getKey)
400   - .findFirst();
401   - registrationIdOpt.ifPresent(registrationId -> this.onDeviceUpdateLwM2MClient(registrationId, device, deviceProfileOpt));
  371 + //TODO: check, maybe device has multiple sessions/registrations? Is this possible according to the standard.
  372 + LwM2mClient client = clientContext.getClientByDeviceId(device.getUuidId());
  373 + if (client != null) {
  374 + this.onDeviceUpdate(client, device, deviceProfileOpt);
  375 + }
402 376 }
403 377
404   - /**
405   - * @param resourceUpdateMsgOpt -
406   - */
407 378 @Override
408 379 public void onResourceUpdate(Optional<TransportProtos.ResourceUpdateMsg> resourceUpdateMsgOpt) {
409 380 String idVer = resourceUpdateMsgOpt.get().getResourceKey();
410   - lwM2mClientContext.getLwM2mClients().values().stream().forEach(e -> e.updateResourceModel(idVer, this.config.getModelProvider()));
  381 + clientContext.getLwM2mClients().forEach(e -> e.updateResourceModel(idVer, this.config.getModelProvider()));
411 382 }
412 383
413   - /**
414   - * @param resourceDeleteMsgOpt -
415   - */
416 384 @Override
417 385 public void onResourceDelete(Optional<TransportProtos.ResourceDeleteMsg> resourceDeleteMsgOpt) {
418 386 String pathIdVer = resourceDeleteMsgOpt.get().getResourceKey();
419   - lwM2mClientContext.getLwM2mClients().values().stream().forEach(e -> e.deleteResources(pathIdVer, this.config.getModelProvider()));
  387 + clientContext.getLwM2mClients().forEach(e -> e.deleteResources(pathIdVer, this.config.getModelProvider()));
420 388 }
421 389
422 390 @Override
... ... @@ -424,9 +392,9 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
424 392 Lwm2mClientRpcRequest lwm2mClientRpcRequest = null;
425 393 try {
426 394 log.info("[{}] toDeviceRpcRequest", toDeviceRequest);
427   - Registration registration = lwM2mClientContext.getLwM2mClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())).getRegistration();
  395 + Registration registration = clientContext.getClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())).getRegistration();
428 396 lwm2mClientRpcRequest = this.getDeviceRpcRequest(toDeviceRequest, sessionInfo, registration);
429   - if (lwm2mClientRpcRequest != null && lwm2mClientRpcRequest.getErrorMsg() != null) {
  397 + if (lwm2mClientRpcRequest.getErrorMsg() != null) {
430 398 lwm2mClientRpcRequest.setResponseCode(BAD_REQUEST.name());
431 399 this.onToDeviceRpcResponse(lwm2mClientRpcRequest.getDeviceRpcResponseResultMsg(), sessionInfo);
432 400 } else {
... ... @@ -446,13 +414,6 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
446 414 }
447 415 }
448 416
449   - /**
450   - * @param toDeviceRequest -
451   - * @param sessionInfo -
452   - * @param registration -
453   - * @return
454   - * @throws IllegalArgumentException
455   - */
456 417 private Lwm2mClientRpcRequest getDeviceRpcRequest(TransportProtos.ToDeviceRpcRequestMsg toDeviceRequest,
457 418 SessionInfoProto sessionInfo, Registration registration) throws IllegalArgumentException {
458 419 Lwm2mClientRpcRequest lwm2mClientRpcRequest = new Lwm2mClientRpcRequest();
... ... @@ -590,35 +551,14 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
590 551 }
591 552
592 553 /**
593   - * This method is used to sync with sessions
594   - * Removes a profile if not used in sessions
595   - */
596   - private void syncSessionsAndProfiles() {
597   - Map<UUID, LwM2mClientProfile> profilesClone = lwM2mClientContext.getProfiles().entrySet()
598   - .stream()
599   - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
600   - profilesClone.forEach((k, v) -> {
601   - String registrationId = lwM2mClientContext.getLwM2mClients().entrySet()
602   - .stream()
603   - .filter(e -> e.getValue().getProfileId().equals(k))
604   - .findFirst()
605   - .map(Map.Entry::getKey) // return the key of the matching entry if found
606   - .orElse("");
607   - if (registrationId.isEmpty()) {
608   - lwM2mClientContext.getProfiles().remove(k);
609   - }
610   - });
611   - }
612   -
613   - /**
614   - * @param logMsg - text msg
  554 + * @param logMsg - text msg
615 555 * @param registrationId - Id of Registration LwM2M Client
616 556 */
617 557 @Override
618 558 public void sendLogsToThingsboard(String logMsg, String registrationId) {
619   - SessionInfoProto sessionInfo = this.getValidateSessionInfo(registrationId);
  559 + SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(registrationId);
620 560 if (logMsg != null && sessionInfo != null) {
621   - if(logMsg.length() > 1024){
  561 + if (logMsg.length() > 1024) {
622 562 logMsg = logMsg.substring(0, 1024);
623 563 }
624 564 this.helper.sendParametersOnThingsboardTelemetry(this.helper.getKvLogyToThingsboard(logMsg), sessionInfo);
... ... @@ -638,8 +578,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
638 578 * @param lwM2MClient - object with All parameters off client
639 579 */
640 580 private void initLwM2mFromClientValue(Registration registration, LwM2mClient lwM2MClient) {
641   - LwM2mClientProfile lwM2MClientProfile = lwM2mClientContext.getProfile(registration);
642   - Set<String> clientObjects = lwM2mClientContext.getSupportedIdVerInClient(registration);
  581 + LwM2mClientProfile lwM2MClientProfile = clientContext.getProfile(registration);
  582 + Set<String> clientObjects = clientContext.getSupportedIdVerInClient(registration);
643 583 if (clientObjects != null && clientObjects.size() > 0) {
644 584 if (LWM2M_STRATEGY_2 == LwM2mTransportUtil.getClientOnlyObserveAfterConnect(lwM2MClientProfile)) {
645 585 // #2
... ... @@ -693,7 +633,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
693 633 * @param path - resource
694 634 */
695 635 private void updateResourcesValue(Registration registration, LwM2mResource lwM2mResource, String path) {
696   - LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null);
  636 + LwM2mClient lwM2MClient = clientContext.getOrRegister(registration);
697 637 if (lwM2MClient.saveResourceValue(path, lwM2mResource, this.config
698 638 .getModelProvider())) {
699 639 if (FR_PATH_RESOURCE_VER_ID.equals(convertPathFromIdVerToObjectId(path)) &&
... ... @@ -730,7 +670,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
730 670 private void updateAttrTelemetry(Registration registration, Set<String> paths) {
731 671 try {
732 672 ResultsAddKeyValueProto results = getParametersFromProfile(registration, paths);
733   - SessionInfoProto sessionInfo = this.getValidateSessionInfo(registration);
  673 + SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(registration);
734 674 if (results != null && sessionInfo != null) {
735 675 if (results.getResultAttributes().size() > 0) {
736 676 this.helper.sendParametersOnThingsboardAttribute(results.getResultAttributes(), sessionInfo);
... ... @@ -752,7 +692,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
752 692 */
753 693 private void initReadAttrTelemetryObserveToClient(Registration registration, LwM2mClient lwM2MClient,
754 694 LwM2mTypeOper typeOper, Set<String> clientObjects) {
755   - LwM2mClientProfile lwM2MClientProfile = lwM2mClientContext.getProfile(registration);
  695 + LwM2mClientProfile lwM2MClientProfile = clientContext.getProfile(registration);
756 696 Set<String> result = null;
757 697 ConcurrentHashMap<String, Object> params = null;
758 698 if (READ.equals(typeOper)) {
... ... @@ -784,8 +724,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
784 724 lwM2MClient.getPendingReadRequests().addAll(pathSend);
785 725 ConcurrentHashMap<String, Object> finalParams = params;
786 726 pathSend.forEach(target -> {
787   - lwM2mTransportRequest.sendAllRequest(registration, target, typeOper, ContentFormat.TLV.getName(),
788   - finalParams != null ? finalParams.get(target) : null, this.config.getTimeout(), null);
  727 + lwM2mTransportRequest.sendAllRequest(registration, target, typeOper, ContentFormat.TLV.getName(),
  728 + finalParams != null ? finalParams.get(target) : null, this.config.getTimeout(), null);
789 729 });
790 730 if (OBSERVE.equals(typeOper)) {
791 731 lwM2MClient.initReadValue(this, null);
... ... @@ -801,23 +741,9 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
801 741 return pathAttributes;
802 742 }
803 743
804   - /**
805   - * Update parameters device in LwM2MClient
806   - * If new deviceProfile != old deviceProfile => update deviceProfile
807   - *
808   - * @param registrationId -
809   - * @param device -
810   - */
811   - private void onDeviceUpdateLwM2MClient(String registrationId, Device device, Optional<DeviceProfile> deviceProfileOpt) {
812   - LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClients().get(registrationId);
813   - lwM2MClient.setDeviceName(device.getName());
814   - if (!lwM2MClient.getProfileId().equals(device.getDeviceProfileId().getId())) {
815   - Set<String> registrationIds = new HashSet<>();
816   - registrationIds.add(registrationId);
817   - deviceProfileOpt.ifPresent(deviceProfile -> this.onDeviceUpdateChangeProfile(registrationIds, deviceProfile));
818   - }
819   -
820   - lwM2MClient.setProfileId(device.getDeviceProfileId().getId());
  744 + private void onDeviceUpdate(LwM2mClient lwM2MClient, Device device, Optional<DeviceProfile> deviceProfileOpt) {
  745 + deviceProfileOpt.ifPresent(deviceProfile -> this.onDeviceProfileUpdate(Collections.singleton(lwM2MClient.getRegistration().getId()), deviceProfile));
  746 + lwM2MClient.onDeviceUpdate(device, deviceProfileOpt);
821 747 }
822 748
823 749 /**
... ... @@ -830,7 +756,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
830 756 private ResultsAddKeyValueProto getParametersFromProfile(Registration registration, Set<String> path) {
831 757 if (path != null && path.size() > 0) {
832 758 ResultsAddKeyValueProto results = new ResultsAddKeyValueProto();
833   - LwM2mClientProfile lwM2MClientProfile = lwM2mClientContext.getProfile(registration);
  759 + LwM2mClientProfile lwM2MClientProfile = clientContext.getProfile(registration);
834 760 List<TransportProtos.KeyValueProto> resultAttributes = new ArrayList<>();
835 761 lwM2MClientProfile.getPostAttributeProfile().forEach(pathIdVer -> {
836 762 if (path.contains(pathIdVer.getAsString())) {
... ... @@ -861,8 +787,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
861 787 }
862 788
863 789 private TransportProtos.KeyValueProto getKvToThingsboard(String pathIdVer, Registration registration) {
864   - LwM2mClient lwM2MClient = this.lwM2mClientContext.getLwM2mClientWithReg(null, registration.getId());
865   - JsonObject names = lwM2mClientContext.getProfiles().get(lwM2MClient.getProfileId()).getPostKeyNameProfile();
  790 + LwM2mClient lwM2MClient = this.clientContext.getClientByRegistrationId(registration.getId());
  791 + JsonObject names = clientContext.getProfiles().get(lwM2MClient.getProfileId()).getPostKeyNameProfile();
866 792 if (names != null && names.has(pathIdVer)) {
867 793 String resourceName = names.get(pathIdVer).getAsString();
868 794 if (resourceName != null && !resourceName.isEmpty()) {
... ... @@ -960,9 +886,9 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
960 886 * @param registrationIds -
961 887 * @param deviceProfile -
962 888 */
963   - private void onDeviceUpdateChangeProfile(Set<String> registrationIds, DeviceProfile deviceProfile) {
964   - LwM2mClientProfile lwM2MClientProfileOld = lwM2mClientContext.getProfiles().get(deviceProfile.getUuidId()).clone();
965   - if (lwM2mClientContext.addUpdateProfileParameters(deviceProfile)) {
  889 + private void onDeviceProfileUpdate(Set<String> registrationIds, DeviceProfile deviceProfile) {
  890 + LwM2mClientProfile lwM2MClientProfileOld = clientContext.getProfiles().get(deviceProfile.getUuidId()).clone();
  891 + if (clientContext.toClientProfile(deviceProfile) != null) {
966 892 // #1
967 893 JsonArray attributeOld = lwM2MClientProfileOld.getPostAttributeProfile();
968 894 Set<String> attributeSetOld = convertJsonArrayToSet(attributeOld);
... ... @@ -972,7 +898,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
972 898 JsonObject keyNameOld = lwM2MClientProfileOld.getPostKeyNameProfile();
973 899 JsonObject attributeLwm2mOld = lwM2MClientProfileOld.getPostAttributeLwm2mProfile();
974 900
975   - LwM2mClientProfile lwM2MClientProfileNew = lwM2mClientContext.getProfiles().get(deviceProfile.getUuidId());
  901 + LwM2mClientProfile lwM2MClientProfileNew = clientContext.getProfiles().get(deviceProfile.getUuidId());
976 902 JsonArray attributeNew = lwM2MClientProfileNew.getPostAttributeProfile();
977 903 Set<String> attributeSetNew = convertJsonArrayToSet(attributeNew);
978 904 JsonArray telemetryNew = lwM2MClientProfileNew.getPostTelemetryProfile();
... ... @@ -1018,7 +944,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1018 944 if (sendAttrToThingsboard.getPathPostParametersAdd().size() > 0) {
1019 945 // update value in Resources
1020 946 registrationIds.forEach(registrationId -> {
1021   - Registration registration = lwM2mClientContext.getRegistration(registrationId);
  947 + Registration registration = clientContext.getRegistration(registrationId);
1022 948 this.readObserveFromProfile(registration, sendAttrToThingsboard.getPathPostParametersAdd(), READ);
1023 949 // send attr/telemetry to tingsboard for new path
1024 950 this.updateAttrTelemetry(registration, sendAttrToThingsboard.getPathPostParametersAdd());
... ... @@ -1046,7 +972,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1046 972 ResultsAnalyzerParameters postObserveAnalyzer = this.getAnalyzerParameters(sendObserveToClientOld.getPathPostParametersAdd(), sendObserveToClientNew.getPathPostParametersAdd());
1047 973 // send Request observe to Client
1048 974 registrationIds.forEach(registrationId -> {
1049   - Registration registration = lwM2mClientContext.getRegistration(registrationId);
  975 + Registration registration = clientContext.getRegistration(registrationId);
1050 976 if (postObserveAnalyzer.getPathPostParametersAdd().size() > 0) {
1051 977 this.readObserveFromProfile(registration, postObserveAnalyzer.getPathPostParametersAdd(), OBSERVE);
1052 978 }
... ... @@ -1151,8 +1077,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1151 1077 // #6.2
1152 1078 if (analyzerParameters.getPathPostParametersAdd().size() > 0) {
1153 1079 registrationIds.forEach(registrationId -> {
1154   - Registration registration = this.lwM2mClientContext.getRegistration(registrationId);
1155   - Set<String> clientObjects = lwM2mClientContext.getSupportedIdVerInClient(registration);
  1080 + Registration registration = this.clientContext.getRegistration(registrationId);
  1081 + Set<String> clientObjects = clientContext.getSupportedIdVerInClient(registration);
1156 1082 Set<String> pathSend = analyzerParameters.getPathPostParametersAdd().stream().filter(target -> clientObjects.contains("/" + target.split(LWM2M_SEPARATOR_PATH)[1]))
1157 1083 .collect(Collectors.toUnmodifiableSet());
1158 1084 if (!pathSend.isEmpty()) {
... ... @@ -1165,8 +1091,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1165 1091 // #6.2
1166 1092 if (analyzerParameters.getPathPostParametersDel().size() > 0) {
1167 1093 registrationIds.forEach(registrationId -> {
1168   - Registration registration = this.lwM2mClientContext.getRegistration(registrationId);
1169   - Set<String> clientObjects = lwM2mClientContext.getSupportedIdVerInClient(registration);
  1094 + Registration registration = this.clientContext.getRegistration(registrationId);
  1095 + Set<String> clientObjects = clientContext.getSupportedIdVerInClient(registration);
1170 1096 Set<String> pathSend = analyzerParameters.getPathPostParametersDel().stream().filter(target -> clientObjects.contains("/" + target.split(LWM2M_SEPARATOR_PATH)[1]))
1171 1097 .collect(Collectors.toUnmodifiableSet());
1172 1098 if (!pathSend.isEmpty()) {
... ... @@ -1184,7 +1110,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1184 1110 }
1185 1111
1186 1112 private void cancelObserveFromProfile(Registration registration, Set<String> paramAnallyzer) {
1187   - LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null);
  1113 + LwM2mClient lwM2MClient = clientContext.getOrRegister(registration);
1188 1114 paramAnallyzer.forEach(pathIdVer -> {
1189 1115 if (this.getResourceValueFromLwM2MClient(lwM2MClient, pathIdVer) != null) {
1190 1116 lwM2mTransportRequest.sendAllRequest(registration, pathIdVer, OBSERVE_CANCEL, null,
... ... @@ -1224,8 +1150,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1224 1150 * @return -
1225 1151 */
1226 1152 private String getPresentPathIntoProfile(TransportProtos.SessionInfoProto sessionInfo, String name) {
1227   - LwM2mClientProfile profile = lwM2mClientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB()));
1228   - LwM2mClient lwM2mClient = lwM2mClientContext.getLwM2MClient(sessionInfo);
  1153 + LwM2mClientProfile profile = clientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB()));
  1154 + LwM2mClient lwM2mClient = clientContext.getClient(sessionInfo);
1229 1155 return profile.getPostKeyNameProfile().getAsJsonObject().entrySet().stream()
1230 1156 .filter(e -> e.getValue().getAsString().equals(name) && validateResourceInModel(lwM2mClient, e.getKey(), false)).findFirst().map(Map.Entry::getKey)
1231 1157 .orElse(null);
... ... @@ -1244,7 +1170,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1244 1170 try {
1245 1171 List<TransportProtos.TsKvProto> tsKvProtos = attributesResponse.getSharedAttributeListList();
1246 1172
1247   - this.updateAttriuteFromThingsboard(tsKvProtos, sessionInfo);
  1173 + this.updateAttributeFromThingsboard(tsKvProtos, sessionInfo);
1248 1174 } catch (Exception e) {
1249 1175 log.error(String.valueOf(e));
1250 1176 }
... ... @@ -1260,8 +1186,8 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1260 1186 * @param tsKvProtos
1261 1187 * @param sessionInfo
1262 1188 */
1263   - public void updateAttriuteFromThingsboard(List<TransportProtos.TsKvProto> tsKvProtos, TransportProtos.SessionInfoProto sessionInfo) {
1264   - LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2MClient(sessionInfo);
  1189 + public void updateAttributeFromThingsboard(List<TransportProtos.TsKvProto> tsKvProtos, TransportProtos.SessionInfoProto sessionInfo) {
  1190 + LwM2mClient lwM2MClient = clientContext.getClient(sessionInfo);
1265 1191 tsKvProtos.forEach(tsKvProto -> {
1266 1192 String pathIdVer = this.getPresentPathIntoProfile(sessionInfo, tsKvProto.getKv().getKey());
1267 1193 if (pathIdVer != null) {
... ... @@ -1276,7 +1202,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1276 1202 // #2.1
1277 1203 lwM2MClient.getDelayedRequests().forEach((pathIdVer, tsKvProto) -> {
1278 1204 this.updateResourcesValueToClient(lwM2MClient, this.getResourceValueFormatKv(lwM2MClient, pathIdVer),
1279   - this.helper.getValueFromKvProto(tsKvProto.getKv()), pathIdVer);
  1205 + getValueFromKvProto(tsKvProto.getKv()), pathIdVer);
1280 1206 });
1281 1207 }
1282 1208
... ... @@ -1284,30 +1210,14 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1284 1210 * @param lwM2MClient -
1285 1211 * @return SessionInfoProto -
1286 1212 */
1287   - private SessionInfoProto getNewSessionInfoProto(LwM2mClient lwM2MClient) {
  1213 + private SessionInfoProto getSessionInfoOrCloseSession(LwM2mClient lwM2MClient) {
1288 1214 if (lwM2MClient != null) {
1289   - TransportProtos.ValidateDeviceCredentialsResponseMsg msg = lwM2MClient.getCredentialsResponse();
1290   - if (msg == null) {
1291   - log.error("[{}] [{}]", lwM2MClient.getEndpoint(), CLIENT_NOT_AUTHORIZED);
  1215 + SessionInfoProto sessionInfoProto = lwM2MClient.getSession();
  1216 + if (sessionInfoProto == null) {
  1217 + log.info("[{}] [{}]", lwM2MClient.getEndpoint(), CLIENT_NOT_AUTHORIZED);
1292 1218 this.closeClientSession(lwM2MClient.getRegistration());
1293   - return null;
1294   - } else {
1295   - return SessionInfoProto.newBuilder()
1296   - .setNodeId(this.context.getNodeId())
1297   - .setSessionIdMSB(lwM2MClient.getSessionId().getMostSignificantBits())
1298   - .setSessionIdLSB(lwM2MClient.getSessionId().getLeastSignificantBits())
1299   - .setDeviceIdMSB(msg.getDeviceInfo().getDeviceIdMSB())
1300   - .setDeviceIdLSB(msg.getDeviceInfo().getDeviceIdLSB())
1301   - .setTenantIdMSB(msg.getDeviceInfo().getTenantIdMSB())
1302   - .setTenantIdLSB(msg.getDeviceInfo().getTenantIdLSB())
1303   - .setCustomerIdMSB(msg.getDeviceInfo().getCustomerIdMSB())
1304   - .setCustomerIdLSB(msg.getDeviceInfo().getCustomerIdLSB())
1305   - .setDeviceName(msg.getDeviceInfo().getDeviceName())
1306   - .setDeviceType(msg.getDeviceInfo().getDeviceType())
1307   - .setDeviceProfileIdLSB(msg.getDeviceInfo().getDeviceProfileIdLSB())
1308   - .setDeviceProfileIdMSB(msg.getDeviceInfo().getDeviceProfileIdMSB())
1309   - .build();
1310 1219 }
  1220 + return sessionInfoProto;
1311 1221 }
1312 1222 return null;
1313 1223 }
... ... @@ -1316,18 +1226,16 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1316 1226 * @param registration - Registration LwM2M Client
1317 1227 * @return - sessionInfo after access connect client
1318 1228 */
1319   - private SessionInfoProto getValidateSessionInfo(Registration registration) {
1320   - LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null);
1321   - return getNewSessionInfoProto(lwM2MClient);
  1229 + private SessionInfoProto getSessionInfoOrCloseSession(Registration registration) {
  1230 + return getSessionInfoOrCloseSession(clientContext.getOrRegister(registration));
1322 1231 }
1323 1232
1324 1233 /**
1325 1234 * @param registrationId -
1326 1235 * @return -
1327 1236 */
1328   - private SessionInfoProto getValidateSessionInfo(String registrationId) {
1329   - LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(null, registrationId);
1330   - return lwM2MClient != null ? this.getNewSessionInfoProto(lwM2MClient) : null;
  1237 + private SessionInfoProto getSessionInfoOrCloseSession(String registrationId) {
  1238 + return getSessionInfoOrCloseSession(clientContext.getClientByRegistrationId(registrationId));
1331 1239 }
1332 1240
1333 1241 /**
... ... @@ -1335,14 +1243,14 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1335 1243 *
1336 1244 * @param sessionInfo -
1337 1245 */
1338   - private void checkInactivity(SessionInfoProto sessionInfo) {
1339   - if (transportService.reportActivity(sessionInfo) == null) {
  1246 + private void reportActivityAndRegister(SessionInfoProto sessionInfo) {
  1247 + if (sessionInfo != null && transportService.reportActivity(sessionInfo) == null) {
1340 1248 transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(this, sessionInfo));
1341 1249 }
1342 1250 }
1343 1251
1344   - private void checkInactivityAndReportActivity() {
1345   - lwM2mClientContext.getLwM2mClients().forEach((key, value) -> this.checkInactivity(this.getValidateSessionInfo(key)));
  1252 + private void reportActivity() {
  1253 + clientContext.getLwM2mClients().forEach(client -> reportActivityAndRegister(client.getSession()));
1346 1254 }
1347 1255
1348 1256 /**
... ... @@ -1356,7 +1264,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1356 1264 * @param lwM2MClient - LwM2M Client
1357 1265 */
1358 1266 public void putDelayedUpdateResourcesThingsboard(LwM2mClient lwM2MClient) {
1359   - SessionInfoProto sessionInfo = this.getValidateSessionInfo(lwM2MClient.getRegistration());
  1267 + SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(lwM2MClient);
1360 1268 if (sessionInfo != null) {
1361 1269 //#1.1
1362 1270 ConcurrentMap<String, String> keyNamesMap = this.getNamesFromProfileForSharedAttributes(lwM2MClient);
... ... @@ -1374,7 +1282,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1374 1282 }
1375 1283
1376 1284 public void getInfoFirmwareUpdate(LwM2mClient lwM2MClient) {
1377   - SessionInfoProto sessionInfo = this.getValidateSessionInfo(lwM2MClient.getRegistration());
  1285 + SessionInfoProto sessionInfo = this.getSessionInfoOrCloseSession(lwM2MClient);
1378 1286 if (sessionInfo != null) {
1379 1287 TransportProtos.GetFirmwareRequestMsg getFirmwareRequestMsg = TransportProtos.GetFirmwareRequestMsg.newBuilder()
1380 1288 .setDeviceIdMSB(sessionInfo.getDeviceIdMSB())
... ... @@ -1415,7 +1323,6 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1415 1323 }
1416 1324
1417 1325 /**
1418   - *
1419 1326 * @param lwM2MClient -
1420 1327 */
1421 1328 public void updateFirmwareClient(LwM2mClient lwM2MClient) {
... ... @@ -1441,7 +1348,7 @@ public class DefaultLwM2MTransportMsgHandler implements LwM2mTransportMsgHandler
1441 1348 */
1442 1349 private ConcurrentMap<String, String> getNamesFromProfileForSharedAttributes(LwM2mClient lwM2MClient) {
1443 1350
1444   - LwM2mClientProfile profile = lwM2mClientContext.getProfile(lwM2MClient.getProfileId());
  1351 + LwM2mClientProfile profile = clientContext.getProfile(lwM2MClient.getProfileId());
1445 1352 return new Gson().fromJson(profile.getPostKeyNameProfile().toString(),
1446 1353 new TypeToken<ConcurrentHashMap<String, String>>() {
1447 1354 }.getType());
... ...
... ... @@ -115,7 +115,7 @@ public class LwM2mTransportRequest {
115 115 String target = convertPathFromIdVerToObjectId(targetIdVer);
116 116 DownlinkRequest request = null;
117 117 ContentFormat contentFormat = contentFormatName != null ? ContentFormat.fromName(contentFormatName.toUpperCase()) : ContentFormat.DEFAULT;
118   - LwM2mClient lwM2MClient = this.lwM2mClientContext.getLwM2mClientWithReg(registration, null);
  118 + LwM2mClient lwM2MClient = this.lwM2mClientContext.getOrRegister(registration);
119 119 LwM2mPath resultIds = target != null ? new LwM2mPath(target) : null;
120 120 if (!OBSERVE_READ_ALL.name().equals(typeOper.name()) && resultIds != null && registration != null && resultIds.getObjectId() >= 0 && lwM2MClient != null) {
121 121 if (lwM2MClient.isValidObjectVersion(targetIdVer)) {
... ...
... ... @@ -183,7 +183,6 @@ public class LwM2mTransportUtil {
183 183 }
184 184
185 185 public static final String EVENT_AWAKE = "AWAKE";
186   - public static final String SERVICE_CHANNEL = "SERVICE";
187 186 public static final String RESPONSE_CHANNEL = "RESP";
188 187
189 188 public static boolean equalsResourceValue(Object valueOld, Object valueNew, ResourceModel.Type type, LwM2mPath resourcePath) throws CodecException {
... ... @@ -249,7 +248,7 @@ public class LwM2mTransportUtil {
249 248 * "/3_1.0/0": {"gt": 17},
250 249 * "/3_1.0/0/9": {"pmax": 45}, "/3_1.2": {ver": "3_1.2"}}
251 250 */
252   - public static LwM2mClientProfile getLwM2MClientProfileFromThingsboard(DeviceProfile deviceProfile) {
  251 + public static LwM2mClientProfile toLwM2MClientProfile(DeviceProfile deviceProfile) {
253 252 if (deviceProfile != null && ((Lwm2mDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration()).getProperties().size() > 0) {
254 253 Object profile = ((Lwm2mDeviceProfileTransportConfiguration) deviceProfile.getProfileData().getTransportConfiguration()).getProperties();
255 254 try {
... ...
... ... @@ -16,6 +16,8 @@
16 16 package org.thingsboard.server.transport.lwm2m.server.client;
17 17
18 18 import lombok.Data;
  19 +import lombok.Getter;
  20 +import lombok.Setter;
19 21 import lombok.extern.slf4j.Slf4j;
20 22 import org.eclipse.leshan.core.model.ResourceModel;
21 23 import org.eclipse.leshan.core.node.LwM2mPath;
... ... @@ -24,7 +26,11 @@ import org.eclipse.leshan.core.node.LwM2mSingleResource;
24 26 import org.eclipse.leshan.server.model.LwM2mModelProvider;
25 27 import org.eclipse.leshan.server.registration.Registration;
26 28 import org.eclipse.leshan.server.security.SecurityInfo;
  29 +import org.thingsboard.server.common.data.Device;
  30 +import org.thingsboard.server.common.data.DeviceProfile;
27 31 import org.thingsboard.server.gen.transport.TransportProtos;
  32 +import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto;
  33 +import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto;
28 34 import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg;
29 35 import org.thingsboard.server.transport.lwm2m.server.DefaultLwM2MTransportMsgHandler;
30 36 import org.thingsboard.server.transport.lwm2m.server.LwM2mQueuedRequest;
... ... @@ -33,6 +39,7 @@ import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;
33 39 import java.util.Collection;
34 40 import java.util.List;
35 41 import java.util.Map;
  42 +import java.util.Optional;
36 43 import java.util.Queue;
37 44 import java.util.Set;
38 45 import java.util.UUID;
... ... @@ -47,31 +54,52 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.c
47 54 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.getVerFromPathIdVerOrId;
48 55
49 56 @Slf4j
50   -@Data
51 57 public class LwM2mClient implements Cloneable {
  58 + @Getter
52 59 private String deviceName;
  60 + @Getter
53 61 private String deviceProfileName;
  62 + @Getter
54 63 private String endpoint;
  64 + @Getter
55 65 private String identity;
  66 + @Getter
56 67 private SecurityInfo securityInfo;
  68 + @Getter
57 69 private UUID deviceId;
  70 + @Getter
58 71 private UUID sessionId;
  72 + @Getter
  73 + private SessionInfoProto session;
  74 + @Getter
59 75 private UUID profileId;
  76 + @Getter
  77 + @Setter
60 78 private volatile LwM2mFirmwareUpdate frUpdate;
  79 + @Getter
  80 + @Setter
61 81 private Registration registration;
  82 +
62 83 private ValidateDeviceCredentialsResponseMsg credentialsResponse;
  84 + @Getter
63 85 private final Map<String, ResourceValue> resources;
64   - private final Map<String, TransportProtos.TsKvProto> delayedRequests;
  86 + @Getter
  87 + private final Map<String, TsKvProto> delayedRequests;
  88 + @Getter
65 89 private final List<String> pendingReadRequests;
  90 + @Getter
66 91 private final Queue<LwM2mQueuedRequest> queuedRequests;
  92 + @Getter
67 93 private boolean init;
  94 + @Getter
  95 + @Setter
68 96 private volatile boolean updateFw;
69 97
70 98 public Object clone() throws CloneNotSupportedException {
71 99 return super.clone();
72 100 }
73 101
74   - public LwM2mClient(String endpoint, String identity, SecurityInfo securityInfo, ValidateDeviceCredentialsResponseMsg credentialsResponse, UUID profileId, UUID sessionId) {
  102 + public LwM2mClient(String nodeId, String endpoint, String identity, SecurityInfo securityInfo, ValidateDeviceCredentialsResponseMsg credentialsResponse, UUID profileId, UUID sessionId) {
75 103 this.endpoint = endpoint;
76 104 this.identity = identity;
77 105 this.securityInfo = securityInfo;
... ... @@ -85,6 +113,56 @@ public class LwM2mClient implements Cloneable {
85 113 this.updateFw = false;
86 114 this.queuedRequests = new ConcurrentLinkedQueue<>();
87 115 this.frUpdate = new LwM2mFirmwareUpdate();
  116 + if (this.credentialsResponse != null && this.credentialsResponse.hasDeviceInfo()) {
  117 + this.session = createSession(nodeId, sessionId, credentialsResponse);
  118 + this.deviceId = new UUID(session.getDeviceIdMSB(), session.getDeviceIdLSB());
  119 + this.profileId = new UUID(session.getDeviceProfileIdMSB(), session.getDeviceProfileIdLSB());
  120 + this.deviceName = session.getDeviceName();
  121 + this.deviceProfileName = session.getDeviceType();
  122 + }
  123 + }
  124 +
  125 + public void onDeviceUpdate(Device device, Optional<DeviceProfile> deviceProfileOpt) {
  126 + SessionInfoProto.Builder builder = SessionInfoProto.newBuilder().mergeFrom(session);
  127 + this.deviceId = device.getUuidId();
  128 + this.deviceName = device.getName();
  129 + builder.setDeviceIdMSB(deviceId.getMostSignificantBits());
  130 + builder.setDeviceIdLSB(deviceId.getLeastSignificantBits());
  131 + builder.setDeviceName(deviceName);
  132 + deviceProfileOpt.ifPresent(deviceProfile -> updateSession(deviceProfile, builder));
  133 + this.session = builder.build();
  134 + }
  135 +
  136 + public void onDeviceProfileUpdate(DeviceProfile deviceProfile) {
  137 + SessionInfoProto.Builder builder = SessionInfoProto.newBuilder().mergeFrom(session);
  138 + updateSession(deviceProfile, builder);
  139 + this.session = builder.build();
  140 + }
  141 +
  142 + private void updateSession(DeviceProfile deviceProfile, SessionInfoProto.Builder builder) {
  143 + this.deviceProfileName = deviceProfile.getName();
  144 + this.profileId = deviceProfile.getUuidId();
  145 + builder.setDeviceProfileIdMSB(profileId.getMostSignificantBits());
  146 + builder.setDeviceProfileIdLSB(profileId.getLeastSignificantBits());
  147 + builder.setDeviceType(this.deviceProfileName);
  148 + }
  149 +
  150 + private SessionInfoProto createSession(String nodeId, UUID sessionId, ValidateDeviceCredentialsResponseMsg msg) {
  151 + return SessionInfoProto.newBuilder()
  152 + .setNodeId(nodeId)
  153 + .setSessionIdMSB(sessionId.getMostSignificantBits())
  154 + .setSessionIdLSB(sessionId.getLeastSignificantBits())
  155 + .setDeviceIdMSB(msg.getDeviceInfo().getDeviceIdMSB())
  156 + .setDeviceIdLSB(msg.getDeviceInfo().getDeviceIdLSB())
  157 + .setTenantIdMSB(msg.getDeviceInfo().getTenantIdMSB())
  158 + .setTenantIdLSB(msg.getDeviceInfo().getTenantIdLSB())
  159 + .setCustomerIdMSB(msg.getDeviceInfo().getCustomerIdMSB())
  160 + .setCustomerIdLSB(msg.getDeviceInfo().getCustomerIdLSB())
  161 + .setDeviceName(msg.getDeviceInfo().getDeviceName())
  162 + .setDeviceType(msg.getDeviceInfo().getDeviceType())
  163 + .setDeviceProfileIdLSB(msg.getDeviceInfo().getDeviceProfileIdLSB())
  164 + .setDeviceProfileIdMSB(msg.getDeviceInfo().getDeviceProfileIdMSB())
  165 + .build();
88 166 }
89 167
90 168 public boolean saveResourceValue(String pathRez, LwM2mResource rez, LwM2mModelProvider modelProvider) {
... ... @@ -123,7 +201,7 @@ public class LwM2mClient implements Cloneable {
123 201 return resources;
124 202 }
125 203
126   - public boolean isValidObjectVersion (String path) {
  204 + public boolean isValidObjectVersion(String path) {
127 205 LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(path));
128 206 String verSupportedObject = registration.getSupportedObject().get(pathIds.getObjectId());
129 207 String verRez = getVerFromPathIdVerOrId(path);
... ... @@ -131,8 +209,7 @@ public class LwM2mClient implements Cloneable {
131 209 }
132 210
133 211 /**
134   - *
135   - * @param pathIdVer == "3_1.0"
  212 + * @param pathIdVer == "3_1.0"
136 213 * @param modelProvider -
137 214 */
138 215 public void deleteResources(String pathIdVer, LwM2mModelProvider modelProvider) {
... ... @@ -142,16 +219,14 @@ public class LwM2mClient implements Cloneable {
142 219 ResourceModel resourceModel = modelProvider.getObjectModel(registration).getResourceModel(pathIds.getObjectId(), pathIds.getResourceId());
143 220 if (resourceModel != null) {
144 221 this.resources.get(pathRez).setResourceModel(resourceModel);
145   - }
146   - else {
  222 + } else {
147 223 this.resources.remove(pathRez);
148 224 }
149 225 });
150 226 }
151 227
152 228 /**
153   - *
154   - * @param idVer -
  229 + * @param idVer -
155 230 * @param modelProvider -
156 231 */
157 232 public void updateResourceModel(String idVer, LwM2mModelProvider modelProvider) {
... ... @@ -182,8 +257,5 @@ public class LwM2mClient implements Cloneable {
182 257 }
183 258 }
184 259
185   - public LwM2mClient copy() {
186   - return new LwM2mClient(this.endpoint, this.identity, this.securityInfo, this.credentialsResponse, this.profileId, this.sessionId);
187   - }
188 260 }
189 261
... ...
... ... @@ -19,29 +19,32 @@ import org.eclipse.leshan.server.registration.Registration;
19 19 import org.thingsboard.server.common.data.DeviceProfile;
20 20 import org.thingsboard.server.gen.transport.TransportProtos;
21 21
  22 +import java.util.Collection;
22 23 import java.util.Map;
23 24 import java.util.Set;
24 25 import java.util.UUID;
25 26
26 27 public interface LwM2mClientContext {
27 28
28   - void delRemoveSessionAndListener(String registrationId);
  29 + void removeClientByRegistrationId(String registrationId);
29 30
30   - LwM2mClient getLwM2MClient(String endPoint, String identity);
  31 + LwM2mClient getClientByEndpoint(String endpoint);
31 32
32   - LwM2mClient getLwM2MClient(TransportProtos.SessionInfoProto sessionInfo);
  33 + LwM2mClient getClientByRegistrationId(String registrationId);
33 34
34   - LwM2mClient getLwM2mClient(UUID sessionId);
  35 + LwM2mClient getClient(TransportProtos.SessionInfoProto sessionInfo);
35 36
36   - LwM2mClient getLwM2mClientWithReg(Registration registration, String registrationId);
  37 + LwM2mClient getClient(UUID sessionId);
37 38
38   - LwM2mClient updateInSessionsLwM2MClient(Registration registration);
  39 + LwM2mClient getOrRegister(Registration registration);
39 40
40   - LwM2mClient addLwM2mClientToSession(String identity);
  41 + LwM2mClient registerOrUpdate(Registration registration);
  42 +
  43 + LwM2mClient fetchClientByEndpoint(String endpoint);
41 44
42 45 Registration getRegistration(String registrationId);
43 46
44   - Map<String, LwM2mClient> getLwM2mClients();
  47 + Collection<LwM2mClient> getLwM2mClients();
45 48
46 49 Map<UUID, LwM2mClientProfile> getProfiles();
47 50
... ... @@ -51,7 +54,9 @@ public interface LwM2mClientContext {
51 54
52 55 Map<UUID, LwM2mClientProfile> setProfiles(Map<UUID, LwM2mClientProfile> profiles);
53 56
54   - boolean addUpdateProfileParameters(DeviceProfile deviceProfile);
  57 + LwM2mClientProfile toClientProfile(DeviceProfile deviceProfile);
55 58
56 59 Set<String> getSupportedIdVerInClient(Registration registration);
  60 +
  61 + LwM2mClient getClientByDeviceId(UUID deviceId);
57 62 }
... ...
... ... @@ -15,6 +15,7 @@
15 15 */
16 16 package org.thingsboard.server.transport.lwm2m.server.client;
17 17
  18 +import lombok.RequiredArgsConstructor;
18 19 import org.eclipse.leshan.core.node.LwM2mPath;
19 20 import org.eclipse.leshan.server.registration.Registration;
20 21 import org.eclipse.leshan.server.security.EditableSecurityStore;
... ... @@ -24,123 +25,121 @@ import org.thingsboard.server.gen.transport.TransportProtos;
24 25 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
25 26 import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode;
26 27 import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInfoValidator;
27   -import org.thingsboard.server.transport.lwm2m.secure.ReadResultSecurityStore;
  28 +import org.thingsboard.server.transport.lwm2m.secure.EndpointSecurityInfo;
  29 +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext;
28 30 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil;
29 31
30 32 import java.util.Arrays;
  33 +import java.util.Collection;
31 34 import java.util.Map;
  35 +import java.util.Optional;
32 36 import java.util.Set;
33 37 import java.util.UUID;
34 38 import java.util.concurrent.ConcurrentHashMap;
  39 +import java.util.stream.Collectors;
35 40
36 41 import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.NO_SEC;
37 42 import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.convertPathFromObjectIdToIdVer;
38 43
39 44 @Service
40 45 @TbLwM2mTransportComponent
  46 +@RequiredArgsConstructor
41 47 public class LwM2mClientContextImpl implements LwM2mClientContext {
42 48
43   - private static final boolean INFOS_ARE_COMPROMISED = false;
44   -
45   - private final Map<String /** registrationId */, LwM2mClient> lwM2mClients = new ConcurrentHashMap<>();
46   - private Map<UUID /** profileUUid */, LwM2mClientProfile> profiles = new ConcurrentHashMap<>();
  49 + private final LwM2mTransportContext context;
  50 + private final Map<String, LwM2mClient> lwM2mClientsByEndpoint = new ConcurrentHashMap<>();
  51 + private final Map<String, LwM2mClient> lwM2mClientsByRegistrationId = new ConcurrentHashMap<>();
  52 + private Map<UUID, LwM2mClientProfile> profiles = new ConcurrentHashMap<>();
47 53
48 54 private final LwM2mCredentialsSecurityInfoValidator lwM2MCredentialsSecurityInfoValidator;
49 55
50 56 private final EditableSecurityStore securityStore;
51 57
52   - public LwM2mClientContextImpl(LwM2mCredentialsSecurityInfoValidator lwM2MCredentialsSecurityInfoValidator, EditableSecurityStore securityStore) {
53   - this.lwM2MCredentialsSecurityInfoValidator = lwM2MCredentialsSecurityInfoValidator;
54   - this.securityStore = securityStore;
55   - }
56   -
57   - public void delRemoveSessionAndListener(String registrationId) {
58   - LwM2mClient lwM2MClient = this.lwM2mClients.get(registrationId);
59   - if (lwM2MClient != null) {
60   - this.securityStore.remove(lwM2MClient.getEndpoint(), INFOS_ARE_COMPROMISED);
61   - this.lwM2mClients.remove(registrationId);
62   - }
  58 + @Override
  59 + public LwM2mClient getClientByEndpoint(String endpoint) {
  60 + return lwM2mClientsByEndpoint.get(endpoint);
63 61 }
64 62
65 63 @Override
66   - public LwM2mClient getLwM2MClient(String endPoint, String identity) {
67   - Map.Entry<String, LwM2mClient> modelClients = endPoint != null ?
68   - this.lwM2mClients.entrySet().stream().filter(model -> endPoint.equals(model.getValue().getEndpoint())).findAny().orElse(null) :
69   - this.lwM2mClients.entrySet().stream().filter(model -> identity.equals(model.getValue().getIdentity())).findAny().orElse(null);
70   - return modelClients != null ? modelClients.getValue() : null;
  64 + public LwM2mClient getClientByRegistrationId(String registrationId) {
  65 + return lwM2mClientsByRegistrationId.get(registrationId);
71 66 }
72 67
73 68 @Override
74   - public LwM2mClient getLwM2MClient(TransportProtos.SessionInfoProto sessionInfo) {
75   - return getLwM2mClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()));
  69 + public LwM2mClient getOrRegister(Registration registration) {
  70 + if (registration == null) {
  71 + return null;
  72 + }
  73 + LwM2mClient client = lwM2mClientsByRegistrationId.get(registration.getId());
  74 + if (client == null) {
  75 + client = lwM2mClientsByEndpoint.get(registration.getEndpoint());
  76 + if (client == null) {
  77 + client = registerOrUpdate(registration);
  78 + }
  79 + }
  80 + return client;
76 81 }
77 82
78 83 @Override
79   - public LwM2mClient getLwM2mClient(UUID sessionId) {
80   - return lwM2mClients.values().stream().filter(c -> c.getSessionId().equals(sessionId)).findAny().get();
  84 + public LwM2mClient getClient(TransportProtos.SessionInfoProto sessionInfo) {
  85 + return getClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()));
81 86 }
82 87
83 88 @Override
84   - public LwM2mClient getLwM2mClientWithReg(Registration registration, String registrationId) {
85   - LwM2mClient client = registrationId != null && this.lwM2mClients.containsKey(registrationId) ?
86   - this.lwM2mClients.get(registrationId) :
87   - registration !=null && this.lwM2mClients.containsKey(registration.getId()) ?
88   - this.lwM2mClients.get(registration.getId()) : registration !=null && this.lwM2mClients.containsKey(registration) ?
89   - this.lwM2mClients.get(registration.getEndpoint()) : null;
90   - return client != null ? client : registration!= null ? updateInSessionsLwM2MClient(registration) : null;
  89 + public LwM2mClient getClient(UUID sessionId) {
  90 + //TODO: refactor this to search by sessionId efficiently.
  91 + return lwM2mClientsByEndpoint.values().stream().filter(c -> c.getSessionId().equals(sessionId)).findAny().get();
91 92 }
92 93
93 94 @Override
94   - public LwM2mClient updateInSessionsLwM2MClient(Registration registration) {
95   - if (this.lwM2mClients.get(registration.getEndpoint()) == null) {
96   - this.addLwM2mClientToSession(registration.getEndpoint());
  95 + public LwM2mClient registerOrUpdate(Registration registration) {
  96 + LwM2mClient lwM2MClient = lwM2mClientsByEndpoint.get(registration.getEndpoint());
  97 + if (lwM2MClient == null) {
  98 + lwM2MClient = this.fetchClientByEndpoint(registration.getEndpoint());
97 99 }
98   - LwM2mClient lwM2MClient = lwM2mClients.get(registration.getEndpoint());
99 100 lwM2MClient.setRegistration(registration);
100   - this.lwM2mClients.remove(registration.getEndpoint());
101   - this.lwM2mClients.put(registration.getId(), lwM2MClient);
  101 +// TODO: this remove is probably redundant. We should remove it.
  102 +// this.lwM2mClientsByEndpoint.remove(registration.getEndpoint());
  103 + this.lwM2mClientsByRegistrationId.put(registration.getId(), lwM2MClient);
102 104 return lwM2MClient;
103 105 }
104 106
105 107 public Registration getRegistration(String registrationId) {
106   - return this.lwM2mClients.get(registrationId).getRegistration();
  108 + return this.lwM2mClientsByRegistrationId.get(registrationId).getRegistration();
107 109 }
108 110
109   - /**
110   - * Add new LwM2MClient to session
111   - *
112   - * @param identity-
113   - * @return SecurityInfo. If error - SecurityInfoError
114   - * and log:
115   - * - FORBIDDEN - if there is no authorization
116   - * - profileUuid - if the device does not have a profile
117   - * - device - if the thingsboard does not have a device with a name equal to the identity
118   - */
119 111 @Override
120   - public LwM2mClient addLwM2mClientToSession(String identity) {
121   - ReadResultSecurityStore store = lwM2MCredentialsSecurityInfoValidator.createAndValidateCredentialsSecurityInfo(identity, LwM2mTransportUtil.LwM2mTypeServer.CLIENT);
122   - if (store.getSecurityMode() < LwM2MSecurityMode.DEFAULT_MODE.code) {
123   - UUID profileUuid = (store.getDeviceProfile() != null && addUpdateProfileParameters(store.getDeviceProfile())) ? store.getDeviceProfile().getUuidId() : null;
124   - LwM2mClient client;
125   - if (store.getSecurityInfo() != null && profileUuid != null) {
126   - String endpoint = store.getSecurityInfo().getEndpoint();
127   - client = new LwM2mClient(endpoint, store.getSecurityInfo().getIdentity(), store.getSecurityInfo(), store.getMsg(), profileUuid, UUID.randomUUID());
128   - lwM2mClients.put(endpoint, client);
129   - } else if (store.getSecurityMode() == NO_SEC.code && profileUuid != null) {
130   - client = new LwM2mClient(identity, null, null, store.getMsg(), profileUuid, UUID.randomUUID());
131   - lwM2mClients.put(identity, client);
  112 + public LwM2mClient fetchClientByEndpoint(String endpoint) {
  113 + EndpointSecurityInfo securityInfo = lwM2MCredentialsSecurityInfoValidator.getEndpointSecurityInfo(endpoint, LwM2mTransportUtil.LwM2mTypeServer.CLIENT);
  114 + if (securityInfo.getSecurityMode() < LwM2MSecurityMode.DEFAULT_MODE.code) {
  115 + if (securityInfo.getDeviceProfile() != null) {
  116 + toClientProfile(securityInfo.getDeviceProfile());
  117 + UUID profileUuid = securityInfo.getDeviceProfile().getUuidId();
  118 + LwM2mClient client;
  119 + if (securityInfo.getSecurityInfo() != null) {
  120 + client = new LwM2mClient(context.getNodeId(), securityInfo.getSecurityInfo().getEndpoint(),
  121 + securityInfo.getSecurityInfo().getIdentity(), securityInfo.getSecurityInfo(),
  122 + securityInfo.getMsg(), profileUuid, UUID.randomUUID());
  123 + } else if (securityInfo.getSecurityMode() == NO_SEC.code) {
  124 + client = new LwM2mClient(context.getNodeId(), endpoint,
  125 + null, null,
  126 + securityInfo.getMsg(), profileUuid, UUID.randomUUID());
  127 + } else {
  128 + throw new RuntimeException(String.format("Registration failed: device %s not found.", endpoint));
  129 + }
  130 + lwM2mClientsByEndpoint.put(client.getEndpoint(), client);
  131 + return client;
132 132 } else {
133   - throw new RuntimeException(String.format("Registration failed: FORBIDDEN/profileUuid/device %s , endpointId: %s [PSK]", profileUuid, identity));
  133 + throw new RuntimeException(String.format("Registration failed: device %s not found.", endpoint));
134 134 }
135   - return client;
136 135 } else {
137   - throw new RuntimeException(String.format("Registration failed: FORBIDDEN, endpointId: %s", identity));
  136 + throw new RuntimeException(String.format("Registration failed: FORBIDDEN, endpointId: %s", endpoint));
138 137 }
139 138 }
140 139
141 140 @Override
142   - public Map<String, LwM2mClient> getLwM2mClients() {
143   - return lwM2mClients;
  141 + public Collection<LwM2mClient> getLwM2mClients() {
  142 + return lwM2mClientsByEndpoint.values();
144 143 }
145 144
146 145 @Override
... ... @@ -155,7 +154,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
155 154
156 155 @Override
157 156 public LwM2mClientProfile getProfile(Registration registration) {
158   - return this.getProfiles().get(getLwM2mClientWithReg(registration, null).getProfileId());
  157 + return this.getProfiles().get(getOrRegister(registration).getProfileId());
159 158 }
160 159
161 160 @Override
... ... @@ -164,17 +163,18 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
164 163 }
165 164
166 165 @Override
167   - public boolean addUpdateProfileParameters(DeviceProfile deviceProfile) {
168   - LwM2mClientProfile lwM2MClientProfile = LwM2mTransportUtil.getLwM2MClientProfileFromThingsboard(deviceProfile);
169   - if (lwM2MClientProfile != null) {
  166 + public LwM2mClientProfile toClientProfile(DeviceProfile deviceProfile) {
  167 + LwM2mClientProfile lwM2MClientProfile = profiles.get(deviceProfile.getUuidId());
  168 + if (lwM2MClientProfile == null) {
  169 + lwM2MClientProfile = LwM2mTransportUtil.toLwM2MClientProfile(deviceProfile);
170 170 profiles.put(deviceProfile.getUuidId(), lwM2MClientProfile);
171   - return true;
172 171 }
173   - return false;
  172 + return lwM2MClientProfile;
174 173 }
175 174
176 175 /**
177 176 * if isVer - ok or default ver=DEFAULT_LWM2M_VERSION
  177 + *
178 178 * @param registration -
179 179 * @return - all objectIdVer in client
180 180 */
... ... @@ -184,9 +184,31 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
184 184 Arrays.stream(registration.getObjectLinks()).forEach(url -> {
185 185 LwM2mPath pathIds = new LwM2mPath(url.getUrl());
186 186 if (!pathIds.isRoot()) {
187   - clientObjects.add(convertPathFromObjectIdToIdVer(url.getUrl(), registration));
  187 + clientObjects.add(convertPathFromObjectIdToIdVer(url.getUrl(), registration));
188 188 }
189 189 });
190 190 return (clientObjects.size() > 0) ? clientObjects : null;
191 191 }
  192 +
  193 + @Override
  194 + public LwM2mClient getClientByDeviceId(UUID deviceId) {
  195 + return lwM2mClientsByRegistrationId.values().stream().filter(e -> deviceId.equals(e.getDeviceId())).findFirst().orElse(null);
  196 + }
  197 +
  198 + @Override
  199 + public void removeClientByRegistrationId(String registrationId) {
  200 + LwM2mClient lwM2MClient = this.lwM2mClientsByRegistrationId.get(registrationId);
  201 + if (lwM2MClient != null) {
  202 + this.securityStore.remove(lwM2MClient.getEndpoint(), false);
  203 + this.lwM2mClientsByEndpoint.remove(lwM2MClient.getEndpoint());
  204 + this.lwM2mClientsByRegistrationId.remove(registrationId);
  205 + UUID profileId = lwM2MClient.getProfileId();
  206 + if (profileId != null) {
  207 + Optional<LwM2mClient> otherClients = lwM2mClientsByRegistrationId.values().stream().filter(e -> e.getProfileId().equals(profileId)).findFirst();
  208 + if (otherClients.isEmpty()) {
  209 + profiles.remove(profileId);
  210 + }
  211 + }
  212 + }
  213 + }
192 214 }
... ...
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mSecurityStore.java renamed from common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mStoreConfiguration.java
... ... @@ -15,114 +15,80 @@
15 15 */
16 16 package org.thingsboard.server.transport.lwm2m.server.store;
17 17
18   -import org.eclipse.leshan.server.californium.registration.CaliforniumRegistrationStore;
19   -import org.eclipse.leshan.server.californium.registration.InMemoryRegistrationStore;
  18 +import lombok.extern.slf4j.Slf4j;
20 19 import org.eclipse.leshan.server.security.EditableSecurityStore;
21   -import org.eclipse.leshan.server.security.InMemorySecurityStore;
22 20 import org.eclipse.leshan.server.security.NonUniqueSecurityInfoException;
23 21 import org.eclipse.leshan.server.security.SecurityInfo;
24 22 import org.eclipse.leshan.server.security.SecurityStoreListener;
25   -import org.springframework.beans.factory.annotation.Autowired;
26   -import org.springframework.beans.factory.annotation.Value;
27   -import org.springframework.context.annotation.Bean;
28   -import org.springframework.context.annotation.Lazy;
29   -import org.springframework.stereotype.Service;
30   -import org.thingsboard.server.cache.TBRedisCacheConfiguration;
31   -import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
32 23 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
33 24 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
34 25
35 26 import java.util.Collection;
36   -import java.util.Optional;
37 27
38   -@Service
39   -@TbLwM2mTransportComponent
40   -public class TbLwM2mStoreConfiguration {
  28 +@Slf4j
  29 +public class TbLwM2mSecurityStore implements EditableSecurityStore {
41 30
42   - @Autowired(required = false)
43   - private Optional<TBRedisCacheConfiguration> redisConfiguration;
  31 + private final LwM2mClientContext clientContext;
  32 + private final EditableSecurityStore securityStore;
44 33
45   - @Autowired
46   - @Lazy
47   - private LwM2mClientContext clientContext;
48   -
49   - @Value("${transport.lwm2m.redis.enabled:false}")
50   - private boolean useRedis;
51   -
52   - @Bean
53   - private CaliforniumRegistrationStore registrationStore() {
54   - return redisConfiguration.isPresent() && useRedis ?
55   - new TbLwM2mRedisRegistrationStore(redisConfiguration.get().redisConnectionFactory()) : new InMemoryRegistrationStore();
  34 + public TbLwM2mSecurityStore(LwM2mClientContext clientContext, EditableSecurityStore securityStore) {
  35 + this.clientContext = clientContext;
  36 + this.securityStore = securityStore;
56 37 }
57 38
58   - @Bean
59   - private EditableSecurityStore securityStore() {
60   - return new TbLwM2mSecurityStoreWrapper(redisConfiguration.isPresent() && useRedis ?
61   - new TbLwM2mRedisSecurityStore(redisConfiguration.get().redisConnectionFactory()) : new InMemorySecurityStore());
  39 + @Override
  40 + public Collection<SecurityInfo> getAll() {
  41 + return securityStore.getAll();
62 42 }
63 43
64   - public class TbLwM2mSecurityStoreWrapper implements EditableSecurityStore {
65   -
66   - private final EditableSecurityStore securityStore;
67   -
68   - public TbLwM2mSecurityStoreWrapper(EditableSecurityStore securityStore) {
69   - this.securityStore = securityStore;
70   - }
71   -
72   - @Override
73   - public Collection<SecurityInfo> getAll() {
74   - return securityStore.getAll();
75   - }
76   -
77   - @Override
78   - public SecurityInfo add(SecurityInfo info) throws NonUniqueSecurityInfoException {
79   - return securityStore.add(info);
80   - }
  44 + @Override
  45 + public SecurityInfo add(SecurityInfo info) throws NonUniqueSecurityInfoException {
  46 + return securityStore.add(info);
  47 + }
81 48
82   - @Override
83   - public SecurityInfo remove(String endpoint, boolean infosAreCompromised) {
84   - return securityStore.remove(endpoint, infosAreCompromised);
85   - }
  49 + @Override
  50 + public SecurityInfo remove(String endpoint, boolean infosAreCompromised) {
  51 + return securityStore.remove(endpoint, infosAreCompromised);
  52 + }
86 53
87   - @Override
88   - public void setListener(SecurityStoreListener listener) {
89   - securityStore.setListener(listener);
90   - }
  54 + @Override
  55 + public void setListener(SecurityStoreListener listener) {
  56 + securityStore.setListener(listener);
  57 + }
91 58
92   - @Override
93   - public SecurityInfo getByEndpoint(String endPoint) {
94   - SecurityInfo securityInfo = securityStore.getByEndpoint(endPoint);
95   - if (securityInfo == null) {
96   - LwM2mClient lwM2mClient = clientContext.getLwM2MClient(endPoint, null);
97   - if (lwM2mClient != null && lwM2mClient.getRegistration() != null && !lwM2mClient.getRegistration().getIdentity().isSecure()){
98   - return null;
99   - }
100   - securityInfo = clientContext.addLwM2mClientToSession(endPoint).getSecurityInfo();
101   - try {
102   - if (securityInfo != null) {
103   - add(securityInfo);
104   - }
105   - } catch (NonUniqueSecurityInfoException e) {
106   - e.printStackTrace();
  59 + @Override
  60 + public SecurityInfo getByEndpoint(String endpoint) {
  61 + SecurityInfo securityInfo = securityStore.getByEndpoint(endpoint);
  62 + if (securityInfo == null) {
  63 + LwM2mClient lwM2mClient = clientContext.getClientByEndpoint(endpoint);
  64 + if (lwM2mClient != null && lwM2mClient.getRegistration() != null && !lwM2mClient.getRegistration().getIdentity().isSecure()) {
  65 + return null;
  66 + }
  67 + securityInfo = clientContext.fetchClientByEndpoint(endpoint).getSecurityInfo();
  68 + try {
  69 + if (securityInfo != null) {
  70 + add(securityInfo);
107 71 }
  72 + } catch (NonUniqueSecurityInfoException e) {
  73 + log.warn("Failed to add security info: {}", securityInfo, e);
108 74 }
109   - return securityInfo;
110 75 }
  76 + return securityInfo;
  77 + }
111 78
112   - @Override
113   - public SecurityInfo getByIdentity(String pskIdentity) {
114   - SecurityInfo securityInfo = securityStore.getByIdentity(pskIdentity);
115   - if (securityInfo == null) {
116   - securityInfo = clientContext.addLwM2mClientToSession(pskIdentity).getSecurityInfo();
117   - try {
118   - if (securityInfo != null) {
119   - add(securityInfo);
120   - }
121   - } catch (NonUniqueSecurityInfoException e) {
122   - e.printStackTrace();
  79 + @Override
  80 + public SecurityInfo getByIdentity(String pskIdentity) {
  81 + SecurityInfo securityInfo = securityStore.getByIdentity(pskIdentity);
  82 + if (securityInfo == null) {
  83 + securityInfo = clientContext.fetchClientByEndpoint(pskIdentity).getSecurityInfo();
  84 + try {
  85 + if (securityInfo != null) {
  86 + add(securityInfo);
123 87 }
  88 + } catch (NonUniqueSecurityInfoException e) {
  89 + log.warn("Failed to add security info: {}", securityInfo, e);
124 90 }
125   - return securityInfo;
126 91 }
  92 + return securityInfo;
127 93 }
128 94 }
... ...
  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 org.eclipse.leshan.server.californium.registration.CaliforniumRegistrationStore;
  19 +import org.eclipse.leshan.server.californium.registration.InMemoryRegistrationStore;
  20 +import org.eclipse.leshan.server.security.EditableSecurityStore;
  21 +import org.eclipse.leshan.server.security.InMemorySecurityStore;
  22 +import org.springframework.beans.factory.annotation.Autowired;
  23 +import org.springframework.beans.factory.annotation.Value;
  24 +import org.springframework.context.annotation.Bean;
  25 +import org.springframework.context.annotation.Lazy;
  26 +import org.springframework.stereotype.Component;
  27 +import org.thingsboard.server.cache.TBRedisCacheConfiguration;
  28 +import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
  29 +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext;
  30 +
  31 +import java.util.Optional;
  32 +
  33 +@Component
  34 +@TbLwM2mTransportComponent
  35 +public class TbLwM2mStoreFactory {
  36 +
  37 + @Autowired(required = false)
  38 + private Optional<TBRedisCacheConfiguration> redisConfiguration;
  39 +
  40 + @Autowired
  41 + @Lazy
  42 + private LwM2mClientContext clientContext;
  43 +
  44 + @Value("${transport.lwm2m.redis.enabled:false}")
  45 + private boolean useRedis;
  46 +
  47 + @Bean
  48 + private CaliforniumRegistrationStore registrationStore() {
  49 + return redisConfiguration.isPresent() && useRedis ?
  50 + new TbLwM2mRedisRegistrationStore(redisConfiguration.get().redisConnectionFactory()) : new InMemoryRegistrationStore();
  51 + }
  52 +
  53 + @Bean
  54 + private EditableSecurityStore securityStore() {
  55 + return new TbLwM2mSecurityStore(clientContext, redisConfiguration.isPresent() && useRedis ?
  56 + new TbLwM2mRedisSecurityStore(redisConfiguration.get().redisConnectionFactory()) : new InMemorySecurityStore());
  57 + }
  58 +
  59 +}
... ...