From 96a71ad8dc07ba4f08eebe878ea52be699532327 Mon Sep 17 00:00:00 2001 From: thingsboard648 Date: Tue, 5 Mar 2024 16:03:00 +0200 Subject: [PATCH] changed the check to exclude only 0 deltas from the message --- .../engine/metadata/CalculateDeltaNode.java | 14 +-- .../CalculateDeltaNodeConfiguration.java | 5 +- .../metadata/CalculateDeltaNodeTest.java | 90 ++++++++++++++++--- 3 files changed, 88 insertions(+), 21 deletions(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/CalculateDeltaNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/CalculateDeltaNode.java index 510d089372..ce3a318fe6 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/CalculateDeltaNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/CalculateDeltaNode.java @@ -99,13 +99,13 @@ public class CalculateDeltaNode implements TbNode { BigDecimal delta = BigDecimal.valueOf(previousData != null ? currentValue - previousData.value : 0.0); - if (config.isOnlyComputeTrueDeltas() && delta.doubleValue() == 0) { - ctx.tellSuccess(msg); + if (config.isTellFailureIfDeltaIsNegative() && delta.doubleValue() < 0) { + ctx.tellFailure(msg, new IllegalArgumentException("Delta value is negative!")); return; } - if (config.isTellFailureIfDeltaIsNegative() && delta.doubleValue() < 0) { - ctx.tellFailure(msg, new IllegalArgumentException("Delta value is negative!")); + if (config.isExcludeZeroDeltasFromOutboundMessage() && delta.doubleValue() == 0) { + ctx.tellSuccess(msg); return; } @@ -141,10 +141,10 @@ public class CalculateDeltaNode implements TbNode { boolean hasChanges = false; switch (fromVersion) { case 0: - String onlyComputeTrueDeltas = "onlyComputeTrueDeltas"; - if (!oldConfiguration.has(onlyComputeTrueDeltas)) { + String excludeZeroDeltasFromOutboundMessage = "excludeZeroDeltasFromOutboundMessage"; + if (!oldConfiguration.has(excludeZeroDeltasFromOutboundMessage)) { hasChanges = true; - ((ObjectNode) oldConfiguration).put(onlyComputeTrueDeltas, false); + ((ObjectNode) oldConfiguration).put(excludeZeroDeltasFromOutboundMessage, false); } break; default: diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/CalculateDeltaNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/CalculateDeltaNodeConfiguration.java index 9f30aae22b..82a2eb85b0 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/CalculateDeltaNodeConfiguration.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/CalculateDeltaNodeConfiguration.java @@ -30,7 +30,7 @@ public class CalculateDeltaNodeConfiguration implements NodeConfiguration CalculateDeltaTestConfig() { + return Stream.of( + // delta = 0, tell failure if delta is negative is set to true and exclude zero deltas from outbound message is set to true so delta should filter out the message. + new CalculateDeltaTestConfig(true, true, 40, 40, (ctx, msg) -> { + verify(ctx).tellSuccess(eq(msg)); + verify(ctx).getDbCallbackExecutor(); + verifyNoMoreInteractions(ctx); + }), + // delta < 0, tell failure if delta is negative is set to true so it should throw exception. + new CalculateDeltaTestConfig(true, true, 40, 41, (ctx, msg) -> { + var errorCaptor = ArgumentCaptor.forClass(Throwable.class); + verify(ctx).tellFailure(eq(msg), errorCaptor.capture()); + verify(ctx).getDbCallbackExecutor(); + verifyNoMoreInteractions(ctx); + assertThat(errorCaptor.getValue()).isInstanceOf(IllegalArgumentException.class).hasMessage("Delta value is negative!"); + }), + // delta < 0, exclude zero deltas from outbound message is set to true so it should return message with delta if delta is negative is set to false. + new CalculateDeltaTestConfig(false, true, 40, 41, (ctx, msg) -> { + var actualMsgCaptor = ArgumentCaptor.forClass(TbMsg.class); + verify(ctx).tellSuccess(actualMsgCaptor.capture()); + verify(ctx).getDbCallbackExecutor(); + verifyNoMoreInteractions(ctx); + String expectedMsgData = "{\"temperature\":40.0,\"airPressure\":123,\"delta\":-1}"; + assertEquals(expectedMsgData, actualMsgCaptor.getValue().getData()); + }), + // delta = 0, tell failure if delta is negative is set to false and exclude zero deltas from outbound message is set to true so delta should filter out the message. + new CalculateDeltaTestConfig(false, true, 40, 40, (ctx, msg) -> { + verify(ctx).tellSuccess(eq(msg)); + verify(ctx).getDbCallbackExecutor(); + verifyNoMoreInteractions(ctx); + }), + // delta > 0, exclude zero deltas from outbound message is set to true so it should return message with delta. + new CalculateDeltaTestConfig(false, true, 40, 39, (ctx, msg) -> { + var actualMsgCaptor = ArgumentCaptor.forClass(TbMsg.class); + verify(ctx).tellSuccess(actualMsgCaptor.capture()); + verify(ctx).getDbCallbackExecutor(); + verifyNoMoreInteractions(ctx); + String expectedMsgData = "{\"temperature\":40.0,\"airPressure\":123,\"delta\":1}"; + assertEquals(expectedMsgData, actualMsgCaptor.getValue().getData()); + }), + // delta > 0, exclude zero deltas from outbound message is set to false so it should return message with delta. + new CalculateDeltaTestConfig(false, false, 40, 39, (ctx, msg) -> { + var actualMsgCaptor = ArgumentCaptor.forClass(TbMsg.class); + verify(ctx).tellSuccess(actualMsgCaptor.capture()); + verify(ctx).getDbCallbackExecutor(); + verifyNoMoreInteractions(ctx); + String expectedMsgData = "{\"temperature\":40.0,\"airPressure\":123,\"delta\":1}"; + assertEquals(expectedMsgData, actualMsgCaptor.getValue().getData()); + }) + ); + } + + @Data + @RequiredArgsConstructor + static class CalculateDeltaTestConfig { + private final boolean tellFailureIfDeltaIsNegative; + private final boolean computeOnlyTrueDeltas; + private final double currentValue; + private final double prevValue; + private final BiConsumer verificationMethod; } private void mockFindLatest(TsKvEntry tsKvEntry) { @@ -493,12 +559,12 @@ public class CalculateDeltaNodeTest extends AbstractRuleNodeUpgradeTest { Arguments.of(0, "{\"inputValueKey\":\"pulseCounter\",\"outputValueKey\":\"delta\",\"useCache\":true,\"addPeriodBetweenMsgs\":false, \"periodValueKey\":\"periodInMs\", \"round\":null,\"tellFailureIfDeltaIsNegative\":true}", true, - "{\"inputValueKey\":\"pulseCounter\",\"outputValueKey\":\"delta\",\"useCache\":true,\"addPeriodBetweenMsgs\":false, \"periodValueKey\":\"periodInMs\", \"round\":null,\"tellFailureIfDeltaIsNegative\":true, \"onlyComputeTrueDeltas\":false}"), + "{\"inputValueKey\":\"pulseCounter\",\"outputValueKey\":\"delta\",\"useCache\":true,\"addPeriodBetweenMsgs\":false, \"periodValueKey\":\"periodInMs\", \"round\":null,\"tellFailureIfDeltaIsNegative\":true, \"excludeZeroDeltasFromOutboundMessage\":false}"), // default config for version 1 with upgrade from version 0 Arguments.of(1, - "{\"inputValueKey\":\"pulseCounter\",\"outputValueKey\":\"delta\",\"useCache\":true,\"addPeriodBetweenMsgs\":false, \"periodValueKey\":\"periodInMs\", \"round\":null,\"tellFailureIfDeltaIsNegative\":true, \"onlyComputeTrueDeltas\":false}", + "{\"inputValueKey\":\"pulseCounter\",\"outputValueKey\":\"delta\",\"useCache\":true,\"addPeriodBetweenMsgs\":false, \"periodValueKey\":\"periodInMs\", \"round\":null,\"tellFailureIfDeltaIsNegative\":true, \"excludeZeroDeltasFromOutboundMessage\":false}", false, - "{\"inputValueKey\":\"pulseCounter\",\"outputValueKey\":\"delta\",\"useCache\":true,\"addPeriodBetweenMsgs\":false, \"periodValueKey\":\"periodInMs\", \"round\":null,\"tellFailureIfDeltaIsNegative\":true, \"onlyComputeTrueDeltas\":false}") + "{\"inputValueKey\":\"pulseCounter\",\"outputValueKey\":\"delta\",\"useCache\":true,\"addPeriodBetweenMsgs\":false, \"periodValueKey\":\"periodInMs\", \"round\":null,\"tellFailureIfDeltaIsNegative\":true, \"excludeZeroDeltasFromOutboundMessage\":false}") ); }