diff --git a/bundles/org.openhab.core.io.rest.sse/src/main/java/org/openhab/core/io/rest/sse/internal/SseItemStatesEventBuilder.java b/bundles/org.openhab.core.io.rest.sse/src/main/java/org/openhab/core/io/rest/sse/internal/SseItemStatesEventBuilder.java index 3391c3e9dd..f7f164edc5 100644 --- a/bundles/org.openhab.core.io.rest.sse/src/main/java/org/openhab/core/io/rest/sse/internal/SseItemStatesEventBuilder.java +++ b/bundles/org.openhab.core.io.rest.sse/src/main/java/org/openhab/core/io/rest/sse/internal/SseItemStatesEventBuilder.java @@ -135,7 +135,7 @@ public class SseItemStatesEventBuilder { // state description will display the new unit: Unit patternUnit = UnitUtils.parseUnit(pattern); if (patternUnit != null && !quantityState.getUnit().equals(patternUnit)) { - quantityState = quantityState.toUnit(patternUnit); + quantityState = quantityState.toInvertibleUnit(patternUnit); } if (quantityState != null) { diff --git a/bundles/org.openhab.core.model.script/src/org/openhab/core/model/script/lib/NumberExtensions.java b/bundles/org.openhab.core.model.script/src/org/openhab/core/model/script/lib/NumberExtensions.java index 2cfe4428f2..d1b37673f6 100644 --- a/bundles/org.openhab.core.model.script/src/org/openhab/core/model/script/lib/NumberExtensions.java +++ b/bundles/org.openhab.core.model.script/src/org/openhab/core/model/script/lib/NumberExtensions.java @@ -374,7 +374,7 @@ public class NumberExtensions { public static BigDecimal numberToBigDecimal(Number number) { if (number instanceof QuantityType) { QuantityType state = ((QuantityType) number) - .toUnit(((QuantityType) number).getUnit().getSystemUnit()); + .toInvertibleUnit(((QuantityType) number).getUnit().getSystemUnit()); if (state != null) { return state.toBigDecimal(); } diff --git a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/SystemHysteresisStateProfile.java b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/SystemHysteresisStateProfile.java index 28fc07f6e5..83f09b371d 100644 --- a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/SystemHysteresisStateProfile.java +++ b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/SystemHysteresisStateProfile.java @@ -66,7 +66,8 @@ public class SystemHysteresisStateProfile implements StateProfile { } this.lower = lowerParam; final QuantityType upperParam = getParam(context, UPPER_PARAM); - final QuantityType convertedUpperParam = upperParam == null ? lower : upperParam.toUnit(lower.getUnit()); + final QuantityType convertedUpperParam = upperParam == null ? lower + : upperParam.toInvertibleUnit(lower.getUnit()); if (convertedUpperParam == null) { throw new IllegalArgumentException( String.format("Units of parameters '%s' and '%s' are not compatible: %s != %s", LOWER_PARAM, @@ -145,8 +146,8 @@ public class SystemHysteresisStateProfile implements StateProfile { finalLower = new QuantityType<>(lower.toBigDecimal(), qtState.getUnit()); finalUpper = new QuantityType<>(upper.toBigDecimal(), qtState.getUnit()); } else { - finalLower = lower.toUnit(qtState.getUnit()); - finalUpper = upper.toUnit(qtState.getUnit()); + finalLower = lower.toInvertibleUnit(qtState.getUnit()); + finalUpper = upper.toInvertibleUnit(qtState.getUnit()); if (finalLower == null || finalUpper == null) { logger.warn( "Cannot compare state '{}' to boundaries because units (lower={}, upper={}) do not match.", diff --git a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/SystemRangeStateProfile.java b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/SystemRangeStateProfile.java index 84ecd36e25..adb5dc025d 100644 --- a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/SystemRangeStateProfile.java +++ b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/SystemRangeStateProfile.java @@ -69,7 +69,7 @@ public class SystemRangeStateProfile implements StateProfile { if (upperParam == null) { throw new IllegalArgumentException(String.format("Parameter '%s' is not a Number value.", UPPER_PARAM)); } - final QuantityType convertedUpperParam = upperParam.toUnit(lower.getUnit()); + final QuantityType convertedUpperParam = upperParam.toInvertibleUnit(lower.getUnit()); if (convertedUpperParam == null) { throw new IllegalArgumentException( String.format("Units of parameters '%s' and '%s' are not compatible: %s != %s", LOWER_PARAM, @@ -153,8 +153,8 @@ public class SystemRangeStateProfile implements StateProfile { finalLower = new QuantityType<>(lower.toBigDecimal(), qtState.getUnit()); finalUpper = new QuantityType<>(upper.toBigDecimal(), qtState.getUnit()); } else { - finalLower = lower.toUnit(qtState.getUnit()); - finalUpper = upper.toUnit(qtState.getUnit()); + finalLower = lower.toInvertibleUnit(qtState.getUnit()); + finalUpper = upper.toInvertibleUnit(qtState.getUnit()); if (finalLower == null || finalUpper == null) { logger.warn( "Cannot compare state '{}' to boundaries because units (lower={}, upper={}) do not match.", diff --git a/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java index 27a826fb90..f8302862cd 100644 --- a/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java +++ b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java @@ -413,7 +413,7 @@ public class ItemUIRegistryImpl implements ItemUIRegistry { // display the new unit: Unit patternUnit = UnitUtils.parseUnit(formatPattern); if (patternUnit != null && !quantityState.getUnit().equals(patternUnit)) { - quantityState = quantityState.toUnit(patternUnit); + quantityState = quantityState.toInvertibleUnit(patternUnit); } // The widget may define its own unit in the widget label. Convert to this unit: @@ -462,7 +462,7 @@ public class ItemUIRegistryImpl implements ItemUIRegistry { private QuantityType convertStateToWidgetUnit(QuantityType quantityState, Widget w) { Unit widgetUnit = UnitUtils.parseUnit(getFormatPattern(w.getLabel())); if (widgetUnit != null && !widgetUnit.equals(quantityState.getUnit())) { - return Objects.requireNonNullElse(quantityState.toUnit(widgetUnit), quantityState); + return Objects.requireNonNullElse(quantityState.toInvertibleUnit(widgetUnit), quantityState); } return quantityState; diff --git a/bundles/org.openhab.core/src/main/java/org/openhab/core/library/items/NumberItem.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/library/items/NumberItem.java index 90e22bc9b0..4f337676f1 100644 --- a/bundles/org.openhab.core/src/main/java/org/openhab/core/library/items/NumberItem.java +++ b/bundles/org.openhab.core/src/main/java/org/openhab/core/library/items/NumberItem.java @@ -124,7 +124,7 @@ public class NumberItem extends GenericItem { Unit stateUnit = ((QuantityType) state).getUnit(); if (itemUnit != null && (!stateUnit.getSystemUnit().equals(itemUnit.getSystemUnit()) || UnitUtils.isDifferentMeasurementSystem(itemUnit, stateUnit))) { - QuantityType convertedState = ((QuantityType) state).toUnit(itemUnit); + QuantityType convertedState = ((QuantityType) state).toInvertibleUnit(itemUnit); if (convertedState != null) { super.setState(convertedState); return; diff --git a/bundles/org.openhab.core/src/main/java/org/openhab/core/library/types/QuantityType.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/library/types/QuantityType.java index d4bed2c4ee..22869b661a 100644 --- a/bundles/org.openhab.core/src/main/java/org/openhab/core/library/types/QuantityType.java +++ b/bundles/org.openhab.core/src/main/java/org/openhab/core/library/types/QuantityType.java @@ -219,9 +219,10 @@ public class QuantityType> extends Number return false; } QuantityType other = (QuantityType) obj; - if (!quantity.getUnit().isCompatible(other.quantity.getUnit())) { + if (!quantity.getUnit().isCompatible(other.quantity.getUnit()) + && !quantity.getUnit().inverse().isCompatible(other.quantity.getUnit())) { return false; - } else if (compareTo((QuantityType) other) != 0) { + } else if (internalCompareTo(other) != 0) { return false; } @@ -230,6 +231,10 @@ public class QuantityType> extends Number @Override public int compareTo(QuantityType o) { + return internalCompareTo((QuantityType) o); + } + + private int internalCompareTo(QuantityType o) { if (quantity.getUnit().isCompatible(o.quantity.getUnit())) { QuantityType v1 = this.toUnit(getUnit().getSystemUnit()); QuantityType v2 = o.toUnit(o.getUnit().getSystemUnit()); @@ -238,6 +243,8 @@ public class QuantityType> extends Number } else { throw new IllegalArgumentException("Unable to convert to system unit during compare."); } + } else if (quantity.getUnit().inverse().isCompatible(o.quantity.getUnit())) { + return inverse().internalCompareTo(o); } else { throw new IllegalArgumentException("Can not compare incompatible units."); } @@ -255,7 +262,7 @@ public class QuantityType> extends Number * Convert this QuantityType to a new {@link QuantityType} using the given target unit. * * @param targetUnit the unit to which this {@link QuantityType} will be converted to. - * @return the new {@link QuantityType} in the given {@link Unit} or {@code null} in case of a + * @return the new {@link QuantityType} in the given {@link Unit} or {@code null} in case of an error. */ @SuppressWarnings("unchecked") public @Nullable QuantityType toUnit(Unit targetUnit) { @@ -283,6 +290,22 @@ public class QuantityType> extends Number return null; } + /** + * Convert this QuantityType to a new {@link QuantityType} using the given target unit. + * + * Implicit conversions using inverse units are allowed (i.e. mired <=> Kelvin). This may + * change the dimension. + * + * @param targetUnit the unit to which this {@link QuantityType} will be converted to. + * @return the new {@link QuantityType} in the given {@link Unit} or {@code null} in case of an erro. + */ + public @Nullable QuantityType toInvertibleUnit(Unit targetUnit) { + if (!targetUnit.equals(getUnit()) && getUnit().inverse().isCompatible(targetUnit)) { + return inverse().toUnit(targetUnit); + } + return toUnit(targetUnit); + } + public BigDecimal toBigDecimal() { return new BigDecimal(quantity.getValue().toString()); } @@ -490,4 +513,13 @@ public class QuantityType> extends Number .get(); return new QuantityType(sum); } + + /** + * Return the reciprocal of this QuantityType. + * + * @return a QuantityType with both the value and unit reciprocated + */ + public QuantityType inverse() { + return new QuantityType<>(this.quantity.inverse()); + } } diff --git a/bundles/org.openhab.core/src/main/java/org/openhab/core/library/types/QuantityTypeArithmeticGroupFunction.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/library/types/QuantityTypeArithmeticGroupFunction.java index 74a0985ee6..0b4b4a32ae 100644 --- a/bundles/org.openhab.core/src/main/java/org/openhab/core/library/types/QuantityTypeArithmeticGroupFunction.java +++ b/bundles/org.openhab.core/src/main/java/org/openhab/core/library/types/QuantityTypeArithmeticGroupFunction.java @@ -92,7 +92,7 @@ public interface QuantityTypeArithmeticGroupFunction extends GroupFunction { sum = itemState; // initialise the sum from the first item count++; } else { - itemState = itemState.toUnit(sum.getUnit()); + itemState = itemState.toInvertibleUnit(sum.getUnit()); if (itemState != null) { sum = sum.add(itemState); count++; diff --git a/bundles/org.openhab.core/src/main/java/org/openhab/core/library/unit/Units.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/library/unit/Units.java index fee3aa592e..0419aca16f 100644 --- a/bundles/org.openhab.core/src/main/java/org/openhab/core/library/unit/Units.java +++ b/bundles/org.openhab.core/src/main/java/org/openhab/core/library/unit/Units.java @@ -171,6 +171,7 @@ public final class Units extends CustomUnits { MultiplyConverter.ofRational(BigInteger.valueOf(1852), BigInteger.valueOf(1000)))); public static final Unit STERADIAN = addUnit(tech.units.indriya.unit.Units.STERADIAN); public static final Unit KELVIN = addUnit(tech.units.indriya.unit.Units.KELVIN); + public static final Unit MIRED = addUnit(MetricPrefix.MEGA(tech.units.indriya.unit.Units.KELVIN).inverse()); public static final Unit