Merge pull request #12398 from thingsboard/fix_bug_lwm2m_profile_update_dynamic
fix bug: lwm2m update Observe dynamically and between connections
This commit is contained in:
commit
f4b5c4321b
@ -359,7 +359,7 @@ public class DeviceProfileEdgeTest extends AbstractEdgeTest {
|
|||||||
transportConfiguration.setBootstrapServerUpdateEnable(true);
|
transportConfiguration.setBootstrapServerUpdateEnable(true);
|
||||||
|
|
||||||
TelemetryMappingConfiguration observeAttrConfiguration =
|
TelemetryMappingConfiguration observeAttrConfiguration =
|
||||||
JacksonUtil.fromString(AbstractLwM2MIntegrationTest.OBSERVE_ATTRIBUTES_WITH_PARAMS, TelemetryMappingConfiguration.class);
|
JacksonUtil.fromString(AbstractLwM2MIntegrationTest.TELEMETRY_WITHOUT_OBSERVE, TelemetryMappingConfiguration.class);
|
||||||
transportConfiguration.setObserveAttr(observeAttrConfiguration);
|
transportConfiguration.setObserveAttr(observeAttrConfiguration);
|
||||||
|
|
||||||
List<LwM2MBootstrapServerCredential> bootstrap = new ArrayList<>();
|
List<LwM2MBootstrapServerCredential> bootstrap = new ArrayList<>();
|
||||||
|
|||||||
@ -147,8 +147,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte
|
|||||||
" \"telemetry\": [],\n" +
|
" \"telemetry\": [],\n" +
|
||||||
" \"attributeLwm2m\": {}\n" +
|
" \"attributeLwm2m\": {}\n" +
|
||||||
" }";
|
" }";
|
||||||
public static String OBSERVE_ATTRIBUTES_WITH_PARAMS =
|
public static String TELEMETRY_WITHOUT_OBSERVE =
|
||||||
|
|
||||||
" {\n" +
|
" {\n" +
|
||||||
" \"keyName\": {\n" +
|
" \"keyName\": {\n" +
|
||||||
" \"/3_1.2/0/9\": \"batteryLevel\"\n" +
|
" \"/3_1.2/0/9\": \"batteryLevel\"\n" +
|
||||||
@ -161,6 +160,39 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte
|
|||||||
" ],\n" +
|
" ],\n" +
|
||||||
" \"attributeLwm2m\": {}\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" +
|
||||||
|
" ],\n" +
|
||||||
|
" \"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 =
|
public static final String CLIENT_LWM2M_SETTINGS =
|
||||||
" {\n" +
|
" {\n" +
|
||||||
@ -217,7 +249,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte
|
|||||||
LwM2MDeviceCredentials deviceCredentials,
|
LwM2MDeviceCredentials deviceCredentials,
|
||||||
String endpoint,
|
String endpoint,
|
||||||
boolean queueMode) throws Exception {
|
boolean queueMode) throws Exception {
|
||||||
Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITH_PARAMS, getBootstrapServerCredentialsNoSec(NONE));
|
Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(TELEMETRY_WITHOUT_OBSERVE, getBootstrapServerCredentialsNoSec(NONE));
|
||||||
DeviceProfile deviceProfile = createLwm2mDeviceProfile("profileFor" + endpoint, transportConfiguration);
|
DeviceProfile deviceProfile = createLwm2mDeviceProfile("profileFor" + endpoint, transportConfiguration);
|
||||||
Device device = createLwm2mDevice(deviceCredentials, endpoint, deviceProfile.getId());
|
Device device = createLwm2mDevice(deviceCredentials, endpoint, deviceProfile.getId());
|
||||||
|
|
||||||
|
|||||||
@ -458,6 +458,12 @@ public class LwM2MTestClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void stop(boolean deregister) {
|
||||||
|
if (leshanClient != null) {
|
||||||
|
leshanClient.stop(deregister);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void awaitClientAfterStartConnectLw() {
|
private void awaitClientAfterStartConnectLw() {
|
||||||
LwM2mClient lwM2MClient = this.clientContext.getClientByEndpoint(endpoint);
|
LwM2mClient lwM2MClient = this.clientContext.getClientByEndpoint(endpoint);
|
||||||
Mockito.doAnswer(invocationOnMock -> null).when(defaultLwM2mUplinkMsgHandlerTest).initAttributes(lwM2MClient, true);
|
Mockito.doAnswer(invocationOnMock -> null).when(defaultLwM2mUplinkMsgHandlerTest).initAttributes(lwM2MClient, true);
|
||||||
|
|||||||
@ -93,6 +93,7 @@ public class SimpleLwM2MDevice extends BaseInstanceEnabler implements Destroyabl
|
|||||||
try {
|
try {
|
||||||
executorService.scheduleWithFixedDelay(() -> {
|
executorService.scheduleWithFixedDelay(() -> {
|
||||||
fireResourceChange(9);
|
fireResourceChange(9);
|
||||||
|
fireResourceChange(20);
|
||||||
}
|
}
|
||||||
, 1, 1, TimeUnit.SECONDS); // 2 sec
|
, 1, 1, TimeUnit.SECONDS); // 2 sec
|
||||||
// , 1800000, 1800000, TimeUnit.MILLISECONDS); // 30 MIN
|
// , 1800000, 1800000, TimeUnit.MILLISECONDS); // 30 MIN
|
||||||
|
|||||||
@ -51,7 +51,7 @@ public class Ota5LwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFirmwareUpdateWithClientWithoutFirmwareOtaInfoFromProfile_IsNotSupported() throws Exception {
|
public void testFirmwareUpdateWithClientWithoutFirmwareOtaInfoFromProfile_IsNotSupported() throws Exception {
|
||||||
Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITH_PARAMS, getBootstrapServerCredentialsNoSec(NONE));
|
Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(TELEMETRY_WITHOUT_OBSERVE, getBootstrapServerCredentialsNoSec(NONE));
|
||||||
DeviceProfile deviceProfile = createLwm2mDeviceProfile("profileFor" + this.CLIENT_ENDPOINT_WITHOUT_FW_INFO, transportConfiguration);
|
DeviceProfile deviceProfile = createLwm2mDeviceProfile("profileFor" + this.CLIENT_ENDPOINT_WITHOUT_FW_INFO, transportConfiguration);
|
||||||
LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_WITHOUT_FW_INFO));
|
LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_WITHOUT_FW_INFO));
|
||||||
final Device device = createLwm2mDevice(deviceCredentials, this.CLIENT_ENDPOINT_WITHOUT_FW_INFO, deviceProfile.getId());
|
final Device device = createLwm2mDevice(deviceCredentials, this.CLIENT_ENDPOINT_WITHOUT_FW_INFO, deviceProfile.getId());
|
||||||
|
|||||||
@ -196,7 +196,7 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M
|
|||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void basicTestConnection(Security security, Security securityBs,
|
protected Device basicTestConnection(Security security, Security securityBs,
|
||||||
LwM2MDeviceCredentials deviceCredentials,
|
LwM2MDeviceCredentials deviceCredentials,
|
||||||
String endpoint,
|
String endpoint,
|
||||||
Lwm2mDeviceProfileTransportConfiguration transportConfiguration,
|
Lwm2mDeviceProfileTransportConfiguration transportConfiguration,
|
||||||
@ -227,6 +227,7 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M
|
|||||||
return lwM2MTestClient.getClientStates().contains(finishState) || lwM2MTestClient.getClientStates().contains(ON_UPDATE_SUCCESS);
|
return lwM2MTestClient.getClientStates().contains(finishState) || lwM2MTestClient.getClientStates().contains(ON_UPDATE_SUCCESS);
|
||||||
});
|
});
|
||||||
Assert.assertTrue(lwM2MTestClient.getClientStates().containsAll(expectedStatuses));
|
Assert.assertTrue(lwM2MTestClient.getClientStates().containsAll(expectedStatuses));
|
||||||
|
return device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -16,10 +16,13 @@
|
|||||||
package org.thingsboard.server.transport.lwm2m.security.sql;
|
package org.thingsboard.server.transport.lwm2m.security.sql;
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.eclipse.leshan.client.object.Security;
|
import org.eclipse.leshan.client.object.Security;
|
||||||
import org.eclipse.leshan.core.util.Hex;
|
import org.eclipse.leshan.core.util.Hex;
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.test.web.servlet.MvcResult;
|
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.DeviceProfile;
|
||||||
import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MDeviceCredentials;
|
import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MDeviceCredentials;
|
||||||
import org.thingsboard.server.common.data.device.credentials.lwm2m.PSKClientCredential;
|
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 org.thingsboard.server.transport.lwm2m.security.AbstractSecurityLwM2MIntegrationTest;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
import static org.eclipse.leshan.client.object.Security.psk;
|
import static org.eclipse.leshan.client.object.Security.psk;
|
||||||
import static org.eclipse.leshan.client.object.Security.pskBootstrap;
|
import static org.eclipse.leshan.client.object.Security.pskBootstrap;
|
||||||
import static org.junit.Assert.assertEquals;
|
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.BOTH;
|
||||||
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE;
|
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTest {
|
public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTest {
|
||||||
|
|
||||||
//Lwm2m only
|
//Lwm2m only
|
||||||
@ -66,6 +69,82 @@ public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTes
|
|||||||
ON_REGISTRATION_SUCCESS,
|
ON_REGISTRATION_SUCCESS,
|
||||||
true);
|
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
|
@Test
|
||||||
public void testWithPskConnectLwm2mBadPskKeyByLength_BAD_REQUEST() throws Exception {
|
public void testWithPskConnectLwm2mBadPskKeyByLength_BAD_REQUEST() throws Exception {
|
||||||
|
|||||||
@ -279,6 +279,7 @@ public class DefaultLwM2mUplinkMsgHandler extends LwM2MExecutorAwareService impl
|
|||||||
clientContext.unregister(client, registration);
|
clientContext.unregister(client, registration);
|
||||||
SessionInfoProto sessionInfo = client.getSession();
|
SessionInfoProto sessionInfo = client.getSession();
|
||||||
if (sessionInfo != null) {
|
if (sessionInfo != null) {
|
||||||
|
securityStore.remove(client.getEndpoint(), client.getRegistration().getId());
|
||||||
sessionManager.deregister(sessionInfo);
|
sessionManager.deregister(sessionInfo);
|
||||||
sessionStore.remove(registration.getEndpoint());
|
sessionStore.remove(registration.getEndpoint());
|
||||||
log.info("Client close session: [{}] unReg [{}] name [{}] profile ", registration.getId(), registration.getEndpoint(), sessionInfo.getDeviceType());
|
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)
|
.stream().filter(e -> e.getProfileId() != null)
|
||||||
.filter(e -> e.getProfileId().equals(deviceProfile.getUuidId())).collect(Collectors.toList());
|
.filter(e -> e.getProfileId().equals(deviceProfile.getUuidId())).collect(Collectors.toList());
|
||||||
clients.forEach(client -> {
|
clients.forEach(client -> {
|
||||||
this.securityStore.remove(client.getEndpoint(), client.getRegistration().getId());
|
|
||||||
client.onDeviceProfileUpdate(deviceProfile);
|
client.onDeviceProfileUpdate(deviceProfile);
|
||||||
});
|
});
|
||||||
if (clients.size() > 0) {
|
if (clients.size() > 0) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user