Skip to content

Commit 019fb8a

Browse files
authored
[basicprofiles] Convert to relative unit in State Filter's Delta check (openhab#18127)
* [basicprofiles] Convert to relative unit in State Filter's Delta check Signed-off-by: Jimmy Tanagra <[email protected]>
1 parent 2474953 commit 019fb8a

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed

bundles/org.openhab.transform.basicprofiles/src/main/java/org/openhab/transform/basicprofiles/internal/profiles/StateFilterProfile.java

+14
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ public boolean check(State input) {
334334
State rhsState = this.rhsState;
335335
Item lhsItem = null;
336336
Item rhsItem = null;
337+
boolean isDeltaCheck = false;
337338

338339
if (rhsState == null) {
339340
rhsItem = getItemOrNull(rhsString);
@@ -387,6 +388,9 @@ public boolean check(State input) {
387388
logger.debug("Couldn't calculate the left hand side function '{}'", lhsString);
388389
return false;
389390
}
391+
if (lhsFunction.getType() == FunctionType.Function.DELTA) {
392+
isDeltaCheck = true;
393+
}
390394
}
391395

392396
if (rhsState == null) {
@@ -395,6 +399,10 @@ public boolean check(State input) {
395399

396400
// Don't convert QuantityType to other types, so that 1500 != 1500 W
397401
if (rhsState != null && !(rhsState instanceof QuantityType)) {
402+
if (rhsState instanceof FunctionType rhsFunction
403+
&& rhsFunction.getType() == FunctionType.Function.DELTA) {
404+
isDeltaCheck = true;
405+
}
398406
// Try to convert it to the same type as the lhs
399407
// This allows comparing compatible types, e.g. PercentType vs OnOffType
400408
rhsState = rhsState.as(lhsState.getClass());
@@ -432,6 +440,12 @@ public boolean check(State input) {
432440

433441
rhs = Objects.requireNonNull(rhsState instanceof StringType ? rhsState.toString() : rhsState);
434442

443+
if (isDeltaCheck && rhs instanceof QuantityType rhsQty && lhs instanceof QuantityType lhsQty) {
444+
if (rhsQty.toUnitRelative(lhsQty.getUnit()) instanceof QuantityType relativeRhs) {
445+
rhs = relativeRhs;
446+
}
447+
}
448+
435449
if (logger.isDebugEnabled()) {
436450
if (lhsString.isEmpty()) {
437451
logger.debug("Performing a comparison between input '{}' ({}) and value '{}' ({})", lhs,

bundles/org.openhab.transform.basicprofiles/src/test/java/org/openhab/transform/basicprofiles/internal/profiles/StateFilterProfileTest.java

+62
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,68 @@ public static Stream<Arguments> testFunctions() {
793793
@MethodSource
794794
public void testFunctions(Item item, String condition, List<State> states, State input, boolean expected)
795795
throws ItemNotFoundException {
796+
internalTestFunctions(item, condition, states, input, expected);
797+
}
798+
799+
public static Stream<Arguments> testDeltaWithRelativeUnit() {
800+
NumberItem temperatureItem = new NumberItem("Number:Temperature", "temperatureItem", UNIT_PROVIDER);
801+
802+
State initialC = QuantityType.valueOf("5 °C");
803+
State initialF = QuantityType.valueOf("5 °F");
804+
805+
State qty_7_C = QuantityType.valueOf("7 °C");
806+
State qty_7_F = QuantityType.valueOf("7 °F");
807+
808+
return Stream.of( //
809+
// Celsius inputs
810+
// same unit
811+
Arguments.of(temperatureItem, "$DELTA > 1 °C", initialC, qty_7_C, true), //
812+
Arguments.of(temperatureItem, "1 °C < $DELTA", initialC, qty_7_C, true), //
813+
Arguments.of(temperatureItem, "$DELTA < 1 °C", initialC, qty_7_C, false), //
814+
Arguments.of(temperatureItem, "1 °C > $DELTA", initialC, qty_7_C, false), //
815+
816+
// Celsius vs Fahrenheit: 2 °C = 35.6 °F (absolute), 2 °C = 3.6 °F (relative)
817+
Arguments.of(temperatureItem, "$DELTA > 4 °F", initialC, qty_7_C, false), //
818+
Arguments.of(temperatureItem, "4 °F < $DELTA", initialC, qty_7_C, false), //
819+
Arguments.of(temperatureItem, "$DELTA < 4 °F", initialC, qty_7_C, true), //
820+
Arguments.of(temperatureItem, "4 °F > $DELTA", initialC, qty_7_C, true), //
821+
822+
// Celsius vs Kelvin: °C = K in relative unit
823+
Arguments.of(temperatureItem, "$DELTA > 1 K", initialC, qty_7_C, true), //
824+
Arguments.of(temperatureItem, "1 K < $DELTA", initialC, qty_7_C, true), //
825+
Arguments.of(temperatureItem, "$DELTA < 1 K", initialC, qty_7_C, false), //
826+
Arguments.of(temperatureItem, "1 K > $DELTA", initialC, qty_7_C, false), //
827+
828+
// Fahrenheit inputs
829+
// same unit, in F
830+
Arguments.of(temperatureItem, "$DELTA > 1 °F", initialF, qty_7_F, true), //
831+
Arguments.of(temperatureItem, "1 °F < $DELTA", initialF, qty_7_F, true), //
832+
Arguments.of(temperatureItem, "$DELTA < 2 °F", initialF, qty_7_F, false), //
833+
Arguments.of(temperatureItem, "2 °F > $DELTA", initialF, qty_7_F, false), //
834+
835+
// Fahrenheit vs Celsius: 2 °F = -16.67 °C (absolute), 2 °F = 1.11 °C (relative)
836+
Arguments.of(temperatureItem, "$DELTA > 1 °C", initialF, qty_7_F, true), //
837+
Arguments.of(temperatureItem, "1 °C < $DELTA", initialF, qty_7_F, true), //
838+
Arguments.of(temperatureItem, "$DELTA < 1 °C", initialF, qty_7_F, false), //
839+
Arguments.of(temperatureItem, "1 °C > $DELTA", initialF, qty_7_F, false), //
840+
841+
// Fahreheit vs Kelvin: 2 °F = 256.48 K (absolute), 2 °F = 1.11 K (relative)
842+
Arguments.of(temperatureItem, "$DELTA > 2 K", initialF, qty_7_F, false), //
843+
Arguments.of(temperatureItem, "2 K < $DELTA", initialF, qty_7_F, false), //
844+
Arguments.of(temperatureItem, "$DELTA < 2 K", initialF, qty_7_F, true), //
845+
Arguments.of(temperatureItem, "2 K > $DELTA", initialF, qty_7_F, true) //
846+
);
847+
}
848+
849+
@ParameterizedTest
850+
@MethodSource
851+
public void testDeltaWithRelativeUnit(Item item, String condition, State initialState, State input,
852+
boolean expected) throws ItemNotFoundException {
853+
internalTestFunctions(item, condition, List.of(initialState), input, expected);
854+
}
855+
856+
private void internalTestFunctions(Item item, String condition, List<State> states, State input, boolean expected)
857+
throws ItemNotFoundException {
796858
when(mockContext.getConfiguration()).thenReturn(new Configuration(Map.of("conditions", condition)));
797859
when(mockItemRegistry.getItem(item.getName())).thenReturn(item);
798860
when(mockItemChannelLink.getItemName()).thenReturn(item.getName());

0 commit comments

Comments
 (0)