diff --git a/application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java b/application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java index d042fb2657..c8925f9ee9 100644 --- a/application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java +++ b/application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java @@ -258,8 +258,7 @@ public class DeviceBulkImportService extends AbstractBulkImportService { Lwm2mDeviceProfileTransportConfiguration transportConfiguration = new Lwm2mDeviceProfileTransportConfiguration(); transportConfiguration.setBootstrap(Collections.emptyList()); - transportConfiguration.setClientLwM2mSettings(new OtherConfiguration(false,1, 1, 1, PowerMode.DRX, null, null, null, null, null, V1_0.toString())); - transportConfiguration.setObserveAttr(new TelemetryMappingConfiguration(Collections.emptyMap(), Collections.emptySet(), Collections.emptySet(), Collections.emptySet(), Collections.emptyMap(), SINGLE)); + transportConfiguration.setClientLwM2mSettings(new OtherConfiguration()); DeviceProfileData deviceProfileData = new DeviceProfileData(); DefaultDeviceProfileConfiguration configuration = new DefaultDeviceProfileConfiguration(); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/AbstractOtaLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/AbstractOtaLwM2MIntegrationTest.java index cff56694e5..e9dd427f7f 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/AbstractOtaLwM2MIntegrationTest.java +++ b/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.Optional; import java.util.UUID; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; +import static org.awaitility.Awaitility.await; import static org.junit.Assert.assertEquals; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 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 { + await("await on Read") + .atMost(TIMEOUT*2, TimeUnit.SECONDS) + .until(() -> Boolean.valueOf(sendRPCById(resourceIdVer))); String actualResult = sendRPCById(resourceIdVer); ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); assertEquals(ResponseCode.CONTENT.getName(), rpcActualResult.get("result").asText()); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/Lwm2mDeviceProfileTransportConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/Lwm2mDeviceProfileTransportConfiguration.java index 614da6cde6..e58ed8c04a 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/Lwm2mDeviceProfileTransportConfiguration.java +++ b/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 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.TelemetryMappingConfiguration; 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; @Data @@ -33,9 +38,18 @@ public class Lwm2mDeviceProfileTransportConfiguration implements DeviceProfileTr private List bootstrap; private OtherConfiguration clientLwM2mSettings; + public Lwm2mDeviceProfileTransportConfiguration() { + updateDefault(); + } + @Override public DeviceTransportType getType() { 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)); + } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java index 4cf8d825b9..36cf1639db 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java +++ b/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 public Lwm2mDeviceProfileTransportConfiguration getProfile(Registration registration) { UUID profileId = getClientByEndpoint(registration.getEndpoint()).getProfileId(); - return doGetAndCache(profileId); + return profileId != null ? doGetAndCache(profileId) : null; } private Lwm2mDeviceProfileTransportConfiguration doGetAndCache(UUID profileId) { - - Lwm2mDeviceProfileTransportConfiguration result = profiles.get(profileId); - if (result == null) { - log.debug("Fetching profile [{}]", profileId); - DeviceProfile deviceProfile = deviceProfileCache.get(new DeviceProfileId(profileId)); - if (deviceProfile != null) { - result = profileUpdate(deviceProfile); - } else { - log.warn("Device profile was not found! Most probably device profile [{}] has been removed from the database.", profileId); + Lwm2mDeviceProfileTransportConfiguration result; + if (profileId != null) { + result = profiles.get(profileId); + if (result == null) { + log.debug("Fetching profile [{}]", profileId); + DeviceProfile deviceProfile = deviceProfileCache.get(new DeviceProfileId(profileId)); + if (deviceProfile != null) { + result = profileUpdate(deviceProfile); + } 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; } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java index 79f077a71e..325f1e2280 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java +++ b/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(); - initFwStrategy(client, clientSettings); - initSwStrategy(client, clientSettings); - - if (!attributesToFetch.isEmpty()) { - var future = attributesService.getSharedAttributes(client, attributesToFetch); - DonAsynchron.withCallback(future, attrs -> { - if (fwInfo.isSupported()) { - Optional newFwTitle = getAttributeValue(attrs, FIRMWARE_TITLE); - Optional newFwVersion = getAttributeValue(attrs, FIRMWARE_VERSION); - Optional newFwTag = getAttributeValue(attrs, FIRMWARE_TAG); - Optional 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 (clientSettings != null) { + initFwStrategy(client, clientSettings); + initSwStrategy(client, clientSettings); + + + if (!attributesToFetch.isEmpty()) { + var future = attributesService.getSharedAttributes(client, attributesToFetch); + DonAsynchron.withCallback(future, attrs -> { + if (fwInfo.isSupported()) { + Optional newFwTitle = getAttributeValue(attrs, FIRMWARE_TITLE); + Optional newFwVersion = getAttributeValue(attrs, FIRMWARE_VERSION); + Optional newFwTag = getAttributeValue(attrs, FIRMWARE_TAG); + Optional 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()) { - Optional newSwTitle = getAttributeValue(attrs, SOFTWARE_TITLE); - Optional newSwVersion = getAttributeValue(attrs, SOFTWARE_VERSION); - Optional newSwTag = getAttributeValue(attrs, SOFTWARE_TAG); - Optional newSwUrl = getAttributeValue(attrs, SOFTWARE_URL); - if (newSwTitle.isPresent() && newSwVersion.isPresent()) { - onTargetSoftwareUpdate(client, newSwTitle.get(), newSwVersion.get(), newSwUrl, newSwTag); + if (swInfo.isSupported()) { + Optional newSwTitle = getAttributeValue(attrs, SOFTWARE_TITLE); + Optional newSwVersion = getAttributeValue(attrs, SOFTWARE_VERSION); + Optional newSwTag = getAttributeValue(attrs, SOFTWARE_TAG); + Optional newSwUrl = getAttributeValue(attrs, SOFTWARE_URL); + if (newSwTitle.isPresent() && newSwVersion.isPresent()) { + onTargetSoftwareUpdate(client, newSwTitle.get(), newSwVersion.get(), newSwUrl, newSwTag); + } } - } - }, throwable -> { - if (fwInfo.isSupported()) { - update(fwInfo); - } - }, executor); + + }, throwable -> { + if (fwInfo.isSupported()) { + update(fwInfo); + } + }, executor); + } } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisRegistrationStore.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisRegistrationStore.java index df432732b2..3c9828af22 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisRegistrationStore.java +++ b/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); for (byte[] endpoint : endpointsExpired) { - Registration r = deserializeReg(connection.get(toEndpointKey(endpoint))); - if (!r.isAlive(gracePeriod)) { - Deregistration dereg = removeRegistration(connection, r.getId(), true); - if (dereg != null) - expirationListener.registrationExpired(dereg.getRegistration(), dereg.getObservations()); + byte[] data = connection.get(toEndpointKey(endpoint)); + if (data != null && data.length > 0) { + Registration r = deserializeReg(data); + if (!r.isAlive(gracePeriod)) { + Deregistration dereg = removeRegistration(connection, r.getId(), true); + if (dereg != null) + expirationListener.registrationExpired(dereg.getRegistration(), dereg.getObservations()); + } } } } catch (Exception e) { diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java index 79b9d4481a..5e27b936f3 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java +++ b/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) { Lwm2mDeviceProfileTransportConfiguration profile = clientContext.getProfile(lwM2MClient.getRegistration()); - Set supportedObjects = clientContext.getSupportedIdVerInClient(lwM2MClient); - if (supportedObjects != null && supportedObjects.size() > 0) { - this.sendReadRequests(lwM2MClient, profile, supportedObjects); - this.sendInitObserveRequests(lwM2MClient, profile, supportedObjects); - this.sendWriteAttributeRequests(lwM2MClient, profile, supportedObjects); + if (profile != null) { + Set supportedObjects = clientContext.getSupportedIdVerInClient(lwM2MClient); + if (supportedObjects != null && !supportedObjects.isEmpty()) { + this.sendInitObserveRequests(lwM2MClient, profile, supportedObjects); + this.sendReadRequests(lwM2MClient, profile, supportedObjects); + this.sendWriteAttributeRequests(lwM2MClient, profile, supportedObjects); // Removed. Used only for debug. // 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 clients, Lwm2mDeviceProfileTransportConfiguration oldProfile, Lwm2mDeviceProfileTransportConfiguration newProfile) { + private void updateValueOta(List clients, Lwm2mDeviceProfileTransportConfiguration newProfile, Lwm2mDeviceProfileTransportConfiguration oldProfile) { OtherConfiguration newLwM2mSettings = newProfile.getClientLwM2mSettings(); OtherConfiguration oldLwM2mSettings = oldProfile.getClientLwM2mSettings(); if (!newLwM2mSettings.getFwUpdateStrategy().equals(oldLwM2mSettings.getFwUpdateStrategy()) @@ -1098,6 +1103,9 @@ public class DefaultLwM2mUplinkMsgHandler extends LwM2MExecutorAwareService impl v -> attributesService.onAttributesUpdate(lwM2MClient, v, logFailedUpdateOfNonChangedValue), t -> log.error("[{}] Failed to get attributes", lwM2MClient.getEndpoint(), t), 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 getNamesFromProfileForSharedAttributes(LwM2mClient lwM2MClient) { Lwm2mDeviceProfileTransportConfiguration profile = clientContext.getProfile(lwM2MClient.getRegistration()); - return profile.getObserveAttr().getKeyName(); + return profile != null ? profile.getObserveAttr().getKeyName() : Collections.emptyMap(); } public LwM2MTransportServerConfig getConfig() {