mirror of
https://github.com/danieldemus/openhab-core.git
synced 2026-07-29 12:34:22 +02:00
Fix group calculations to use GroupItem's system unit (#4563)
* QuantityType improve group calculations * support inverse units, extend tests * refactoring * javadoc and code simplification * use streams; make sums absolute Signed-off-by: Andrew Fiddian-Green <software@whitebear.ch>
This commit is contained in:
+21
-27
@@ -15,7 +15,7 @@ package org.openhab.core.internal.items;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.measure.Quantity;
|
import javax.measure.Unit;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
@@ -48,13 +48,12 @@ public class GroupFunctionHelper {
|
|||||||
* arithmetic group function will take unit conversion into account.
|
* arithmetic group function will take unit conversion into account.
|
||||||
*
|
*
|
||||||
* @param function the {@link GroupFunctionDTO} describing the group function.
|
* @param function the {@link GroupFunctionDTO} describing the group function.
|
||||||
* @param baseItem an optional {@link Item} defining the dimension for unit conversion.
|
* @param baseItem an optional {@link Item} defining the dimension/unit for unit conversion.
|
||||||
* @return a {@link GroupFunction} according to the given parameters.
|
* @return a {@link GroupFunction} according to the given parameters.
|
||||||
*/
|
*/
|
||||||
public GroupFunction createGroupFunction(GroupFunctionDTO function, @Nullable Item baseItem) {
|
public GroupFunction createGroupFunction(GroupFunctionDTO function, @Nullable Item baseItem) {
|
||||||
Class<? extends Quantity<?>> dimension = getDimension(baseItem);
|
if (baseItem instanceof NumberItem baseNumberItem && baseNumberItem.getDimension() != null) {
|
||||||
if (dimension != null) {
|
return createDimensionGroupFunction(function, baseNumberItem);
|
||||||
return createDimensionGroupFunction(function, baseItem, dimension);
|
|
||||||
}
|
}
|
||||||
return createDefaultGroupFunction(function, baseItem);
|
return createDefaultGroupFunction(function, baseItem);
|
||||||
}
|
}
|
||||||
@@ -78,30 +77,25 @@ public class GroupFunctionHelper {
|
|||||||
return states;
|
return states;
|
||||||
}
|
}
|
||||||
|
|
||||||
private @Nullable Class<? extends Quantity<?>> getDimension(@Nullable Item baseItem) {
|
private GroupFunction createDimensionGroupFunction(GroupFunctionDTO function, NumberItem baseItem) {
|
||||||
if (baseItem instanceof NumberItem numberItem) {
|
|
||||||
return numberItem.getDimension();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private GroupFunction createDimensionGroupFunction(GroupFunctionDTO function, @Nullable Item baseItem,
|
|
||||||
Class<? extends Quantity<?>> dimension) {
|
|
||||||
final String functionName = function.name;
|
final String functionName = function.name;
|
||||||
switch (functionName.toUpperCase()) {
|
Unit<?> baseItemUnit = baseItem.getUnit();
|
||||||
case "AVG":
|
if (baseItemUnit != null) {
|
||||||
return new QuantityTypeArithmeticGroupFunction.Avg(dimension);
|
switch (functionName.toUpperCase()) {
|
||||||
case "MEDIAN":
|
case "AVG":
|
||||||
return new QuantityTypeArithmeticGroupFunction.Median(dimension, baseItem);
|
return new QuantityTypeArithmeticGroupFunction.Avg(baseItemUnit);
|
||||||
case "SUM":
|
case "MEDIAN":
|
||||||
return new QuantityTypeArithmeticGroupFunction.Sum(dimension);
|
return new QuantityTypeArithmeticGroupFunction.Median(baseItemUnit);
|
||||||
case "MIN":
|
case "SUM":
|
||||||
return new QuantityTypeArithmeticGroupFunction.Min(dimension);
|
return new QuantityTypeArithmeticGroupFunction.Sum(baseItemUnit);
|
||||||
case "MAX":
|
case "MIN":
|
||||||
return new QuantityTypeArithmeticGroupFunction.Max(dimension);
|
return new QuantityTypeArithmeticGroupFunction.Min(baseItemUnit);
|
||||||
default:
|
case "MAX":
|
||||||
return createDefaultGroupFunction(function, baseItem);
|
return new QuantityTypeArithmeticGroupFunction.Max(baseItemUnit);
|
||||||
|
default:
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return createDefaultGroupFunction(function, baseItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
private GroupFunction createDefaultGroupFunction(GroupFunctionDTO function, @Nullable Item baseItem) {
|
private GroupFunction createDefaultGroupFunction(GroupFunctionDTO function, @Nullable Item baseItem) {
|
||||||
|
|||||||
+127
-153
@@ -13,12 +13,11 @@
|
|||||||
package org.openhab.core.library.types;
|
package org.openhab.core.library.types;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.MathContext;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.measure.Quantity;
|
|
||||||
import javax.measure.Unit;
|
import javax.measure.Unit;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
@@ -26,31 +25,38 @@ import org.eclipse.jdt.annotation.Nullable;
|
|||||||
import org.openhab.core.items.GroupFunction;
|
import org.openhab.core.items.GroupFunction;
|
||||||
import org.openhab.core.items.GroupItem;
|
import org.openhab.core.items.GroupItem;
|
||||||
import org.openhab.core.items.Item;
|
import org.openhab.core.items.Item;
|
||||||
import org.openhab.core.library.items.NumberItem;
|
|
||||||
import org.openhab.core.types.State;
|
import org.openhab.core.types.State;
|
||||||
import org.openhab.core.types.UnDefType;
|
import org.openhab.core.types.UnDefType;
|
||||||
import org.openhab.core.util.Statistics;
|
import org.openhab.core.util.Statistics;
|
||||||
|
|
||||||
|
import tech.units.indriya.AbstractUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface is a container for dimension based functions that require {@link QuantityType}s for its calculations.
|
* This interface is a container for dimension based functions that require {@link QuantityType}s for its calculations.
|
||||||
*
|
*
|
||||||
* @author Henning Treu - Initial contribution
|
* @author Henning Treu - Initial contribution
|
||||||
|
* @author Andrew Fiddian-Green - Normalise calculations based on the Unit of the GroupItem
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public interface QuantityTypeArithmeticGroupFunction extends GroupFunction {
|
public interface QuantityTypeArithmeticGroupFunction extends GroupFunction {
|
||||||
|
|
||||||
abstract class DimensionalGroupFunction implements GroupFunction {
|
abstract class DimensionalGroupFunction implements GroupFunction {
|
||||||
|
|
||||||
protected final Class<? extends Quantity<?>> dimension;
|
protected final Unit<?> baseItemUnit; // the actual unit of the owning group item
|
||||||
|
protected final Unit<?> systemUnit; // the reference unit for group member calculations
|
||||||
|
|
||||||
public DimensionalGroupFunction(Class<? extends Quantity<?>> dimension) {
|
public DimensionalGroupFunction(Unit<?> baseItemUnit) {
|
||||||
this.dimension = dimension;
|
this.baseItemUnit = baseItemUnit;
|
||||||
|
this.systemUnit = baseItemUnit.getSystemUnit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable <T extends State> T getStateAs(@Nullable Set<Item> items, Class<T> stateClass) {
|
public @Nullable <T extends State> T getStateAs(@Nullable Set<Item> items, Class<T> stateClass) {
|
||||||
State state = calculate(items);
|
State state = calculate(items);
|
||||||
if (stateClass.isInstance(state)) {
|
if (stateClass.isInstance(state)) {
|
||||||
|
if (state instanceof QuantityType<?> quantity) {
|
||||||
|
state = toInvertibleUnit(quantity, baseItemUnit);
|
||||||
|
}
|
||||||
return stateClass.cast(state);
|
return stateClass.cast(state);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
@@ -62,102 +68,76 @@ public interface QuantityTypeArithmeticGroupFunction extends GroupFunction {
|
|||||||
return new State[0];
|
return new State[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isSameDimension(@Nullable Item item) {
|
/**
|
||||||
if (item instanceof GroupItem groupItem) {
|
* Convert the given {@link QuantityType} to an equivalent based on the given {@link Unit}. The conversion can
|
||||||
return isSameDimension(groupItem.getBaseItem());
|
* be made to both inverted and non-inverted units, so invertible type conversions (e.g. Mirek <=> Kelvin) are
|
||||||
|
* supported.
|
||||||
|
* <p>
|
||||||
|
* Note: we can use {@link QuantityType.toInvertibleUnit()} if OH Core PR #4561 is merged.
|
||||||
|
*
|
||||||
|
* @param source the {@link QuantityType} to be converted.
|
||||||
|
* @param targetUnit the {@link Unit} to convert to.
|
||||||
|
*
|
||||||
|
* @return a new {@link QuantityType} based on 'targetUnit' or null.
|
||||||
|
*/
|
||||||
|
private @Nullable QuantityType<?> toInvertibleUnit(QuantityType<?> source, Unit<?> targetUnit) {
|
||||||
|
if (!targetUnit.equals(source.getUnit()) && !targetUnit.isCompatible(AbstractUnit.ONE)
|
||||||
|
&& source.getUnit().inverse().isCompatible(targetUnit)) {
|
||||||
|
QuantityType<?> sourceInSystemUnit = source.toUnit(source.getUnit().getSystemUnit());
|
||||||
|
return sourceInSystemUnit != null ? sourceInSystemUnit.inverse().toUnit(targetUnit) : null;
|
||||||
}
|
}
|
||||||
return item instanceof NumberItem ni && dimension.equals(ni.getDimension());
|
return source.toUnit(targetUnit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given item {@link State} to a {@link QuantityType} based on the {@link Unit} of the
|
||||||
|
* {@link GroupItem} i.e. 'referenceUnit'. Returns null if the {@link State} is not a {@link QuantityType} or
|
||||||
|
* if the {@link QuantityType} could not be converted to 'referenceUnit'.
|
||||||
|
*
|
||||||
|
* The conversion can be made to both inverted and non-inverted units, so invertible type conversions (e.g.
|
||||||
|
* Mirek <=> Kelvin) are supported.
|
||||||
|
*
|
||||||
|
* @param state the State of any given group member item
|
||||||
|
* @return a QuantityType or null
|
||||||
|
*/
|
||||||
|
private @Nullable QuantityType<?> toQuantityTypeOfUnit(@Nullable State state, Unit<?> unit) {
|
||||||
|
return state instanceof QuantityType<?> quantity //
|
||||||
|
? toInvertibleUnit(quantity, unit)
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a set of {@link Item} to a respective list of {@link QuantityType}. Exclude any {@link Item}s whose
|
||||||
|
* current {@link State} is not a {@link QuantityType}. Convert any remaining {@link QuantityType} to the
|
||||||
|
* 'referenceUnit' and exclude any values that did not convert.
|
||||||
|
*
|
||||||
|
* @param items a list of {@link Item}
|
||||||
|
* @return a list of {@link QuantityType} converted to the 'referenceUnit'
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({ "rawtypes" })
|
||||||
|
protected List<QuantityType> toQuantityTypesOfUnit(Set<Item> items, Unit<?> unit) {
|
||||||
|
return items.stream().map(i -> i.getState()).map(s -> toQuantityTypeOfUnit(s, unit))
|
||||||
|
.filter(Objects::nonNull).map(s -> (QuantityType) s).toList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This calculates the numeric average over all item states of {@link QuantityType}.
|
* Calculates the average of a set of item states whose value could be converted to the 'referenceUnit'.
|
||||||
*/
|
*/
|
||||||
class Avg extends DimensionalGroupFunction {
|
class Avg extends DimensionalGroupFunction {
|
||||||
|
|
||||||
public Avg(Class<? extends Quantity<?>> dimension) {
|
public Avg(Unit<?> baseItemUnit) {
|
||||||
super(dimension);
|
super(baseItemUnit);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
|
||||||
public State calculate(@Nullable Set<Item> items) {
|
|
||||||
if (items == null || items.isEmpty()) {
|
|
||||||
return UnDefType.UNDEF;
|
|
||||||
}
|
|
||||||
|
|
||||||
QuantityType<?> sum = null;
|
|
||||||
int count = 0;
|
|
||||||
for (Item item : items) {
|
|
||||||
if (isSameDimension(item)) {
|
|
||||||
QuantityType itemState = item.getStateAs(QuantityType.class);
|
|
||||||
if (itemState != null) {
|
|
||||||
if (sum == null) {
|
|
||||||
sum = itemState; // initialise the sum from the first item
|
|
||||||
count++;
|
|
||||||
} else {
|
|
||||||
itemState = itemState.toInvertibleUnit(sum.getUnit());
|
|
||||||
if (itemState != null) {
|
|
||||||
sum = sum.add(itemState);
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sum != null && count > 0) {
|
|
||||||
BigDecimal result = sum.toBigDecimal().divide(BigDecimal.valueOf(count), MathContext.DECIMAL128);
|
|
||||||
return new QuantityType(result, sum.getUnit());
|
|
||||||
}
|
|
||||||
|
|
||||||
return UnDefType.UNDEF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This calculates the numeric median over all item states of {@link QuantityType}.
|
|
||||||
*/
|
|
||||||
class Median extends DimensionalGroupFunction {
|
|
||||||
|
|
||||||
private @Nullable Item baseItem;
|
|
||||||
|
|
||||||
public Median(Class<? extends Quantity<?>> dimension, @Nullable Item baseItem) {
|
|
||||||
super(dimension);
|
|
||||||
this.baseItem = baseItem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
public State calculate(@Nullable Set<Item> items) {
|
public State calculate(@Nullable Set<Item> items) {
|
||||||
if (items != null) {
|
if (items != null) {
|
||||||
List<BigDecimal> values = new ArrayList<>();
|
List<QuantityType> systemUnitQuantities = toQuantityTypesOfUnit(items, systemUnit);
|
||||||
Unit<?> unit = null;
|
if (!systemUnitQuantities.isEmpty()) {
|
||||||
if (baseItem instanceof NumberItem numberItem) {
|
return systemUnitQuantities.stream().reduce(new QuantityType<>(0, systemUnit), QuantityType::add)
|
||||||
unit = numberItem.getUnit();
|
.divide(BigDecimal.valueOf(systemUnitQuantities.size()));
|
||||||
}
|
|
||||||
for (Item item : items) {
|
|
||||||
if (!isSameDimension(item)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
QuantityType itemState = item.getStateAs(QuantityType.class);
|
|
||||||
if (itemState == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (unit == null) {
|
|
||||||
unit = itemState.getUnit(); // set it to the first item's unit
|
|
||||||
}
|
|
||||||
if (itemState.toInvertibleUnit(unit) instanceof QuantityType<?> inverted) {
|
|
||||||
values.add(inverted.toBigDecimal());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!values.isEmpty()) {
|
|
||||||
BigDecimal median = Statistics.median(values);
|
|
||||||
if (median != null && unit != null) {
|
|
||||||
return new QuantityType<>(median, unit);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return UnDefType.UNDEF;
|
return UnDefType.UNDEF;
|
||||||
@@ -165,105 +145,99 @@ public interface QuantityTypeArithmeticGroupFunction extends GroupFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This calculates the numeric sum over all item states of {@link QuantityType}.
|
* Calculates the median of a set of item states whose value could be converted to the 'referenceUnit'.
|
||||||
|
*/
|
||||||
|
class Median extends DimensionalGroupFunction {
|
||||||
|
|
||||||
|
public Median(Unit<?> baseItemUnit) {
|
||||||
|
super(baseItemUnit);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public State calculate(@Nullable Set<Item> items) {
|
||||||
|
if (items != null) {
|
||||||
|
BigDecimal median = Statistics
|
||||||
|
.median(toQuantityTypesOfUnit(items, systemUnit).stream().map(q -> q.toBigDecimal()).toList());
|
||||||
|
if (median != null) {
|
||||||
|
return new QuantityType<>(median, systemUnit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return UnDefType.UNDEF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the sum of a set of item states whose value could be converted to the 'referenceUnit'.
|
||||||
|
*
|
||||||
|
* Uses the {@link QuanitityType.add()} method so the result is an incremental sum based on the 'referenceUnit'. As
|
||||||
|
* a general rule this class is instantiated with a 'referenceUnit' that is a "system unit" (which are zero based)
|
||||||
|
* so such incremental sum is in fact also an absolute sum. However the class COULD be instantiated with a "non-
|
||||||
|
* system unit" (e.g. °C, °F) in which case the result would be an incremental sum based on that unit.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
class Sum extends DimensionalGroupFunction {
|
class Sum extends DimensionalGroupFunction {
|
||||||
|
|
||||||
public Sum(Class<? extends Quantity<?>> dimension) {
|
public Sum(Unit<?> baseItemUnit) {
|
||||||
super(dimension);
|
super(baseItemUnit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
@SuppressWarnings("unchecked")
|
||||||
public State calculate(@Nullable Set<Item> items) {
|
public State calculate(@Nullable Set<Item> items) {
|
||||||
if (items == null || items.isEmpty()) {
|
if (items != null) {
|
||||||
return UnDefType.UNDEF;
|
@SuppressWarnings("rawtypes")
|
||||||
}
|
List<QuantityType> systemUnitQuantities = toQuantityTypesOfUnit(items, baseItemUnit);
|
||||||
|
if (!systemUnitQuantities.isEmpty()) {
|
||||||
QuantityType<?> sum = null;
|
return systemUnitQuantities.stream().reduce(new QuantityType<>(0, baseItemUnit), QuantityType::add);
|
||||||
for (Item item : items) {
|
|
||||||
if (isSameDimension(item)) {
|
|
||||||
QuantityType itemState = item.getStateAs(QuantityType.class);
|
|
||||||
if (itemState != null) {
|
|
||||||
if (sum == null) {
|
|
||||||
sum = itemState; // initialise the sum from the first item
|
|
||||||
} else {
|
|
||||||
itemState = itemState.toUnit(sum.getUnit());
|
|
||||||
if (itemState != null) {
|
|
||||||
sum = sum.add(itemState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return UnDefType.UNDEF;
|
||||||
return sum != null ? sum : UnDefType.UNDEF;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This calculates the minimum value of all item states of {@link QuantityType}.
|
* Calculates the minimum of a set of item states whose value could be converted to the 'referenceUnit'.
|
||||||
*/
|
*/
|
||||||
class Min extends DimensionalGroupFunction {
|
class Min extends DimensionalGroupFunction {
|
||||||
|
|
||||||
public Min(Class<? extends Quantity<?>> dimension) {
|
public Min(Unit<?> baseItemUnit) {
|
||||||
super(dimension);
|
super(baseItemUnit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
|
||||||
public State calculate(@Nullable Set<Item> items) {
|
public State calculate(@Nullable Set<Item> items) {
|
||||||
if (items == null || items.isEmpty()) {
|
if (items != null) {
|
||||||
return UnDefType.UNDEF;
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
}
|
Optional<QuantityType> min = toQuantityTypesOfUnit(items, systemUnit).stream()
|
||||||
|
.min(QuantityType::compareTo);
|
||||||
QuantityType<?> min = null;
|
if (min.isPresent()) {
|
||||||
for (Item item : items) {
|
return min.get();
|
||||||
if (isSameDimension(item)) {
|
|
||||||
QuantityType itemState = item.getStateAs(QuantityType.class);
|
|
||||||
if (itemState != null) {
|
|
||||||
if (min == null
|
|
||||||
|| (min.getUnit().isCompatible(itemState.getUnit()) && min.compareTo(itemState) > 0)) {
|
|
||||||
min = itemState;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return UnDefType.UNDEF;
|
||||||
return min != null ? min : UnDefType.UNDEF;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This calculates the maximum value of all item states of {@link QuantityType}.
|
* Calculates the maximum of a set of item states whose value could be converted to the 'referenceUnit'.
|
||||||
*/
|
*/
|
||||||
class Max extends DimensionalGroupFunction {
|
class Max extends DimensionalGroupFunction {
|
||||||
|
|
||||||
public Max(Class<? extends Quantity<?>> dimension) {
|
public Max(Unit<?> targetUnit) {
|
||||||
super(dimension);
|
super(targetUnit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
|
||||||
public State calculate(@Nullable Set<Item> items) {
|
public State calculate(@Nullable Set<Item> items) {
|
||||||
if (items == null || items.isEmpty()) {
|
if (items != null) {
|
||||||
return UnDefType.UNDEF;
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
}
|
Optional<QuantityType> max = toQuantityTypesOfUnit(items, systemUnit).stream()
|
||||||
|
.max(QuantityType::compareTo);
|
||||||
QuantityType<?> max = null;
|
if (max.isPresent()) {
|
||||||
for (Item item : items) {
|
return max.get();
|
||||||
if (isSameDimension(item)) {
|
|
||||||
QuantityType itemState = item.getStateAs(QuantityType.class);
|
|
||||||
if (itemState != null) {
|
|
||||||
if (max == null
|
|
||||||
|| (max.getUnit().isCompatible(itemState.getUnit()) && max.compareTo(itemState) < 0)) {
|
|
||||||
max = itemState;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return UnDefType.UNDEF;
|
||||||
return max != null ? max : UnDefType.UNDEF;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+209
-17
@@ -15,7 +15,7 @@ package org.openhab.core.library.types;
|
|||||||
import static org.hamcrest.CoreMatchers.is;
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.number.IsCloseTo.closeTo;
|
import static org.hamcrest.number.IsCloseTo.closeTo;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
import static org.junit.jupiter.params.provider.Arguments.arguments;
|
import static org.junit.jupiter.params.provider.Arguments.arguments;
|
||||||
|
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
@@ -46,6 +46,9 @@ import org.openhab.core.items.GroupItem;
|
|||||||
import org.openhab.core.items.Item;
|
import org.openhab.core.items.Item;
|
||||||
import org.openhab.core.library.CoreItemFactory;
|
import org.openhab.core.library.CoreItemFactory;
|
||||||
import org.openhab.core.library.items.NumberItem;
|
import org.openhab.core.library.items.NumberItem;
|
||||||
|
import org.openhab.core.library.unit.ImperialUnits;
|
||||||
|
import org.openhab.core.library.unit.SIUnits;
|
||||||
|
import org.openhab.core.library.unit.Units;
|
||||||
import org.openhab.core.types.State;
|
import org.openhab.core.types.State;
|
||||||
import org.openhab.core.types.UnDefType;
|
import org.openhab.core.types.UnDefType;
|
||||||
import org.osgi.service.component.ComponentContext;
|
import org.osgi.service.component.ComponentContext;
|
||||||
@@ -85,7 +88,7 @@ public class QuantityTypeArithmeticGroupFunctionTest {
|
|||||||
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
||||||
items.add(createNumberItem("TestItem5", Temperature.class, new QuantityType<>("122.41 °C")));
|
items.add(createNumberItem("TestItem5", Temperature.class, new QuantityType<>("122.41 °C")));
|
||||||
|
|
||||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Sum(Temperature.class);
|
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Sum(SIUnits.CELSIUS);
|
||||||
State state = function.calculate(items);
|
State state = function.calculate(items);
|
||||||
|
|
||||||
assertEquals(new QuantityType<>("234.95 °C"), state);
|
assertEquals(new QuantityType<>("234.95 °C"), state);
|
||||||
@@ -103,7 +106,7 @@ public class QuantityTypeArithmeticGroupFunctionTest {
|
|||||||
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
||||||
items.add(createNumberItem("TestItem5", Temperature.class, new QuantityType<>("395.56 K")));
|
items.add(createNumberItem("TestItem5", Temperature.class, new QuantityType<>("395.56 K")));
|
||||||
|
|
||||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Sum(Temperature.class);
|
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Sum(SIUnits.CELSIUS);
|
||||||
State state = function.calculate(items);
|
State state = function.calculate(items);
|
||||||
|
|
||||||
assertEquals(new QuantityType<>("234.95 °C"), state);
|
assertEquals(new QuantityType<>("234.95 °C"), state);
|
||||||
@@ -119,7 +122,7 @@ public class QuantityTypeArithmeticGroupFunctionTest {
|
|||||||
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
||||||
items.add(createNumberItem("TestItem3", Pressure.class, new QuantityType<>("192.2 hPa")));
|
items.add(createNumberItem("TestItem3", Pressure.class, new QuantityType<>("192.2 hPa")));
|
||||||
|
|
||||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Sum(Temperature.class);
|
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Sum(SIUnits.CELSIUS);
|
||||||
State state = function.calculate(items);
|
State state = function.calculate(items);
|
||||||
|
|
||||||
assertEquals(new QuantityType<>("23.54 °C"), state);
|
assertEquals(new QuantityType<>("23.54 °C"), state);
|
||||||
@@ -137,7 +140,7 @@ public class QuantityTypeArithmeticGroupFunctionTest {
|
|||||||
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
||||||
items.add(createNumberItem("TestItem5", Temperature.class, new QuantityType<>("300 °C")));
|
items.add(createNumberItem("TestItem5", Temperature.class, new QuantityType<>("300 °C")));
|
||||||
|
|
||||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Avg(Temperature.class);
|
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Avg(Units.KELVIN);
|
||||||
State state = function.calculate(items);
|
State state = function.calculate(items);
|
||||||
|
|
||||||
assertEquals(new QuantityType<>("200 °C"), state);
|
assertEquals(new QuantityType<>("200 °C"), state);
|
||||||
@@ -163,10 +166,11 @@ public class QuantityTypeArithmeticGroupFunctionTest {
|
|||||||
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
||||||
items.add(createNumberItem("TestItem5", Temperature.class, new QuantityType<>("294.15 K")));
|
items.add(createNumberItem("TestItem5", Temperature.class, new QuantityType<>("294.15 K")));
|
||||||
|
|
||||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Avg(Temperature.class);
|
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Avg(Units.KELVIN);
|
||||||
State state = function.calculate(items);
|
State state = function.calculate(items);
|
||||||
|
|
||||||
assertEquals(new QuantityType<>("55.33333333333333333333333333333334 °C"), state);
|
assertTrue(state instanceof QuantityType<?>);
|
||||||
|
assertEquals(328.48, ((QuantityType<?>) state).doubleValue(), 0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@@ -179,12 +183,13 @@ public class QuantityTypeArithmeticGroupFunctionTest {
|
|||||||
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
||||||
items.add(createNumberItem("TestItem3", Pressure.class, new QuantityType<>("192.2 hPa")));
|
items.add(createNumberItem("TestItem3", Pressure.class, new QuantityType<>("192.2 hPa")));
|
||||||
|
|
||||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Avg(Temperature.class);
|
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Avg(SIUnits.CELSIUS);
|
||||||
State state = function.calculate(items);
|
State state = function.calculate(items);
|
||||||
|
|
||||||
assertEquals(new QuantityType<>("23.54 °C"), state);
|
assertEquals(new QuantityType<>("23.54 °C"), state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
static Stream<Arguments> medianTestSource() {
|
static Stream<Arguments> medianTestSource() {
|
||||||
return Stream.of( //
|
return Stream.of( //
|
||||||
arguments( //
|
arguments( //
|
||||||
@@ -214,13 +219,14 @@ public class QuantityTypeArithmeticGroupFunctionTest {
|
|||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("medianTestSource")
|
@MethodSource("medianTestSource")
|
||||||
|
@SuppressWarnings({ "null", "rawtypes", "unchecked" })
|
||||||
public void testMedianFunctionQuantityType(List<State> states, State expected) {
|
public void testMedianFunctionQuantityType(List<State> states, State expected) {
|
||||||
AtomicInteger index = new AtomicInteger(1);
|
AtomicInteger index = new AtomicInteger(1);
|
||||||
Set<Item> items = states.stream()
|
Set<Item> items = states.stream()
|
||||||
.map(state -> createNumberItem("TestItem" + index.getAndIncrement(), Temperature.class, state))
|
.map(state -> createNumberItem("TestItem" + index.getAndIncrement(), Temperature.class, state))
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Median(Temperature.class, null);
|
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Median(SIUnits.CELSIUS);
|
||||||
State state = function.calculate(items);
|
State state = function.calculate(items);
|
||||||
|
|
||||||
assertEquals(state.getClass(), expected.getClass());
|
assertEquals(state.getClass(), expected.getClass());
|
||||||
@@ -242,7 +248,7 @@ public class QuantityTypeArithmeticGroupFunctionTest {
|
|||||||
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
||||||
items.add(createNumberItem("TestItem5", Temperature.class, new QuantityType<>("300 °C")));
|
items.add(createNumberItem("TestItem5", Temperature.class, new QuantityType<>("300 °C")));
|
||||||
|
|
||||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Max(Temperature.class);
|
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Max(SIUnits.CELSIUS);
|
||||||
State state = function.calculate(items);
|
State state = function.calculate(items);
|
||||||
|
|
||||||
assertEquals(new QuantityType<>("300 °C"), state);
|
assertEquals(new QuantityType<>("300 °C"), state);
|
||||||
@@ -260,7 +266,7 @@ public class QuantityTypeArithmeticGroupFunctionTest {
|
|||||||
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
||||||
items.add(createNumberItem("TestItem5", Temperature.class, new QuantityType<>("294.15 K")));
|
items.add(createNumberItem("TestItem5", Temperature.class, new QuantityType<>("294.15 K")));
|
||||||
|
|
||||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Max(Temperature.class);
|
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Max(SIUnits.CELSIUS);
|
||||||
State state = function.calculate(items);
|
State state = function.calculate(items);
|
||||||
|
|
||||||
assertEquals(new QuantityType<>("100 °C"), state);
|
assertEquals(new QuantityType<>("100 °C"), state);
|
||||||
@@ -276,7 +282,7 @@ public class QuantityTypeArithmeticGroupFunctionTest {
|
|||||||
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
||||||
items.add(createNumberItem("TestItem3", Pressure.class, new QuantityType<>("192.2 hPa")));
|
items.add(createNumberItem("TestItem3", Pressure.class, new QuantityType<>("192.2 hPa")));
|
||||||
|
|
||||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Max(Temperature.class);
|
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Max(SIUnits.CELSIUS);
|
||||||
State state = function.calculate(items);
|
State state = function.calculate(items);
|
||||||
|
|
||||||
assertEquals(new QuantityType<>("23.54 °C"), state);
|
assertEquals(new QuantityType<>("23.54 °C"), state);
|
||||||
@@ -294,7 +300,7 @@ public class QuantityTypeArithmeticGroupFunctionTest {
|
|||||||
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
||||||
items.add(createNumberItem("TestItem5", Temperature.class, new QuantityType<>("300 °C")));
|
items.add(createNumberItem("TestItem5", Temperature.class, new QuantityType<>("300 °C")));
|
||||||
|
|
||||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Min(Temperature.class);
|
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Min(SIUnits.CELSIUS);
|
||||||
State state = function.calculate(items);
|
State state = function.calculate(items);
|
||||||
|
|
||||||
assertEquals(new QuantityType<>("100 °C"), state);
|
assertEquals(new QuantityType<>("100 °C"), state);
|
||||||
@@ -313,7 +319,7 @@ public class QuantityTypeArithmeticGroupFunctionTest {
|
|||||||
items.add(createNumberItem("TestItem5", Dimensionless.class, new QuantityType<>("0 %")));
|
items.add(createNumberItem("TestItem5", Dimensionless.class, new QuantityType<>("0 %")));
|
||||||
items.add(createNumberItem("TestItem6", Dimensionless.class, new QuantityType<>("0 %")));
|
items.add(createNumberItem("TestItem6", Dimensionless.class, new QuantityType<>("0 %")));
|
||||||
|
|
||||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Max(Dimensionless.class);
|
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Max(Units.ONE);
|
||||||
State state = function.calculate(items);
|
State state = function.calculate(items);
|
||||||
|
|
||||||
assertEquals(new QuantityType<>("48 %"), state);
|
assertEquals(new QuantityType<>("48 %"), state);
|
||||||
@@ -331,7 +337,7 @@ public class QuantityTypeArithmeticGroupFunctionTest {
|
|||||||
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
||||||
items.add(createNumberItem("TestItem5", Temperature.class, new QuantityType<>("294.15 K")));
|
items.add(createNumberItem("TestItem5", Temperature.class, new QuantityType<>("294.15 K")));
|
||||||
|
|
||||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Min(Temperature.class);
|
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Min(SIUnits.CELSIUS);
|
||||||
State state = function.calculate(items);
|
State state = function.calculate(items);
|
||||||
|
|
||||||
assertEquals(new QuantityType<>("294.15 K"), state);
|
assertEquals(new QuantityType<>("294.15 K"), state);
|
||||||
@@ -347,7 +353,7 @@ public class QuantityTypeArithmeticGroupFunctionTest {
|
|||||||
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
||||||
items.add(createNumberItem("TestItem3", Pressure.class, new QuantityType<>("192.2 hPa")));
|
items.add(createNumberItem("TestItem3", Pressure.class, new QuantityType<>("192.2 hPa")));
|
||||||
|
|
||||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Min(Temperature.class);
|
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Min(SIUnits.CELSIUS);
|
||||||
State state = function.calculate(items);
|
State state = function.calculate(items);
|
||||||
|
|
||||||
assertEquals(new QuantityType<>("23.54 °C"), state);
|
assertEquals(new QuantityType<>("23.54 °C"), state);
|
||||||
@@ -362,7 +368,7 @@ public class QuantityTypeArithmeticGroupFunctionTest {
|
|||||||
items.add(createNumberItem("TestItem1", Power.class, new QuantityType<>("5 W")));
|
items.add(createNumberItem("TestItem1", Power.class, new QuantityType<>("5 W")));
|
||||||
items.add(createGroupItem("TestGroup1", Power.class, new QuantityType<>("5 W")));
|
items.add(createGroupItem("TestGroup1", Power.class, new QuantityType<>("5 W")));
|
||||||
|
|
||||||
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Sum(Power.class);
|
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Sum(Units.WATT);
|
||||||
State state = function.calculate(items);
|
State state = function.calculate(items);
|
||||||
|
|
||||||
assertEquals(new QuantityType<>("10 W"), state);
|
assertEquals(new QuantityType<>("10 W"), state);
|
||||||
@@ -380,4 +386,190 @@ public class QuantityTypeArithmeticGroupFunctionTest {
|
|||||||
item.setState(state);
|
item.setState(state);
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("locales")
|
||||||
|
public void testSumFunctionQuantityTypeDifferentUnitsBaseKelvin(Locale locale) {
|
||||||
|
Locale.setDefault(locale);
|
||||||
|
|
||||||
|
Set<Item> items = new LinkedHashSet<>();
|
||||||
|
items.add(createNumberItem("TestItem1", Temperature.class, new QuantityType<>("23.54 °C")));
|
||||||
|
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
||||||
|
items.add(createNumberItem("TestItem3", Temperature.class, new QuantityType<>("192.2 °F")));
|
||||||
|
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
||||||
|
items.add(createNumberItem("TestItem5", Temperature.class, new QuantityType<>("395.56 K")));
|
||||||
|
|
||||||
|
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Sum(Units.KELVIN);
|
||||||
|
State state = function.calculate(items);
|
||||||
|
|
||||||
|
assertEquals(new QuantityType<>("1054.40 K"), state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("locales")
|
||||||
|
public void testAvgFunctionQuantityTypeDifferentUnitsBaseKelvin(Locale locale) {
|
||||||
|
Locale.setDefault(locale);
|
||||||
|
|
||||||
|
Set<Item> items = new LinkedHashSet<>();
|
||||||
|
items.add(createNumberItem("TestItem1", Temperature.class, new QuantityType<>("100 °C")));
|
||||||
|
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
||||||
|
items.add(createNumberItem("TestItem3", Temperature.class, new QuantityType<>("113 °F")));
|
||||||
|
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
||||||
|
items.add(createNumberItem("TestItem5", Temperature.class, new QuantityType<>("294.15 K")));
|
||||||
|
|
||||||
|
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Avg(Units.KELVIN);
|
||||||
|
State state = function.calculate(items);
|
||||||
|
|
||||||
|
assertTrue(state instanceof QuantityType<?>);
|
||||||
|
assertEquals(328.48, ((QuantityType<?>) state).doubleValue(), 0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("locales")
|
||||||
|
public void testMaxFunctionQuantityTypeDifferentUnitsBaseKelvin(Locale locale) {
|
||||||
|
Locale.setDefault(locale);
|
||||||
|
|
||||||
|
Set<Item> items = new LinkedHashSet<>();
|
||||||
|
items.add(createNumberItem("TestItem1", Temperature.class, new QuantityType<>("100 °C")));
|
||||||
|
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
||||||
|
items.add(createNumberItem("TestItem3", Temperature.class, new QuantityType<>("113 °F")));
|
||||||
|
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
||||||
|
items.add(createNumberItem("TestItem5", Temperature.class, new QuantityType<>("294.15 K")));
|
||||||
|
|
||||||
|
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Max(Units.KELVIN);
|
||||||
|
State state = function.calculate(items);
|
||||||
|
|
||||||
|
assertEquals(new QuantityType<>("100 °C"), state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("locales")
|
||||||
|
public void testMinFunctionQuantityTypeDifferentUnitsBaseKelvin(Locale locale) {
|
||||||
|
Locale.setDefault(locale);
|
||||||
|
|
||||||
|
Set<Item> items = new LinkedHashSet<>();
|
||||||
|
items.add(createNumberItem("TestItem1", Temperature.class, new QuantityType<>("100 °C")));
|
||||||
|
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
||||||
|
items.add(createNumberItem("TestItem3", Temperature.class, new QuantityType<>("113 °F")));
|
||||||
|
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
||||||
|
items.add(createNumberItem("TestItem5", Temperature.class, new QuantityType<>("294.15 K")));
|
||||||
|
|
||||||
|
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Min(Units.KELVIN);
|
||||||
|
State state = function.calculate(items);
|
||||||
|
|
||||||
|
assertEquals(new QuantityType<>("294.15 K"), state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("locales")
|
||||||
|
public void testSumFunctionColorTemperatureDifferentUnitsBaseKelvin(Locale locale) {
|
||||||
|
Locale.setDefault(locale);
|
||||||
|
|
||||||
|
Set<Item> items = new LinkedHashSet<>();
|
||||||
|
items.add(createNumberItem("TestItem1", Temperature.class, QuantityType.valueOf(2000, Units.KELVIN)));
|
||||||
|
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
||||||
|
items.add(createNumberItem("TestItem3", Temperature.class, QuantityType.valueOf(1726.85, SIUnits.CELSIUS)));
|
||||||
|
items.add(createNumberItem("TestItem4", Temperature.class, QuantityType.valueOf(500, Units.MIRED)));
|
||||||
|
items.add(createNumberItem("TestItem5", Temperature.class,
|
||||||
|
QuantityType.valueOf(3140.33, ImperialUnits.FAHRENHEIT)));
|
||||||
|
|
||||||
|
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Sum(Units.KELVIN);
|
||||||
|
State state = function.calculate(items);
|
||||||
|
|
||||||
|
assertEquals(new QuantityType<>("8000 K"), state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("locales")
|
||||||
|
public void testAvgFunctionQuantityTypeColorTempDifferentUnitsBaseKelvin(Locale locale) {
|
||||||
|
Locale.setDefault(locale);
|
||||||
|
|
||||||
|
Set<Item> items = new LinkedHashSet<>();
|
||||||
|
items.add(createNumberItem("TestItem1", Temperature.class, QuantityType.valueOf(2000, Units.KELVIN)));
|
||||||
|
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
||||||
|
items.add(createNumberItem("TestItem3", Temperature.class, QuantityType.valueOf(1726.85, SIUnits.CELSIUS)));
|
||||||
|
items.add(createNumberItem("TestItem4", Temperature.class, QuantityType.valueOf(500, Units.MIRED)));
|
||||||
|
items.add(createNumberItem("TestItem5", Temperature.class,
|
||||||
|
QuantityType.valueOf(3140.33, ImperialUnits.FAHRENHEIT)));
|
||||||
|
|
||||||
|
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Avg(Units.KELVIN);
|
||||||
|
State state = function.calculate(items);
|
||||||
|
|
||||||
|
assertEquals(new QuantityType<>("2000 K"), state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("locales")
|
||||||
|
public void testAvgFunctionQuantityTypeColorTempDifferentUnitsBaseMirek(Locale locale) {
|
||||||
|
Locale.setDefault(locale);
|
||||||
|
|
||||||
|
Set<Item> items = new LinkedHashSet<>();
|
||||||
|
items.add(createNumberItem("TestItem1", Temperature.class, QuantityType.valueOf(2000, Units.KELVIN)));
|
||||||
|
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
||||||
|
items.add(createNumberItem("TestItem3", Temperature.class, QuantityType.valueOf(1726.85, SIUnits.CELSIUS)));
|
||||||
|
items.add(createNumberItem("TestItem4", Temperature.class, QuantityType.valueOf(500, Units.MIRED)));
|
||||||
|
items.add(createNumberItem("TestItem5", Temperature.class,
|
||||||
|
QuantityType.valueOf(3140.33, ImperialUnits.FAHRENHEIT)));
|
||||||
|
|
||||||
|
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Avg(Units.MIRED);
|
||||||
|
State state = function.calculate(items);
|
||||||
|
|
||||||
|
assertEquals(new QuantityType<>("2000 K"), state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("locales")
|
||||||
|
public void testMinFunctionColorTemperatureDifferentUnitsBaseKelvin(Locale locale) {
|
||||||
|
Locale.setDefault(locale);
|
||||||
|
|
||||||
|
Set<Item> items = new LinkedHashSet<>();
|
||||||
|
items.add(createNumberItem("TestItem1", Temperature.class, QuantityType.valueOf(1999, Units.KELVIN)));
|
||||||
|
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
||||||
|
items.add(createNumberItem("TestItem3", Temperature.class, QuantityType.valueOf(1726.85, SIUnits.CELSIUS)));
|
||||||
|
items.add(createNumberItem("TestItem4", Temperature.class, QuantityType.valueOf(500, Units.MIRED)));
|
||||||
|
items.add(createNumberItem("TestItem5", Temperature.class,
|
||||||
|
QuantityType.valueOf(3140.33, ImperialUnits.FAHRENHEIT)));
|
||||||
|
|
||||||
|
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Min(Units.KELVIN);
|
||||||
|
State state = function.calculate(items);
|
||||||
|
|
||||||
|
assertEquals(new QuantityType<>("1999 K"), state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("locales")
|
||||||
|
public void testMaxFunctionColorTemperatureDifferentUnitsBaseKelvin(Locale locale) {
|
||||||
|
Locale.setDefault(locale);
|
||||||
|
|
||||||
|
Set<Item> items = new LinkedHashSet<>();
|
||||||
|
items.add(createNumberItem("TestItem1", Temperature.class, QuantityType.valueOf(2001, Units.KELVIN)));
|
||||||
|
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
||||||
|
items.add(createNumberItem("TestItem3", Temperature.class, QuantityType.valueOf(1726.85, SIUnits.CELSIUS)));
|
||||||
|
items.add(createNumberItem("TestItem4", Temperature.class, QuantityType.valueOf(500, Units.MIRED)));
|
||||||
|
items.add(createNumberItem("TestItem5", Temperature.class,
|
||||||
|
QuantityType.valueOf(3140.33, ImperialUnits.FAHRENHEIT)));
|
||||||
|
|
||||||
|
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Max(Units.KELVIN);
|
||||||
|
State state = function.calculate(items);
|
||||||
|
|
||||||
|
assertEquals(new QuantityType<>("2001 K"), state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("locales")
|
||||||
|
public void testSumFunctionQuantityTypeDifferentUnitsBaseWatt(Locale locale) {
|
||||||
|
Locale.setDefault(locale);
|
||||||
|
|
||||||
|
Set<Item> items = new LinkedHashSet<>();
|
||||||
|
items.add(createNumberItem("TestItem1", Power.class, new QuantityType<>("1 W")));
|
||||||
|
items.add(createNumberItem("TestItem2", Temperature.class, UnDefType.NULL));
|
||||||
|
items.add(createNumberItem("TestItem3", Temperature.class, new QuantityType<>("192.2 °F")));
|
||||||
|
items.add(createNumberItem("TestItem4", Temperature.class, UnDefType.UNDEF));
|
||||||
|
items.add(createNumberItem("TestItem5", Power.class, new QuantityType<>("3000 mW")));
|
||||||
|
|
||||||
|
GroupFunction function = new QuantityTypeArithmeticGroupFunction.Sum(Units.WATT);
|
||||||
|
State state = function.calculate(items);
|
||||||
|
|
||||||
|
assertEquals(new QuantityType<>("4 W"), state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user