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.NoArgsConstructor;
 | 
			
		||||
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.configuration.Output;
 | 
			
		||||
import org.thingsboard.server.common.data.kv.BasicKvEntry;
 | 
			
		||||
@ -64,7 +65,19 @@ public class SimpleCalculatedFieldState extends BaseCalculatedFieldState {
 | 
			
		||||
        double expressionResult = expr.evaluate();
 | 
			
		||||
 | 
			
		||||
        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.DeviceId;
 | 
			
		||||
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.StringDataEntry;
 | 
			
		||||
import org.thingsboard.server.dao.usagerecord.ApiLimitService;
 | 
			
		||||
@ -138,7 +139,7 @@ public class SimpleCalculatedFieldStateTest {
 | 
			
		||||
        Output output = getCalculatedFieldConfig().getOutput();
 | 
			
		||||
        assertThat(result.getType()).isEqualTo(output.getType());
 | 
			
		||||
        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
 | 
			
		||||
@ -154,6 +155,26 @@ public class SimpleCalculatedFieldStateTest {
 | 
			
		||||
                .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
 | 
			
		||||
    void testIsReadyWhenNotAllArgPresent() {
 | 
			
		||||
        assertThat(state.isReady()).isFalse();
 | 
			
		||||
@ -219,6 +240,7 @@ public class SimpleCalculatedFieldStateTest {
 | 
			
		||||
        output.setName("output");
 | 
			
		||||
        output.setType(OutputType.ATTRIBUTES);
 | 
			
		||||
        output.setScope(AttributeScope.SERVER_SCOPE);
 | 
			
		||||
        output.setDecimalsByDefault(0);
 | 
			
		||||
 | 
			
		||||
        config.setOutput(output);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -26,5 +26,6 @@ public class Output {
 | 
			
		||||
    private String name;
 | 
			
		||||
    private OutputType type;
 | 
			
		||||
    private AttributeScope scope;
 | 
			
		||||
    private Integer decimalsByDefault;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -44,7 +44,6 @@ import java.util.LinkedHashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
import java.util.TreeSet;
 | 
			
		||||
import java.util.regex.Matcher;
 | 
			
		||||
 | 
			
		||||
import static java.lang.Character.MAX_RADIX;
 | 
			
		||||
@ -256,6 +255,8 @@ public class TbUtils {
 | 
			
		||||
                double.class, int.class)));
 | 
			
		||||
        parserConfig.addImport("toFixed", new MethodStub(TbUtils.class.getMethod("toFixed",
 | 
			
		||||
                float.class, int.class)));
 | 
			
		||||
        parserConfig.addImport("toInt", new MethodStub(TbUtils.class.getMethod("toInt",
 | 
			
		||||
                double.class)));
 | 
			
		||||
        parserConfig.addImport("hexToBytes", new MethodStub(TbUtils.class.getMethod("hexToBytes",
 | 
			
		||||
                ExecutionContext.class, String.class)));
 | 
			
		||||
        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();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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) {
 | 
			
		||||
        return toFlatMap(ctx, json, new ArrayList<>(), true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1137,6 +1137,13 @@ public class TbUtilsTest {
 | 
			
		||||
        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) {
 | 
			
		||||
        List<Byte> result = new ArrayList<>(data.length);
 | 
			
		||||
        for (Byte b : data) {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user