Skip to content

Commit

Permalink
[basicprofiles] Fix inability to filter a percent QuantityType input
Browse files Browse the repository at this point in the history
Signed-off-by: Jimmy Tanagra <[email protected]>
  • Loading branch information
jimtng committed Jan 11, 2025
1 parent a1fc363 commit 402f179
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 0 deletions.
5 changes: 5 additions & 0 deletions bundles/org.openhab.transform.basicprofiles/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,11 +231,16 @@ The `LHS_OPERAND` and the `RHS_OPERAND` can be either one of these:
It is calculated as `($DELTA / current_data) * 100`.
Note that this can also be done by omitting the `LHS_OPERAND` and using a number followed with a percent sign `%` as the `RHS_OPERAND`.
See the example below.
- `$INPUT` to represent the incoming value.
Conditions that compare QuantityType inputs to a constant must include the relevant unit (e.g. `> 100 W`).
However, when the unit is `%`, such conditions (e.g. `> 10 %`) will trigger a `$DELTA_PERCENT` check.
To avoid this, write the condition as `$INPUT > 10 %`.
- `$AVERAGE`, or `$AVG` to represent the average of the previous unfiltered incoming values.
- `$STDDEV` to represent the _population_ standard deviation of the previous unfiltered incoming values.
- `$MEDIAN` to represent the median value of the previous unfiltered incoming values.
- `$MIN` to represent the minimum value of the previous unfiltered incoming values.
- `$MAX` to represent the maximum value of the previous unfiltered incoming values.

These are only applicable to numeric states.
By default, 5 samples of the previous values are kept.
This can be customized by specifying the "window size" or sample count applicable to the function, e.g. `$MEDIAN(10)` will return the median of the last 10 values.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,7 @@ public String toString() {
*/
class FunctionType implements State {
enum Function {
INPUT,
DELTA,
DELTA_PERCENT,
AVERAGE,
Expand All @@ -535,6 +536,7 @@ public FunctionType(Function type, Optional<Integer> windowSize) {
int start = windowSize.map(w -> size - w).orElse(0);
List<State> states = start <= 0 ? previousStates : previousStates.subList(start, size);
return switch (type) {
case INPUT -> newState;
case DELTA -> calculateDelta();
case DELTA_PERCENT -> calculateDeltaPercent();
case AVG, AVERAGE -> calculateAverage(states);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,11 @@
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Stream;

import javax.measure.Unit;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -67,6 +70,7 @@
import org.openhab.core.thing.profiles.ProfileContext;
import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;
import org.openhab.core.types.util.UnitUtils;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext;

Expand Down Expand Up @@ -657,14 +661,22 @@ public void testComparingInputStateWithItem(GenericItem linkedItem, State inputS

public static Stream<Arguments> testFunctions() {
NumberItem powerItem = new NumberItem("Number:Power", "powerItem", UNIT_PROVIDER);
NumberItem percentItem = new NumberItem("Number:Dimensionless", "percentItem", 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();
Unit percentUnit = Objects.requireNonNull(UnitUtils.parseUnit("%"));
List<QuantityType> percents = numbers.stream().map(n -> new QuantityType(n, percentUnit)).toList();
List<DecimalType> decimals = numbers.stream().map(DecimalType::new).toList();
List<DecimalType> negativeDecimals = negatives.stream().map(DecimalType::new).toList();

return Stream.of( //
Arguments.of(decimalItem, "$INPUT < 10", decimals, DecimalType.valueOf("3"), true), //
Arguments.of(decimalItem, "$INPUT < 10", decimals, DecimalType.valueOf("10"), false), //
Arguments.of(percentItem, "$INPUT < 10 %", percents, QuantityType.valueOf("-10 %"), true), //
Arguments.of(percentItem, "$INPUT < 10 %", percents, QuantityType.valueOf("10 %"), false), //

// test custom window size
Arguments.of(decimalItem, "$AVERAGE(3) == 4", decimals, DecimalType.valueOf("5"), true), //
Arguments.of(decimalItem, "$AVERAGE(4) == 3.5", decimals, DecimalType.valueOf("5"), true), //
Expand Down

0 comments on commit 402f179

Please sign in to comment.