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 fd785e9de0..5786cf985d 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 @@ -84,6 +84,7 @@ import static org.eclipse.californium.core.config.CoapConfig.COAP_PORT; import static org.eclipse.californium.core.config.CoapConfig.COAP_SECURE_PORT; import static org.eclipse.leshan.client.object.Security.noSec; import static org.eclipse.leshan.client.object.Security.noSecBootstap; +import static org.hamcrest.core.IsInstanceOf.instanceOf; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_BOOTSTRAP_STARTED; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_BOOTSTRAP_SUCCESS; @@ -235,7 +236,11 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest Assert.assertEquals(device.getId(), eData.get(0).getEntityId()); Assert.assertNotNull(eData.get(0).getLatest().get(EntityKeyType.TIME_SERIES)); var tsValue = eData.get(0).getLatest().get(EntityKeyType.TIME_SERIES).get("batteryLevel"); - Assert.assertEquals(42, Long.parseLong(tsValue.getValue())); + Assert.assertThat(Long.parseLong(tsValue.getValue()), instanceOf(Long.class)); + int expectedMax = 50; + int expectedMin = 5; + Assert.assertTrue(expectedMax >= Long.parseLong(tsValue.getValue())); + Assert.assertTrue(expectedMin <= Long.parseLong(tsValue.getValue())); } protected void createDeviceProfile(Lwm2mDeviceProfileTransportConfiguration transportConfiguration) throws Exception { @@ -289,6 +294,9 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractWebsocketTest lwM2MTestClient = new LwM2MTestClient(this.executor, endpoint); int clientPort = SocketUtils.findAvailableUdpPort(); lwM2MTestClient.init(security, coapConfig, clientPort, isRpc, isBootstrap, this.shortServerId, this.shortServerIdBs, securityBs); + if (!isRpc) { + Thread.sleep(1000); + } } private void clientDestroy() { diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java index f662b61d91..8ff0962811 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java @@ -46,6 +46,7 @@ public class Lwm2mTestHelper { public static final String RESOURCE_ID_NAME_3_14 = "UtfOffset"; public static final String RESOURCE_ID_NAME_19_0_0 = "dataRead"; public static final String RESOURCE_ID_NAME_19_1_0 = "dataWrite"; + public static final String RESOURCE_ID_NAME_19_0_3 = "dataDescription"; public enum LwM2MClientState { 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 6e055783fe..a40922d136 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 @@ -138,7 +138,7 @@ public class LwM2MTestClient { initializer.setInstancesForObject(SERVER, instances); } } - initializer.setInstancesForObject(DEVICE, lwM2MDevice = new SimpleLwM2MDevice()); + initializer.setInstancesForObject(DEVICE, lwM2MDevice = new SimpleLwM2MDevice(executor)); initializer.setInstancesForObject(FIRMWARE, fwLwM2MDevice = new FwLwM2MDevice()); initializer.setInstancesForObject(SOFTWARE_MANAGEMENT, swLwM2MDevice = new SwLwM2MDevice()); initializer.setClassForObject(ACCESS_CONTROL, DummyInstanceEnabler.class); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mBinaryAppDataContainer.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mBinaryAppDataContainer.java index a88c795f9c..797a5da2e3 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mBinaryAppDataContainer.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mBinaryAppDataContainer.java @@ -173,7 +173,8 @@ public class LwM2mBinaryAppDataContainer extends BaseInstanceEnabler implements } private String getDescription() { - return this.description == null ? "meter reading" : this.description; +// return this.description == null ? "meter reading" : this.description; + return this.description; } private void setTimestamp(long time) { @@ -203,6 +204,10 @@ public class LwM2mBinaryAppDataContainer extends BaseInstanceEnabler implements } private Map getData() { + if (data == null) { + this.data = new HashMap<>(); + this.data.put(0, new byte[]{(byte) 0xAC}); + } return data; } 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 37d93279bf..ffd3df0a09 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 @@ -32,16 +32,39 @@ import java.util.Calendar; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.PrimitiveIterator; import java.util.Random; import java.util.TimeZone; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; @Slf4j public class SimpleLwM2MDevice extends BaseInstanceEnabler implements Destroyable { private static final Random RANDOM = new Random(); + private static final int min = 5; + private static final int max = 50; + private static final PrimitiveIterator.OfInt randomIterator = new Random().ints(min,max + 1).iterator(); private static final List supportedResources = Arrays.asList(0, 1, 2, 3, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21); + + public SimpleLwM2MDevice() { + } + + public SimpleLwM2MDevice(ScheduledExecutorService executorService) { + try { + executorService.scheduleWithFixedDelay(() -> { + fireResourceChange(9); + } + , 1800000, 1800000, TimeUnit.MILLISECONDS); // 30 MIN + } catch (Throwable e) { + log.error("[{}]Throwable", e.toString()); + e.printStackTrace(); + } + } + + @Override public ReadResponse read(ServerIdentity identity, int resourceId) { if (!identity.isSystem()) @@ -135,7 +158,8 @@ public class SimpleLwM2MDevice extends BaseInstanceEnabler implements Destroyabl } private int getBatteryLevel() { - return 42; + return randomIterator.nextInt(); +// return 42; } private long getMemoryFree() { diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java index e572b854b5..8173b39b5c 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java @@ -100,9 +100,6 @@ public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_WITHOUT_FW_INFO)); final Device device = createDevice(deviceCredentials, this.CLIENT_ENDPOINT_WITHOUT_FW_INFO); createNewClient(SECURITY_NO_SEC, COAP_CONFIG, false, this.CLIENT_ENDPOINT_WITHOUT_FW_INFO, false, null); - - Thread.sleep(1000); - device.setFirmwareId(createFirmware().getId()); final Device savedDevice = doPost("/api/device", device, Device.class); @@ -126,9 +123,6 @@ public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_OTA5)); final Device device = createDevice(deviceCredentials, this.CLIENT_ENDPOINT_OTA5); createNewClient(SECURITY_NO_SEC, COAP_CONFIG, false, this.CLIENT_ENDPOINT_OTA5, false, null); - - Thread.sleep(1000); - device.setFirmwareId(createFirmware().getId()); final Device savedDevice = doPost("/api/device", device, Device.class); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java index 669d8de55a..d80b556d72 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java @@ -60,7 +60,7 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg protected String objectInstanceIdVer_1; protected String objectIdVer_0; protected String objectIdVer_2; - private static final Predicate PREDICATE_3 = path -> (!((String) path).contains("/" + TEMPERATURE_SENSOR) && ((String) path).contains("/" + DEVICE)); + private static final Predicate PREDICATE_3 = path -> (!((String) path).startsWith("/" + TEMPERATURE_SENSOR) && ((String) path).startsWith("/" + DEVICE)); protected String objectIdVer_3; protected String objectInstanceIdVer_3; protected String objectInstanceIdVer_5; @@ -70,6 +70,8 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg protected String objectIdVer_3303; protected static AtomicInteger endpointSequence = new AtomicInteger(); protected static String DEVICE_ENDPOINT_RPC_PREF = "deviceEndpointRpc"; + protected String idVer_3_0_9; + protected String idVer_19_0_0; public AbstractRpcLwM2MIntegrationTest() { setResources(resources); @@ -90,9 +92,7 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg lwM2MTestClient.getLeshanClient().getObjectTree().getObjectEnablers().forEach((key, val) -> { if (key > 0) { String objectVerId = "/" + key; - if (!val.getObjectModel().version.equals("1.0")) { - objectVerId += ("_" + val.getObjectModel().version); - } + objectVerId += ("_" + val.getObjectModel().version); expectedObjects.add("/" + key); expectedObjectIdVers.add(objectVerId); String finalObjectVerId = objectVerId; @@ -103,38 +103,37 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg } }); String ver_Id_0 = lwM2MTestClient.getLeshanClient().getObjectTree().getModel().getObjectModel(OBJECT_ID_0).version; - if ("1.0".equals(ver_Id_0)) { - objectIdVer_0 = "/" + OBJECT_ID_0; - } else { - objectIdVer_0 = "/" + OBJECT_ID_0 + "_" + ver_Id_0; - } - objectIdVer_2 = (String) expectedObjectIdVers.stream().filter(path -> ((String) path).contains("/" + ACCESS_CONTROL)).findFirst().get(); - objectIdVer_3 = (String) expectedObjects.stream().filter(PREDICATE_3).findFirst().get(); - objectIdVer_19 = (String) expectedObjectIdVers.stream().filter(path -> ((String) path).contains("/" + BINARY_APP_DATA_CONTAINER)).findFirst().get(); - objectIdVer_3303 = (String) expectedObjectIdVers.stream().filter(path -> ((String) path).contains("/" + TEMPERATURE_SENSOR)).findFirst().get(); - objectInstanceIdVer_1 = (String) expectedObjectIdVerInstances.stream().filter(path -> (!((String) path).contains("/" + BINARY_APP_DATA_CONTAINER) && ((String) path).contains("/" + SERVER))).findFirst().get(); + objectIdVer_0 = "/" + OBJECT_ID_0 + "_" + ver_Id_0; + objectIdVer_2 = (String) expectedObjectIdVers.stream().filter(path -> ((String) path).startsWith("/" + ACCESS_CONTROL)).findFirst().get(); + objectIdVer_3 = (String) expectedObjectIdVers.stream().filter(PREDICATE_3).findFirst().get(); + objectIdVer_19 = (String) expectedObjectIdVers.stream().filter(path -> ((String) path).startsWith("/" + BINARY_APP_DATA_CONTAINER)).findFirst().get(); + objectIdVer_3303 = (String) expectedObjectIdVers.stream().filter(path -> ((String) path).startsWith("/" + TEMPERATURE_SENSOR)).findFirst().get(); + objectInstanceIdVer_1 = (String) expectedObjectIdVerInstances.stream().filter(path -> (!((String) path).startsWith("/" + BINARY_APP_DATA_CONTAINER) && ((String) path).startsWith("/" + SERVER))).findFirst().get(); objectInstanceIdVer_3 = (String) expectedObjectIdVerInstances.stream().filter(PREDICATE_3).findFirst().get(); - objectInstanceIdVer_5 = (String) expectedObjectIdVerInstances.stream().filter(path -> ((String) path).contains("/" + FIRMWARE)).findFirst().get(); - objectInstanceIdVer_9 = (String) expectedObjectIdVerInstances.stream().filter(path -> ((String) path).contains("/" + SOFTWARE_MANAGEMENT)).findFirst().get(); + objectInstanceIdVer_5 = (String) expectedObjectIdVerInstances.stream().filter(path -> ((String) path).startsWith("/" + FIRMWARE)).findFirst().get(); + objectInstanceIdVer_9 = (String) expectedObjectIdVerInstances.stream().filter(path -> ((String) path).startsWith("/" + SOFTWARE_MANAGEMENT)).findFirst().get(); + + idVer_3_0_9 = objectIdVer_3 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_9; + idVer_19_0_0 = objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_0; OBSERVE_ATTRIBUTES_WITH_PARAMS_RPC = " {\n" + " \"keyName\": {\n" + - " \"" + objectIdVer_3 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_9 + "\": \"" + RESOURCE_ID_NAME_3_9 + "\",\n" + + " \"" + idVer_3_0_9 + "\": \"" + RESOURCE_ID_NAME_3_9 + "\",\n" + " \"" + objectIdVer_3 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_14 + "\": \"" + RESOURCE_ID_NAME_3_14 + "\",\n" + - " \"" + objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_0 + "\": \"" + RESOURCE_ID_NAME_19_0_0 + "\",\n" + + " \"" + idVer_19_0_0 + "\": \"" + RESOURCE_ID_NAME_19_0_0 + "\",\n" + " \"" + objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_1 + "/" + RESOURCE_ID_0 + "\": \"" + RESOURCE_ID_NAME_19_1_0 + "\"\n" + " },\n" + " \"observe\": [\n" + - " \"" + objectIdVer_3 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_9 + "\",\n" + - " \"" + objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_0 + "\"\n" + + " \"" + idVer_3_0_9 + "\",\n" + + " \"" + idVer_19_0_0 + "\"\n" + " ],\n" + " \"attribute\": [\n" + + " \"" + objectIdVer_3 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_14 + "\"\n" + " ],\n" + " \"telemetry\": [\n" + - " \"" + objectIdVer_3 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_9 + "\",\n" + - " \"" + objectIdVer_3 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_14 + "\",\n" + - " \"" + objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_0 + "\",\n" + + " \"" + idVer_3_0_9 + "\",\n" + + " \"" + idVer_19_0_0 + "\",\n" + " \"" + objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_1 + "/" + RESOURCE_ID_0 + "\"\n" + " ],\n" + " \"attributeLwm2m\": {}\n" + @@ -148,6 +147,9 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg deviceId = device.getId().getId().toString(); lwM2MTestClient.start(); + + Thread.sleep(1000); + } protected String pathIdVerToObjectId(String pathIdVer) { diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationExecuteTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationExecuteTest.java index cd016de5ba..073a9fa8ed 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationExecuteTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationExecuteTest.java @@ -121,8 +121,8 @@ public class RpcLwm2mIntegrationExecuteTest extends AbstractRpcLwM2MIntegrationT /** * bad: resource operation not "E" - * Execute {"id":"5/0/3"} - * {"result":"BAD_REQUEST","error":"Resource with /5/0/3 is not executable."} + * Execute {"id":"5_1.0/0/3"} + * {"result":"BAD_REQUEST","error":"Resource with /5_1.0/0/3 is not executable."} */ @Test public void testExecuteResourceWithOperationNotExecuteById_Result_METHOD_NOT_ALLOWED() throws Exception { @@ -130,8 +130,7 @@ public class RpcLwm2mIntegrationExecuteTest extends AbstractRpcLwM2MIntegrationT String actualResult = sendRPCExecuteById(expectedPath); ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); assertEquals(ResponseCode.BAD_REQUEST.getName(), rpcActualResult.get("result").asText()); - String expectedObjectId = pathIdVerToObjectId((String) expectedPath); - String expected = "Resource with " + expectedObjectId + " is not executable."; + String expected = "Resource with " + expectedPath + " is not executable."; String actual = rpcActualResult.get("error").asText(); assertTrue(actual.equals(expected)); } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationObserveTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationObserveTest.java index d9631928a7..77d6e6cfab 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationObserveTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationObserveTest.java @@ -26,11 +26,11 @@ import static org.eclipse.leshan.core.LwM2mId.ACCESS_CONTROL; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.BINARY_APP_DATA_CONTAINER; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_INSTANCE_ID_0; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_0; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_14; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_3; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_9; +import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.fromVersionedIdToObjectId; public class RpcLwm2mIntegrationObserveTest extends AbstractRpcLwM2MIntegrationTest { @@ -40,23 +40,42 @@ public class RpcLwm2mIntegrationObserveTest extends AbstractRpcLwM2MIntegrationT */ @Test public void testObserveReadAllNothingObservation_Result_CONTENT_Value_Count_0() throws Exception { + String actualResultBefore = sendObserve("ObserveReadAll", null); + ObjectNode rpcActualResultBefore = JacksonUtil.fromString(actualResultBefore, ObjectNode.class); + assertEquals(ResponseCode.CONTENT.getName(), rpcActualResultBefore.get("result").asText()); + assertTrue(rpcActualResultBefore.get("value").asText().contains(fromVersionedIdToObjectId(idVer_3_0_9))); + assertTrue(rpcActualResultBefore.get("value").asText().contains(fromVersionedIdToObjectId(idVer_19_0_0))); String actualResult = sendObserve("ObserveCancelAll", null); ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); assertEquals(ResponseCode.CONTENT.getName(), rpcActualResult.get("result").asText()); - actualResult = sendObserve("ObserveReadAll", null); - rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); - assertEquals(ResponseCode.CONTENT.getName(), rpcActualResult.get("result").asText()); - assertEquals("[]", rpcActualResult.get("value").asText()); + assertEquals("2", rpcActualResult.get("value").asText()); + String actualResultAfter = sendObserve("ObserveReadAll", null); + ObjectNode rpcActualResultAfter = JacksonUtil.fromString(actualResultAfter, ObjectNode.class); + assertEquals(ResponseCode.CONTENT.getName(), rpcActualResultAfter.get("result").asText()); + String expectResultAfter = "[]"; + assertEquals( expectResultAfter, rpcActualResultAfter.get("value").asText()); } /** - * Observe {"id":"/3/0/9"} + * Observe {"id":"/3/0/0"} * @throws Exception */ @Test - public void testObserveSingleResource_Result_CONTENT_Value_SingleResource() throws Exception { - String expectedIdVer = objectInstanceIdVer_3 + "/" + RESOURCE_ID_9; - String actualResult = sendObserve("Observe", expectedIdVer); + public void testObserveSingleResourceWithout_IdVer_1_0_Result_CONTENT_Value_SingleResource() throws Exception { + String expectedId = objectInstanceIdVer_3 + "/" + RESOURCE_ID_0; + String actualResult = sendObserve("Observe", fromVersionedIdToObjectId(expectedId)); + ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); + assertEquals(ResponseCode.CONTENT.getName(), rpcActualResult.get("result").asText()); + assertTrue(rpcActualResult.get("value").asText().contains("LwM2mSingleResource")); + } + /** + * Observe {"id":"/3_1.0/0/14"} + * @throws Exception + */ + @Test + public void testObserveSingleResourceWith_IdVer_1_0_Result_CONTENT_Value_SingleResource() throws Exception { + String expectedId = objectInstanceIdVer_3 + "/" + RESOURCE_ID_14; + String actualResult = sendObserve("Observe", expectedId); ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); assertEquals(ResponseCode.CONTENT.getName(), rpcActualResult.get("result").asText()); assertTrue(rpcActualResult.get("value").asText().contains("LwM2mSingleResource")); @@ -100,11 +119,10 @@ public class RpcLwm2mIntegrationObserveTest extends AbstractRpcLwM2MIntegrationT */ @Test public void testObserveNoImplementedResourceOnDeviceValueNull_Result_BadRequest() throws Exception { - String objectIdVer = (String) expectedObjectIdVers.stream().filter(path -> ((String)path).contains("/" + BINARY_APP_DATA_CONTAINER)).findFirst().get(); - String expected = objectIdVer + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_0; + String expected = objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_3; String actualResult = sendObserve("Observe", expected); ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); - String expectedValue = "values MUST NOT be null"; + String expectedValue = "value MUST NOT be null"; assertEquals(ResponseCode.BAD_REQUEST.getName(), rpcActualResult.get("result").asText()); assertEquals(expectedValue, rpcActualResult.get("error").asText()); } @@ -125,14 +143,12 @@ public class RpcLwm2mIntegrationObserveTest extends AbstractRpcLwM2MIntegrationT /** * Repeated request on Observe - * Observe {"id":"/3/0/0"} + * Observe {"id":"/3/0/9"} * @throws Exception */ @Test public void testObserveRepeatedRequestObserveOnDevice_Result_BAD_REQUEST_ErrorMsg_AlreadyRegistered() throws Exception { - String expectedId = objectInstanceIdVer_3 + "/" + RESOURCE_ID_0; - sendObserve("Observe", expectedId); - String actualResult = sendObserve("Observe", expectedId); + String actualResult = sendObserve("Observe", idVer_3_0_9); ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); assertEquals(ResponseCode.BAD_REQUEST.getName(), rpcActualResult.get("result").asText()); String expected = "Observation is already registered!"; @@ -144,18 +160,18 @@ public class RpcLwm2mIntegrationObserveTest extends AbstractRpcLwM2MIntegrationT * @throws Exception */ @Test - public void testObserveReadAll_Result_CONTENT_Value_Contains_Paths_Count_ObserveAll() throws Exception { - sendObserve("ObserveCancelAll", null); - String expectedId_0 = objectInstanceIdVer_3 + "/" + RESOURCE_ID_0; - String expectedId_9 = objectInstanceIdVer_3 + "/" + RESOURCE_ID_9; - sendObserve("Observe", expectedId_0); - sendObserve("Observe", expectedId_9); + public void testObserveReadAll_Result_CONTENT_Value_Contains_Paths_Count_ObserveReadAll() throws Exception { + String actualResultCancel = sendObserve("ObserveCancelAll", null); + ObjectNode rpcActualResultCancel = JacksonUtil.fromString(actualResultCancel, ObjectNode.class); + assertEquals(ResponseCode.CONTENT.getName(), rpcActualResultCancel.get("result").asText()); + sendObserve("Observe",idVer_19_0_0); + sendObserve("Observe", idVer_3_0_9); String actualResult = sendObserve("ObserveReadAll", null); ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); assertEquals(ResponseCode.CONTENT.getName(), rpcActualResult.get("result").asText()); String actualValues = rpcActualResult.get("value").asText(); - assertTrue(actualValues.contains(expectedId_0)); - assertTrue(actualValues.contains(expectedId_9)); + assertTrue(actualValues.contains(fromVersionedIdToObjectId(idVer_19_0_0))); + assertTrue(actualValues.contains(fromVersionedIdToObjectId(idVer_3_0_9))); assertEquals(2, actualValues.split(",").length); } @@ -167,11 +183,11 @@ public class RpcLwm2mIntegrationObserveTest extends AbstractRpcLwM2MIntegrationT @Test public void testObserveCancelOneResource_Result_CONTENT_Value_Count_1() throws Exception { sendObserve("ObserveCancelAll", null); - String expectedId_0 = objectInstanceIdVer_3 + "/" + RESOURCE_ID_0; - String expectedId_3 = objectInstanceIdVer_5 + "/" + RESOURCE_ID_3; - sendObserve("Observe", expectedId_0); - sendObserve("Observe", expectedId_3); - String actualResult = sendObserve("ObserveCancel", expectedId_0); + String expectedId_3_0_3 = objectInstanceIdVer_3 + "/" + RESOURCE_ID_3; + String expectedId_5_0_3 = objectInstanceIdVer_5 + "/" + RESOURCE_ID_3; + sendObserve("Observe", expectedId_3_0_3); + sendObserve("Observe", expectedId_5_0_3); + String actualResult = sendObserve("ObserveCancel", expectedId_3_0_3); ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); assertEquals(ResponseCode.CONTENT.getName(), rpcActualResult.get("result").asText()); assertEquals("1", rpcActualResult.get("value").asText()); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationReadTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationReadTest.java index 4b13c8d757..404bbdc545 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationReadTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationReadTest.java @@ -30,6 +30,7 @@ import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.BINARY_APP_ import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_INSTANCE_ID_0; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_INSTANCE_ID_1; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_NAME_19_0_0; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_NAME_19_0_3; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_NAME_19_1_0; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_NAME_3_14; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.RESOURCE_ID_NAME_3_9; @@ -181,11 +182,12 @@ public class RpcLwm2mIntegrationReadTest extends AbstractRpcLwM2MIntegrationTest * ReadComposite {"keys":["batteryLevel", "UtfOffset", "dataRead", "dataWrite"]} */ @Test - public void testReadCompositeSingleResourceByKeys_Result_CONTENT_Value_3_0_IsLwM2mSingleResource_19_0_0_AND_19_0_1_Null() throws Exception { + public void testReadCompositeSingleResourceByKeys_Result_CONTENT_Value_3_0_IsLwM2mSingleResource_19_0_0_AND_19_0_1__IsLwM2mMultipleResource() throws Exception { String expectedKey3_0_9 = RESOURCE_ID_NAME_3_9; String expectedKey3_0_14 = RESOURCE_ID_NAME_3_14; String expectedKey19_0_0 = RESOURCE_ID_NAME_19_0_0; String expectedKey19_1_0 = RESOURCE_ID_NAME_19_1_0; + String expectedKey19_X_0 = "=LwM2mMultipleResource [id=0, values={0=LwM2mResourceInstance [id=0, value=1Bytes, type=OPAQUE]"; String expectedKeys = "[\"" + expectedKey3_0_9 + "\", \"" + expectedKey3_0_14 + "\", \"" + expectedKey19_0_0 + "\", \"" + expectedKey19_1_0 + "\"]"; String actualResult = sendCompositeRPCByKeys(expectedKeys); ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); @@ -194,8 +196,8 @@ public class RpcLwm2mIntegrationReadTest extends AbstractRpcLwM2MIntegrationTest String objectId_19 = pathIdVerToObjectId(objectIdVer_19); String expected3_0_9 = objectInstanceId_3 + "/" + RESOURCE_ID_9 + "=LwM2mSingleResource [id=" + RESOURCE_ID_9 + ", value="; String expected3_0_14 = objectInstanceId_3 + "/" + RESOURCE_ID_14 + "=LwM2mSingleResource [id=" + RESOURCE_ID_14 + ", value="; - String expected19_0_0 = objectId_19 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_0 + "=null"; - String expected19_1_0 = objectId_19 + "/" + OBJECT_INSTANCE_ID_1 + "/" + RESOURCE_ID_0 + "=null"; + String expected19_0_0 = objectId_19 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_0 + expectedKey19_X_0; + String expected19_1_0 = objectId_19 + "/" + OBJECT_INSTANCE_ID_1 + "/" + RESOURCE_ID_0 + expectedKey19_X_0; String actualValues = rpcActualResult.get("value").asText(); assertTrue(actualValues.contains(expected3_0_9)); assertTrue(actualValues.contains(expected3_0_14)); @@ -203,6 +205,23 @@ public class RpcLwm2mIntegrationReadTest extends AbstractRpcLwM2MIntegrationTest assertTrue(actualValues.contains(expected19_1_0)); } + /** + * ReadComposite {"keys":["batteryLevel", "UtfOffset", "dataDescription"]} + */ + @Test + public void testReadCompositeSingleResourceByKeys_Result_CONTENT_Value_3_0_IsLwM2mSingleResource_19_0_3_IsNotConfiguredInTheDeviceProfile() throws Exception { + String expectedKey3_0_9 = RESOURCE_ID_NAME_3_9; + String expectedKey3_0_14 = RESOURCE_ID_NAME_3_14; + String expectedKey19_0_3 = RESOURCE_ID_NAME_19_0_3; + String expectedKeys = "[\"" + expectedKey3_0_9 + "\", \"" + expectedKey3_0_14 + "\", \"" + expectedKey19_0_3 + "\"]"; + String actualResult = sendCompositeRPCByKeys(expectedKeys); + ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); + assertEquals(ResponseCode.BAD_REQUEST.getName(), rpcActualResult.get("result").asText()); + String actualValue = rpcActualResult.get("error").asText(); + String expectedValue = expectedKey19_0_3 + " is not configured in the device profile!"; + assertEquals(actualValue, expectedValue); + } + private String sendRPCById(String path) throws Exception { String setRpcRequest = "{\"method\": \"Read\", \"params\": {\"id\": \"" + path + "\"}}"; 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 fa4b601ed0..15ddf062f7 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 @@ -15,10 +15,12 @@ */ package org.thingsboard.server.transport.lwm2m.security; +import com.fasterxml.jackson.databind.node.ObjectNode; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.binary.Base64; import org.eclipse.californium.elements.config.Configuration; import org.eclipse.leshan.client.object.Security; +import org.eclipse.leshan.core.ResponseCode; import org.eclipse.leshan.core.util.Hex; import org.junit.Assert; import org.springframework.test.web.servlet.MvcResult; @@ -61,6 +63,7 @@ import java.util.concurrent.TimeUnit; import static org.awaitility.Awaitility.await; import static org.eclipse.leshan.client.object.Security.noSecBootstap; +import static org.junit.Assert.assertEquals; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_DEREGISTRATION_STARTED; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_DEREGISTRATION_SUCCESS; @@ -190,6 +193,7 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M final Device device = createDevice(deviceCredentials, endpoint); device.getId().getId().toString(); lwM2MTestClient.start(); + Thread.sleep(1000); await(awaitAlias) .atMost(1000, TimeUnit.MILLISECONDS) @@ -229,14 +233,18 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M final Device device = createDevice(deviceCredentials, endpoint); String deviceId = device.getId().getId().toString(); lwM2MTestClient.start(); + Thread.sleep(1000); await(awaitAlias) .atMost(1000, TimeUnit.MILLISECONDS) .until(() -> ON_REGISTRATION_SUCCESS.equals(lwM2MTestClient.getClientState())); Assert.assertEquals(expectedStatusesLwm2m, lwM2MTestClient.getClientStates()); - String executedPath = getObjectIdVer_1() + "/0/" + RESOURCE_ID_9; - sendRPCSecurityExecuteById(executedPath, deviceId, endpoint); + String executedPath = "/" + OBJECT_ID_1 + "_" + lwM2MTestClient.getLeshanClient().getObjectTree().getModel().getObjectModel(OBJECT_ID_1).version + + "/0/" + RESOURCE_ID_9; + String actualResult = sendRPCSecurityExecuteById(executedPath, deviceId, endpoint); + ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); + assertEquals(ResponseCode.CHANGED.getName(), rpcActualResult.get("result").asText()); expectedStatusesBs.add(ON_DEREGISTRATION_STARTED); expectedStatusesBs.add(ON_DEREGISTRATION_SUCCESS); await(awaitAlias) @@ -398,15 +406,4 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M String setRpcRequest = "{\"method\": \"Execute\", \"params\": {\"id\": \"" + path + "\"}}"; return doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setRpcRequest, String.class, status().isOk()); } - - private String getObjectIdVer_1() { - String ver_Id_0 = lwM2MTestClient.getLeshanClient().getObjectTree().getModel().getObjectModel(OBJECT_ID_1).version; - String objectIdVer_1; - if ("1.0".equals(ver_Id_0)) { - objectIdVer_1 = "/" + OBJECT_ID_1; - } else { - objectIdVer_1 = "/" + OBJECT_ID_1 + "_" + ver_Id_0; - } - return objectIdVer_1; - } } diff --git a/application/src/test/resources/logback.xml b/application/src/test/resources/logback-test.xml similarity index 100% rename from application/src/test/resources/logback.xml rename to application/src/test/resources/logback-test.xml 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 a4c92de9b1..b7205de7cc 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 @@ -374,14 +374,15 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { } private Lwm2mDeviceProfileTransportConfiguration doGetAndCache(UUID profileId) { - Lwm2mDeviceProfileTransportConfiguration result = profiles.get(profileId); + + Lwm2mDeviceProfileTransportConfiguration result = profiles != null ? profiles.get(profileId) : null; if (result == null) { log.debug("Fetching profile [{}]", profileId); - DeviceProfile deviceProfile = deviceProfileCache.get(new DeviceProfileId(profileId)); + DeviceProfile deviceProfile = deviceProfileCache != null ? deviceProfileCache.get(new DeviceProfileId(profileId)) : null; if (deviceProfile != null) { result = profileUpdate(deviceProfile); } else { - log.info("Device profile was not found! Most probably device profile [{}] has been removed from the database.", profileId); + log.error("Device profile was not found! Most probably device profile [{}] has been removed from the database.", profileId); } } return result; 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 283f1d852c..f193a929e6 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 @@ -486,9 +486,9 @@ public class DefaultLwM2mUplinkMsgHandler extends LwM2MExecutorAwareService impl new TbLwM2MLatchCallback<>(latch, new TbLwM2MReadCallback(this, logService, lwM2MClient, versionedId)))); latch.await(); } catch (InterruptedException e) { - log.error("[{}] Failed to await Read requests!", lwM2MClient.getEndpoint()); - } catch (Exception e) { - log.error("[{}] Failed to process read requests!", lwM2MClient.getEndpoint(), e); + log.error("[{}] Failed to await Read requests!", lwM2MClient.getEndpoint(), e); + } catch (Exception e1) { + log.error("[{}] Failed to process read requests!", lwM2MClient.getEndpoint(), e1); logService.log(lwM2MClient, "Failed to process read requests. Possible profile misconfiguration."); } } @@ -504,9 +504,9 @@ public class DefaultLwM2mUplinkMsgHandler extends LwM2MExecutorAwareService impl latch.await(); } catch (InterruptedException e) { - log.error("[{}] Failed to await Observe requests!", lwM2MClient.getEndpoint()); - } catch (Exception e) { - log.error("[{}] Failed to process observe requests!", lwM2MClient.getEndpoint(), e); + log.error("[{}] Failed to await Observe requests!", lwM2MClient.getEndpoint(), e); + } catch (Exception e1) { + log.error("[{}] Failed to process observe requests!", lwM2MClient.getEndpoint(), e1); logService.log(lwM2MClient, "Failed to process observe requests. Possible profile misconfiguration."); } }