Commit 1b391847d3f425e41bfe249a4198567196b0e3e7

Authored by Andrii Shvaika
1 parent 78f91946

OTA Info store and client lookup

Showing 18 changed files with 416 additions and 136 deletions
... ... @@ -181,6 +181,7 @@ public class DefaultLwM2MAttributesService implements LwM2MAttributesService {
181 181 }
182 182 }
183 183 });
  184 + clientContext.update(lwM2MClient);
184 185 // #2.1
185 186 lwM2MClient.getSharedAttributes().forEach((pathIdVer, tsKvProto) -> {
186 187 this.pushUpdateToClientIfNeeded(lwM2MClient, this.getResourceValueFormatKv(lwM2MClient, pathIdVer),
... ...
... ... @@ -5,7 +5,7 @@
5 5 * you may not use this file except in compliance with the License.
6 6 * You may obtain a copy of the License at
7 7 *
8   - * http://www.apache.org/licenses/LICENSE-2.0
  8 + * http://www.apache.org/licenses/LICENSE-2.0
9 9 *
10 10 * Unless required by applicable law or agreed to in writing, software
11 11 * distributed under the License is distributed on an "AS IS" BASIS,
... ... @@ -142,6 +142,16 @@ public class LwM2mClient implements Serializable {
142 142 builder.setDeviceType(deviceProfile.getName());
143 143 }
144 144
  145 + public void refreshSessionId(String nodeId) {
  146 + UUID newId = UUID.randomUUID();
  147 + SessionInfoProto.Builder builder = SessionInfoProto.newBuilder().mergeFrom(session);
  148 + builder.setNodeId(nodeId);
  149 + builder.setSessionIdMSB(newId.getMostSignificantBits());
  150 + builder.setSessionIdLSB(newId.getLeastSignificantBits());
  151 + this.session = builder.build();
  152 + }
  153 +
  154 +
145 155 private SessionInfoProto createSession(String nodeId, UUID sessionId, ValidateDeviceCredentialsResponse msg) {
146 156 return SessionInfoProto.newBuilder()
147 157 .setNodeId(nodeId)
... ...
... ... @@ -55,4 +55,5 @@ public interface LwM2mClientContext {
55 55
56 56 void registerClient(Registration registration, ValidateDeviceCredentialsResponse credentials);
57 57
  58 + void update(LwM2mClient lwM2MClient);
58 59 }
... ...
... ... @@ -5,7 +5,7 @@
5 5 * you may not use this file except in compliance with the License.
6 6 * You may obtain a copy of the License at
7 7 *
8   - * http://www.apache.org/licenses/LICENSE-2.0
  8 + * http://www.apache.org/licenses/LICENSE-2.0
9 9 *
10 10 * Unless required by applicable law or agreed to in writing, software
11 11 * distributed under the License is distributed on an "AS IS" BASIS,
... ... @@ -24,6 +24,7 @@ import org.eclipse.leshan.server.registration.Registration;
24 24 import org.springframework.stereotype.Service;
25 25 import org.thingsboard.server.common.data.DeviceProfile;
26 26 import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration;
  27 +import org.thingsboard.server.common.transport.TransportService;
27 28 import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
28 29 import org.thingsboard.server.gen.transport.TransportProtos;
29 30 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
... ... @@ -31,6 +32,7 @@ import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
31 32 import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo;
32 33 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext;
33 34 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil;
  35 +import org.thingsboard.server.transport.lwm2m.server.session.LwM2MSessionManager;
34 36 import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MClientStore;
35 37 import org.thingsboard.server.transport.lwm2m.server.store.TbMainSecurityStore;
36 38
... ... @@ -58,6 +60,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
58 60 private final LwM2MTransportServerConfig config;
59 61 private final TbMainSecurityStore securityStore;
60 62 private final TbLwM2MClientStore clientStore;
  63 + private final LwM2MSessionManager sessionManager;
61 64 private final Map<String, LwM2mClient> lwM2mClientsByEndpoint = new ConcurrentHashMap<>();
62 65 private final Map<String, LwM2mClient> lwM2mClientsByRegistrationId = new ConcurrentHashMap<>();
63 66 private final Map<UUID, Lwm2mDeviceProfileTransportConfiguration> profiles = new ConcurrentHashMap<>();
... ... @@ -66,14 +69,23 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
66 69 public LwM2mClient getClientByEndpoint(String endpoint) {
67 70 return lwM2mClientsByEndpoint.computeIfAbsent(endpoint, ep -> {
68 71 LwM2mClient client = clientStore.get(ep);
  72 + String nodeId = context.getNodeId();
69 73 if (client == null) {
70 74 log.info("[{}] initialized new client.", endpoint);
71   - client = new LwM2mClient(context.getNodeId(), ep);
  75 + client = new LwM2mClient(nodeId, ep);
72 76 } else {
73 77 log.debug("[{}] fetched client from store: {}", endpoint, client);
  78 + boolean updated = false;
74 79 if (client.getRegistration() != null) {
75 80 lwM2mClientsByRegistrationId.put(client.getRegistration().getId(), client);
76   - //TODO: create ThingsBoard session.
  81 + }
  82 + if (client.getSession() != null) {
  83 + client.refreshSessionId(nodeId);
  84 + sessionManager.register(client.getSession());
  85 + updated = true;
  86 + }
  87 + if (updated) {
  88 + clientStore.put(client);
77 89 }
78 90 }
79 91 return client;
... ... @@ -81,15 +93,15 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
81 93 }
82 94
83 95 @Override
84   - public Optional<TransportProtos.SessionInfoProto> register(LwM2mClient lwM2MClient, Registration registration) throws LwM2MClientStateException {
  96 + public Optional<TransportProtos.SessionInfoProto> register(LwM2mClient client, Registration registration) throws LwM2MClientStateException {
85 97 TransportProtos.SessionInfoProto oldSession = null;
86   - lwM2MClient.lock();
  98 + client.lock();
87 99 try {
88   - if (LwM2MClientState.UNREGISTERED.equals(lwM2MClient.getState())) {
89   - throw new LwM2MClientStateException(lwM2MClient.getState(), "Client is in invalid state.");
  100 + if (LwM2MClientState.UNREGISTERED.equals(client.getState())) {
  101 + throw new LwM2MClientStateException(client.getState(), "Client is in invalid state.");
90 102 }
91   - oldSession = lwM2MClient.getSession();
92   - TbLwM2MSecurityInfo securityInfo = securityStore.getTbLwM2MSecurityInfoByEndpoint(lwM2MClient.getEndpoint());
  103 + oldSession = client.getSession();
  104 + TbLwM2MSecurityInfo securityInfo = securityStore.getTbLwM2MSecurityInfoByEndpoint(client.getEndpoint());
93 105 if (securityInfo.getSecurityMode() != null) {
94 106 if (SecurityMode.X509.equals(securityInfo.getSecurityMode())) {
95 107 securityStore.registerX509(registration.getEndpoint(), registration.getId());
... ... @@ -97,57 +109,57 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
97 109 if (securityInfo.getDeviceProfile() != null) {
98 110 profileUpdate(securityInfo.getDeviceProfile());
99 111 if (securityInfo.getSecurityInfo() != null) {
100   - lwM2MClient.init(securityInfo.getMsg(), UUID.randomUUID());
  112 + client.init(securityInfo.getMsg(), UUID.randomUUID());
101 113 } else if (NO_SEC.equals(securityInfo.getSecurityMode())) {
102   - lwM2MClient.init(securityInfo.getMsg(), UUID.randomUUID());
  114 + client.init(securityInfo.getMsg(), UUID.randomUUID());
103 115 } else {
104   - throw new RuntimeException(String.format("Registration failed: device %s not found.", lwM2MClient.getEndpoint()));
  116 + throw new RuntimeException(String.format("Registration failed: device %s not found.", client.getEndpoint()));
105 117 }
106 118 } else {
107   - throw new RuntimeException(String.format("Registration failed: device %s not found.", lwM2MClient.getEndpoint()));
  119 + throw new RuntimeException(String.format("Registration failed: device %s not found.", client.getEndpoint()));
108 120 }
109 121 } else {
110   - throw new RuntimeException(String.format("Registration failed: FORBIDDEN, endpointId: %s", lwM2MClient.getEndpoint()));
  122 + throw new RuntimeException(String.format("Registration failed: FORBIDDEN, endpointId: %s", client.getEndpoint()));
111 123 }
112   - lwM2MClient.setRegistration(registration);
113   - this.lwM2mClientsByRegistrationId.put(registration.getId(), lwM2MClient);
114   - lwM2MClient.setState(LwM2MClientState.REGISTERED);
115   - clientStore.put(lwM2MClient);
  124 + client.setRegistration(registration);
  125 + this.lwM2mClientsByRegistrationId.put(registration.getId(), client);
  126 + client.setState(LwM2MClientState.REGISTERED);
  127 + clientStore.put(client);
116 128 } finally {
117   - lwM2MClient.unlock();
  129 + client.unlock();
118 130 }
119 131 return Optional.ofNullable(oldSession);
120 132 }
121 133
122 134 @Override
123   - public void updateRegistration(LwM2mClient lwM2MClient, Registration registration) throws LwM2MClientStateException {
124   - lwM2MClient.lock();
  135 + public void updateRegistration(LwM2mClient client, Registration registration) throws LwM2MClientStateException {
  136 + client.lock();
125 137 try {
126   - if (!LwM2MClientState.REGISTERED.equals(lwM2MClient.getState())) {
127   - throw new LwM2MClientStateException(lwM2MClient.getState(), "Client is in invalid state.");
  138 + if (!LwM2MClientState.REGISTERED.equals(client.getState())) {
  139 + throw new LwM2MClientStateException(client.getState(), "Client is in invalid state.");
128 140 }
129   - lwM2MClient.setRegistration(registration);
130   - clientStore.put(lwM2MClient);
  141 + client.setRegistration(registration);
  142 + clientStore.put(client);
131 143 } finally {
132   - lwM2MClient.unlock();
  144 + client.unlock();
133 145 }
134 146 }
135 147
136 148 @Override
137   - public void unregister(LwM2mClient lwM2MClient, Registration registration) throws LwM2MClientStateException {
138   - lwM2MClient.lock();
  149 + public void unregister(LwM2mClient client, Registration registration) throws LwM2MClientStateException {
  150 + client.lock();
139 151 try {
140   - if (!LwM2MClientState.REGISTERED.equals(lwM2MClient.getState())) {
141   - throw new LwM2MClientStateException(lwM2MClient.getState(), "Client is in invalid state.");
  152 + if (!LwM2MClientState.REGISTERED.equals(client.getState())) {
  153 + throw new LwM2MClientStateException(client.getState(), "Client is in invalid state.");
142 154 }
143 155 lwM2mClientsByRegistrationId.remove(registration.getId());
144   - Registration currentRegistration = lwM2MClient.getRegistration();
  156 + Registration currentRegistration = client.getRegistration();
145 157 if (currentRegistration.getId().equals(registration.getId())) {
146   - lwM2MClient.setState(LwM2MClientState.UNREGISTERED);
147   - lwM2mClientsByEndpoint.remove(lwM2MClient.getEndpoint());
148   - this.securityStore.remove(lwM2MClient.getEndpoint(), registration.getId());
149   - clientStore.remove(lwM2MClient.getEndpoint());
150   - UUID profileId = lwM2MClient.getProfileId();
  158 + client.setState(LwM2MClientState.UNREGISTERED);
  159 + lwM2mClientsByEndpoint.remove(client.getEndpoint());
  160 + this.securityStore.remove(client.getEndpoint(), registration.getId());
  161 + clientStore.remove(client.getEndpoint());
  162 + UUID profileId = client.getProfileId();
151 163 if (profileId != null) {
152 164 Optional<LwM2mClient> otherClients = lwM2mClientsByRegistrationId.values().stream().filter(e -> e.getProfileId().equals(profileId)).findFirst();
153 165 if (otherClients.isEmpty()) {
... ... @@ -155,19 +167,19 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
155 167 }
156 168 }
157 169 } else {
158   - throw new LwM2MClientStateException(lwM2MClient.getState(), "Client has different registration.");
  170 + throw new LwM2MClientStateException(client.getState(), "Client has different registration.");
159 171 }
160 172 } finally {
161   - lwM2MClient.unlock();
  173 + client.unlock();
162 174 }
163 175 }
164 176
165 177 @Override
166 178 public LwM2mClient getClientBySessionInfo(TransportProtos.SessionInfoProto sessionInfo) {
167 179 LwM2mClient lwM2mClient = null;
  180 + UUID sessionId = new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB());
168 181 Predicate<LwM2mClient> isClientFilter = c ->
169   - (new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()))
170   - .equals((new UUID(c.getSession().getSessionIdMSB(), c.getSession().getSessionIdLSB())));
  182 + sessionId.equals((new UUID(c.getSession().getSessionIdMSB(), c.getSession().getSessionIdLSB())));
171 183 if (this.lwM2mClientsByEndpoint.size() > 0) {
172 184 lwM2mClient = this.lwM2mClientsByEndpoint.values().stream().filter(isClientFilter).findAny().orElse(null);
173 185 }
... ... @@ -175,19 +187,17 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
175 187 lwM2mClient = this.lwM2mClientsByRegistrationId.values().stream().filter(isClientFilter).findAny().orElse(null);
176 188 }
177 189 if (lwM2mClient == null) {
178   - log.warn("Device TimeOut? lwM2mClient is null.");
179   - log.warn("SessionInfo input [{}], lwM2mClientsByEndpoint size: [{}] lwM2mClientsByRegistrationId: [{}]", sessionInfo, lwM2mClientsByEndpoint.values(), lwM2mClientsByRegistrationId.values());
180   - log.error("", new RuntimeException());
  190 + log.error("[{}] Failed to lookup client by session id.", sessionId);
181 191 }
182 192 return lwM2mClient;
183 193 }
184 194
185 195 @Override
186   - public String getObjectIdByKeyNameFromProfile(LwM2mClient lwM2mClient, String keyName) {
187   - Lwm2mDeviceProfileTransportConfiguration profile = getProfile(lwM2mClient.getProfileId());
  196 + public String getObjectIdByKeyNameFromProfile(LwM2mClient client, String keyName) {
  197 + Lwm2mDeviceProfileTransportConfiguration profile = getProfile(client.getProfileId());
188 198
189 199 return profile.getObserveAttr().getKeyName().entrySet().stream()
190   - .filter(e -> e.getValue().equals(keyName) && validateResourceInModel(lwM2mClient, e.getKey(), false)).findFirst().orElseThrow(
  200 + .filter(e -> e.getValue().equals(keyName) && validateResourceInModel(client, e.getKey(), false)).findFirst().orElseThrow(
191 201 () -> new IllegalArgumentException(keyName + " is not configured in the device profile!")
192 202 ).getKey();
193 203 }
... ... @@ -205,6 +215,16 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
205 215 }
206 216
207 217 @Override
  218 + public void update(LwM2mClient client) {
  219 + client.lock();
  220 + try {
  221 + clientStore.put(client);
  222 + } finally {
  223 + client.unlock();
  224 + }
  225 + }
  226 +
  227 + @Override
208 228 public Collection<LwM2mClient> getLwM2mClients() {
209 229 return lwM2mClientsByEndpoint.values();
210 230 }
... ... @@ -221,9 +241,9 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
221 241
222 242 @Override
223 243 public Lwm2mDeviceProfileTransportConfiguration profileUpdate(DeviceProfile deviceProfile) {
224   - Lwm2mDeviceProfileTransportConfiguration lwM2MClientProfile = LwM2mTransportUtil.toLwM2MClientProfile(deviceProfile);
225   - profiles.put(deviceProfile.getUuidId(), lwM2MClientProfile);
226   - return lwM2MClientProfile;
  244 + Lwm2mDeviceProfileTransportConfiguration clientProfile = LwM2mTransportUtil.toLwM2MClientProfile(deviceProfile);
  245 + profiles.put(deviceProfile.getUuidId(), clientProfile);
  246 + return clientProfile;
227 247 }
228 248
229 249 @Override
... ...
... ... @@ -52,6 +52,7 @@ import org.thingsboard.server.transport.lwm2m.server.ota.firmware.FirmwareUpdate
52 52 import org.thingsboard.server.transport.lwm2m.server.ota.software.LwM2MSoftwareUpdateStrategy;
53 53 import org.thingsboard.server.transport.lwm2m.server.ota.software.SoftwareUpdateResult;
54 54 import org.thingsboard.server.transport.lwm2m.server.ota.software.SoftwareUpdateState;
  55 +import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MClientOtaInfoStore;
55 56 import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler;
56 57
57 58 import javax.annotation.PostConstruct;
... ... @@ -123,6 +124,7 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
123 124 private final OtaPackageDataCache otaPackageDataCache;
124 125 private final LwM2MTelemetryLogService logService;
125 126 private final LwM2mTransportServerHelper helper;
  127 + private final TbLwM2MClientOtaInfoStore otaInfoStore;
126 128
127 129 @Autowired
128 130 @Lazy
... ... @@ -174,6 +176,7 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
174 176 }, throwable -> {
175 177 if (fwInfo.isSupported()) {
176 178 fwInfo.setTargetFetchFailure(true);
  179 + update(fwInfo);
177 180 }
178 181 }, executor);
179 182 }
... ... @@ -191,6 +194,7 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
191 194 public void onTargetFirmwareUpdate(LwM2mClient client, String newFirmwareTitle, String newFirmwareVersion, Optional<String> newFirmwareUrl) {
192 195 LwM2MClientOtaInfo fwInfo = getOrInitFwInfo(client);
193 196 fwInfo.updateTarget(newFirmwareTitle, newFirmwareVersion, newFirmwareUrl);
  197 + update(fwInfo);
194 198 startFirmwareUpdateIfNeeded(client, fwInfo);
195 199 }
196 200
... ... @@ -202,7 +206,7 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
202 206 }
203 207
204 208 @Override
205   - public void onCurrentFirmwareStrategyUpdate(LwM2mClient client, OtherConfiguration configuration) {
  209 + public void onFirmwareStrategyUpdate(LwM2mClient client, OtherConfiguration configuration) {
206 210 log.debug("[{}] Current fw strategy: {}", client.getEndpoint(), configuration.getFwUpdateStrategy());
207 211 LwM2MClientOtaInfo fwInfo = getOrInitFwInfo(client);
208 212 fwInfo.setFwStrategy(LwM2MFirmwareUpdateStrategy.fromStrategyFwByCode(configuration.getFwUpdateStrategy()));
... ... @@ -242,9 +246,10 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
242 246 executeFwUpdate(client);
243 247 }
244 248 fwInfo.setUpdateState(state);
245   - Optional<OtaPackageUpdateStatus> status = this.toOtaPackageUpdateStatus(state);
  249 + Optional<OtaPackageUpdateStatus> status = toOtaPackageUpdateStatus(state);
246 250 status.ifPresent(otaStatus -> sendStateUpdateToTelemetry(client, fwInfo,
247 251 otaStatus, "Firmware Update State: " + state.name()));
  252 + update(fwInfo);
248 253 }
249 254
250 255 @Override
... ... @@ -252,15 +257,16 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
252 257 log.debug("[{}] Current fw result: {}", client.getEndpoint(), code);
253 258 LwM2MClientOtaInfo fwInfo = getOrInitFwInfo(client);
254 259 FirmwareUpdateResult result = FirmwareUpdateResult.fromUpdateResultFwByCode(code.intValue());
255   - Optional<OtaPackageUpdateStatus> status = this.toOtaPackageUpdateStatus(result);
  260 + Optional<OtaPackageUpdateStatus> status = toOtaPackageUpdateStatus(result);
256 261 status.ifPresent(otaStatus -> sendStateUpdateToTelemetry(client, fwInfo,
257 262 otaStatus, "Firmware Update Result: " + result.name()));
258 263 if (result.isAgain() && fwInfo.getRetryAttempts() <= 2) {
259 264 fwInfo.setRetryAttempts(fwInfo.getRetryAttempts() + 1);
260 265 startFirmwareUpdateIfNeeded(client, fwInfo);
261 266 } else {
262   - fwInfo.setUpdateResult(result);
  267 + fwInfo.update(result);
263 268 }
  269 + update(fwInfo);
264 270 }
265 271
266 272 @Override
... ... @@ -378,23 +384,38 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
378 384 }
379 385
380 386 public LwM2MClientOtaInfo getOrInitFwInfo(LwM2mClient client) {
381   - //TODO: fetch state from the cache or DB.
382 387 return this.fwStates.computeIfAbsent(client.getEndpoint(), endpoint -> {
383   - var profile = clientContext.getProfile(client.getProfileId());
384   - return new LwM2MClientOtaInfo(endpoint, OtaPackageType.FIRMWARE, profile.getClientLwM2mSettings().getFwUpdateStrategy(),
385   - profile.getClientLwM2mSettings().getFwUpdateResource());
  388 + LwM2MClientOtaInfo info = otaInfoStore.get(OtaPackageType.FIRMWARE, endpoint);
  389 + if (info == null) {
  390 + var profile = clientContext.getProfile(client.getProfileId());
  391 + info = new LwM2MClientOtaInfo(endpoint, OtaPackageType.FIRMWARE,
  392 + LwM2MFirmwareUpdateStrategy.fromStrategyFwByCode(profile.getClientLwM2mSettings().getFwUpdateStrategy()),
  393 + profile.getClientLwM2mSettings().getFwUpdateResource());
  394 + update(info);
  395 + }
  396 + return info;
386 397 });
387 398 }
388 399
389 400 private LwM2MClientOtaInfo getOrInitSwInfo(LwM2mClient client) {
390   - //TODO: fetch state from the cache or DB.
391   - return swStates.computeIfAbsent(client.getEndpoint(), endpoint -> {
392   - var profile = clientContext.getProfile(client.getProfileId());
393   - return new LwM2MClientOtaInfo(endpoint, OtaPackageType.SOFTWARE, profile.getClientLwM2mSettings().getSwUpdateStrategy(), profile.getClientLwM2mSettings().getSwUpdateResource());
  401 + return this.fwStates.computeIfAbsent(client.getEndpoint(), endpoint -> {
  402 + LwM2MClientOtaInfo info = otaInfoStore.get(OtaPackageType.SOFTWARE, endpoint);
  403 + if (info == null) {
  404 + var profile = clientContext.getProfile(client.getProfileId());
  405 + info = new LwM2MClientOtaInfo(endpoint, OtaPackageType.SOFTWARE,
  406 + LwM2MSoftwareUpdateStrategy.fromStrategySwByCode(profile.getClientLwM2mSettings().getFwUpdateStrategy()),
  407 + profile.getClientLwM2mSettings().getSwUpdateResource());
  408 + update(info);
  409 + }
  410 + return info;
394 411 });
395 412
396 413 }
397 414
  415 + private void update(LwM2MClientOtaInfo info) {
  416 + otaInfoStore.put(info);
  417 + }
  418 +
398 419 private void sendStateUpdateToTelemetry(LwM2mClient client, LwM2MClientOtaInfo fwInfo, OtaPackageUpdateStatus status, String log) {
399 420 List<TransportProtos.KeyValueProto> result = new ArrayList<>();
400 421 TransportProtos.KeyValueProto.Builder kvProto = TransportProtos.KeyValueProto.newBuilder().setKey(getAttributeKey(fwInfo.getType(), STATE));
... ...
... ... @@ -15,7 +15,9 @@
15 15 */
16 16 package org.thingsboard.server.transport.lwm2m.server.ota;
17 17
  18 +import com.fasterxml.jackson.annotation.JsonIgnore;
18 19 import lombok.Data;
  20 +import lombok.NoArgsConstructor;
19 21 import org.thingsboard.server.common.data.StringUtils;
20 22 import org.thingsboard.server.common.data.ota.OtaPackageType;
21 23 import org.thingsboard.server.transport.lwm2m.server.ota.firmware.LwM2MFirmwareUpdateStrategy;
... ... @@ -26,10 +28,11 @@ import org.thingsboard.server.transport.lwm2m.server.ota.software.LwM2MSoftwareU
26 28 import java.util.Optional;
27 29
28 30 @Data
  31 +@NoArgsConstructor
29 32 public class LwM2MClientOtaInfo {
30 33
31   - private final String endpoint;
32   - private final OtaPackageType type;
  34 + private String endpoint;
  35 + private OtaPackageType type;
33 36
34 37 private String baseUrl;
35 38
... ... @@ -53,10 +56,17 @@ public class LwM2MClientOtaInfo {
53 56 private String failedPackageId;
54 57 private int retryAttempts;
55 58
56   - public LwM2MClientOtaInfo(String endpoint, OtaPackageType type, Integer strategyCode, String baseUrl) {
  59 + public LwM2MClientOtaInfo(String endpoint, OtaPackageType type, LwM2MFirmwareUpdateStrategy fwStrategy, String baseUrl) {
57 60 this.endpoint = endpoint;
58 61 this.type = type;
59   - this.fwStrategy = LwM2MFirmwareUpdateStrategy.fromStrategyFwByCode(strategyCode);
  62 + this.fwStrategy = fwStrategy;
  63 + this.baseUrl = baseUrl;
  64 + }
  65 +
  66 + public LwM2MClientOtaInfo(String endpoint, OtaPackageType type, LwM2MSoftwareUpdateStrategy swStrategy, String baseUrl) {
  67 + this.endpoint = endpoint;
  68 + this.type = type;
  69 + this.swStrategy = swStrategy;
60 70 this.baseUrl = baseUrl;
61 71 }
62 72
... ... @@ -66,6 +76,7 @@ public class LwM2MClientOtaInfo {
66 76 this.targetUrl = newFirmwareUrl.orElse(null);
67 77 }
68 78
  79 + @JsonIgnore
69 80 public boolean isUpdateRequired() {
70 81 if (StringUtils.isEmpty(targetName) || StringUtils.isEmpty(targetVersion) || !isSupported()) {
71 82 return false;
... ... @@ -86,11 +97,12 @@ public class LwM2MClientOtaInfo {
86 97 }
87 98 }
88 99
  100 + @JsonIgnore
89 101 public boolean isSupported() {
90 102 return StringUtils.isNotEmpty(currentName) || StringUtils.isNotEmpty(currentVersion5) || StringUtils.isNotEmpty(currentVersion3);
91 103 }
92 104
93   - public void setUpdateResult(FirmwareUpdateResult updateResult) {
  105 + public void update(FirmwareUpdateResult updateResult) {
94 106 this.updateResult = updateResult;
95 107 switch (updateResult) {
96 108 case INITIAL:
... ...
... ... @@ -32,7 +32,7 @@ public interface LwM2MOtaUpdateService {
32 32
33 33 void onCurrentFirmwareNameUpdate(LwM2mClient client, String name);
34 34
35   - void onCurrentFirmwareStrategyUpdate(LwM2mClient client, OtherConfiguration configuration);
  35 + void onFirmwareStrategyUpdate(LwM2mClient client, OtherConfiguration configuration);
36 36
37 37 void onCurrentSoftwareStrategyUpdate(LwM2mClient client, OtherConfiguration configuration);
38 38
... ...
  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.session;
  17 +
  18 +import lombok.extern.slf4j.Slf4j;
  19 +import org.springframework.context.annotation.Lazy;
  20 +import org.springframework.stereotype.Service;
  21 +import org.thingsboard.server.common.transport.TransportService;
  22 +import org.thingsboard.server.common.transport.service.DefaultTransportService;
  23 +import org.thingsboard.server.gen.transport.TransportProtos;
  24 +import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
  25 +import org.thingsboard.server.transport.lwm2m.server.LwM2mSessionMsgListener;
  26 +import org.thingsboard.server.transport.lwm2m.server.attributes.LwM2MAttributesService;
  27 +import org.thingsboard.server.transport.lwm2m.server.rpc.LwM2MRpcRequestHandler;
  28 +import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler;
  29 +
  30 +@Slf4j
  31 +@Service
  32 +@TbLwM2mTransportComponent
  33 +public class DefaultLwM2MSessionManager implements LwM2MSessionManager {
  34 +
  35 + private final TransportService transportService;
  36 + private final LwM2MAttributesService attributesService;
  37 + private final LwM2MRpcRequestHandler rpcHandler;
  38 + private final LwM2mUplinkMsgHandler uplinkHandler;
  39 +
  40 + public DefaultLwM2MSessionManager(TransportService transportService,
  41 + @Lazy LwM2MAttributesService attributesService,
  42 + @Lazy LwM2MRpcRequestHandler rpcHandler,
  43 + @Lazy LwM2mUplinkMsgHandler uplinkHandler) {
  44 + this.transportService = transportService;
  45 + this.attributesService = attributesService;
  46 + this.rpcHandler = rpcHandler;
  47 + this.uplinkHandler = uplinkHandler;
  48 + }
  49 +
  50 + @Override
  51 + public void register(TransportProtos.SessionInfoProto sessionInfo) {
  52 + transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(uplinkHandler, attributesService, rpcHandler, sessionInfo, transportService));
  53 + TransportProtos.TransportToDeviceActorMsg msg = TransportProtos.TransportToDeviceActorMsg.newBuilder()
  54 + .setSessionInfo(sessionInfo)
  55 + .setSessionEvent(DefaultTransportService.getSessionEventMsg(TransportProtos.SessionEvent.OPEN))
  56 + .setSubscribeToAttributes(TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().setSessionType(TransportProtos.SessionType.ASYNC).build())
  57 + .setSubscribeToRPC(TransportProtos.SubscribeToRPCMsg.newBuilder().setSessionType(TransportProtos.SessionType.ASYNC).build())
  58 + .build();
  59 + transportService.process(msg, null);
  60 + }
  61 +
  62 + @Override
  63 + public void deregister(TransportProtos.SessionInfoProto sessionInfo) {
  64 + transportService.process(sessionInfo, DefaultTransportService.getSessionEventMsg(TransportProtos.SessionEvent.CLOSED), null);
  65 + transportService.deregisterSession(sessionInfo);
  66 + }
  67 +}
... ...
  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.session;
  17 +
  18 +import org.thingsboard.server.gen.transport.TransportProtos;
  19 +
  20 +public interface LwM2MSessionManager {
  21 +
  22 + void register(TransportProtos.SessionInfoProto sessionInfo);
  23 +
  24 + void deregister(TransportProtos.SessionInfoProto sessionInfo);
  25 +
  26 +
  27 +}
... ...
  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.thingsboard.server.common.data.ota.OtaPackageType;
  19 +import org.thingsboard.server.transport.lwm2m.server.ota.LwM2MClientOtaInfo;
  20 +
  21 +public class TbDummyLwM2MClientOtaInfoStore implements TbLwM2MClientOtaInfoStore {
  22 +
  23 + @Override
  24 + public LwM2MClientOtaInfo get(OtaPackageType type, String endpoint) {
  25 + return null;
  26 + }
  27 +
  28 + @Override
  29 + public void put(LwM2MClientOtaInfo info) {
  30 +
  31 + }
  32 +}
... ...
  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 + */
1 16 package org.thingsboard.server.transport.lwm2m.server.store;
2 17
3 18 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
... ...
  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.thingsboard.server.common.data.ota.OtaPackageType;
  19 +import org.thingsboard.server.transport.lwm2m.server.ota.LwM2MClientOtaInfo;
  20 +
  21 +public interface TbLwM2MClientOtaInfoStore {
  22 +
  23 + LwM2MClientOtaInfo get(OtaPackageType type, String endpoint);
  24 +
  25 + void put(LwM2MClientOtaInfo info);
  26 +}
... ...
  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 + */
1 16 package org.thingsboard.server.transport.lwm2m.server.store;
2 17
3 18 import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
... ...
  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.security.NonUniqueSecurityInfoException;
  19 +import org.eclipse.leshan.server.security.SecurityInfo;
  20 +import org.nustaq.serialization.FSTConfiguration;
  21 +import org.springframework.data.redis.connection.RedisConnectionFactory;
  22 +import org.springframework.integration.redis.util.RedisLockRegistry;
  23 +import org.thingsboard.common.util.JacksonUtil;
  24 +import org.thingsboard.server.common.data.ota.OtaPackageType;
  25 +import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo;
  26 +import org.thingsboard.server.transport.lwm2m.server.ota.LwM2MClientOtaInfo;
  27 +
  28 +import java.util.concurrent.locks.Lock;
  29 +
  30 +public class TbLwM2mRedisClientOtaInfoStore implements TbLwM2MClientOtaInfoStore {
  31 + private static final String OTA_EP = "OTA#EP#";
  32 +
  33 + private final RedisConnectionFactory connectionFactory;
  34 +
  35 + public TbLwM2mRedisClientOtaInfoStore(RedisConnectionFactory connectionFactory) {
  36 + this.connectionFactory = connectionFactory;
  37 + }
  38 +
  39 + @Override
  40 + public LwM2MClientOtaInfo get(OtaPackageType type, String endpoint) {
  41 + try (var connection = connectionFactory.getConnection()) {
  42 + byte[] data = connection.get((OTA_EP + type + endpoint).getBytes());
  43 + return JacksonUtil.fromBytes(data, LwM2MClientOtaInfo.class);
  44 + }
  45 + }
  46 +
  47 + @Override
  48 + public void put(LwM2MClientOtaInfo info) {
  49 + try (var connection = connectionFactory.getConnection()) {
  50 + connection.set((OTA_EP + info.getType() + info.getEndpoint()).getBytes(), JacksonUtil.toString(info).getBytes());
  51 + }
  52 + }
  53 +
  54 +}
... ...
... ... @@ -5,7 +5,7 @@
5 5 * you may not use this file except in compliance with the License.
6 6 * You may obtain a copy of the License at
7 7 *
8   - * http://www.apache.org/licenses/LICENSE-2.0
  8 + * http://www.apache.org/licenses/LICENSE-2.0
9 9 *
10 10 * Unless required by applicable law or agreed to in writing, software
11 11 * distributed under the License is distributed on an "AS IS" BASIS,
... ... @@ -20,6 +20,7 @@ import org.eclipse.leshan.server.californium.registration.InMemoryRegistrationSt
20 20 import org.springframework.beans.factory.annotation.Autowired;
21 21 import org.springframework.beans.factory.annotation.Value;
22 22 import org.springframework.context.annotation.Bean;
  23 +import org.springframework.data.redis.connection.RedisConnectionFactory;
23 24 import org.springframework.stereotype.Component;
24 25 import org.thingsboard.server.cache.TBRedisCacheConfiguration;
25 26 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
... ... @@ -46,14 +47,14 @@ public class TbLwM2mStoreFactory {
46 47
47 48 @Bean
48 49 private CaliforniumRegistrationStore registrationStore() {
49   - return redisConfiguration.isPresent() && useRedis ?
50   - new TbLwM2mRedisRegistrationStore(redisConfiguration.get().redisConnectionFactory()) : new InMemoryRegistrationStore(config.getCleanPeriodInSec());
  50 + return isRedis() ?
  51 + new TbLwM2mRedisRegistrationStore(getConnectionFactory()) : new InMemoryRegistrationStore(config.getCleanPeriodInSec());
51 52 }
52 53
53 54 @Bean
54 55 private TbMainSecurityStore securityStore() {
55   - return new TbLwM2mSecurityStore(redisConfiguration.isPresent() && useRedis ?
56   - new TbLwM2mRedisSecurityStore(redisConfiguration.get().redisConnectionFactory()) : new TbInMemorySecurityStore(), validator);
  56 + return new TbLwM2mSecurityStore(isRedis() ?
  57 + new TbLwM2mRedisSecurityStore(getConnectionFactory()) : new TbInMemorySecurityStore(), validator);
57 58 }
58 59
59 60 @Bean
... ... @@ -62,9 +63,21 @@ public class TbLwM2mStoreFactory {
62 63 }
63 64
64 65 @Bean
  66 + private TbLwM2MClientOtaInfoStore otaStore() {
  67 + return isRedis() ? new TbLwM2mRedisClientOtaInfoStore(getConnectionFactory()) : new TbDummyLwM2MClientOtaInfoStore();
  68 + }
  69 +
  70 + @Bean
65 71 private TbLwM2MDtlsSessionStore sessionStore() {
66   - return redisConfiguration.isPresent() && useRedis ?
67   - new TbLwM2MDtlsSessionRedisStore(redisConfiguration.get().redisConnectionFactory()) : new TbL2M2MDtlsSessionInMemoryStore();
  72 + return isRedis() ? new TbLwM2MDtlsSessionRedisStore(getConnectionFactory()) : new TbL2M2MDtlsSessionInMemoryStore();
  73 + }
  74 +
  75 + private RedisConnectionFactory getConnectionFactory() {
  76 + return redisConfiguration.get().redisConnectionFactory();
  77 + }
  78 +
  79 + private boolean isRedis() {
  80 + return redisConfiguration.isPresent() && useRedis;
68 81 }
69 82
70 83 }
... ...
... ... @@ -5,7 +5,7 @@
5 5 * you may not use this file except in compliance with the License.
6 6 * You may obtain a copy of the License at
7 7 *
8   - * http://www.apache.org/licenses/LICENSE-2.0
  8 + * http://www.apache.org/licenses/LICENSE-2.0
9 9 *
10 10 * Unless required by applicable law or agreed to in writing, software
11 11 * distributed under the License is distributed on an "AS IS" BASIS,
... ... @@ -48,15 +48,11 @@ import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTrans
48 48 import org.thingsboard.server.common.data.ota.OtaPackageUtil;
49 49 import org.thingsboard.server.common.transport.TransportService;
50 50 import org.thingsboard.server.common.transport.TransportServiceCallback;
51   -import org.thingsboard.server.common.transport.service.DefaultTransportService;
52 51 import org.thingsboard.server.gen.transport.TransportProtos;
53   -import org.thingsboard.server.gen.transport.TransportProtos.SessionEvent;
54 52 import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto;
55 53 import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
56 54 import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
57 55 import org.thingsboard.server.transport.lwm2m.server.LwM2mOtaConvert;
58   -import org.thingsboard.server.transport.lwm2m.server.LwM2mQueuedRequest;
59   -import org.thingsboard.server.transport.lwm2m.server.LwM2mSessionMsgListener;
60 56 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext;
61 57 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper;
62 58 import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil;
... ... @@ -84,6 +80,7 @@ import org.thingsboard.server.transport.lwm2m.server.downlink.TbLwM2MWriteAttrib
84 80 import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogService;
85 81 import org.thingsboard.server.transport.lwm2m.server.ota.LwM2MOtaUpdateService;
86 82 import org.thingsboard.server.transport.lwm2m.server.rpc.LwM2MRpcRequestHandler;
  83 +import org.thingsboard.server.transport.lwm2m.server.session.LwM2MSessionManager;
87 84 import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MDtlsSessionStore;
88 85 import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;
89 86
... ... @@ -129,6 +126,7 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
129 126 private final TransportService transportService;
130 127 private final LwM2mTransportContext context;
131 128 private final LwM2MAttributesService attributesService;
  129 + private final LwM2MSessionManager sessionManager;
132 130 private final LwM2MOtaUpdateService otaService;
133 131 private final LwM2MTransportServerConfig config;
134 132 private final LwM2MTelemetryLogService logService;
... ... @@ -143,12 +141,14 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
143 141 LwM2mTransportServerHelper helper,
144 142 LwM2mClientContext clientContext,
145 143 LwM2MTelemetryLogService logService,
  144 + LwM2MSessionManager sessionManager,
146 145 @Lazy LwM2MOtaUpdateService otaService,
147 146 @Lazy LwM2MAttributesService attributesService,
148 147 @Lazy LwM2MRpcRequestHandler rpcHandler,
149 148 @Lazy LwM2mDownlinkMsgHandler defaultLwM2MDownlinkMsgHandler,
150 149 LwM2mTransportContext context, TbLwM2MDtlsSessionStore sessionStore) {
151 150 this.transportService = transportService;
  151 + this.sessionManager = sessionManager;
152 152 this.attributesService = attributesService;
153 153 this.otaService = otaService;
154 154 this.config = config;
... ... @@ -205,18 +205,10 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
205 205 Optional<SessionInfoProto> oldSessionInfo = this.clientContext.register(lwM2MClient, registration);
206 206 if (oldSessionInfo.isPresent()) {
207 207 log.info("[{}] Closing old session: {}", registration.getEndpoint(), new UUID(oldSessionInfo.get().getSessionIdMSB(), oldSessionInfo.get().getSessionIdLSB()));
208   - closeSession(oldSessionInfo.get());
  208 + sessionManager.deregister(oldSessionInfo.get());
209 209 }
210 210 logService.log(lwM2MClient, LOG_LWM2M_INFO + ": Client registered with registration id: " + registration.getId());
211   - SessionInfoProto sessionInfo = lwM2MClient.getSession();
212   - transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(this, attributesService, rpcHandler, sessionInfo, transportService));
213   - TransportProtos.TransportToDeviceActorMsg msg = TransportProtos.TransportToDeviceActorMsg.newBuilder()
214   - .setSessionInfo(sessionInfo)
215   - .setSessionEvent(DefaultTransportService.getSessionEventMsg(SessionEvent.OPEN))
216   - .setSubscribeToAttributes(TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().setSessionType(TransportProtos.SessionType.ASYNC).build())
217   - .setSubscribeToRPC(TransportProtos.SubscribeToRPCMsg.newBuilder().setSessionType(TransportProtos.SessionType.ASYNC).build())
218   - .build();
219   - transportService.process(msg, null);
  211 + sessionManager.register(lwM2MClient.getSession());
220 212 this.initClientTelemetry(lwM2MClient);
221 213 this.initAttributes(lwM2MClient);
222 214 otaService.init(lwM2MClient);
... ... @@ -273,7 +265,7 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
273 265 clientContext.unregister(client, registration);
274 266 SessionInfoProto sessionInfo = client.getSession();
275 267 if (sessionInfo != null) {
276   - closeSession(sessionInfo);
  268 + sessionManager.deregister(sessionInfo);
277 269 sessionStore.remove(registration.getEndpoint());
278 270 log.info("Client close session: [{}] unReg [{}] name [{}] profile ", registration.getId(), registration.getEndpoint(), sessionInfo.getDeviceType());
279 271 } else {
... ... @@ -288,11 +280,6 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
288 280 });
289 281 }
290 282
291   - public void closeSession(SessionInfoProto sessionInfo) {
292   - transportService.process(sessionInfo, DefaultTransportService.getSessionEventMsg(SessionEvent.CLOSED), null);
293   - transportService.deregisterSession(sessionInfo);
294   - }
295   -
296 283 @Override
297 284 public void onSleepingDev(Registration registration) {
298 285 log.info("[{}] [{}] Received endpoint Sleeping version event", registration.getId(), registration.getEndpoint());
... ... @@ -300,19 +287,6 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
300 287 //TODO: associate endpointId with device information.
301 288 }
302 289
303   -// /**
304   -// * Cancel observation for All objects for this registration
305   -// */
306   -// @Override
307   -// public void setCancelObservationsAll(Registration registration) {
308   -// if (registration != null) {
309   -// LwM2mClient client = clientContext.getClientByEndpoint(registration.getEndpoint());
310   -// if (client != null && client.getRegistration() != null && client.getRegistration().getId().equals(registration.getId())) {
311   -// defaultLwM2MDownlinkMsgHandler.sendCancelAllRequest(client, TbLwM2MCancelAllRequest.builder().build(), new TbLwM2MCancelAllObserveRequestCallback(this, client));
312   -// }
313   -// }
314   -// }
315   -
316 290 /**
317 291 * Sending observe value to thingsboard from ObservationListener.onResponse: object, instance, SingleResource or MultipleResource
318 292 *
... ... @@ -337,6 +311,7 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
337 311 this.updateResourcesValue(lwM2MClient, lwM2mResource, path);
338 312 }
339 313 }
  314 + clientContext.update(lwM2MClient);
340 315 }
341 316 }
342 317
... ... @@ -376,16 +351,6 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
376 351 }
377 352
378 353 /**
379   - * Deregister session in transport
380   - *
381   - * @param sessionInfo - lwm2m client
382   - */
383   - @Override
384   - public void doDisconnect(SessionInfoProto sessionInfo) {
385   - closeSession(sessionInfo);
386   - }
387   -
388   - /**
389 354 * Those methods are called by the protocol stage thread pool, this means that execution MUST be done in a short delay,
390 355 * * if you need to do long time processing use a dedicated thread pool.
391 356 *
... ... @@ -479,14 +444,6 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
479 444 attributesMap.forEach((targetId, params) -> sendWriteAttributesRequest(lwM2MClient, targetId, params));
480 445 }
481 446
482   - private void sendDiscoverRequests(LwM2mClient lwM2MClient, Lwm2mDeviceProfileTransportConfiguration profile, Set<String> supportedObjects) {
483   - Set<String> targetIds = profile.getObserveAttr().getAttributeLwm2m().keySet();
484   - targetIds = targetIds.stream().filter(target -> isSupportedTargetId(supportedObjects, target)).collect(Collectors.toSet());
485   -// TODO: why do we need to put observe into pending read requests?
486   -// lwM2MClient.getPendingReadRequests().addAll(targetIds);
487   - targetIds.forEach(targetId -> sendDiscoverRequest(lwM2MClient, targetId));
488   - }
489   -
490 447 private void sendDiscoverRequest(LwM2mClient lwM2MClient, String targetId) {
491 448 TbLwM2MDiscoverRequest request = TbLwM2MDiscoverRequest.builder().versionedId(targetId).timeout(this.config.getTimeout()).build();
492 449 defaultLwM2MDownlinkMsgHandler.sendDiscoverRequest(lwM2MClient, request, new TbLwM2MDiscoverCallback(logService, lwM2MClient, targetId));
... ... @@ -637,7 +594,7 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
637 594 List<TransportProtos.KeyValueProto> resultAttributes = new ArrayList<>();
638 595 profile.getObserveAttr().getAttribute().forEach(pathIdVer -> {
639 596 if (path.contains(pathIdVer)) {
640   - TransportProtos.KeyValueProto kvAttr = this.getKvToThingsboard(pathIdVer, registration);
  597 + TransportProtos.KeyValueProto kvAttr = this.getKvToThingsBoard(pathIdVer, registration);
641 598 if (kvAttr != null) {
642 599 resultAttributes.add(kvAttr);
643 600 }
... ... @@ -646,7 +603,7 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
646 603 List<TransportProtos.KeyValueProto> resultTelemetries = new ArrayList<>();
647 604 profile.getObserveAttr().getTelemetry().forEach(pathIdVer -> {
648 605 if (path.contains(pathIdVer)) {
649   - TransportProtos.KeyValueProto kvAttr = this.getKvToThingsboard(pathIdVer, registration);
  606 + TransportProtos.KeyValueProto kvAttr = this.getKvToThingsBoard(pathIdVer, registration);
650 607 if (kvAttr != null) {
651 608 resultTelemetries.add(kvAttr);
652 609 }
... ... @@ -663,7 +620,7 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
663 620 return null;
664 621 }
665 622
666   - private TransportProtos.KeyValueProto getKvToThingsboard(String pathIdVer, Registration registration) {
  623 + private TransportProtos.KeyValueProto getKvToThingsBoard(String pathIdVer, Registration registration) {
667 624 LwM2mClient lwM2MClient = this.clientContext.getClientByEndpoint(registration.getEndpoint());
668 625 Map<String, String> names = clientContext.getProfile(lwM2MClient.getProfileId()).getObserveAttr().getKeyName();
669 626 if (names != null && names.containsKey(pathIdVer)) {
... ... @@ -710,10 +667,12 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
710 667 public void onWriteResponseOk(LwM2mClient client, String path, WriteRequest request) {
711 668 if (request.getNode() instanceof LwM2mResource) {
712 669 this.updateResourcesValue(client, ((LwM2mResource) request.getNode()), path);
  670 + clientContext.update(client);
713 671 } else if (request.getNode() instanceof LwM2mObjectInstance) {
714 672 ((LwM2mObjectInstance) request.getNode()).getResources().forEach((resId, resource) -> {
715 673 this.updateResourcesValue(client, resource, path + "/" + resId);
716 674 });
  675 + clientContext.update(client);
717 676 }
718 677 }
719 678
... ... @@ -788,7 +747,7 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
788 747 if (!newLwM2mSettings.getFwUpdateStrategy().equals(oldLwM2mSettings.getFwUpdateStrategy())
789 748 || (StringUtils.isNotEmpty(newLwM2mSettings.getFwUpdateResource()) &&
790 749 !newLwM2mSettings.getFwUpdateResource().equals(oldLwM2mSettings.getFwUpdateResource()))) {
791   - clients.forEach(lwM2MClient -> otaService.onCurrentFirmwareStrategyUpdate(lwM2MClient, newLwM2mSettings));
  750 + clients.forEach(lwM2MClient -> otaService.onFirmwareStrategyUpdate(lwM2MClient, newLwM2mSettings));
792 751 }
793 752
794 753 if (!newLwM2mSettings.getSwUpdateStrategy().equals(oldLwM2mSettings.getSwUpdateStrategy())
... ... @@ -893,7 +852,7 @@ public class DefaultLwM2MUplinkMsgHandler extends LwM2MExecutorAwareService impl
893 852 */
894 853 private void reportActivityAndRegister(SessionInfoProto sessionInfo) {
895 854 if (sessionInfo != null && transportService.reportActivity(sessionInfo) == null) {
896   - transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(this, attributesService, rpcHandler, sessionInfo, transportService));
  855 + sessionManager.register(sessionInfo);
897 856 this.reportActivitySubscription(sessionInfo);
898 857 }
899 858 }
... ...
... ... @@ -48,8 +48,6 @@ public interface LwM2mUplinkMsgHandler {
48 48
49 49 void onResourceDelete(Optional<TransportProtos.ResourceDeleteMsg> resourceDeleteMsgOpt);
50 50
51   - void doDisconnect(TransportProtos.SessionInfoProto sessionInfo);
52   -
53 51 void onAwakeDev(Registration registration);
54 52
55 53 void onWriteResponseOk(LwM2mClient client, String path, WriteRequest request);
... ...
... ... @@ -47,7 +47,7 @@ public class JacksonUtil {
47 47 throw new IllegalArgumentException("The given object value: "
48 48 + fromValue + " cannot be converted to " + toValueTypeRef, e);
49 49 }
50   - }
  50 + }
51 51
52 52 public static <T> T fromString(String string, Class<T> clazz) {
53 53 try {
... ... @@ -67,6 +67,15 @@ public class JacksonUtil {
67 67 }
68 68 }
69 69
  70 + public static <T> T fromBytes(byte[] bytes, Class<T> clazz) {
  71 + try {
  72 + return bytes != null ? OBJECT_MAPPER.readValue(bytes, clazz) : null;
  73 + } catch (IOException e) {
  74 + throw new IllegalArgumentException("The given string value: "
  75 + + Arrays.toString(bytes) + " cannot be transformed to Json object", e);
  76 + }
  77 + }
  78 +
70 79 public static JsonNode fromBytes(byte[] bytes) {
71 80 try {
72 81 return OBJECT_MAPPER.readTree(bytes);
... ... @@ -96,7 +105,7 @@ public class JacksonUtil {
96 105 }
97 106 }
98 107
99   - public static ObjectNode newObjectNode(){
  108 + public static ObjectNode newObjectNode() {
100 109 return OBJECT_MAPPER.createObjectNode();
101 110 }
102 111
... ...