Merge pull request #12825 from irynamatveieva/cf-rounding-result
Added option to round result for simple type
This commit is contained in:
commit
e6438c51f0
@ -20,6 +20,7 @@ import com.google.common.util.concurrent.ListenableFuture;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import org.thingsboard.common.util.JacksonUtil;
|
import org.thingsboard.common.util.JacksonUtil;
|
||||||
|
import org.thingsboard.script.api.tbel.TbUtils;
|
||||||
import org.thingsboard.server.common.data.cf.CalculatedFieldType;
|
import org.thingsboard.server.common.data.cf.CalculatedFieldType;
|
||||||
import org.thingsboard.server.common.data.cf.configuration.Output;
|
import org.thingsboard.server.common.data.cf.configuration.Output;
|
||||||
import org.thingsboard.server.common.data.kv.BasicKvEntry;
|
import org.thingsboard.server.common.data.kv.BasicKvEntry;
|
||||||
@ -64,7 +65,19 @@ public class SimpleCalculatedFieldState extends BaseCalculatedFieldState {
|
|||||||
double expressionResult = expr.evaluate();
|
double expressionResult = expr.evaluate();
|
||||||
|
|
||||||
Output output = ctx.getOutput();
|
Output output = ctx.getOutput();
|
||||||
return Futures.immediateFuture(new CalculatedFieldResult(output.getType(), output.getScope(), JacksonUtil.valueToTree(Map.of(output.getName(), expressionResult))));
|
Object result;
|
||||||
|
Integer decimals = output.getDecimalsByDefault();
|
||||||
|
if (decimals != null) {
|
||||||
|
if (decimals.equals(0)) {
|
||||||
|
result = TbUtils.toInt(expressionResult);
|
||||||
|
} else {
|
||||||
|
result = TbUtils.toFixed(expressionResult, decimals);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = expressionResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Futures.immediateFuture(new CalculatedFieldResult(output.getType(), output.getScope(), JacksonUtil.valueToTree(Map.of(output.getName(), result))));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,6 +34,7 @@ import org.thingsboard.server.common.data.cf.configuration.SimpleCalculatedField
|
|||||||
import org.thingsboard.server.common.data.id.AssetId;
|
import org.thingsboard.server.common.data.id.AssetId;
|
||||||
import org.thingsboard.server.common.data.id.DeviceId;
|
import org.thingsboard.server.common.data.id.DeviceId;
|
||||||
import org.thingsboard.server.common.data.id.TenantId;
|
import org.thingsboard.server.common.data.id.TenantId;
|
||||||
|
import org.thingsboard.server.common.data.kv.DoubleDataEntry;
|
||||||
import org.thingsboard.server.common.data.kv.LongDataEntry;
|
import org.thingsboard.server.common.data.kv.LongDataEntry;
|
||||||
import org.thingsboard.server.common.data.kv.StringDataEntry;
|
import org.thingsboard.server.common.data.kv.StringDataEntry;
|
||||||
import org.thingsboard.server.dao.usagerecord.ApiLimitService;
|
import org.thingsboard.server.dao.usagerecord.ApiLimitService;
|
||||||
@ -138,7 +139,7 @@ public class SimpleCalculatedFieldStateTest {
|
|||||||
Output output = getCalculatedFieldConfig().getOutput();
|
Output output = getCalculatedFieldConfig().getOutput();
|
||||||
assertThat(result.getType()).isEqualTo(output.getType());
|
assertThat(result.getType()).isEqualTo(output.getType());
|
||||||
assertThat(result.getScope()).isEqualTo(output.getScope());
|
assertThat(result.getScope()).isEqualTo(output.getScope());
|
||||||
assertThat(result.getResult()).isEqualTo(JacksonUtil.valueToTree(Map.of("output", 49.0)));
|
assertThat(result.getResult()).isEqualTo(JacksonUtil.valueToTree(Map.of("output", 49)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -154,6 +155,26 @@ public class SimpleCalculatedFieldStateTest {
|
|||||||
.hasMessage("Argument 'key2' is not a number.");
|
.hasMessage("Argument 'key2' is not a number.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testPerformCalculationWhenDecimalsByDefault() throws ExecutionException, InterruptedException {
|
||||||
|
state.arguments = new HashMap<>(Map.of(
|
||||||
|
"key1", new SingleValueArgumentEntry(System.currentTimeMillis() - 10, new DoubleDataEntry("key1", 11.3456), 145L),
|
||||||
|
"key2", new SingleValueArgumentEntry(System.currentTimeMillis() - 6, new DoubleDataEntry("key2", 15.1), 165L),
|
||||||
|
"key3", new SingleValueArgumentEntry(System.currentTimeMillis() - 3, new DoubleDataEntry("key3", 23.1), 184L)
|
||||||
|
));
|
||||||
|
|
||||||
|
Output output = getCalculatedFieldConfig().getOutput();
|
||||||
|
output.setDecimalsByDefault(3);
|
||||||
|
ctx.setOutput(output);
|
||||||
|
|
||||||
|
CalculatedFieldResult result = state.performCalculation(ctx).get();
|
||||||
|
|
||||||
|
assertThat(result).isNotNull();
|
||||||
|
assertThat(result.getType()).isEqualTo(output.getType());
|
||||||
|
assertThat(result.getScope()).isEqualTo(output.getScope());
|
||||||
|
assertThat(result.getResult()).isEqualTo(JacksonUtil.valueToTree(Map.of("output", 49.546)));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testIsReadyWhenNotAllArgPresent() {
|
void testIsReadyWhenNotAllArgPresent() {
|
||||||
assertThat(state.isReady()).isFalse();
|
assertThat(state.isReady()).isFalse();
|
||||||
@ -219,6 +240,7 @@ public class SimpleCalculatedFieldStateTest {
|
|||||||
output.setName("output");
|
output.setName("output");
|
||||||
output.setType(OutputType.ATTRIBUTES);
|
output.setType(OutputType.ATTRIBUTES);
|
||||||
output.setScope(AttributeScope.SERVER_SCOPE);
|
output.setScope(AttributeScope.SERVER_SCOPE);
|
||||||
|
output.setDecimalsByDefault(0);
|
||||||
|
|
||||||
config.setOutput(output);
|
config.setOutput(output);
|
||||||
|
|
||||||
|
|||||||
@ -26,5 +26,6 @@ public class Output {
|
|||||||
private String name;
|
private String name;
|
||||||
private OutputType type;
|
private OutputType type;
|
||||||
private AttributeScope scope;
|
private AttributeScope scope;
|
||||||
|
private Integer decimalsByDefault;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,7 +44,6 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
|
||||||
import static java.lang.Character.MAX_RADIX;
|
import static java.lang.Character.MAX_RADIX;
|
||||||
@ -256,6 +255,8 @@ public class TbUtils {
|
|||||||
double.class, int.class)));
|
double.class, int.class)));
|
||||||
parserConfig.addImport("toFixed", new MethodStub(TbUtils.class.getMethod("toFixed",
|
parserConfig.addImport("toFixed", new MethodStub(TbUtils.class.getMethod("toFixed",
|
||||||
float.class, int.class)));
|
float.class, int.class)));
|
||||||
|
parserConfig.addImport("toInt", new MethodStub(TbUtils.class.getMethod("toInt",
|
||||||
|
double.class)));
|
||||||
parserConfig.addImport("hexToBytes", new MethodStub(TbUtils.class.getMethod("hexToBytes",
|
parserConfig.addImport("hexToBytes", new MethodStub(TbUtils.class.getMethod("hexToBytes",
|
||||||
ExecutionContext.class, String.class)));
|
ExecutionContext.class, String.class)));
|
||||||
parserConfig.addImport("hexToBytesArray", new MethodStub(TbUtils.class.getMethod("hexToBytesArray",
|
parserConfig.addImport("hexToBytesArray", new MethodStub(TbUtils.class.getMethod("hexToBytesArray",
|
||||||
@ -1156,6 +1157,10 @@ public class TbUtils {
|
|||||||
return BigDecimal.valueOf(value).setScale(precision, RoundingMode.HALF_UP).floatValue();
|
return BigDecimal.valueOf(value).setScale(precision, RoundingMode.HALF_UP).floatValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int toInt(double value) {
|
||||||
|
return BigDecimal.valueOf(value).setScale(0, RoundingMode.HALF_UP).intValue();
|
||||||
|
}
|
||||||
|
|
||||||
public static ExecutionHashMap<String, Object> toFlatMap(ExecutionContext ctx, Map<String, Object> json) {
|
public static ExecutionHashMap<String, Object> toFlatMap(ExecutionContext ctx, Map<String, Object> json) {
|
||||||
return toFlatMap(ctx, json, new ArrayList<>(), true);
|
return toFlatMap(ctx, json, new ArrayList<>(), true);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1137,6 +1137,13 @@ public class TbUtilsTest {
|
|||||||
Assertions.assertEquals(expected, actual);
|
Assertions.assertEquals(expected, actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void toInt() {
|
||||||
|
Assertions.assertEquals(1729, TbUtils.toInt(doubleVal));
|
||||||
|
Assertions.assertEquals(13, TbUtils.toInt(12.8));
|
||||||
|
Assertions.assertEquals(28, TbUtils.toInt(28.0));
|
||||||
|
}
|
||||||
|
|
||||||
private static List<Byte> toList(byte[] data) {
|
private static List<Byte> toList(byte[] data) {
|
||||||
List<Byte> result = new ArrayList<>(data.length);
|
List<Byte> result = new ArrayList<>(data.length);
|
||||||
for (Byte b : data) {
|
for (Byte b : data) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user