Skip to content

Commit

Permalink
[basicprofiles] Fix delta state filter handling of negative values (#…
Browse files Browse the repository at this point in the history
…17997)

* [basicprofiles] Pass the initial data for delta state filter

Signed-off-by: Jimmy Tanagra <[email protected]>
  • Loading branch information
jimtng authored Dec 31, 2024
1 parent 37c491b commit 34d8fec
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,12 @@ public boolean check(State input) {

if (rhsState == null) {
rhsItem = getItemOrNull(rhsString);
} else if (rhsState instanceof FunctionType) {
} else if (rhsState instanceof FunctionType rhsFunction) {
if (acceptedState == UnDefType.UNDEF && (rhsFunction.getType() == FunctionType.Function.DELTA
|| rhsFunction.getType() == FunctionType.Function.DELTA_PERCENT)) {
acceptedState = input;
return true;
}
rhsItem = getLinkedItem();
}

Expand All @@ -359,6 +364,11 @@ public boolean check(State input) {
return false;
}
} else if (lhsState instanceof FunctionType lhsFunction) {
if (acceptedState == UnDefType.UNDEF && (lhsFunction.getType() == FunctionType.Function.DELTA
|| lhsFunction.getType() == FunctionType.Function.DELTA_PERCENT)) {
acceptedState = input;
return true;
}
lhsItem = getLinkedItem();
lhsState = lhsFunction.calculate();
if (lhsState == null) {
Expand Down Expand Up @@ -660,27 +670,18 @@ public String toString() {
}

private @Nullable State calculateDelta() {
if (acceptedState == UnDefType.UNDEF) {
logger.debug("No previous data to calculate delta");
acceptedState = newState;
return null;
}

if (newState instanceof QuantityType newStateQuantity) {
QuantityType result = newStateQuantity.subtract((QuantityType) acceptedState);
return result.toBigDecimal().compareTo(BigDecimal.ZERO) < 0 ? result.negate() : result;
}
BigDecimal result = ((DecimalType) newState).toBigDecimal()
.subtract(((DecimalType) acceptedState).toBigDecimal());
return result.compareTo(BigDecimal.ZERO) < 0 ? new DecimalType(result.negate()) : new DecimalType(result);
.subtract(((DecimalType) acceptedState).toBigDecimal()) //
.abs();
return new DecimalType(result);
}

private @Nullable State calculateDeltaPercent() {
State calculatedDelta = calculateDelta();
if (calculatedDelta == null) {
return null;
}

BigDecimal bdDelta;
BigDecimal bdBase;
if (acceptedState instanceof QuantityType acceptedStateQuantity) {
Expand All @@ -691,6 +692,7 @@ public String toString() {
bdDelta = ((DecimalType) calculatedDelta).toBigDecimal();
bdBase = ((DecimalType) acceptedState).toBigDecimal();
}
bdBase = bdBase.abs();
BigDecimal percent = bdDelta.multiply(BigDecimal.valueOf(100)).divide(bdBase, 2, RoundingMode.HALF_EVEN);
return new DecimalType(percent);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
Expand Down Expand Up @@ -658,8 +659,10 @@ public static Stream<Arguments> testFunctions() {
NumberItem powerItem = new NumberItem("Number:Power", "powerItem", UNIT_PROVIDER);
NumberItem decimalItem = new NumberItem("decimalItem");
List<Number> numbers = List.of(1, 2, 3, 4, 5);
List<Number> negatives = List.of(-1, -2, -3, -4, -5);
List<QuantityType> quantities = numbers.stream().map(n -> new QuantityType(n, Units.WATT)).toList();
List<DecimalType> decimals = numbers.stream().map(DecimalType::new).toList();
List<DecimalType> negativeDecimals = negatives.stream().map(DecimalType::new).toList();

return Stream.of( //
// test custom window size
Expand Down Expand Up @@ -695,6 +698,9 @@ public static Stream<Arguments> testFunctions() {
Arguments.of(decimalItem, "$DELTA_PERCENT < 10", decimals, DecimalType.valueOf("0.91"), true), //
Arguments.of(decimalItem, "$DELTA_PERCENT < 10", decimals, DecimalType.valueOf("0.89"), false), //

Arguments.of(decimalItem, "$DELTA_PERCENT < 10", negativeDecimals, DecimalType.valueOf("0"), false), //
Arguments.of(decimalItem, "10 > $DELTA_PERCENT", negativeDecimals, DecimalType.valueOf("0"), false), //

Arguments.of(decimalItem, "< 10%", decimals, DecimalType.valueOf("1.09"), true), //
Arguments.of(decimalItem, "< 10%", decimals, DecimalType.valueOf("1.11"), false), //
Arguments.of(decimalItem, "< 10%", decimals, DecimalType.valueOf("0.91"), true), //
Expand Down Expand Up @@ -762,4 +768,30 @@ public void testFunctions(Item item, String condition, List<State> states, State
profile.onStateUpdateFromHandler(input);
verify(mockCallback, times(expected ? 1 : 0)).sendUpdate(input);
}

@ParameterizedTest
@ValueSource(strings = { //
"$DELTA > 10", //
"$DELTA < 10", //
"10 < $DELTA", //
"10 > $DELTA", //
"$DELTA_PERCENT > 10", //
"$DELTA_PERCENT < 10", //
"10 < $DELTA_PERCENT", //
"10 > $DELTA_PERCENT", //
"> 10%", //
"< 10%" //
})
public void testFirstDataIsAcceptedForDeltaFunctions(String conditions) throws ItemNotFoundException {
NumberItem decimalItem = new NumberItem("decimalItem");

when(mockContext.getConfiguration()).thenReturn(new Configuration(Map.of("conditions", conditions)));
when(mockItemRegistry.getItem(decimalItem.getName())).thenReturn(decimalItem);
when(mockItemChannelLink.getItemName()).thenReturn(decimalItem.getName());

StateFilterProfile profile = new StateFilterProfile(mockCallback, mockContext, mockItemRegistry);

profile.onStateUpdateFromHandler(DecimalType.valueOf("1"));
verify(mockCallback, times(1)).sendUpdate(DecimalType.valueOf("1"));
}
}

0 comments on commit 34d8fec

Please sign in to comment.