@@ -103,7 +103,7 @@ public class StateFilterProfile implements StateProfile {
103
103
private @ Nullable Item linkedItem = null ;
104
104
105
105
private State newState = UnDefType .UNDEF ;
106
- private State acceptedState = UnDefType . UNDEF ;
106
+ private Optional < State > acceptedState = Optional . empty () ;
107
107
private LinkedList <State > previousStates = new LinkedList <>();
108
108
109
109
private final int windowSize ;
@@ -230,7 +230,7 @@ private State checkCondition(State state) {
230
230
}
231
231
232
232
if (conditions .stream ().allMatch (c -> c .check (state ))) {
233
- acceptedState = state ;
233
+ acceptedState = Optional . of ( state ) ;
234
234
return state ;
235
235
} else {
236
236
return configMismatchState ;
@@ -339,8 +339,7 @@ public boolean check(State input) {
339
339
if (rhsState == null ) {
340
340
rhsItem = getItemOrNull (rhsString );
341
341
} else if (rhsState instanceof FunctionType rhsFunction ) {
342
- if (acceptedState == UnDefType .UNDEF && (rhsFunction .getType () == FunctionType .Function .DELTA
343
- || rhsFunction .getType () == FunctionType .Function .DELTA_PERCENT )) {
342
+ if (rhsFunction .alwaysAccept ()) {
344
343
return true ;
345
344
}
346
345
rhsItem = getLinkedItem ();
@@ -378,8 +377,7 @@ public boolean check(State input) {
378
377
}
379
378
380
379
if (lhsState instanceof FunctionType lhsFunction ) {
381
- if (acceptedState == UnDefType .UNDEF && (lhsFunction .getType () == FunctionType .Function .DELTA
382
- || lhsFunction .getType () == FunctionType .Function .DELTA_PERCENT )) {
380
+ if (lhsFunction .alwaysAccept ()) {
383
381
return true ;
384
382
}
385
383
lhsItem = getLinkedItem ();
@@ -567,6 +565,30 @@ public FunctionType(Function type, Optional<Integer> windowSize) {
567
565
};
568
566
}
569
567
568
+ /**
569
+ * If the profile uses the DELTA or DELTA_PERCENT functions, the new state value will always be accepted if the
570
+ * 'acceptedState' (prior state) has not yet been initialised, or -- in the case of the DELTA_PERCENT function
571
+ * only -- if 'acceptedState' has a zero value. This ensures that 'acceptedState' is always initialised. And it
572
+ * also ensures that the DELTA_PERCENT function cannot cause a divide by zero error.
573
+ *
574
+ * @return true if the new state value shall be accepted
575
+ */
576
+ public boolean alwaysAccept () {
577
+ if ((type == Function .DELTA || type == Function .DELTA_PERCENT ) && acceptedState .isEmpty ()) {
578
+ return true ;
579
+ }
580
+ if (type == Function .DELTA_PERCENT ) {
581
+ // avoid division by zero
582
+ if (acceptedState .get () instanceof QuantityType base ) {
583
+ return base .toBigDecimal ().compareTo (BigDecimal .ZERO ) == 0 ;
584
+ }
585
+ if (acceptedState .get () instanceof DecimalType base ) {
586
+ return base .toBigDecimal ().compareTo (BigDecimal .ZERO ) == 0 ;
587
+ }
588
+ }
589
+ return false ;
590
+ }
591
+
570
592
@ Override
571
593
public <T extends State > @ Nullable T as (@ Nullable Class <T > target ) {
572
594
if (target == DecimalType .class || target == QuantityType .class ) {
@@ -692,27 +714,33 @@ public String toString() {
692
714
}
693
715
694
716
private @ Nullable State calculateDelta () {
717
+ if (acceptedState .isEmpty ()) {
718
+ return null ;
719
+ }
695
720
if (newState instanceof QuantityType newStateQuantity ) {
696
- QuantityType result = newStateQuantity .subtract ((QuantityType ) acceptedState );
721
+ QuantityType result = newStateQuantity .subtract ((QuantityType ) acceptedState . get () );
697
722
return result .toBigDecimal ().compareTo (BigDecimal .ZERO ) < 0 ? result .negate () : result ;
698
723
}
699
724
BigDecimal result = ((DecimalType ) newState ).toBigDecimal ()
700
- .subtract (((DecimalType ) acceptedState ).toBigDecimal ()) //
725
+ .subtract (((DecimalType ) acceptedState . get () ).toBigDecimal ()) //
701
726
.abs ();
702
727
return new DecimalType (result );
703
728
}
704
729
705
730
private @ Nullable State calculateDeltaPercent () {
731
+ if (acceptedState .isEmpty ()) {
732
+ return null ;
733
+ }
706
734
State calculatedDelta = calculateDelta ();
707
735
BigDecimal bdDelta ;
708
736
BigDecimal bdBase ;
709
- if (acceptedState instanceof QuantityType acceptedStateQuantity ) {
737
+ if (acceptedState . get () instanceof QuantityType acceptedStateQuantity ) {
710
738
// Assume that delta and base are in the same unit
711
739
bdDelta = ((QuantityType ) calculatedDelta ).toBigDecimal ();
712
740
bdBase = acceptedStateQuantity .toBigDecimal ();
713
741
} else {
714
742
bdDelta = ((DecimalType ) calculatedDelta ).toBigDecimal ();
715
- bdBase = ((DecimalType ) acceptedState ).toBigDecimal ();
743
+ bdBase = ((DecimalType ) acceptedState . get () ).toBigDecimal ();
716
744
}
717
745
bdBase = bdBase .abs ();
718
746
BigDecimal percent = bdDelta .multiply (BigDecimal .valueOf (100 )).divide (bdBase , 2 , RoundingMode .HALF_EVEN );
0 commit comments