diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java index a1fb723681..065c4a2d26 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java @@ -148,13 +148,27 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte " \"attributeLwm2m\": {}\n" + " }"; public static String OBSERVE_ATTRIBUTES_WITH_PARAMS = - " {\n" + " \"keyName\": {\n" + " \"/3_1.2/0/9\": \"batteryLevel\"\n" + " },\n" + " \"observe\": [],\n" + " \"attribute\": [\n" + + " \"/3_1.2/0/9\"\n" + + " ],\n" + + " \"telemetry\": [\n" + + " ],\n" + + " \"attributeLwm2m\": {}\n" + + " }"; + public static String TELEMETRY_WITH_ONE_OBSERVE = + " {\n" + + " \"keyName\": {\n" + + " \"/3_1.2/0/9\": \"batteryLevel\"\n" + + " },\n" + + " \"observe\": [\n" + + " \"/3_1.2/0/9\"\n" + + " ],\n" + + " \"attribute\": [\n" + " ],\n" + " \"telemetry\": [\n" + " \"/3_1.2/0/9\"\n" + @@ -162,6 +176,24 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte " \"attributeLwm2m\": {}\n" + " }"; + public static String TELEMETRY_WITH_MANY_OBSERVE = + " {\n" + + " \"keyName\": {\n" + + " \"/3_1.2/0/9\": \"batteryLevel\",\n" + + " \"/3_1.2/0/20\": \"batteryStatus\"\n" + + " },\n" + + " \"observe\": [\n" + + " \"/3_1.2/0/9\",\n" + + " \"/3_1.2/0/20\"\n" + + " ],\n" + + " \"attribute\": [],\n" + + " \"telemetry\": [\n" + + " \"/3_1.2/0/9\",\n" + + " \"/3_1.2/0/20\"\n" + + " ],\n" + + " \"attributeLwm2m\": {}\n" + + " }"; + public static final String CLIENT_LWM2M_SETTINGS = " {\n" + " \"edrxCycle\": null,\n" + diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java index 387085c511..1c09825e92 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java @@ -458,6 +458,12 @@ public class LwM2MTestClient { } } + public void stop(boolean deregister) { + if (leshanClient != null) { + leshanClient.stop(deregister); + } + } + private void awaitClientAfterStartConnectLw() { LwM2mClient lwM2MClient = this.clientContext.getClientByEndpoint(endpoint); Mockito.doAnswer(invocationOnMock -> null).when(defaultLwM2mUplinkMsgHandlerTest).initAttributes(lwM2MClient, true); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/SimpleLwM2MDevice.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/SimpleLwM2MDevice.java index a6a850a897..e94a6b4822 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/SimpleLwM2MDevice.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/SimpleLwM2MDevice.java @@ -93,6 +93,7 @@ public class SimpleLwM2MDevice extends BaseInstanceEnabler implements Destroyabl try { executorService.scheduleWithFixedDelay(() -> { fireResourceChange(9); + fireResourceChange(20); } , 1, 1, TimeUnit.SECONDS); // 2 sec // , 1800000, 1800000, TimeUnit.MILLISECONDS); // 30 MIN diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java index eaade683d8..3f43c59068 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java @@ -196,7 +196,7 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M false); } - protected void basicTestConnection(Security security, Security securityBs, + protected Device basicTestConnection(Security security, Security securityBs, LwM2MDeviceCredentials deviceCredentials, String endpoint, Lwm2mDeviceProfileTransportConfiguration transportConfiguration, @@ -227,6 +227,7 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M return lwM2MTestClient.getClientStates().contains(finishState) || lwM2MTestClient.getClientStates().contains(ON_UPDATE_SUCCESS); }); Assert.assertTrue(lwM2MTestClient.getClientStates().containsAll(expectedStatuses)); + return device; } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java index ac1c0866de..42014a4a75 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java @@ -16,10 +16,13 @@ package org.thingsboard.server.transport.lwm2m.security.sql; import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; import org.eclipse.leshan.client.object.Security; import org.eclipse.leshan.core.util.Hex; +import org.junit.Assert; import org.junit.Test; import org.springframework.test.web.servlet.MvcResult; +import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MDeviceCredentials; import org.thingsboard.server.common.data.device.credentials.lwm2m.PSKClientCredential; @@ -27,7 +30,6 @@ import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTrans import org.thingsboard.server.transport.lwm2m.security.AbstractSecurityLwM2MIntegrationTest; import java.nio.charset.StandardCharsets; - import static org.eclipse.leshan.client.object.Security.psk; import static org.eclipse.leshan.client.object.Security.pskBootstrap; import static org.junit.Assert.assertEquals; @@ -37,6 +39,7 @@ import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClient import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.BOTH; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; +@Slf4j public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTest { //Lwm2m only @@ -66,6 +69,82 @@ public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTes ON_REGISTRATION_SUCCESS, true); } + @Test + public void testWithPskConnectLwm2mOneObserveSuccessUpdateProfileManyObserveUpdateRegistrationSuccess() throws Exception { + String clientEndpoint = CLIENT_ENDPOINT_PSK; + String identity = CLIENT_PSK_IDENTITY; + String keyPsk = CLIENT_PSK_KEY; + PSKClientCredential clientCredentials = new PSKClientCredential(); + clientCredentials.setEndpoint(clientEndpoint); + clientCredentials.setIdentity(identity); + clientCredentials.setKey(keyPsk); + Security security = psk(SECURE_URI, + shortServerId, + identity.getBytes(StandardCharsets.UTF_8), + Hex.decodeHex(keyPsk.toCharArray())); + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(TELEMETRY_WITH_ONE_OBSERVE, getBootstrapServerCredentialsSecure(PSK, NONE)); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, null, null, PSK, false); + String awaitAlias = "await on client state (Psk_Lwm2m)"; + Device lwm2mDevice = this.basicTestConnection(security, + null, + deviceCredentials, + clientEndpoint, + transportConfiguration, + awaitAlias, + expectedStatusesRegistrationLwm2mSuccess, + false, + ON_REGISTRATION_SUCCESS, + true); + + awaitObserveReadAll(1, lwm2mDevice.getId().getId().toString()); + DeviceProfile foundDeviceProfile = doGet("/api/deviceProfile/" + lwm2mDevice.getDeviceProfileId().getId().toString(), DeviceProfile.class); + transportConfiguration = getTransportConfiguration(TELEMETRY_WITH_MANY_OBSERVE, getBootstrapServerCredentialsSecure(PSK, NONE)); + foundDeviceProfile.getProfileData().setTransportConfiguration(transportConfiguration); + DeviceProfile lwm2mDeviceProfileManyParams = doPost("/api/deviceProfile", foundDeviceProfile, DeviceProfile.class); + Assert.assertNotNull(lwm2mDeviceProfileManyParams); + awaitObserveReadAll(2, lwm2mDevice.getId().getId().toString()); + awaitUpdateReg(3); + } + @Test + public void testWithPskConnectLwm2mSuccessObserveSuccessUnRegClientUpdateProfileObserveConnectLwm2mSuccessOWithNewObserve() throws Exception { + String clientEndpoint = CLIENT_ENDPOINT_PSK; + String identity = CLIENT_PSK_IDENTITY; + String keyPsk = CLIENT_PSK_KEY; + PSKClientCredential clientCredentials = new PSKClientCredential(); + clientCredentials.setEndpoint(clientEndpoint); + clientCredentials.setIdentity(identity); + clientCredentials.setKey(keyPsk); + Security security = psk(SECURE_URI, + shortServerId, + identity.getBytes(StandardCharsets.UTF_8), + Hex.decodeHex(keyPsk.toCharArray())); + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(TELEMETRY_WITH_ONE_OBSERVE, getBootstrapServerCredentialsSecure(PSK, NONE)); + LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, null, null, PSK, false); + String awaitAlias = "await on client state (Psk_Lwm2m)"; + Device lwm2mDevice = this.basicTestConnection(security, + null, + deviceCredentials, + clientEndpoint, + transportConfiguration, + awaitAlias, + expectedStatusesRegistrationLwm2mSuccess, + false, + ON_REGISTRATION_SUCCESS, + true); + + awaitObserveReadAll(1, lwm2mDevice.getId().getId().toString()); + lwM2MTestClient.stop(true); + + DeviceProfile foundDeviceProfile = doGet("/api/deviceProfile/" + lwm2mDevice.getDeviceProfileId().getId().toString(), DeviceProfile.class); + transportConfiguration = getTransportConfiguration(TELEMETRY_WITH_MANY_OBSERVE, getBootstrapServerCredentialsSecure(PSK, NONE)); + foundDeviceProfile.getProfileData().setTransportConfiguration(transportConfiguration); + DeviceProfile lwm2mDeviceProfileManyParams = doPost("/api/deviceProfile", foundDeviceProfile, DeviceProfile.class); + Assert.assertNotNull(lwm2mDeviceProfileManyParams); + + lwM2MTestClient.start(true); + awaitObserveReadAll(2, lwm2mDevice.getId().getId().toString()); + awaitUpdateReg(3); + } @Test public void testWithPskConnectLwm2mBadPskKeyByLength_BAD_REQUEST() throws Exception { 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 a79ed43784..d415b8c22a 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 @@ -279,6 +279,7 @@ public class DefaultLwM2mUplinkMsgHandler extends LwM2MExecutorAwareService impl clientContext.unregister(client, registration); SessionInfoProto sessionInfo = client.getSession(); if (sessionInfo != null) { + securityStore.remove(client.getEndpoint(), client.getRegistration().getId()); sessionManager.deregister(sessionInfo); sessionStore.remove(registration.getEndpoint()); log.info("Client close session: [{}] unReg [{}] name [{}] profile ", registration.getId(), registration.getEndpoint(), sessionInfo.getDeviceType()); @@ -401,7 +402,6 @@ public class DefaultLwM2mUplinkMsgHandler extends LwM2MExecutorAwareService impl .stream().filter(e -> e.getProfileId() != null) .filter(e -> e.getProfileId().equals(deviceProfile.getUuidId())).collect(Collectors.toList()); clients.forEach(client -> { - this.securityStore.remove(client.getEndpoint(), client.getRegistration().getId()); client.onDeviceProfileUpdate(deviceProfile); }); if (clients.size() > 0) {