Browse Source

Merge pull request #11896 from thingsboard/lwm2m_write_obj_19

Lwm2m_write_obj_19
pull/11952/head
Andrew Shvayka 2 years ago
committed by GitHub
parent
commit
342aaa8be7
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 56
      application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java
  2. 1
      application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java
  3. 2
      application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mBinaryAppDataContainer.java
  4. 4
      application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota5LwM2MIntegrationTest.java
  5. 2
      application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota9LwM2MIntegrationTest.java
  6. 5
      application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java
  7. 12
      application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2MIntegrationObserveCompositeTest.java
  8. 2
      application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationCreateTest.java
  9. 2
      application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationDeleteTest.java
  10. 4
      application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationDiscoverTest.java
  11. 4
      application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationDiscoverWriteAttributesTest.java
  12. 4
      application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationExecuteTest.java
  13. 26
      application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationObserveTest.java
  14. 4
      application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationReadCollectedValueTest.java
  15. 8
      application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationReadTest.java
  16. 4
      application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationWriteCborTest.java
  17. 196
      application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationWriteTest.java
  18. 14
      application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java
  19. 7
      application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLengthTest.java
  20. 17
      application/src/test/java/org/thingsboard/server/transport/lwm2m/security/diffPort/AbstractLwM2MIntegrationDiffPortTest.java
  21. 10
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java
  22. 23
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/rpc/DefaultLwM2MRpcRequestHandler.java
  23. 51
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2MTransportUtil.java
  24. 17
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java
  25. 1
      common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java
  26. 29
      common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/util/JsonUtils.java

56
application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java

@ -21,15 +21,16 @@ import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.eclipse.leshan.client.LeshanClient;
import org.eclipse.leshan.client.object.Security;
import org.eclipse.leshan.core.ResponseCode;
import org.eclipse.leshan.server.registration.Registration;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.http.HttpStatus;
import org.springframework.test.context.TestPropertySource;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.common.util.ThingsBoardThreadFactory;
@ -89,6 +90,8 @@ import static org.awaitility.Awaitility.await;
import static org.eclipse.leshan.client.object.Security.noSec;
import static org.hamcrest.core.IsInstanceOf.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
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;
@ -188,7 +191,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte
@After
public void after() throws Exception {
clientDestroy();
this.clientDestroy(true);
if (executor != null && !executor.isShutdown()) {
executor.shutdownNow();
}
@ -231,9 +234,8 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte
getWsClient().waitForReply();
getWsClient().registerWaitForUpdate();
createNewClient(security, null, false, endpoint, null, queueMode);
deviceId = device.getId().getId().toString();
awaitObserveReadAll(0, deviceId);
this.createNewClient(security, null, false, endpoint, null, queueMode, device.getId().getId().toString());
awaitObserveReadAll(0, lwM2MTestClient.getDeviceIdStr());
String msg = getWsClient().waitForUpdate();
EntityDataUpdate update = JacksonUtil.fromString(msg, EntityDataUpdate.class);
@ -301,18 +303,18 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte
}
public void createNewClient(Security security, Security securityBs, boolean isRpc,
String endpoint) throws Exception {
this.createNewClient(security, securityBs, isRpc, endpoint, null, false);
String endpoint, String deviceIdStr) throws Exception {
this.createNewClient(security, securityBs, isRpc, endpoint, null, false, deviceIdStr);
}
public void createNewClient(Security security, Security securityBs, boolean isRpc,
String endpoint, Integer clientDtlsCidLength) throws Exception {
this.createNewClient(security, securityBs, isRpc, endpoint, clientDtlsCidLength, false);
String endpoint, Integer clientDtlsCidLength, String deviceIdStr) throws Exception {
this.createNewClient(security, securityBs, isRpc, endpoint, clientDtlsCidLength, false, deviceIdStr);
}
public void createNewClient(Security security, Security securityBs, boolean isRpc,
String endpoint, Integer clientDtlsCidLength, boolean queueMode) throws Exception {
this.clientDestroy();
String endpoint, Integer clientDtlsCidLength, boolean queueMode, String deviceIdStr) throws Exception {
this.clientDestroy(false);
lwM2MTestClient = new LwM2MTestClient(this.executor, endpoint);
try (ServerSocket socket = new ServerSocket(0)) {
@ -321,13 +323,17 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte
this.defaultLwM2mUplinkMsgHandlerTest, this.clientContextTest,
clientDtlsCidLength, queueMode, supportFormatOnly_SenMLJSON_SenMLCBOR);
}
lwM2MTestClient.setDeviceIdStr(deviceIdStr);
}
private void clientDestroy() {
private void clientDestroy(boolean isAfter) {
try {
if (lwM2MTestClient != null) {
if (isAfter) {
sendObserveCancelAllWithAwait(lwM2MTestClient.getDeviceIdStr());
awaitDeleteDevice(lwM2MTestClient.getDeviceIdStr());
}
lwM2MTestClient.destroy();
awaitClientDestroy(lwM2MTestClient.getLeshanClient());
}
} catch (Exception e) {
log.error("Failed client Destroy", e);
@ -384,17 +390,20 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte
return credentials;
}
private static void awaitClientDestroy(LeshanClient leshanClient) {
await("Destroy LeshanClient: delete All is registered Servers.")
.atMost(DEFAULT_WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS)
.until(() -> leshanClient.getRegisteredServers().size() == 0);
}
protected void awaitObserveReadAll(int cntObserve, String deviceIdStr) throws Exception {
await("ObserveReadAll: countObserve " + cntObserve)
.atMost(40, TimeUnit.SECONDS)
.until(() -> cntObserve == getCntObserveAll(deviceIdStr));
}
protected void awaitDeleteDevice(String deviceIdStr) throws Exception {
await("Delete device with id: " + deviceIdStr)
.atMost(40, TimeUnit.SECONDS)
.until(() -> {
doDelete("/api/device/" + deviceIdStr)
.andExpect(status().isOk());
return HttpStatus.NOT_FOUND.value() == doGet("/api/device/" + deviceIdStr).andReturn().getResponse().getStatus();
});
}
protected Integer getCntObserveAll(String deviceIdStr) throws Exception {
String actualResult = sendObserveOK("ObserveReadAll", null, deviceIdStr);
@ -408,7 +417,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte
String actualResultCancelAll = sendObserveOK("ObserveCancelAll", null, deviceIdStr);
ObjectNode rpcActualResultCancelAll = JacksonUtil.fromString(actualResultCancelAll, ObjectNode.class);
assertEquals(ResponseCode.CONTENT.getName(), rpcActualResultCancelAll.get("result").asText());
awaitObserveReadAll(0, deviceId);
awaitObserveReadAll(0, lwM2MTestClient.getDeviceIdStr());
}
protected String sendRpcObserveOkWithResultValue(String method, String params) throws Exception {
@ -418,7 +427,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte
return rpcActualResult.get("value").asText();
}
protected String sendRpcObserveOk(String method, String params) throws Exception {
return sendObserveOK(method, params, deviceId);
return sendObserveOK(method, params, lwM2MTestClient.getDeviceIdStr());
}
protected String sendObserveOK(String method, String params, String deviceIdStr) throws Exception {
String sendRpcRequest;
@ -442,4 +451,9 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte
.filter(invocation -> invocation.getMethod().getName().equals("updatedReg"))
.count();
}
protected void awaitUpdateReg(int cntUpdate) {
verify(defaultUplinkMsgHandlerTest, timeout(50000).atLeast(cntUpdate))
.updatedReg(Mockito.any(Registration.class));
}
}

1
application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java

@ -138,6 +138,7 @@ public class LwM2MTestClient {
private LwM2mUplinkMsgHandler defaultLwM2mUplinkMsgHandlerTest;
private LwM2mClientContext clientContext;
private LwM2mTemperatureSensor lwM2mTemperatureSensor12;
private String deviceIdStr;
public void init(Security security, Security securityBs, int port, boolean isRpc,
LwM2mUplinkMsgHandler defaultLwM2mUplinkMsgHandler,

2
application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2mBinaryAppDataContainer.java

@ -129,7 +129,7 @@ public class LwM2mBinaryAppDataContainer extends BaseInstanceEnabler implements
fireResourceChange(resourceId);
return WriteResponse.success();
} else {
WriteResponse.badRequest("Invalidate value ...");
return WriteResponse.badRequest("Invalidate value ...");
}
case 1:
setPriority((Integer) (value.getValue() instanceof Long ? ((Long) value.getValue()).intValue() : value.getValue()));

4
application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota5LwM2MIntegrationTest.java

@ -55,7 +55,7 @@ public class Ota5LwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest {
DeviceProfile deviceProfile = createLwm2mDeviceProfile("profileFor" + this.CLIENT_ENDPOINT_WITHOUT_FW_INFO, transportConfiguration);
LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_WITHOUT_FW_INFO));
final Device device = createLwm2mDevice(deviceCredentials, this.CLIENT_ENDPOINT_WITHOUT_FW_INFO, deviceProfile.getId());
createNewClient(SECURITY_NO_SEC, null, false, this.CLIENT_ENDPOINT_WITHOUT_FW_INFO);
createNewClient(SECURITY_NO_SEC, null, false, this.CLIENT_ENDPOINT_WITHOUT_FW_INFO, device.getId().getId().toString());
awaitObserveReadAll(0, device.getId().getId().toString());
device.setFirmwareId(createFirmware("5.1", deviceProfile.getId()).getId());
@ -90,7 +90,7 @@ public class Ota5LwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest {
DeviceProfile deviceProfile = createLwm2mDeviceProfile("profileFor" + this.CLIENT_ENDPOINT_OTA5, transportConfiguration);
LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_OTA5));
final Device device = createLwm2mDevice(deviceCredentials, this.CLIENT_ENDPOINT_OTA5, deviceProfile.getId());
createNewClient(SECURITY_NO_SEC, null, false, this.CLIENT_ENDPOINT_OTA5);
createNewClient(SECURITY_NO_SEC, null, false, this.CLIENT_ENDPOINT_OTA5, device.getId().getId().toString());
awaitObserveReadAll(5, device.getId().getId().toString());
device.setFirmwareId(createFirmware("fw.v.1.5.0-update", deviceProfile.getId()).getId());

2
application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/Ota9LwM2MIntegrationTest.java

@ -54,7 +54,7 @@ public class Ota9LwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest {
DeviceProfile deviceProfile = createLwm2mDeviceProfile("profileFor" + this.CLIENT_ENDPOINT_OTA9, transportConfiguration);
LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_OTA9));
final Device device = createLwm2mDevice(deviceCredentials, this.CLIENT_ENDPOINT_OTA9, deviceProfile.getId());
createNewClient(SECURITY_NO_SEC, null, false, this.CLIENT_ENDPOINT_OTA9);
createNewClient(SECURITY_NO_SEC, null, false, this.CLIENT_ENDPOINT_OTA9, device.getId().getId().toString());
awaitObserveReadAll(4, device.getId().getId().toString());
device.setSoftwareId(createSoftware(deviceProfile.getId()).getId());

5
application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java

@ -121,7 +121,7 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg
protected void initRpc(int typeConfigProfile) throws Exception {
String endpoint = DEVICE_ENDPOINT_RPC_PREF + endpointSequence.incrementAndGet();
createNewClient(SECURITY_NO_SEC, null, true, endpoint);
createNewClient(SECURITY_NO_SEC, null, true, endpoint, null);
expectedObjects = ConcurrentHashMap.newKeySet();
expectedObjectIdVers = ConcurrentHashMap.newKeySet();
expectedInstances = ConcurrentHashMap.newKeySet();
@ -232,8 +232,7 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg
LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(endpoint));
final Device device = createLwm2mDevice(deviceCredentials, endpoint, deviceProfile.getId());
deviceId = device.getId().getId().toString();
lwM2MTestClient.setDeviceIdStr(device.getId().getId().toString());
lwM2MTestClient.start(true);
}

12
application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2MIntegrationObserveCompositeTest.java

@ -315,7 +315,7 @@ public class RpcLwm2MIntegrationObserveCompositeTest extends AbstractRpcLwM2MInt
assertEquals(ResponseCode.CONTENT.getName(), rpcActualResult.get("result").asText());
assertEquals("1", rpcActualResult.get("value").asText());
assertEquals(0, (Object) getCntObserveAll(deviceId));
assertEquals(0, (Object) getCntObserveAll(lwM2MTestClient.getDeviceIdStr()));
}
/**
@ -335,7 +335,7 @@ public class RpcLwm2MIntegrationObserveCompositeTest extends AbstractRpcLwM2MInt
String actualResult = sendCompositeRPCByIds("ObserveComposite", expectedIds);
ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
assertEquals(ResponseCode.CONTENT.getName(), rpcActualResult.get("result").asText());
awaitObserveReadAll(1, deviceId);
awaitObserveReadAll(1, lwM2MTestClient.getDeviceIdStr());
// ObserveCompositeCancel two
expectedIds = "[\"" + objectInstanceIdVer_5 + "\", \"" + expectedIdVer19_1_0_0 + "\"]";
@ -418,7 +418,7 @@ public class RpcLwm2MIntegrationObserveCompositeTest extends AbstractRpcLwM2MInt
updateAttrTelemetryResourceAtLeastOnceAfterAction(initAttrTelemetryAtCount_19_0_2, idVer_19_0_2);
// 2 - "ObserveReadAll": No update of all resources we are observing - after "ObserveReadCancelAll"
sendObserveCancelAllWithAwait(deviceId);
sendObserveCancelAllWithAwait(lwM2MTestClient.getDeviceIdStr());
updateRegAtLeastOnceAfterAction();
actualResultReadAll = sendCompositeRPCByKeys("ObserveReadAll", null);
rpcActualResultReadAll = JacksonUtil.fromString(actualResultReadAll, ObjectNode.class);
@ -479,17 +479,17 @@ public class RpcLwm2MIntegrationObserveCompositeTest extends AbstractRpcLwM2MInt
} else {
sendRpcRequest = "{\"method\": \"" + method + "\", \"params\": {\"id\": \"" + params + "\"}}";
}
return doPostAsync("/api/plugins/rpc/twoway/" + deviceId, sendRpcRequest, String.class, status().isOk());
return doPostAsync("/api/plugins/rpc/twoway/" + lwM2MTestClient.getDeviceIdStr(), sendRpcRequest, String.class, status().isOk());
}
private String sendCompositeRPCByIds(String method, String paths) throws Exception {
String setRpcRequest = "{\"method\": \"" + method + "\", \"params\": {\"ids\":" + paths + "}}";
return doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setRpcRequest, String.class, status().isOk());
return doPostAsync("/api/plugins/rpc/twoway/" + lwM2MTestClient.getDeviceIdStr(), setRpcRequest, String.class, status().isOk());
}
private String sendCompositeRPCByKeys(String method, String keys) throws Exception {
String sendRpcRequest = "{\"method\": \"" + method + "\", \"params\": {\"keys\":" + keys + "}}";
return doPostAsync("/api/plugins/rpc/twoway/" + deviceId, sendRpcRequest, String.class, status().isOk());
return doPostAsync("/api/plugins/rpc/twoway/" + lwM2MTestClient.getDeviceIdStr(), sendRpcRequest, String.class, status().isOk());
}
private void updateAttrTelemetryAllAtLeastOnceAfterAction(long initialInvocationCount) {

2
application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationCreateTest.java

@ -127,7 +127,7 @@ public class RpcLwm2mIntegrationCreateTest extends AbstractRpcLwM2MIntegrationTe
private String sendRPCreateById(String path, String value) throws Exception {
String setRpcRequest = "{\"method\": \"Create\", \"params\": {\"id\": \"" + path + "\", \"value\": " + value + " }}";
return doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setRpcRequest, String.class, status().isOk());
return doPostAsync("/api/plugins/rpc/twoway/" + lwM2MTestClient.getDeviceIdStr(), setRpcRequest, String.class, status().isOk());
}
}

2
application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationDeleteTest.java

@ -90,7 +90,7 @@ public class RpcLwm2mIntegrationDeleteTest extends AbstractRpcLwM2MIntegrationTe
private String sendRPCDeleteById(String path) throws Exception {
String setRpcRequest = "{\"method\": \"Delete\", \"params\": {\"id\": \"" + path + "\"}}";
return doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setRpcRequest, String.class, status().isOk());
return doPostAsync("/api/plugins/rpc/twoway/" + lwM2MTestClient.getDeviceIdStr(), setRpcRequest, String.class, status().isOk());
}
}

4
application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationDiscoverTest.java

@ -61,7 +61,7 @@ public class RpcLwm2mIntegrationDiscoverTest extends AbstractRpcLwM2MIntegration
@Test
public void testDiscoverAll_Return_CONTENT_LinksAllObjectsAllInstancesOfClient() throws Exception {
String setRpcRequest = "{\"method\":\"DiscoverAll\"}";
String actualResult = doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setRpcRequest, String.class, status().isOk());
String actualResult = doPostAsync("/api/plugins/rpc/twoway/" + lwM2MTestClient.getDeviceIdStr(), setRpcRequest, String.class, status().isOk());
ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
assertEquals(ResponseCode.CONTENT.getName(), rpcActualResult.get("result").asText());
JsonNode rpcActualValue = JacksonUtil.toJsonNode(rpcActualResult.get("value").asText());
@ -194,7 +194,7 @@ public class RpcLwm2mIntegrationDiscoverTest extends AbstractRpcLwM2MIntegration
private String sendDiscover(String path) throws Exception {
String setRpcRequest = "{\"method\": \"Discover\", \"params\": {\"id\": \"" + path + "\"}}";
return doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setRpcRequest, String.class, status().isOk());
return doPostAsync("/api/plugins/rpc/twoway/" + lwM2MTestClient.getDeviceIdStr(), setRpcRequest, String.class, status().isOk());
}
private String convertObjectIdToVerId(String path, String ver) {

4
application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationDiscoverWriteAttributesTest.java

@ -164,11 +164,11 @@ public class RpcLwm2mIntegrationDiscoverWriteAttributesTest extends AbstractRpcL
private String sendRPCExecuteWithValueById(String path, String value) throws Exception {
String setRpcRequest = "{\"method\": \"WriteAttributes\", \"params\": {\"id\": \"" + path + "\", \"attributes\": " + value + " }}";
return doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setRpcRequest, String.class, status().isOk());
return doPostAsync("/api/plugins/rpc/twoway/" + lwM2MTestClient.getDeviceIdStr(), setRpcRequest, String.class, status().isOk());
}
private String sendDiscover(String path) throws Exception {
String setRpcRequest = "{\"method\": \"Discover\", \"params\": {\"id\": \"" + path + "\"}}";
return doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setRpcRequest, String.class, status().isOk());
return doPostAsync("/api/plugins/rpc/twoway/" + lwM2MTestClient.getDeviceIdStr(), setRpcRequest, String.class, status().isOk());
}
}

4
application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationExecuteTest.java

@ -174,12 +174,12 @@ public class RpcLwm2mIntegrationExecuteTest extends AbstractRpcLwM2MIntegrationT
private String sendRPCExecuteById(String path) throws Exception {
String setRpcRequest = "{\"method\": \"Execute\", \"params\": {\"id\": \"" + path + "\"}}";
return doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setRpcRequest, String.class, status().isOk());
return doPostAsync("/api/plugins/rpc/twoway/" + lwM2MTestClient.getDeviceIdStr(), setRpcRequest, String.class, status().isOk());
}
private String sendRPCExecuteWithValueById(String path, Object value) throws Exception {
String setRpcRequest = "{\"method\": \"Execute\", \"params\": {\"id\": \"" + path + "\", \"value\": " + value + " }}";
return doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setRpcRequest, String.class, status().isOk());
return doPostAsync("/api/plugins/rpc/twoway/" + lwM2MTestClient.getDeviceIdStr(), setRpcRequest, String.class, status().isOk());
}
}

26
application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationObserveTest.java

@ -45,13 +45,13 @@ public class RpcLwm2mIntegrationObserveTest extends AbstractRpcLwM2MIntegrationO
@Before
public void setupObserveTest() throws Exception {
awaitObserveReadAll(4, deviceId);
awaitObserveReadAll(4,lwM2MTestClient.getDeviceIdStr());
}
@Test
public void testObserveReadAll_Count_4_CancelAll_Count_0_Ok() throws Exception {
sendObserveCancelAllWithAwait(deviceId);
sendObserveCancelAllWithAwait(lwM2MTestClient.getDeviceIdStr());
}
/**
@ -61,7 +61,7 @@ public class RpcLwm2mIntegrationObserveTest extends AbstractRpcLwM2MIntegrationO
@Test
public void testObserveOneResource_Result_CONTENT_Value_Count_3_After_Cancel_Count_2() throws Exception {
long initSendTelemetryAtCount = countSendParametersOnThingsboardTelemetryResource(RESOURCE_ID_NAME_3_9);
sendObserveCancelAllWithAwait(deviceId);
sendObserveCancelAllWithAwait(lwM2MTestClient.getDeviceIdStr());
sendRpcObserveWithContainsLwM2mSingleResource(idVer_3_0_9);
updateRegAtLeastOnceAfterAction();
long lastSendTelemetryAtCount = countSendParametersOnThingsboardTelemetryResource(RESOURCE_ID_NAME_3_9);
@ -74,7 +74,7 @@ public class RpcLwm2mIntegrationObserveTest extends AbstractRpcLwM2MIntegrationO
*/
@Test
public void testObserveOneObjectInstance_Result_CONTENT_Value_Count_3_After_Cancel_Count_2() throws Exception {
sendObserveCancelAllWithAwait(deviceId);
sendObserveCancelAllWithAwait(lwM2MTestClient.getDeviceIdStr());
String idVer_3_0 = objectInstanceIdVer_3;
sendRpcObserveWithContainsLwM2mSingleResource(idVer_3_0);
@ -89,7 +89,7 @@ public class RpcLwm2mIntegrationObserveTest extends AbstractRpcLwM2MIntegrationO
*/
@Test
public void testObserveOneObject_Result_CONTENT_Value_Count_3_After_Cancel_Count_2() throws Exception {
sendObserveCancelAllWithAwait(deviceId);
sendObserveCancelAllWithAwait(lwM2MTestClient.getDeviceIdStr());
String idVer_3_0 = objectInstanceIdVer_3;
sendRpcObserveWithContainsLwM2mSingleResource(idVer_3_0);
@ -199,7 +199,7 @@ public class RpcLwm2mIntegrationObserveTest extends AbstractRpcLwM2MIntegrationO
*/
@Test
public void testObserves_OverlappedPaths_FirstResource_SecondObjectOrInstance() throws Exception {
sendObserveCancelAllWithAwait(deviceId);
sendObserveCancelAllWithAwait(lwM2MTestClient.getDeviceIdStr());
// "19/0/0"
sendRpcObserveOkWithResultValue("Observe", idVer_19_0_0);
// PreviousObservation "19/0/0" change to CurrentObservation "19" - object
@ -247,7 +247,7 @@ public class RpcLwm2mIntegrationObserveTest extends AbstractRpcLwM2MIntegrationO
*/
@Test
public void testObserveResource_ObserveCancelResource_Result_CONTENT_Count_1() throws Exception {
sendObserveCancelAllWithAwait(deviceId);
sendObserveCancelAllWithAwait(lwM2MTestClient.getDeviceIdStr());
String actualValuesReadAll = sendRpcObserveReadAllWithResult(idVer_3_0_9);
assertEquals(1, actualValuesReadAll.split(",").length);
@ -265,7 +265,7 @@ public class RpcLwm2mIntegrationObserveTest extends AbstractRpcLwM2MIntegrationO
*/
@Test
public void testObserveObject_ObserveCancelOneResource_Result_INTERNAL_SERVER_ERROR_Than_Cancel_ObserveObject_Result_CONTENT_Count_1() throws Exception {
sendObserveCancelAllWithAwait(deviceId);
sendObserveCancelAllWithAwait(lwM2MTestClient.getDeviceIdStr());
String actualValuesReadAll = sendRpcObserveReadAllWithResult(objectIdVer_3);
assertEquals(1, actualValuesReadAll.split(",").length);
@ -292,7 +292,7 @@ public class RpcLwm2mIntegrationObserveTest extends AbstractRpcLwM2MIntegrationO
*/
@Test
public void testObserveResource_ObserveCancelObject_Result_CONTENT_Count_1() throws Exception {
sendObserveCancelAllWithAwait(deviceId);
sendObserveCancelAllWithAwait(lwM2MTestClient.getDeviceIdStr());
sendRpcObserveWithWithTwoResource(idVer_3_0_0, idVer_3_0_9);
String rpcActualResul = sendRpcObserveOkWithResultValue("ObserveReadAll", null);
assertEquals(2, rpcActualResul.split(",").length);
@ -320,15 +320,13 @@ public class RpcLwm2mIntegrationObserveTest extends AbstractRpcLwM2MIntegrationO
*/
@Test
public void testObserveResource_Update_AfterUpdateRegistration() throws Exception {
sendObserveCancelAllWithAwait(deviceId);
sendObserveCancelAllWithAwait(lwM2MTestClient.getDeviceIdStr());
int cntUpdate = 3;
verify(defaultUplinkMsgHandlerTest, timeout(50000).atLeast(cntUpdate))
.updatedReg(Mockito.any(Registration.class));
awaitUpdateReg(3);
sendRpcObserveWithContainsLwM2mSingleResource(idVer_3_0_9);
cntUpdate = 10;
int cntUpdate = 10;
verify(defaultUplinkMsgHandlerTest, timeout(50000).atLeast(cntUpdate))
.updateAttrTelemetry(Mockito.any(Registration.class), eq(idVer_3_0_9), eq(null));
}

4
application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationReadCollectedValueTest.java

@ -62,7 +62,7 @@ public class RpcLwm2mIntegrationReadCollectedValueTest extends AbstractRpcLwM2MI
AtomicReference<ObjectNode> actualValues = new AtomicReference<>();
await().atMost(40, SECONDS).until(() -> {
actualValues.set(doGetAsync(
"/api/plugins/telemetry/DEVICE/" + deviceId + "/values/timeseries?keys="
"/api/plugins/telemetry/DEVICE/" + lwM2MTestClient.getDeviceIdStr() + "/values/timeseries?keys="
+ RESOURCE_ID_NAME_3303_12_5700
+ "&startTs=" + (RESOURCE_ID_3303_12_5700_TS_0 - RESOURCE_ID_VALUE_3303_12_5700_DELTA_TS)
+ "&endTs=" + (RESOURCE_ID_3303_12_5700_TS_1 + RESOURCE_ID_VALUE_3303_12_5700_DELTA_TS)
@ -93,6 +93,6 @@ public class RpcLwm2mIntegrationReadCollectedValueTest extends AbstractRpcLwM2MI
private String sendRPCById(String path) throws Exception {
String setRpcRequest = "{\"method\": \"Read\", \"params\": {\"id\": \"" + path + "\"}}";
return doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setRpcRequest, String.class, status().isOk());
return doPostAsync("/api/plugins/rpc/twoway/" + lwM2MTestClient.getDeviceIdStr(), setRpcRequest, String.class, status().isOk());
}
}

8
application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationReadTest.java

@ -232,21 +232,21 @@ public class RpcLwm2mIntegrationReadTest extends AbstractRpcLwM2MIntegrationTest
private String sendRPCById(String path) throws Exception {
String setRpcRequest = "{\"method\": \"Read\", \"params\": {\"id\": \"" + path + "\"}}";
return doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setRpcRequest, String.class, status().isOk());
return doPostAsync("/api/plugins/rpc/twoway/" + lwM2MTestClient.getDeviceIdStr(), setRpcRequest, String.class, status().isOk());
}
private String sendRPCByKey(String key) throws Exception {
String setRpcRequest = "{\"method\": \"Read\", \"params\": {\"key\": \"" + key + "\"}}";
return doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setRpcRequest, String.class, status().isOk());
return doPostAsync("/api/plugins/rpc/twoway/" + lwM2MTestClient.getDeviceIdStr(), setRpcRequest, String.class, status().isOk());
}
private String sendCompositeRPCByIds(String paths) throws Exception {
String setRpcRequest = "{\"method\": \"ReadComposite\", \"params\": {\"ids\":" + paths + "}}";
return doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setRpcRequest, String.class, status().isOk());
return doPostAsync("/api/plugins/rpc/twoway/" + lwM2MTestClient.getDeviceIdStr(), setRpcRequest, String.class, status().isOk());
}
private String sendCompositeRPCByKeys(String keys) throws Exception {
String setRpcRequest = "{\"method\": \"ReadComposite\", \"params\": {\"keys\":" + keys + "}}";
return doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setRpcRequest, String.class, status().isOk());
return doPostAsync("/api/plugins/rpc/twoway/" + lwM2MTestClient.getDeviceIdStr(), setRpcRequest, String.class, status().isOk());
}
}

4
application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationWriteCborTest.java

@ -88,11 +88,11 @@ public class RpcLwm2mIntegrationWriteCborTest extends AbstractRpcLwM2MIntegratio
private String sendRPCWriteObjectById(String method, String path, Object value) throws Exception {
String setRpcRequest = "{\"method\": \"" + method + "\", \"params\": {\"id\": \"" + path + "\", \"value\": " + value + " }}";
return doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setRpcRequest, String.class, status().isOk());
return doPostAsync("/api/plugins/rpc/twoway/" + lwM2MTestClient.getDeviceIdStr(), setRpcRequest, String.class, status().isOk());
}
private String sendRPCReadById(String id) throws Exception {
String setRpcRequest = "{\"method\": \"Read\", \"params\": {\"id\": \"" + id + "\"}}";
return doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setRpcRequest, String.class, status().isOk());
return doPostAsync("/api/plugins/rpc/twoway/" + lwM2MTestClient.getDeviceIdStr(), setRpcRequest, String.class, status().isOk());
}
}

196
application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationWriteTest.java

@ -20,6 +20,7 @@ import org.eclipse.leshan.core.ResponseCode;
import org.eclipse.leshan.core.node.LwM2mPath;
import org.junit.Test;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.script.api.tbel.TbUtils;
import org.thingsboard.server.transport.lwm2m.rpc.AbstractRpcLwM2MIntegrationTest;
import static org.junit.Assert.assertEquals;
@ -76,7 +77,157 @@ public class RpcLwm2mIntegrationWriteTest extends AbstractRpcLwM2MIntegrationTes
String expected = "LwM2mSingleResource [id=" + RESOURCE_ID_14 + ", value=" + expectedValue + ", type=STRING]";
assertTrue(actualValues.contains(expected));
}
@Test
public void testWriteReplaceValueMultipleResource_Result_CHANGED_Multi_Instance_Resource_must_One() throws Exception {
int resourceInstanceId0 = 0;
String expectedPath = objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_0 + "/" + resourceInstanceId0;
// base64/String
String expectedValue = "QUJDREVGRw";
String actualResult = sendRPCWriteStringById("WriteReplace", expectedPath, expectedValue);
ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
assertEquals(ResponseCode.CHANGED.getName(), rpcActualResult.get("result").asText());
actualResult = sendRPCReadById(expectedPath);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
String actualValues = rpcActualResult.get("value").asText();
byte[] expectedValue0 = TbUtils.base64ToBytes(expectedValue);
String expected = "LwM2mResourceInstance [id=" + resourceInstanceId0 + ", value=" + expectedValue0.length + "Bytes, type=OPAQUE]";
assertTrue(actualValues.contains(expected));
// base64/String
expectedValue = "ABCDEFG";
actualResult = sendRPCWriteStringById("WriteReplace", expectedPath, expectedValue);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
assertEquals(ResponseCode.CHANGED.getName(), rpcActualResult.get("result").asText());
actualResult = sendRPCReadById(expectedPath);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
actualValues = rpcActualResult.get("value").asText();
expectedValue0 = TbUtils.base64ToBytes(expectedValue);
expected = "LwM2mResourceInstance [id=" + resourceInstanceId0 + ", value=" + expectedValue0.length + "Bytes, type=OPAQUE]";
assertTrue(actualValues.contains(expected));
// hexDecimal/String
expectedValue = "01ABCDEF";
actualResult = sendRPCWriteStringById("WriteReplace", expectedPath, expectedValue);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
assertEquals(ResponseCode.CHANGED.getName(), rpcActualResult.get("result").asText());
actualResult = sendRPCReadById(expectedPath);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
actualValues = rpcActualResult.get("value").asText();
expected = "LwM2mResourceInstance [id=" + resourceInstanceId0 + ", value=" + expectedValue.length()/2 + "Bytes, type=OPAQUE]";
assertTrue(actualValues.contains(expected));
// Integer
Integer expectedIntegerValue = 1234566;
actualResult = sendRPCWriteObjectById("WriteReplace", expectedPath, expectedIntegerValue);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
assertEquals(ResponseCode.CHANGED.getName(), rpcActualResult.get("result").asText());
actualResult = sendRPCReadById(expectedPath);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
actualValues = rpcActualResult.get("value").asText();
expected = "LwM2mResourceInstance [id=" + resourceInstanceId0 + ", value=" + 4 + "Bytes, type=OPAQUE]";
assertTrue(actualValues.contains(expected));
expectedIntegerValue = Integer.MAX_VALUE;
actualResult = sendRPCWriteObjectById("WriteReplace", expectedPath, expectedIntegerValue);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
assertEquals(ResponseCode.CHANGED.getName(), rpcActualResult.get("result").asText());
actualResult = sendRPCReadById(expectedPath);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
actualValues = rpcActualResult.get("value").asText();
expected = "LwM2mResourceInstance [id=" + resourceInstanceId0 + ", value=" + 4 + "Bytes, type=OPAQUE]";
assertTrue(actualValues.contains(expected));
expectedIntegerValue = Integer.MIN_VALUE;
actualResult = sendRPCWriteObjectById("WriteReplace", expectedPath, expectedIntegerValue);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
assertEquals(ResponseCode.CHANGED.getName(), rpcActualResult.get("result").asText());
actualResult = sendRPCReadById(expectedPath);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
actualValues = rpcActualResult.get("value").asText();
expected = "LwM2mResourceInstance [id=" + resourceInstanceId0 + ", value=" + 4 + "Bytes, type=OPAQUE]";
assertTrue(actualValues.contains(expected));
// Long
Long expectedLongValue = 4406483977L;
actualResult = sendRPCWriteObjectById("WriteReplace", expectedPath, expectedLongValue);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
assertEquals(ResponseCode.CHANGED.getName(), rpcActualResult.get("result").asText());
actualResult = sendRPCReadById(expectedPath);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
actualValues = rpcActualResult.get("value").asText();
expected = "LwM2mResourceInstance [id=" + resourceInstanceId0 + ", value=" + 8 + "Bytes, type=OPAQUE]";
assertTrue(actualValues.contains(expected));
expectedLongValue = Long.MAX_VALUE;
actualResult = sendRPCWriteObjectById("WriteReplace", expectedPath, expectedLongValue);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
assertEquals(ResponseCode.CHANGED.getName(), rpcActualResult.get("result").asText());
actualResult = sendRPCReadById(expectedPath);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
actualValues = rpcActualResult.get("value").asText();
expected = "LwM2mResourceInstance [id=" + resourceInstanceId0 + ", value=" + 8 + "Bytes, type=OPAQUE]";
assertTrue(actualValues.contains(expected));
expectedLongValue = Long.MIN_VALUE;
actualResult = sendRPCWriteObjectById("WriteReplace", expectedPath, expectedLongValue);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
assertEquals(ResponseCode.CHANGED.getName(), rpcActualResult.get("result").asText());
actualResult = sendRPCReadById(expectedPath);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
actualValues = rpcActualResult.get("value").asText();
expected = "LwM2mResourceInstance [id=" + resourceInstanceId0 + ", value=" + 8 + "Bytes, type=OPAQUE]";
assertTrue(actualValues.contains(expected));
// Float to byte[]: byte[] bytes = ByteBuffer.allocate(4).putFloat(((Float) value).floatValue()).array();
// Float from byte[]: float f = ByteBuffer.wrap(bytes).getFloat();
Float expectedFloatValue = 8.02f;
actualResult = sendRPCWriteObjectById("WriteReplace", expectedPath, expectedFloatValue);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
assertEquals(ResponseCode.CHANGED.getName(), rpcActualResult.get("result").asText());
actualResult = sendRPCReadById(expectedPath);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
actualValues = rpcActualResult.get("value").asText();
expected = "LwM2mResourceInstance [id=" + resourceInstanceId0 + ", value=" + 4 + "Bytes, type=OPAQUE]";
assertTrue(actualValues.contains(expected));
expectedFloatValue = Float.MAX_VALUE;
actualResult = sendRPCWriteObjectById("WriteReplace", expectedPath, expectedFloatValue);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
assertEquals(ResponseCode.CHANGED.getName(), rpcActualResult.get("result").asText());
actualResult = sendRPCReadById(expectedPath);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
actualValues = rpcActualResult.get("value").asText();
expected = "LwM2mResourceInstance [id=" + resourceInstanceId0 + ", value=" + 4 + "Bytes, type=OPAQUE]";
assertTrue(actualValues.contains(expected));
expectedFloatValue = Float.MIN_VALUE;
actualResult = sendRPCWriteObjectById("WriteReplace", expectedPath, expectedFloatValue);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
assertEquals(ResponseCode.CHANGED.getName(), rpcActualResult.get("result").asText());
actualResult = sendRPCReadById(expectedPath);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
actualValues = rpcActualResult.get("value").asText();
expected = "LwM2mResourceInstance [id=" + resourceInstanceId0 + ", value=" + 4 + "Bytes, type=OPAQUE]";
assertTrue(actualValues.contains(expected));
// Double to byte[]: byte[] bytes = ByteBuffer.allocate(8).putDouble(((Double) value).doubleValue()).array();
// Double from byte[]: double d = ByteBuffer.wrap(bytes).getDouble();
Double expectedDoubleValue = 1022.5906d;
actualResult = sendRPCWriteObjectById("WriteReplace", expectedPath, expectedDoubleValue);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
assertEquals(ResponseCode.CHANGED.getName(), rpcActualResult.get("result").asText());
actualResult = sendRPCReadById(expectedPath);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
actualValues = rpcActualResult.get("value").asText();
expected = "LwM2mResourceInstance [id=" + resourceInstanceId0 + ", value=" + 4 + "Bytes, type=OPAQUE]";
assertTrue(actualValues.contains(expected));
expectedDoubleValue = Double.MAX_VALUE;
actualResult = sendRPCWriteObjectById("WriteReplace", expectedPath, expectedDoubleValue);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
assertEquals(ResponseCode.CHANGED.getName(), rpcActualResult.get("result").asText());
actualResult = sendRPCReadById(expectedPath);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
actualValues = rpcActualResult.get("value").asText();
expected = "LwM2mResourceInstance [id=" + resourceInstanceId0 + ", value=" + 8 + "Bytes, type=OPAQUE]";
assertTrue(actualValues.contains(expected));
expectedDoubleValue = Double.MIN_VALUE;
actualResult = sendRPCWriteObjectById("WriteReplace", expectedPath, expectedDoubleValue);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
assertEquals(ResponseCode.CHANGED.getName(), rpcActualResult.get("result").asText());
actualResult = sendRPCReadById(expectedPath);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
actualValues = rpcActualResult.get("value").asText();
expected = "LwM2mResourceInstance [id=" + resourceInstanceId0 + ", value=" + 8 + "Bytes, type=OPAQUE]";
assertTrue(actualValues.contains(expected));
}
/**
* id
@ -88,9 +239,9 @@ public class RpcLwm2mIntegrationWriteTest extends AbstractRpcLwM2MIntegrationTes
String expectedPath = objectIdVer_19 + "/" + OBJECT_INSTANCE_ID_0 + "/" + RESOURCE_ID_0;
int resourceInstanceId0 = 0;
int resourceInstanceId15 = 15;
String expectedValue0 = "0000ad45675600";
String expectedValue15 = "1525ad45675600cdef";
String expectedValue = "{\"" + resourceInstanceId0 + "\":\"" + expectedValue0 + "\", \"" + resourceInstanceId15 + "\":\"" + expectedValue15 + "\"}";
String expectedValue0 = "1525ad45675600cdef";
Integer expectedValue15 = Integer.MAX_VALUE;
String expectedValue = "{\"" + resourceInstanceId0 + "\":\"" + expectedValue0 + "\", \"" + resourceInstanceId15 + "\":" + expectedValue15 + "}";
String actualResult = sendRPCWriteObjectById("WriteReplace", expectedPath, expectedValue);
ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
assertEquals(ResponseCode.CHANGED.getName(), rpcActualResult.get("result").asText());
@ -99,12 +250,12 @@ public class RpcLwm2mIntegrationWriteTest extends AbstractRpcLwM2MIntegrationTes
actualResult = sendRPCReadById(expectedPath0);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
String actualValues = rpcActualResult.get("value").asText();
String expected = "LwM2mResourceInstance [id=" + resourceInstanceId0 + ", value=" + expectedValue0.length()/2 + "Bytes, type=OPAQUE]";
String expected = "LwM2mResourceInstance [id=" + resourceInstanceId0 + ", value=" + expectedValue0.length() / 2 + "Bytes, type=OPAQUE]";
assertTrue(actualValues.contains(expected));
actualResult = sendRPCReadById(expectedPath15);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
actualValues = rpcActualResult.get("value").asText();
expected = "LwM2mResourceInstance [id=" + resourceInstanceId15 + ", value=" + expectedValue15.length()/2 + "Bytes, type=OPAQUE]";
expected = "LwM2mResourceInstance [id=" + resourceInstanceId15 + ", value=" + Integer.toHexString(expectedValue15).length()/2 + "Bytes, type=OPAQUE]";
assertTrue(actualValues.contains(expected));
}
@ -130,7 +281,7 @@ public class RpcLwm2mIntegrationWriteTest extends AbstractRpcLwM2MIntegrationTes
actualResult = sendRPCReadById(expectedPath0);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
String actualValues = rpcActualResult.get("value").asText();
String expected = "LwM2mResourceInstance [id=" + resourceInstanceId0 + ", value=" + expectedValue0.length()/2 + "Bytes, type=OPAQUE]";
String expected = "LwM2mResourceInstance [id=" + resourceInstanceId0 + ", value=" + expectedValue0.length() / 2 + "Bytes, type=OPAQUE]";
assertFalse(actualValues.contains(expected));
}
@ -193,16 +344,16 @@ public class RpcLwm2mIntegrationWriteTest extends AbstractRpcLwM2MIntegrationTes
ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
assertEquals(ResponseCode.CHANGED.getName(), rpcActualResult.get("result").asText());
String expectedPath0 = expectedPath + "/" + RESOURCE_ID_0 + "/" + resourceInstanceId0;
String expectedPath25 =expectedPath + "/" + RESOURCE_ID_0 + "/" + resourceInstanceId25;
String expectedPath25 = expectedPath + "/" + RESOURCE_ID_0 + "/" + resourceInstanceId25;
actualResult = sendRPCReadById(expectedPath0);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
String actualValues = rpcActualResult.get("value").asText();
String expected = "LwM2mResourceInstance [id=" + resourceInstanceId0 + ", value=" + expectedValue0.length()/2 + "Bytes, type=OPAQUE]";
String expected = "LwM2mResourceInstance [id=" + resourceInstanceId0 + ", value=" + expectedValue0.length() / 2 + "Bytes, type=OPAQUE]";
assertTrue(actualValues.contains(expected));
actualResult = sendRPCReadById(expectedPath25);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
actualValues = rpcActualResult.get("value").asText();
expected = "LwM2mResourceInstance [id=" + resourceInstanceId25 + ", value=" + expectedValue25.length()/2 + "Bytes, type=OPAQUE]";
expected = "LwM2mResourceInstance [id=" + resourceInstanceId25 + ", value=" + expectedValue25.length() / 2 + "Bytes, type=OPAQUE]";
assertTrue(actualValues.contains(expected));
}
@ -232,13 +383,14 @@ public class RpcLwm2mIntegrationWriteTest extends AbstractRpcLwM2MIntegrationTes
actualResult = sendRPCReadById(expectedPath_19_0 + "/" + RESOURCE_ID_0 + "/" + resourceInstanceId0);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
String actualValues = rpcActualResult.get("value").asText();
String expected = "LwM2mResourceInstance [id=" + resourceInstanceId0 + ", value=" + expectedValue0.length()/2 + "Bytes, type=OPAQUE]";
String expected = "LwM2mResourceInstance [id=" + resourceInstanceId0 + ", value=" + expectedValue0.length() / 2 + "Bytes, type=OPAQUE]";
assertTrue(actualValues.contains(expected));
actualResult = sendRPCReadById(expectedPath_19_0 + "/" + RESOURCE_ID_0 + "/" + resourceInstanceId25);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
actualValues = rpcActualResult.get("value").asText();
expected = "LwM2mResourceInstance [id=" + resourceInstanceId25 + ", value=" + expectedValue25.length()/2 + "Bytes, type=OPAQUE]";
assertTrue(actualValues.contains(expected)); actualResult = sendRPCReadByKey(expectedKey3_0_14);
expected = "LwM2mResourceInstance [id=" + resourceInstanceId25 + ", value=" + expectedValue25.length() / 2 + "Bytes, type=OPAQUE]";
assertTrue(actualValues.contains(expected));
actualResult = sendRPCReadByKey(expectedKey3_0_14);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
actualValues = rpcActualResult.get("value").asText();
expected = "LwM2mSingleResource [id=" + RESOURCE_ID_14 + ", value=" + expectedValue3_0_14 + ", type=STRING]";
@ -270,12 +422,12 @@ public class RpcLwm2mIntegrationWriteTest extends AbstractRpcLwM2MIntegrationTes
actualResult = sendRPCReadById(expectedPath_19_0 + "/" + RESOURCE_ID_0 + "/" + resourceInstanceId0);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
String actualValues = rpcActualResult.get("value").asText();
String expected = "LwM2mResourceInstance [id=" + resourceInstanceId0 + ", value=" + expectedValue0.length()/2 + "Bytes, type=OPAQUE]";
String expected = "LwM2mResourceInstance [id=" + resourceInstanceId0 + ", value=" + expectedValue0.length() / 2 + "Bytes, type=OPAQUE]";
assertTrue(actualValues.contains(expected));
actualResult = sendRPCReadById(expectedPath_19_0 + "/" + RESOURCE_ID_0 + "/" + resourceInstanceId25);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
actualValues = rpcActualResult.get("value").asText();
expected = "LwM2mResourceInstance [id=" + resourceInstanceId25 + ", value=" + expectedValue25.length()/2 + "Bytes, type=OPAQUE]";
expected = "LwM2mResourceInstance [id=" + resourceInstanceId25 + ", value=" + expectedValue25.length() / 2 + "Bytes, type=OPAQUE]";
assertTrue(actualValues.contains(expected));
}
@ -301,7 +453,7 @@ public class RpcLwm2mIntegrationWriteTest extends AbstractRpcLwM2MIntegrationTes
actualResult = sendRPCReadById(expectedPath19_1_0_2);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
String actualValues = rpcActualResult.get("value").asText();
String expected = "LwM2mResourceInstance [id=" + RESOURCE_INSTANCE_ID_2 + ", value=" + expectedValue19_1_0_2.length()/2 + "Bytes, type=OPAQUE]";
String expected = "LwM2mResourceInstance [id=" + RESOURCE_INSTANCE_ID_2 + ", value=" + expectedValue19_1_0_2.length() / 2 + "Bytes, type=OPAQUE]";
assertTrue(actualValues.contains(expected));
actualResult = sendRPCReadByKey(expectedKey3_0_14);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
@ -346,31 +498,31 @@ public class RpcLwm2mIntegrationWriteTest extends AbstractRpcLwM2MIntegrationTes
private String sendRPCWriteStringById(String method, String path, String value) throws Exception {
String setRpcRequest = "{\"method\": \"" + method + "\", \"params\": {\"id\": \"" + path + "\", \"value\": \"" + value + "\" }}";
return doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setRpcRequest, String.class, status().isOk());
return doPostAsync("/api/plugins/rpc/twoway/" + lwM2MTestClient.getDeviceIdStr(), setRpcRequest, String.class, status().isOk());
}
private String sendRPCWriteObjectById(String method, String path, Object value) throws Exception {
String setRpcRequest = "{\"method\": \"" + method + "\", \"params\": {\"id\": \"" + path + "\", \"value\": " + value + " }}";
return doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setRpcRequest, String.class, status().isOk());
return doPostAsync("/api/plugins/rpc/twoway/" + lwM2MTestClient.getDeviceIdStr(), setRpcRequest, String.class, status().isOk());
}
private String sendRPCReadById(String id) throws Exception {
String setRpcRequest = "{\"method\": \"Read\", \"params\": {\"id\": \"" + id + "\"}}";
return doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setRpcRequest, String.class, status().isOk());
return doPostAsync("/api/plugins/rpc/twoway/" + lwM2MTestClient.getDeviceIdStr(), setRpcRequest, String.class, status().isOk());
}
private String sendRPCWriteByKey(String method, String key, String value) throws Exception {
String setRpcRequest = "{\"method\": \"" + method + "\", \"params\": {\"key\": \"" + key + "\", \"value\": \"" + value + "\" }}";
return doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setRpcRequest, String.class, status().isOk());
return doPostAsync("/api/plugins/rpc/twoway/" + lwM2MTestClient.getDeviceIdStr(), setRpcRequest, String.class, status().isOk());
}
private String sendRPCReadByKey(String key) throws Exception {
String setRpcRequest = "{\"method\": \"Read\", \"params\": {\"key\": \"" + key + "\"}}";
return doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setRpcRequest, String.class, status().isOk());
return doPostAsync("/api/plugins/rpc/twoway/" + lwM2MTestClient.getDeviceIdStr(), setRpcRequest, String.class, status().isOk());
}
private String sendCompositeRPC(String nodes) throws Exception {
String setRpcRequest = "{\"method\": \"WriteComposite\", \"params\": {\"nodes\":" + nodes + "}}";
return doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setRpcRequest, String.class, status().isOk());
return doPostAsync("/api/plugins/rpc/twoway/" + lwM2MTestClient.getDeviceIdStr(), setRpcRequest, String.class, status().isOk());
}
}

14
application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java

@ -207,7 +207,7 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M
boolean isStartLw) throws Exception {
DeviceProfile deviceProfile = createLwm2mDeviceProfile("profileFor" + endpoint, transportConfiguration);
final Device device = createLwm2mDevice(deviceCredentials, endpoint, deviceProfile.getId());
createNewClient(security, securityBs, true, endpoint);
createNewClient(security, securityBs, true, endpoint, device.getId().getId().toString());
lwM2MTestClient.start(isStartLw);
if (isAwaitObserveReadAll) {
awaitObserveReadAll(0, device.getId().getId().toString());
@ -218,6 +218,8 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M
log.warn("basicTestConnection started -> finishState: [{}] states: {}", finishState, lwM2MTestClient.getClientStates());
return lwM2MTestClient.getClientStates().contains(finishState) || lwM2MTestClient.getClientStates().contains(ON_REGISTRATION_STARTED);
});
awaitUpdateReg(1);
await(awaitAlias)
.atMost(40, TimeUnit.SECONDS)
.until(() -> {
@ -253,7 +255,7 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M
DeviceProfile deviceProfile = createLwm2mDeviceProfile("profileFor" + endpoint, transportConfiguration);
final Device device = createLwm2mDevice(deviceCredentials, endpoint, deviceProfile.getId());
String deviceIdStr = device.getId().getId().toString();
createNewClient(security, securityBs, true, endpoint);
createNewClient(security, securityBs, true, endpoint, deviceIdStr);
lwM2MTestClient.start(true);
awaitObserveReadAll(0, deviceIdStr);
await(awaitAlias)
@ -262,6 +264,8 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M
log.warn("basicTest First Connection started -> finishState: [{}] states: {}", ON_REGISTRATION_SUCCESS, lwM2MTestClient.getClientStates());
return lwM2MTestClient.getClientStates().contains(ON_REGISTRATION_SUCCESS) || lwM2MTestClient.getClientStates().contains(ON_REGISTRATION_STARTED);
});
awaitUpdateReg(1);
await(awaitAlias)
.atMost(40, TimeUnit.SECONDS)
.until(() -> {
@ -288,6 +292,8 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M
log.warn("basicTestConnection started -> finishState: [{}] states: {}", ON_REGISTRATION_SUCCESS, lwM2MTestClient.getClientStates());
return lwM2MTestClient.getClientStates().contains(ON_REGISTRATION_SUCCESS) || lwM2MTestClient.getClientStates().contains(ON_REGISTRATION_STARTED);
});
awaitUpdateReg(1);
await(awaitAlias)
.atMost(40, TimeUnit.SECONDS)
.until(() -> {
@ -392,12 +398,12 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M
protected void initDeviceCredentialsNoSek() {
clientEndpoint = CLIENT_ENDPOINT_NO_SEC + "_" + randomSuffix.nextInt(100);
clientEndpoint = CLIENT_ENDPOINT_NO_SEC + "_" + randomSuffix.nextInt(1000);
security = SECURITY_NO_SEC;
deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(clientEndpoint));
}
protected void initDeviceCredentialsPsk() {
int suf = randomSuffix.nextInt(10);
int suf = randomSuffix.nextInt(1000);
clientEndpoint = CLIENT_ENDPOINT_PSK + "_" + suf;
String identity = CLIENT_PSK_IDENTITY + "_" + suf;
clientCredentials = new PSKClientCredential();

7
application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLengthTest.java

@ -20,6 +20,7 @@ import org.eclipse.californium.elements.config.Configuration;
import org.eclipse.leshan.client.californium.endpoint.CaliforniumClientEndpoint;
import org.eclipse.leshan.client.californium.endpoint.CaliforniumClientEndpointsProvider;
import org.junit.Assert;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.dao.service.DaoSqlTest;
import org.thingsboard.server.transport.lwm2m.security.AbstractSecurityLwM2MIntegrationTest;
@ -50,9 +51,11 @@ public abstract class AbstractSecurityLwM2MIntegrationDtlsCidLengthTest extends
protected void basicTestConnectionDtlsCidLength(Integer clientDtlsCidLength,
Integer serverDtlsCidLength) throws Exception {
DeviceProfile deviceProfile = createLwm2mDeviceProfile("profileFor" + clientEndpoint, transportConfiguration);
createLwm2mDevice(deviceCredentials, clientEndpoint, deviceProfile.getId());
createNewClient(security, null, true, clientEndpoint, clientDtlsCidLength);
final Device device = createLwm2mDevice(deviceCredentials, clientEndpoint, deviceProfile.getId());
createNewClient(security, null, true, clientEndpoint, clientDtlsCidLength, device.getId().getId().toString());
lwM2MTestClient.start(true);
awaitUpdateReg(1);
await(awaitAlias)
.atMost(40, TimeUnit.SECONDS)
.until(() -> lwM2MTestClient.getClientStates().contains(ON_UPDATE_SUCCESS));

17
application/src/test/java/org/thingsboard/server/transport/lwm2m/security/diffPort/AbstractLwM2MIntegrationDiffPortTest.java

@ -19,10 +19,13 @@ import lombok.extern.slf4j.Slf4j;
import org.eclipse.leshan.core.peer.IpPeer;
import org.eclipse.leshan.core.peer.LwM2mPeer;
import org.eclipse.leshan.core.peer.SocketIdentity;
import org.eclipse.leshan.server.registration.Registration;
import org.eclipse.leshan.server.registration.RegistrationStore;
import org.eclipse.leshan.server.registration.RegistrationUpdate;
import org.junit.Assert;
import org.mockito.Mockito;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration;
import org.thingsboard.server.dao.service.DaoSqlTest;
@ -30,11 +33,14 @@ import org.thingsboard.server.transport.lwm2m.security.AbstractSecurityLwM2MInte
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.concurrent.TimeUnit;
import static org.awaitility.Awaitility.await;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_STARTED;
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_SUCCESS;
import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_UPDATE_SUCCESS;
@ -61,19 +67,26 @@ public abstract class AbstractLwM2MIntegrationDiffPortTest extends AbstractSecur
}).when(registrationStoreTest).updateRegistration(any(RegistrationUpdate.class));
DeviceProfile deviceProfile = createLwm2mDeviceProfile("profileFor" + clientEndpoint, transportConfiguration);
createLwm2mDevice(deviceCredentials, clientEndpoint, deviceProfile.getId());
createNewClient(security, null, true, clientEndpoint);
final Device device = createLwm2mDevice(deviceCredentials, clientEndpoint, deviceProfile.getId());
createNewClient(security, null, true, clientEndpoint, device.getId().getId().toString());
lwM2MTestClient.start(true);
verify(defaultUplinkMsgHandlerTest, timeout(50000).atLeast(1))
.onRegistered(Mockito.any(Registration.class), Mockito.any());
await(awaitAlias)
.atMost(40, TimeUnit.SECONDS)
.until(() -> lwM2MTestClient.getClientStates().contains(ON_REGISTRATION_SUCCESS) || lwM2MTestClient.getClientStates().contains(ON_REGISTRATION_STARTED));
Assert.assertTrue(lwM2MTestClient.getClientStates().containsAll(expectedStatusesRegistrationLwm2mSuccess));
awaitUpdateReg(1);
await(awaitAlias)
.atMost(40, TimeUnit.SECONDS)
.until(() -> lwM2MTestClient.getClientStates().contains(ON_UPDATE_SUCCESS));
Assert.assertTrue(lwM2MTestClient.getClientStates().containsAll(expectedStatusesRegistrationLwm2mSuccessUpdate));
long cntBefore = countUpdateReg();
awaitUpdateReg((int) (cntBefore + 1));
}
private RegistrationUpdate registrationUpdateNewPort (RegistrationUpdate update, int portValueChange) {

10
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java

@ -15,6 +15,7 @@
*/
package org.thingsboard.server.transport.lwm2m.server.downlink;
import com.google.gson.JsonParser;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.RequiredArgsConstructor;
@ -396,7 +397,12 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
String msgError = "";
if (resourceModelWrite.multiple) {
try {
Map<Integer, Object> value = convertMultiResourceValuesFromRpcBody(request.getValue(), resourceModelWrite.type, request.getObjectId());
Object valueForMultiResource = request.getValue();
if (resultIds.isResourceInstance()) {
String resourceInstance = "{" + resultIds.getResourceInstanceId() + "=" + request.getValue() + "}";
valueForMultiResource = JsonParser.parseString(resourceInstance);
}
Map<Integer, Object> value = convertMultiResourceValuesFromRpcBody(valueForMultiResource, resourceModelWrite.type, request.getObjectId());
downlink = new WriteRequest(contentFormat, resultIds.getObjectId(), resultIds.getObjectInstanceId(), resultIds.getResourceId(),
value, resourceModelWrite.type);
} catch (Exception e) {
@ -707,7 +713,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im
LwM2mPath pathIds = new LwM2mPath(fromVersionedIdToObjectId(versionedId));
if (pathIds.isResourceInstance() || pathIds.isResource()) {
ResourceModel resourceModel = client.getResourceModel(versionedId, modelProvider);
if (resourceModel != null && (pathIds.isResourceInstance() || (pathIds.isResource() && !resourceModel.multiple))) {
if (resourceModel != null && !resourceModel.multiple) {
ContentFormat[] desiredFormats;
if (OBJLNK.equals(resourceModel.type)) {
desiredFormats = new ContentFormat[]{ContentFormat.LINK, ContentFormat.CBOR, ContentFormat.SENML_CBOR, ContentFormat.SENML_JSON};

23
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/rpc/DefaultLwM2MRpcRequestHandler.java

@ -277,17 +277,6 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
private void sendWriteReplaceRequest(LwM2mClient client, TransportProtos.ToDeviceRpcRequestMsg requestMsg, String versionedId) {
RpcWriteReplaceRequest requestBody = JacksonUtil.fromString(requestMsg.getParams(), RpcWriteReplaceRequest.class);
LwM2mPath path = new LwM2mPath(fromVersionedIdToObjectId(versionedId));
if (path.isResource()) {
ResourceModel resourceModel = client.getResourceModel(versionedId, modelProvider);
if (resourceModel != null && resourceModel.multiple) {
try {
Map<Integer, Object> value = convertMultiResourceValuesFromRpcBody(requestBody.getValue(), resourceModel.type, versionedId);
requestBody.setValue(value);
} catch (Exception e) {
}
}
}
TbLwM2MWriteReplaceRequest request = TbLwM2MWriteReplaceRequest.builder().versionedId(versionedId)
.value(requestBody.getValue())
.timeout(clientContext.getRequestTimeout(client)).build();
@ -330,7 +319,7 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
if (versionedId == null) {
if (path.isResourceInstance()) {
setValueToCompositeNodes(client, newNodes, nodes, key, value.toString());
setValueToCompositeNodes(client, newNodes, nodes, key, value);
} else if (path.isResource()) {
validateResource(client, newNodes, nodes, key , value);
} else if (path.isObjectInstance() && value instanceof Map<?, ?>) {
@ -342,7 +331,7 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
"The WriteComposite operation is only used for SingleResources or/and ResourceInstance.", nodes));
}
} else {
setValueToCompositeNodes(client, newNodes, nodes, versionedId, value.toString());
setValueToCompositeNodes(client, newNodes, nodes, versionedId, value);
}
});
return newNodes;
@ -351,10 +340,10 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
private void validateResource(LwM2mClient client, Map newNodes, Map nodes, String resourceId , Object value) {
if (value instanceof Map<?, ?>) {
((Map<?, ?>) value).forEach((k, v) -> {
setValueToCompositeNodes(client, newNodes, nodes, validateResourceId (resourceId, k.toString(), nodes), v.toString());
setValueToCompositeNodes(client, newNodes, nodes, validateResourceId (resourceId, k.toString(), nodes), v);
});
} else {
setValueToCompositeNodes(client, newNodes, nodes, resourceId, value.toString());
setValueToCompositeNodes(client, newNodes, nodes, resourceId, value);
}
}
@ -368,7 +357,7 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
}
}
private void setValueToCompositeNodes (LwM2mClient client, Map newNodes, Map nodes, String versionedId , String value) {
private void setValueToCompositeNodes (LwM2mClient client, Map newNodes, Map nodes, String versionedId , Object value) {
// validate value. Must be only primitive, not JsonObject or JsonArray
try {
JsonElement element = JsonUtils.parse(value);
@ -378,7 +367,7 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
}
// convert value from JsonPrimitive() to resource/ResourceInstance type
ResourceModel resourceModel = client.getResourceModel(versionedId, modelProvider);
Object newValue = convertValueByTypeResource(value, resourceModel.type, versionedId);
Object newValue = convertValueByTypeResource(element, resourceModel.type, versionedId);
// add new value after convert
newNodes.put(fromVersionedIdToObjectId(versionedId), newValue);

51
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2MTransportUtil.java

@ -16,6 +16,7 @@
package org.thingsboard.server.transport.lwm2m.utils;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.californium.elements.config.Configuration;
import org.eclipse.leshan.core.model.LwM2mModel;
@ -27,7 +28,6 @@ import org.eclipse.leshan.core.node.LwM2mPath;
import org.eclipse.leshan.core.node.LwM2mResource;
import org.eclipse.leshan.core.node.LwM2mSingleResource;
import org.eclipse.leshan.core.util.Hex;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.DeviceTransportType;
import org.thingsboard.server.common.data.StringUtils;
@ -35,7 +35,6 @@ import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportC
import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration;
import org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap.LwM2MBootstrapServerCredential;
import org.thingsboard.server.common.data.ota.OtaPackageKey;
import org.thingsboard.server.common.transport.util.JsonUtils;
import org.thingsboard.server.transport.lwm2m.config.TbLwM2mVersion;
import org.thingsboard.server.transport.lwm2m.server.LwM2mOtaConvert;
import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient;
@ -62,6 +61,7 @@ import static org.eclipse.leshan.core.model.ResourceModel.Type.STRING;
import static org.eclipse.leshan.core.model.ResourceModel.Type.TIME;
import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_KEY;
import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH;
import static org.thingsboard.server.common.transport.util.JsonUtils.convertToJsonObject;
import static org.thingsboard.server.transport.lwm2m.server.ota.DefaultLwM2MOtaUpdateService.FW_RESULT_ID;
import static org.thingsboard.server.transport.lwm2m.server.ota.DefaultLwM2MOtaUpdateService.FW_STATE_ID;
import static org.thingsboard.server.transport.lwm2m.server.ota.DefaultLwM2MOtaUpdateService.SW_RESULT_ID;
@ -180,9 +180,11 @@ public class LwM2MTransportUtil {
*/
public static ResourceModel.Type equalsResourceTypeGetSimpleName(Object value) {
switch (value.getClass().getSimpleName()) {
case "Float":
case "Double":
return FLOAT;
case "Integer":
case "Long":
return INTEGER;
case "String":
return STRING;
@ -199,6 +201,30 @@ public class LwM2MTransportUtil {
}
}
public static Object getJsonPrimitiveValue(JsonPrimitive value) {
if(value.isString()) {
return value.getAsString();
} else if (value.isNumber()){
try {
return Integer.valueOf(value.toString());
} catch (NumberFormatException i) {
try {
return Long.valueOf(value.toString());
} catch (NumberFormatException l){
if (value.getAsFloat() >= Float.MIN_VALUE && value.getAsFloat() <= Float.MAX_VALUE) {
return value.getAsFloat();
} else {
return value.getAsDouble();
}
}
}
} else if (value.isBoolean()){
return value.getAsBoolean();
} else {
return null;
}
}
public static void validateVersionedId(LwM2mClient client, HasVersionedId request) {
String msgExceptionStr = "";
if (request.getObjectId() == null) {
@ -212,22 +238,29 @@ public class LwM2MTransportUtil {
}
public static Map<Integer, Object> convertMultiResourceValuesFromRpcBody(Object value, ResourceModel.Type type, String versionedId) throws Exception {
String valueJsonStr = JacksonUtil.toString(value);
JsonElement element = JsonUtils.parse(valueJsonStr);
return convertMultiResourceValuesFromJson(element, type, versionedId);
if (value instanceof JsonElement) {
return convertMultiResourceValuesFromJson((JsonElement) value, type, versionedId);
} else if (value instanceof Map) {
JsonElement valueConvert = convertToJsonObject((Map<String, ?>) value);
return convertMultiResourceValuesFromJson(valueConvert, type, versionedId);
} else {
return null;
}
}
public static Map<Integer, Object> convertMultiResourceValuesFromJson(JsonElement newValProto, ResourceModel.Type type, String versionedId) {
Map<Integer, Object> newValues = new HashMap<>();
newValProto.getAsJsonObject().entrySet().forEach((obj) -> {
newValues.put(Integer.valueOf(obj.getKey()), convertValueByTypeResource(obj.getValue().getAsString(), type, versionedId));
Object valueByTypeResource = convertValueByTypeResource(obj.getValue(), type, versionedId);
newValues.put(Integer.valueOf(obj.getKey()), valueByTypeResource);
});
return newValues;
}
public static Object convertValueByTypeResource(String value, ResourceModel.Type type, String versionedId) {
return LwM2mValueConverterImpl.getInstance().convertValue(value,
STRING, type, new LwM2mPath(fromVersionedIdToObjectId(versionedId)));
public static Object convertValueByTypeResource(Object value, ResourceModel.Type type, String versionedId) {
Object valueCurrent = getJsonPrimitiveValue((JsonPrimitive) value);
return LwM2mValueConverterImpl.getInstance().convertValue(valueCurrent,
equalsResourceTypeGetSimpleName(valueCurrent), type, new LwM2mPath(fromVersionedIdToObjectId(versionedId)));
}
/**

17
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java

@ -25,6 +25,7 @@ import org.eclipse.leshan.core.util.Hex;
import org.thingsboard.server.common.data.StringUtils;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Base64;
@ -165,7 +166,19 @@ public class LwM2mValueConverterImpl implements LwM2mValueConverter {
}
break;
case OPAQUE:
if (currentType == Type.STRING) {
if (currentType == Type.INTEGER) {
if (value instanceof Integer) {
return ByteBuffer.allocate(4).putInt((Integer) value).array();
} else {
return ByteBuffer.allocate(8).putLong((Long) value).array();
}
} else if (currentType == Type.FLOAT) {
if (value instanceof Float) {
return ByteBuffer.allocate(4).putFloat((Float) value).array();
} else {
return ByteBuffer.allocate(8).putDouble((Double) value).array();
}
} else if (currentType == Type.STRING) {
/** let's assume we received an hexadecimal string */
log.debug("Trying to convert hexadecimal/base64 string [{}] to byte array", value);
try {
@ -178,6 +191,8 @@ public class LwM2mValueConverterImpl implements LwM2mValueConverter {
value, resourcePath);
}
}
} else if (currentType == Type.BOOLEAN) {
return new byte[] {(byte)((boolean)value ? 1 : 0)};
}
break;
case OBJLNK:

1
common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java

@ -45,6 +45,7 @@ import org.thingsboard.server.common.data.ResourceType;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.device.data.PowerMode;
import org.thingsboard.server.common.data.exception.TenantNotFoundException;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.DeviceProfileId;

29
common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/util/JsonUtils.java

@ -18,9 +18,11 @@ package org.thingsboard.server.common.transport.util;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import org.thingsboard.server.gen.transport.TransportProtos.KeyValueProto;
import java.util.List;
import java.util.Map;
public class JsonUtils {
@ -47,9 +49,30 @@ public class JsonUtils {
}
return json;
}
public static JsonElement parse(String params) {
return JsonParser.parseString(params);
public static JsonElement parse(Object value) {
if (value instanceof Integer) {
return new JsonPrimitive((Integer) value);
} else if (value instanceof Long) {
return new JsonPrimitive((Long) value);
} else if (value instanceof String) {
return JsonParser.parseString((String) value);
} else if (value instanceof Boolean) {
return new JsonPrimitive((Boolean) value);
} else if (value instanceof Double) {
return new JsonPrimitive((Double) value);
} else if (value instanceof Float) {
return new JsonPrimitive((Float) value);
} else {
throw new IllegalArgumentException("Unsupported type: " + value.getClass().getSimpleName());
}
}
public static JsonObject convertToJsonObject(Map<String,?> map) {
JsonObject jsonObject = new JsonObject();
for (Map.Entry<String, ?> entry : map.entrySet()) {
jsonObject.add(entry.getKey(), parse(entry.getValue()));
}
return jsonObject;
}
}

Loading…
Cancel
Save