Skip to content

Commit 673e23b

Browse files
committed
Rules DSL: Support arithmetic operations directly on Number Item's State
Signed-off-by: Jimmy Tanagra <jcode@tanagra.id.au>
1 parent ab977df commit 673e23b

2 files changed

Lines changed: 161 additions & 8 deletions

File tree

bundles/org.openhab.core.model.script/src.moved/test/java/org/openhab/core/model/script/lib/NumberExtensionsTest.java

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@
2828
import org.junit.jupiter.params.provider.ValueSource;
2929
import org.openhab.core.library.types.DecimalType;
3030
import org.openhab.core.library.types.HSBType;
31+
import org.openhab.core.library.types.OnOffType;
3132
import org.openhab.core.library.types.PercentType;
3233
import org.openhab.core.library.types.QuantityType;
3334
import org.openhab.core.library.unit.Units;
35+
import org.openhab.core.types.State;
3436
import org.openhab.core.types.Type;
3537

3638
/**
@@ -53,12 +55,12 @@ public class NumberExtensionsTest {
5355

5456
@Test
5557
public void operatorPlusNumberNumber() {
56-
assertThat(NumberExtensions.operator_plus(DECIMAL1, DECIMAL2), is(BigDecimal.valueOf(3)));
58+
assertThat(NumberExtensions.operator_plus((Number) DECIMAL1, (Number) DECIMAL2), is(BigDecimal.valueOf(3)));
5759
}
5860

5961
@Test
6062
public void operatorPlusNumberQuantityOne() {
61-
assertThat(NumberExtensions.operator_plus(Q_ONE_1, DECIMAL2), is(BigDecimal.valueOf(3)));
63+
assertThat(NumberExtensions.operator_plus((Number) Q_ONE_1, (Number) DECIMAL2), is(BigDecimal.valueOf(3)));
6264
}
6365

6466
@Test
@@ -68,7 +70,7 @@ public void operatorPlusQuantityQuantity() {
6870

6971
@Test
7072
public void operatorMinusNumber() {
71-
assertThat(NumberExtensions.operator_minus(DECIMAL1), is(BigDecimal.valueOf(-1)));
73+
assertThat(NumberExtensions.operator_minus((Number) DECIMAL1), is(BigDecimal.valueOf(-1)));
7274
}
7375

7476
@Test
@@ -78,12 +80,12 @@ public void operatorMinusQuantity() {
7880

7981
@Test
8082
public void operatorMinusNumberNumber() {
81-
assertThat(NumberExtensions.operator_minus(DECIMAL2, DECIMAL1), is(BigDecimal.ONE));
83+
assertThat(NumberExtensions.operator_minus((Number) DECIMAL2, (Number) DECIMAL1), is(BigDecimal.ONE));
8284
}
8385

8486
@Test
8587
public void operatorMinusNumberQuantityOne() {
86-
assertThat(NumberExtensions.operator_minus(Q_ONE_2, DECIMAL1), is(BigDecimal.ONE));
88+
assertThat(NumberExtensions.operator_minus((Number) Q_ONE_2, (Number) DECIMAL1), is(BigDecimal.ONE));
8789
}
8890

8991
@Test
@@ -93,7 +95,8 @@ public void operatorMinusQuantityQuantity() {
9395

9496
@Test
9597
public void operatorMultiplyNumberQuantity() {
96-
assertThat(NumberExtensions.operator_multiply(DECIMAL2, Q_LENGTH_2_CM), is(QuantityType.valueOf("4 cm")));
98+
assertThat(NumberExtensions.operator_multiply((Number) DECIMAL2, Q_LENGTH_2_CM),
99+
is(QuantityType.valueOf("4 cm")));
97100
}
98101

99102
@Test
@@ -103,7 +106,8 @@ public void operatorMultiplyQuantityQuantity() {
103106

104107
@Test
105108
public void operatorDivideQuantityNumber() {
106-
assertThat(NumberExtensions.operator_divide(Q_LENGTH_1_M, DECIMAL2), is(QuantityType.valueOf("0.5 m")));
109+
assertThat(NumberExtensions.operator_divide(Q_LENGTH_1_M, (Number) DECIMAL2),
110+
is(QuantityType.valueOf("0.5 m")));
107111
}
108112

109113
@Test
@@ -113,7 +117,43 @@ public void operatorDivideQuantityQuantity() {
113117

114118
@Test
115119
public void operatorDivideNumberQuantity() {
116-
assertThat(NumberExtensions.operator_divide(DECIMAL1, Q_LENGTH_2_CM), is(QuantityType.valueOf("0.5 one/cm")));
120+
assertThat(NumberExtensions.operator_divide((Number) DECIMAL1, Q_LENGTH_2_CM),
121+
is(QuantityType.valueOf("0.5 one/cm")));
122+
}
123+
124+
@Test
125+
public void operatorMinusStateState() {
126+
assertThat(NumberExtensions.operator_minus((State) DECIMAL2, (State) DECIMAL1), is(BigDecimal.ONE));
127+
}
128+
129+
@Test
130+
public void operatorMinusQuantityStateState() {
131+
assertThat(NumberExtensions.operator_minus((State) Q_LENGTH_1_M, (State) Q_LENGTH_2_CM),
132+
is(QuantityType.valueOf("0.98 m")));
133+
}
134+
135+
@Test
136+
public void operatorMultiplyStateNumber() {
137+
assertThat(NumberExtensions.operator_multiply((State) DECIMAL2, BigDecimal.valueOf(1.5)),
138+
is(BigDecimal.valueOf(3.0)));
139+
}
140+
141+
@Test
142+
public void operatorMultiplyQuantityStateNumber() {
143+
assertThat(NumberExtensions.operator_multiply((State) Q_LENGTH_2_CM, (Number) DECIMAL2),
144+
is(QuantityType.valueOf("4 cm")));
145+
}
146+
147+
@Test
148+
public void operatorDivideNumberState() {
149+
assertThat(NumberExtensions.operator_divide(BigDecimal.TEN, (State) DECIMAL2),
150+
is(new BigDecimal("5.00000000")));
151+
}
152+
153+
@Test
154+
public void operatorNonNumericState() {
155+
assertThrows(IllegalArgumentException.class,
156+
() -> NumberExtensions.operator_multiply(OnOffType.ON, (Number) DECIMAL2));
117157
}
118158

119159
@Test

bundles/org.openhab.core.model.script/src/org/openhab/core/model/script/lib/NumberExtensions.java

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.openhab.core.library.types.DecimalType;
2121
import org.openhab.core.library.types.QuantityType;
2222
import org.openhab.core.library.unit.Units;
23+
import org.openhab.core.types.State;
2324
import org.openhab.core.types.Type;
2425

2526
/**
@@ -91,6 +92,60 @@ public static BigDecimal operator_divide(Number x, Number y) {
9192
return xValue.divide(yValue, 8, RoundingMode.HALF_UP);
9293
}
9394

95+
// Calculation operators for states
96+
97+
public static Number operator_plus(State x, State y) {
98+
return plus(stateToNumber(x), stateToNumber(y));
99+
}
100+
101+
public static Number operator_plus(State x, Number y) {
102+
return plus(stateToNumber(x), y);
103+
}
104+
105+
public static Number operator_plus(Number x, State y) {
106+
return plus(x, stateToNumber(y));
107+
}
108+
109+
public static Number operator_minus(State x) {
110+
return minus(stateToNumber(x));
111+
}
112+
113+
public static Number operator_minus(State x, State y) {
114+
return minus(stateToNumber(x), stateToNumber(y));
115+
}
116+
117+
public static Number operator_minus(State x, Number y) {
118+
return minus(stateToNumber(x), y);
119+
}
120+
121+
public static Number operator_minus(Number x, State y) {
122+
return minus(x, stateToNumber(y));
123+
}
124+
125+
public static Number operator_multiply(State x, State y) {
126+
return multiply(stateToNumber(x), stateToNumber(y));
127+
}
128+
129+
public static Number operator_multiply(State x, Number y) {
130+
return multiply(stateToNumber(x), y);
131+
}
132+
133+
public static Number operator_multiply(Number x, State y) {
134+
return multiply(x, stateToNumber(y));
135+
}
136+
137+
public static Number operator_divide(State x, State y) {
138+
return divide(stateToNumber(x), stateToNumber(y));
139+
}
140+
141+
public static Number operator_divide(State x, Number y) {
142+
return divide(stateToNumber(x), y);
143+
}
144+
145+
public static Number operator_divide(Number x, State y) {
146+
return divide(x, stateToNumber(y));
147+
}
148+
94149
// Comparison operations between numbers
95150

96151
public static boolean operator_equals(Number left, Number right) {
@@ -408,4 +463,62 @@ private static boolean oneIsQuantity(Number left, Number right) {
408463
private static boolean isAbstractUnitOne(QuantityType<?> left) {
409464
return Units.ONE.equals(left.getUnit());
410465
}
466+
467+
private static Number stateToNumber(State state) {
468+
if (state == null) {
469+
return null;
470+
}
471+
if (state instanceof Number number) {
472+
return number;
473+
}
474+
throw new IllegalArgumentException(
475+
"State '" + state + "' of type '" + state.getClass().getSimpleName() + "' cannot be used as a number");
476+
}
477+
478+
private static Number plus(Number x, Number y) {
479+
if (x instanceof QuantityType<?> qx && y instanceof QuantityType<?> qy) {
480+
return operator_plus(qx, qy);
481+
}
482+
return operator_plus(x, y);
483+
}
484+
485+
private static Number minus(Number x) {
486+
if (x instanceof QuantityType<?> qx) {
487+
return operator_minus(qx);
488+
}
489+
return operator_minus(x);
490+
}
491+
492+
private static Number minus(Number x, Number y) {
493+
if (x instanceof QuantityType<?> qx && y instanceof QuantityType<?> qy) {
494+
return operator_minus(qx, qy);
495+
}
496+
return operator_minus(x, y);
497+
}
498+
499+
private static Number multiply(Number x, Number y) {
500+
if (x instanceof QuantityType<?> qx && y instanceof QuantityType<?> qy) {
501+
return operator_multiply(qx, qy);
502+
}
503+
if (x instanceof QuantityType<?> qx) {
504+
return operator_multiply(qx, y);
505+
}
506+
if (y instanceof QuantityType<?> qy) {
507+
return operator_multiply(x, qy);
508+
}
509+
return operator_multiply(x, y);
510+
}
511+
512+
private static Number divide(Number x, Number y) {
513+
if (x instanceof QuantityType<?> qx && y instanceof QuantityType<?> qy) {
514+
return operator_divide(qx, qy);
515+
}
516+
if (x instanceof QuantityType<?> qx) {
517+
return operator_divide(qx, y);
518+
}
519+
if (y instanceof QuantityType<?> qy) {
520+
return operator_divide(x, qy);
521+
}
522+
return operator_divide(x, y);
523+
}
411524
}

0 commit comments

Comments
 (0)