Browse Source

lwm2m: fix_bug UNSIGNED_INTEGER-values-encoding-for-LwM2M-multi-resources

pull/16095/head
nickAS21 1 month ago
parent
commit
67c3e1063a
  1. 3
      application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java
  2. 169
      application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationWriteTest.java
  3. 14
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2MTransportUtil.java
  4. 24
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java
  5. 3
      common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/util/JsonUtils.java

3
application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java

@ -43,7 +43,8 @@ public class Lwm2mTestHelper {
public static final int RESOURCE_ID_14 = 14;
public static final int RESOURCE_ID_15 = 15;
public static final int RESOURCE_ID_120 = 120; // INTEGER_VALUE
public static final int RESOURCE_ID_125 = 125; // UNSIGNED_INTEGER_VALUE
public static final int RESOURCE_ID_125 = 125; // UNSIGNED_INTEGER_VALUE single-ресурс
public static final int RESOURCE_ID_1125 = 1125; // UNSIGNED_INTEGER_VALUE multi-instance
public static final int RESOURCE_ID_5700 = 5700;
public static final int RESOURCE_INSTANCE_ID_0 = 0;
public static final int RESOURCE_INSTANCE_ID_2 = 2;

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

@ -82,22 +82,112 @@ public class RpcLwm2mIntegrationWriteTest extends AbstractRpcLwM2MIntegrationTes
}
/**
* update SingleResource:
* WriteReplace {"id":"3442/0/120","value":"18446744073709551615} // ULong.MAX
* UnsignedInteger -> SingleResource (WriteReplace):
* {"method": "WriteReplace", "params": {"id": "/3442_1.0/0/125", "value": 18446744073709551615 }} // ULong.MAX
* {"result":"CHANGED"}
*/
@Test
public void testWriteReplaceUnIntegerValuesSingleResourceById_Result_CHANGED() throws Exception {
String expectedPath = objectInstanceIdVer_3442 + "/" + RESOURCE_ID_125;
ULong expectedValue = ULong.MAX;
String actualResult = sendRPCWriteObjectById("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();
String expected = "LwM2mSingleResource [id=" + RESOURCE_ID_125 + ", value=" + expectedValue + ", type=" + UNSIGNED_INTEGER.name() + "]";
assertTrue(actualValues.contains(expected));
ULong expectedValueId125 = ULong.valueOf(0);
sendRPC_3442_ResourceId_125_WriteReplace(expectedValueId125);
expectedValueId125 = ULong.valueOf(-1);
sendRPC_3442_ResourceId_125_WriteReplace(expectedValueId125);
expectedValueId125 = ULong.valueOf(-100);
sendRPC_3442_ResourceId_125_WriteReplace(expectedValueId125);
expectedValueId125 = ULong.valueOf(Integer.MIN_VALUE);
sendRPC_3442_ResourceId_125_WriteReplace(expectedValueId125);
expectedValueId125 = ULong.valueOf(Integer.MAX_VALUE);
sendRPC_3442_ResourceId_125_WriteReplace(expectedValueId125);
expectedValueId125 = ULong.valueOf(Long.MIN_VALUE);
sendRPC_3442_ResourceId_125_WriteReplace(expectedValueId125);
expectedValueId125 = ULong.valueOf(Long.MAX_VALUE);
sendRPC_3442_ResourceId_125_WriteReplace(expectedValueId125);
expectedValueId125 = ULong.MIN;
sendRPC_3442_ResourceId_125_WriteReplace(expectedValueId125);
expectedValueId125 = ULong.MAX;
sendRPC_3442_ResourceId_125_WriteReplace(expectedValueId125);
}
/**
* UnsignedInteger -> SingleResource (WriteUpdate):
* {"method": "WriteUpdate", "params": {"id": "/3442_1.0/0", "value": {"125":18446744073709551615} }} // ULong.MAX
* {"result":"CHANGED"}
*/
@Test
public void testWriteUpdateUnsignedIntegerValuesSingleResourceById_Result_CHANGED() throws Exception {
ULong expectedValueId125 = ULong.valueOf(0);
sendRPC_3442_ResourceId_125_WriteUpdate(expectedValueId125);
expectedValueId125 = ULong.valueOf(-1);
sendRPC_3442_ResourceId_125_WriteUpdate(expectedValueId125);
expectedValueId125 = ULong.valueOf(-100);
sendRPC_3442_ResourceId_125_WriteUpdate(expectedValueId125);
expectedValueId125 = ULong.valueOf(Integer.MIN_VALUE);
sendRPC_3442_ResourceId_125_WriteUpdate(expectedValueId125);
expectedValueId125 = ULong.valueOf(Integer.MAX_VALUE);
sendRPC_3442_ResourceId_125_WriteUpdate(expectedValueId125);
expectedValueId125 = ULong.valueOf(Long.MIN_VALUE);
sendRPC_3442_ResourceId_125_WriteUpdate(expectedValueId125);
expectedValueId125 = ULong.valueOf(Long.MAX_VALUE);
sendRPC_3442_ResourceId_125_WriteUpdate(expectedValueId125);
expectedValueId125 = ULong.MAX;
sendRPC_3442_ResourceId_125_WriteUpdate(expectedValueId125);
expectedValueId125 = ULong.MIN;
sendRPC_3442_ResourceId_125_WriteUpdate(expectedValueId125);
}
/**
* UnsignedInteger -> MultipleResource (WriteReplace):
* {"method": "WriteReplace", "params": {"id": "/3442_1.0/0/1125/0", "value": 18446744073709551615 }} // ULong.MAX
* {"result":"CHANGED"}
*/
@Test
public void testWriteReplaceUnsignedIntegerValuesMultipleResourceById_Result_CHANGED() throws Exception {
ULong expectedValueId125 = ULong.valueOf(0);
sendRPC_3442_ResourceId_1125_WriteReplace(expectedValueId125);
expectedValueId125 = ULong.valueOf(-1);
sendRPC_3442_ResourceId_1125_WriteReplace(expectedValueId125);
expectedValueId125 = ULong.valueOf(-100);
sendRPC_3442_ResourceId_1125_WriteReplace(expectedValueId125);
expectedValueId125 = ULong.valueOf(Integer.MIN_VALUE);
sendRPC_3442_ResourceId_1125_WriteReplace(expectedValueId125);
expectedValueId125 = ULong.valueOf(Integer.MAX_VALUE);
sendRPC_3442_ResourceId_1125_WriteReplace(expectedValueId125);
expectedValueId125 = ULong.valueOf(Long.MIN_VALUE);
sendRPC_3442_ResourceId_1125_WriteReplace(expectedValueId125);
expectedValueId125 = ULong.valueOf(Long.MAX_VALUE);
sendRPC_3442_ResourceId_1125_WriteReplace(expectedValueId125);
expectedValueId125 = ULong.MAX;
sendRPC_3442_ResourceId_1125_WriteReplace(expectedValueId125);
expectedValueId125 = ULong.MIN;
sendRPC_3442_ResourceId_1125_WriteReplace(expectedValueId125);
}
/**
* UnsignedInteger -> MultipleResource (WriteUpdate):
* {"method": "WriteUpdate", "params": {"id": "/3442_1.0/0", "value": {"1125":{"0":"18446744073709551615"}} }} // 0 ->ULong.MAX
* {"method": "WriteUpdate", "params": {"id": "/3442_1.0/0", "value": {"1125":{"0":"18446744073709551615", "12":"0"}} }} // 0 ->ULong.MAX, 12 - > 0
* {"result":"CHANGED"}
*/
@Test
public void testWriteUpdateUnsignedIntegerValuesMultipleResourceById_Result_CHANGED() throws Exception {
ULong expectedValueId1125 = ULong.valueOf(0);
sendRPC_3442_ResourceId_1125_WriteUpdate(expectedValueId1125);
expectedValueId1125 = ULong.valueOf(-1);
sendRPC_3442_ResourceId_1125_WriteUpdate(expectedValueId1125);
expectedValueId1125 = ULong.valueOf(-100);
sendRPC_3442_ResourceId_1125_WriteUpdate(expectedValueId1125);
expectedValueId1125 = ULong.valueOf(Integer.MIN_VALUE);
sendRPC_3442_ResourceId_1125_WriteUpdate(expectedValueId1125);
expectedValueId1125 = ULong.valueOf(Integer.MAX_VALUE);
sendRPC_3442_ResourceId_1125_WriteUpdate(expectedValueId1125);
expectedValueId1125 = ULong.valueOf(Long.MIN_VALUE);
sendRPC_3442_ResourceId_1125_WriteUpdate(expectedValueId1125);
expectedValueId1125 = ULong.valueOf(Long.MAX_VALUE);
sendRPC_3442_ResourceId_1125_WriteUpdate(expectedValueId1125);
expectedValueId1125 = ULong.MAX;
sendRPC_3442_ResourceId_1125_WriteUpdate(expectedValueId1125);
expectedValueId1125 = ULong.MIN;
sendRPC_3442_ResourceId_1125_WriteUpdate(expectedValueId1125);
}
/**
@ -646,4 +736,59 @@ public class RpcLwm2mIntegrationWriteTest extends AbstractRpcLwM2MIntegrationTes
String expected = "LwM2mSingleResource [id=" + RESOURCE_ID_120 + ", value=" + expectedValue + ", type=" + INTEGER.name() + "]";
assertTrue(actualValues.contains(expected));
}
private void sendRPC_3442_ResourceId_125_WriteReplace (ULong expectedValue) throws Exception {
String expectedPath = objectInstanceIdVer_3442 + "/" + RESOURCE_ID_125;
String actualResult = sendRPCWriteObjectById("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();
String expected = "LwM2mSingleResource [id=" + RESOURCE_ID_125 + ", value=" + expectedValue + ", type=" + UNSIGNED_INTEGER.name() + "]";
assertTrue(actualValues.contains(expected));
}
private void sendRPC_3442_ResourceId_125_WriteUpdate(ULong expectedValueId125) throws Exception {
String expectedPath = objectInstanceIdVer_3442;
String expectedValue = "{\"" + RESOURCE_ID_125 + "\":" + expectedValueId125 + "}";
String actualResult = sendRPCWriteObjectById("WriteUpdate", expectedPath, expectedValue);
ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
assertEquals(ResponseCode.CHANGED.getName(), rpcActualResult.get("result").asText());
String expectedPath125 = objectInstanceIdVer_3442 + "/" + RESOURCE_ID_125;
actualResult = sendRPCReadById(expectedPath125);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
String actualValues = rpcActualResult.get("value").asText();
String expected = "LwM2mSingleResource [id=" + RESOURCE_ID_125 + ", value=" + expectedValueId125 + ", type=" + UNSIGNED_INTEGER.name() + "]";
assertTrue(actualValues.contains(expected));
}
private void sendRPC_3442_ResourceId_1125_WriteReplace(ULong expectedValue) throws Exception {
int resourceInstanceId0 = 0;
String expectedPath = objectInstanceIdVer_3442 + "/" + RESOURCE_ID_1125 + "/" + resourceInstanceId0;
String actualResult = sendRPCWriteObjectById("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();
String expected = "LwM2mResourceInstance [id=" + resourceInstanceId0 + ", value=" + expectedValue + ", type=" + UNSIGNED_INTEGER.name() + "]";
assertTrue(actualValues.contains(expected));
}
private void sendRPC_3442_ResourceId_1125_WriteUpdate(ULong expectedValueId1125) throws Exception {
String expectedPath = objectInstanceIdVer_3442;
int resourceInstanceId0 = 0;
String expectedValue = "{\"" + RESOURCE_ID_1125 + "\":{\"" + RESOURCE_ID_0 + "\":" + expectedValueId1125 + "}}";
String actualResult = sendRPCWriteObjectById("WriteUpdate", expectedPath, expectedValue);
ObjectNode rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
assertEquals(ResponseCode.CHANGED.getName(), rpcActualResult.get("result").asText());
String expectedPath1125 = objectInstanceIdVer_3442 + "/" + RESOURCE_ID_1125 + "/" + resourceInstanceId0;
actualResult = sendRPCReadById(expectedPath1125);
rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class);
String actualValues = rpcActualResult.get("value").asText();
String expected = "LwM2mResourceInstance [id=" + resourceInstanceId0 + ", value=" + expectedValueId1125 + ", type=" + UNSIGNED_INTEGER.name() + "]";
assertTrue(actualValues.contains(expected));
}
}

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

@ -45,6 +45,7 @@ import org.thingsboard.server.transport.lwm2m.server.ota.firmware.FirmwareUpdate
import org.thingsboard.server.transport.lwm2m.server.ota.software.SoftwareUpdateResult;
import org.thingsboard.server.transport.lwm2m.server.ota.software.SoftwareUpdateState;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@ -186,6 +187,7 @@ public class LwM2MTransportUtil {
return FLOAT;
case "Integer":
case "Long":
case "BigInteger":
return INTEGER;
case "String":
return STRING;
@ -212,10 +214,14 @@ public class LwM2MTransportUtil {
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();
try {
return new BigInteger(value.toString());
} catch (NumberFormatException k) {
if (value.getAsFloat() >= Float.MIN_VALUE && value.getAsFloat() <= Float.MAX_VALUE) {
return value.getAsFloat();
} else {
return value.getAsDouble();
}
}
}
}

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

@ -22,6 +22,7 @@ import org.eclipse.leshan.core.node.ObjectLink;
import org.eclipse.leshan.core.node.codec.CodecException;
import org.eclipse.leshan.core.node.codec.LwM2mValueConverter;
import org.eclipse.leshan.core.util.Hex;
import org.eclipse.leshan.core.util.datatype.ULong;
import org.thingsboard.server.common.data.StringUtils;
import java.math.BigInteger;
@ -73,6 +74,7 @@ public class LwM2mValueConverterImpl implements LwM2mValueConverter {
if ((double) value == longValue.doubleValue()) {
return longValue;
}
break;
case STRING:
log.debug("Trying to convert String value [{}] to Integer", value);
return Long.parseLong((String) value);
@ -80,6 +82,28 @@ public class LwM2mValueConverterImpl implements LwM2mValueConverter {
break;
}
break;
case UNSIGNED_INTEGER:
switch (currentType) {
case INTEGER:
if (value instanceof Integer) {
log.debug("Trying to convert Integer value [{}] to Unsigned Integer", value);
return ULong.valueOf(Integer.toUnsignedLong((Integer) value));
} else if (value instanceof Long) {
log.debug("Trying to convert Long value [{}] to Unsigned Integer", value);
return ULong.valueOf((Long) value);
} else if (value instanceof BigInteger) {
log.debug("Trying to convert Biginteger value [{}] to Unsigned Integer", value);
return ULong.valueOf((BigInteger) value);
}
throw new IllegalArgumentException("Trying to convert value [" + value + "] to Unsigned Integer. Unsupported value type: " + value.getClass());
case FLOAT:
log.debug("Trying to convert float value [{}] to Unsigned Integer", value);
return ULong.valueOf(((Float) value).longValue());
case STRING:
log.debug("Trying to convert string value [{}] to Unsigned Integer", value);
return ULong.valueOf((String) value);
}
break;
case FLOAT:
switch (currentType) {
case INTEGER:

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

@ -21,6 +21,7 @@ import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import org.thingsboard.server.gen.transport.TransportProtos.KeyValueProto;
import java.math.BigInteger;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
@ -58,6 +59,8 @@ public class JsonUtils {
return new JsonPrimitive((Integer) value);
} else if (value instanceof Long) {
return new JsonPrimitive((Long) value);
} else if (value instanceof BigInteger) {
return new JsonPrimitive((BigInteger) value);
} else if (value instanceof String) {
try {
return JsonParser.parseString((String) value);

Loading…
Cancel
Save