Browse Source

Merge pull request #14403 from thingsboard/lwm2m_fix_bug_null_point_profileleid_after_sleep_lts

LwM2M: fixed NPE after reboot if sleep
pull/14587/head
Viacheslav Klimov 6 months ago
committed by GitHub
parent
commit
8becf055db
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 3
      application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java
  2. 5
      application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/AbstractOtaLwM2MIntegrationTest.java
  3. 14
      common/data/src/main/java/org/thingsboard/server/common/data/device/profile/Lwm2mDeviceProfileTransportConfiguration.java
  4. 25
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java
  5. 58
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java
  6. 13
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisRegistrationStore.java
  7. 22
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java

3
application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java

@ -258,8 +258,7 @@ public class DeviceBulkImportService extends AbstractBulkImportService<Device> {
Lwm2mDeviceProfileTransportConfiguration transportConfiguration = new Lwm2mDeviceProfileTransportConfiguration(); Lwm2mDeviceProfileTransportConfiguration transportConfiguration = new Lwm2mDeviceProfileTransportConfiguration();
transportConfiguration.setBootstrap(Collections.emptyList()); transportConfiguration.setBootstrap(Collections.emptyList());
transportConfiguration.setClientLwM2mSettings(new OtherConfiguration(false,1, 1, 1, PowerMode.DRX, null, null, null, null, null, V1_0.toString())); transportConfiguration.setClientLwM2mSettings(new OtherConfiguration());
transportConfiguration.setObserveAttr(new TelemetryMappingConfiguration(Collections.emptyMap(), Collections.emptySet(), Collections.emptySet(), Collections.emptySet(), Collections.emptyMap(), SINGLE));
DeviceProfileData deviceProfileData = new DeviceProfileData(); DeviceProfileData deviceProfileData = new DeviceProfileData();
DefaultDeviceProfileConfiguration configuration = new DefaultDeviceProfileConfiguration(); DefaultDeviceProfileConfiguration configuration = new DefaultDeviceProfileConfiguration();

5
application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/AbstractOtaLwM2MIntegrationTest.java

@ -37,8 +37,10 @@ import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.awaitility.Awaitility.await;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.thingsboard.rest.client.utils.RestJsonConverter.toTimeseries; import static org.thingsboard.rest.client.utils.RestJsonConverter.toTimeseries;
@ -249,6 +251,9 @@ public abstract class AbstractOtaLwM2MIntegrationTest extends AbstractLwM2MInteg
} }
protected void resultReadOtaParams_19(String resourceIdVer, OtaPackageInfo otaPackageInfo) throws Exception { protected void resultReadOtaParams_19(String resourceIdVer, OtaPackageInfo otaPackageInfo) throws Exception {
await("await on Read")
.atMost(TIMEOUT*2, TimeUnit.SECONDS)
.until(() -> Boolean.valueOf(sendRPCById(resourceIdVer)));
String actualResult = sendRPCById(resourceIdVer); String actualResult = sendRPCById(resourceIdVer);
ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
assertEquals(ResponseCode.CONTENT.getName(), rpcActualResult.get("result").asText()); assertEquals(ResponseCode.CONTENT.getName(), rpcActualResult.get("result").asText());

14
common/data/src/main/java/org/thingsboard/server/common/data/device/profile/Lwm2mDeviceProfileTransportConfiguration.java

@ -17,10 +17,15 @@ package org.thingsboard.server.common.data.device.profile;
import lombok.Data; import lombok.Data;
import org.thingsboard.server.common.data.DeviceTransportType; import org.thingsboard.server.common.data.DeviceTransportType;
import org.thingsboard.server.common.data.device.data.PowerMode;
import org.thingsboard.server.common.data.device.profile.lwm2m.OtherConfiguration; import org.thingsboard.server.common.data.device.profile.lwm2m.OtherConfiguration;
import org.thingsboard.server.common.data.device.profile.lwm2m.TelemetryMappingConfiguration; import org.thingsboard.server.common.data.device.profile.lwm2m.TelemetryMappingConfiguration;
import org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap.LwM2MBootstrapServerCredential; import org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap.LwM2MBootstrapServerCredential;
import static org.eclipse.leshan.core.LwM2m.Version.V1_0;
import static org.thingsboard.server.common.data.device.profile.lwm2m.TelemetryObserveStrategy.SINGLE;
import java.util.Collections;
import java.util.List; import java.util.List;
@Data @Data
@ -33,9 +38,18 @@ public class Lwm2mDeviceProfileTransportConfiguration implements DeviceProfileTr
private List<LwM2MBootstrapServerCredential> bootstrap; private List<LwM2MBootstrapServerCredential> bootstrap;
private OtherConfiguration clientLwM2mSettings; private OtherConfiguration clientLwM2mSettings;
public Lwm2mDeviceProfileTransportConfiguration() {
updateDefault();
}
@Override @Override
public DeviceTransportType getType() { public DeviceTransportType getType() {
return DeviceTransportType.LWM2M; return DeviceTransportType.LWM2M;
} }
private void updateDefault(){
this.setBootstrap(Collections.emptyList());
this.setClientLwM2mSettings(new OtherConfiguration(false,1, 1, 1, PowerMode.DRX, null, null, null, null, null, V1_0.toString()));
this.setObserveAttr(new TelemetryMappingConfiguration(Collections.emptyMap(), Collections.emptySet(), Collections.emptySet(), Collections.emptySet(), Collections.emptyMap(), SINGLE));
}
} }

25
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java

@ -360,20 +360,25 @@ public class LwM2mClientContextImpl implements LwM2mClientContext {
@Override @Override
public Lwm2mDeviceProfileTransportConfiguration getProfile(Registration registration) { public Lwm2mDeviceProfileTransportConfiguration getProfile(Registration registration) {
UUID profileId = getClientByEndpoint(registration.getEndpoint()).getProfileId(); UUID profileId = getClientByEndpoint(registration.getEndpoint()).getProfileId();
return doGetAndCache(profileId); return profileId != null ? doGetAndCache(profileId) : null;
} }
private Lwm2mDeviceProfileTransportConfiguration doGetAndCache(UUID profileId) { private Lwm2mDeviceProfileTransportConfiguration doGetAndCache(UUID profileId) {
Lwm2mDeviceProfileTransportConfiguration result;
Lwm2mDeviceProfileTransportConfiguration result = profiles.get(profileId); if (profileId != null) {
if (result == null) { result = profiles.get(profileId);
log.debug("Fetching profile [{}]", profileId); if (result == null) {
DeviceProfile deviceProfile = deviceProfileCache.get(new DeviceProfileId(profileId)); log.debug("Fetching profile [{}]", profileId);
if (deviceProfile != null) { DeviceProfile deviceProfile = deviceProfileCache.get(new DeviceProfileId(profileId));
result = profileUpdate(deviceProfile); if (deviceProfile != null) {
} else { result = profileUpdate(deviceProfile);
log.warn("Device profile was not found! Most probably device profile [{}] has been removed from the database.", profileId); } else {
log.warn("Device profile was not found! Most probably device profile [{}] has been removed from the database.", profileId);
}
} }
} else {
log.warn("Device profile not found! The device profile ID is null. Return Lwm2mDeviceProfileTransportConfiguration with default.");
result = new Lwm2mDeviceProfileTransportConfiguration();
} }
return result; return result;
} }

58
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java

@ -201,35 +201,39 @@ public class DefaultLwM2MOtaUpdateService extends LwM2MExecutorAwareService impl
} }
var clientSettings = clientContext.getProfile(client.getRegistration()).getClientLwM2mSettings(); var clientSettings = clientContext.getProfile(client.getRegistration()).getClientLwM2mSettings();
initFwStrategy(client, clientSettings); if (clientSettings != null) {
initSwStrategy(client, clientSettings); initFwStrategy(client, clientSettings);
initSwStrategy(client, clientSettings);
if (!attributesToFetch.isEmpty()) {
var future = attributesService.getSharedAttributes(client, attributesToFetch);
DonAsynchron.withCallback(future, attrs -> { if (!attributesToFetch.isEmpty()) {
if (fwInfo.isSupported()) { var future = attributesService.getSharedAttributes(client, attributesToFetch);
Optional<String> newFwTitle = getAttributeValue(attrs, FIRMWARE_TITLE); DonAsynchron.withCallback(future, attrs -> {
Optional<String> newFwVersion = getAttributeValue(attrs, FIRMWARE_VERSION); if (fwInfo.isSupported()) {
Optional<String> newFwTag = getAttributeValue(attrs, FIRMWARE_TAG); Optional<String> newFwTitle = getAttributeValue(attrs, FIRMWARE_TITLE);
Optional<String> newFwUrl = getAttributeValue(attrs, FIRMWARE_URL); Optional<String> newFwVersion = getAttributeValue(attrs, FIRMWARE_VERSION);
if (newFwTitle.isPresent() && newFwVersion.isPresent() && !isOtaDownloading(client) && !UPDATING.equals(fwInfo.status)) { Optional<String> newFwTag = getAttributeValue(attrs, FIRMWARE_TAG);
onTargetFirmwareUpdate(client, newFwTitle.get(), newFwVersion.get(), newFwUrl, newFwTag); Optional<String> newFwUrl = getAttributeValue(attrs, FIRMWARE_URL);
if (newFwTitle.isPresent() && newFwVersion.isPresent() && !isOtaDownloading(client) && !UPDATING.equals(fwInfo.status)) {
onTargetFirmwareUpdate(client, newFwTitle.get(), newFwVersion.get(), newFwUrl, newFwTag);
}
} }
} if (swInfo.isSupported()) {
if (swInfo.isSupported()) { Optional<String> newSwTitle = getAttributeValue(attrs, SOFTWARE_TITLE);
Optional<String> newSwTitle = getAttributeValue(attrs, SOFTWARE_TITLE); Optional<String> newSwVersion = getAttributeValue(attrs, SOFTWARE_VERSION);
Optional<String> newSwVersion = getAttributeValue(attrs, SOFTWARE_VERSION); Optional<String> newSwTag = getAttributeValue(attrs, SOFTWARE_TAG);
Optional<String> newSwTag = getAttributeValue(attrs, SOFTWARE_TAG); Optional<String> newSwUrl = getAttributeValue(attrs, SOFTWARE_URL);
Optional<String> newSwUrl = getAttributeValue(attrs, SOFTWARE_URL); if (newSwTitle.isPresent() && newSwVersion.isPresent()) {
if (newSwTitle.isPresent() && newSwVersion.isPresent()) { onTargetSoftwareUpdate(client, newSwTitle.get(), newSwVersion.get(), newSwUrl, newSwTag);
onTargetSoftwareUpdate(client, newSwTitle.get(), newSwVersion.get(), newSwUrl, newSwTag); }
} }
}
}, throwable -> { }, throwable -> {
if (fwInfo.isSupported()) { if (fwInfo.isSupported()) {
update(fwInfo); update(fwInfo);
} }
}, executor); }, executor);
}
} }
} }

13
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisRegistrationStore.java

@ -750,11 +750,14 @@ public class TbLwM2mRedisRegistrationStore implements RegistrationStore, Startab
System.currentTimeMillis(), 0, cleanLimit); System.currentTimeMillis(), 0, cleanLimit);
for (byte[] endpoint : endpointsExpired) { for (byte[] endpoint : endpointsExpired) {
Registration r = deserializeReg(connection.get(toEndpointKey(endpoint))); byte[] data = connection.get(toEndpointKey(endpoint));
if (!r.isAlive(gracePeriod)) { if (data != null && data.length > 0) {
Deregistration dereg = removeRegistration(connection, r.getId(), true); Registration r = deserializeReg(data);
if (dereg != null) if (!r.isAlive(gracePeriod)) {
expirationListener.registrationExpired(dereg.getRegistration(), dereg.getObservations()); Deregistration dereg = removeRegistration(connection, r.getId(), true);
if (dereg != null)
expirationListener.registrationExpired(dereg.getRegistration(), dereg.getObservations());
}
} }
} }
} catch (Exception e) { } catch (Exception e) {

22
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java

@ -484,13 +484,18 @@ public class DefaultLwM2mUplinkMsgHandler extends LwM2MExecutorAwareService impl
*/ */
private void initClientTelemetry(LwM2mClient lwM2MClient) { private void initClientTelemetry(LwM2mClient lwM2MClient) {
Lwm2mDeviceProfileTransportConfiguration profile = clientContext.getProfile(lwM2MClient.getRegistration()); Lwm2mDeviceProfileTransportConfiguration profile = clientContext.getProfile(lwM2MClient.getRegistration());
Set<String> supportedObjects = clientContext.getSupportedIdVerInClient(lwM2MClient); if (profile != null) {
if (supportedObjects != null && supportedObjects.size() > 0) { Set<String> supportedObjects = clientContext.getSupportedIdVerInClient(lwM2MClient);
this.sendReadRequests(lwM2MClient, profile, supportedObjects); if (supportedObjects != null && !supportedObjects.isEmpty()) {
this.sendInitObserveRequests(lwM2MClient, profile, supportedObjects); this.sendInitObserveRequests(lwM2MClient, profile, supportedObjects);
this.sendWriteAttributeRequests(lwM2MClient, profile, supportedObjects); this.sendReadRequests(lwM2MClient, profile, supportedObjects);
this.sendWriteAttributeRequests(lwM2MClient, profile, supportedObjects);
// Removed. Used only for debug. // Removed. Used only for debug.
// this.sendDiscoverRequests(lwM2MClient, profile, supportedObjects); // this.sendDiscoverRequests(lwM2MClient, profile, supportedObjects);
}
} else {
log.warn("[{}] Failed to process initClientTelemetry! Profile is null. Update procedure may not have completed after reboot yet", lwM2MClient.getEndpoint());
logService.log(lwM2MClient, "Failed to process initClientTelemetry. Profile is null. Update procedure may not have completed after reboot yet");
} }
} }
@ -1016,7 +1021,7 @@ public class DefaultLwM2mUplinkMsgHandler extends LwM2MExecutorAwareService impl
}); });
} }
private void updateValueOta(List<LwM2mClient> clients, Lwm2mDeviceProfileTransportConfiguration oldProfile, Lwm2mDeviceProfileTransportConfiguration newProfile) { private void updateValueOta(List<LwM2mClient> clients, Lwm2mDeviceProfileTransportConfiguration newProfile, Lwm2mDeviceProfileTransportConfiguration oldProfile) {
OtherConfiguration newLwM2mSettings = newProfile.getClientLwM2mSettings(); OtherConfiguration newLwM2mSettings = newProfile.getClientLwM2mSettings();
OtherConfiguration oldLwM2mSettings = oldProfile.getClientLwM2mSettings(); OtherConfiguration oldLwM2mSettings = oldProfile.getClientLwM2mSettings();
if (!newLwM2mSettings.getFwUpdateStrategy().equals(oldLwM2mSettings.getFwUpdateStrategy()) if (!newLwM2mSettings.getFwUpdateStrategy().equals(oldLwM2mSettings.getFwUpdateStrategy())
@ -1098,6 +1103,9 @@ public class DefaultLwM2mUplinkMsgHandler extends LwM2MExecutorAwareService impl
v -> attributesService.onAttributesUpdate(lwM2MClient, v, logFailedUpdateOfNonChangedValue), v -> attributesService.onAttributesUpdate(lwM2MClient, v, logFailedUpdateOfNonChangedValue),
t -> log.error("[{}] Failed to get attributes", lwM2MClient.getEndpoint(), t), t -> log.error("[{}] Failed to get attributes", lwM2MClient.getEndpoint(), t),
executor); executor);
} else {
log.warn("[{}] Failed to process initAttributes! Profile is null. Update procedure may not have completed after reboot yet", lwM2MClient.getEndpoint());
logService.log(lwM2MClient, "Failed to process initAttributes. Profile is null. Update procedure may not have completed after reboot yet");
} }
} }
@ -1107,7 +1115,7 @@ public class DefaultLwM2mUplinkMsgHandler extends LwM2MExecutorAwareService impl
private Map<String, String> getNamesFromProfileForSharedAttributes(LwM2mClient lwM2MClient) { private Map<String, String> getNamesFromProfileForSharedAttributes(LwM2mClient lwM2MClient) {
Lwm2mDeviceProfileTransportConfiguration profile = clientContext.getProfile(lwM2MClient.getRegistration()); Lwm2mDeviceProfileTransportConfiguration profile = clientContext.getProfile(lwM2MClient.getRegistration());
return profile.getObserveAttr().getKeyName(); return profile != null ? profile.getObserveAttr().getKeyName() : Collections.emptyMap();
} }
public LwM2MTransportServerConfig getConfig() { public LwM2MTransportServerConfig getConfig() {

Loading…
Cancel
Save