Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add QuantityType.toUnitRelative #3177

Merged
merged 1 commit into from
Nov 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.QuantityType;
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.thing.profiles.ProfileCallback;
import org.openhab.core.thing.profiles.ProfileContext;
Expand All @@ -44,10 +42,6 @@
@NonNullByDefault
public class SystemOffsetProfile implements StateProfile {

private static final @Nullable QuantityType<Temperature> ZERO_CELSIUS_IN_KELVIN = new QuantityType<>(0,
SIUnits.CELSIUS).toUnit(Units.KELVIN);
private static final @Nullable QuantityType<Temperature> ZERO_FAHRENHEIT_IN_KELVIN = new QuantityType<>(0,
ImperialUnits.FAHRENHEIT).toUnit(Units.KELVIN);
static final String OFFSET_PARAM = "offset";

private final Logger logger = LoggerFactory.getLogger(SystemOffsetProfile.class);
Expand Down Expand Up @@ -152,20 +146,11 @@ private Type applyOffset(Type state, boolean towardsItem) {
QuantityType<Temperature> offset) {
// do the math in Kelvin and afterwards convert it back to the unit of the state
final QuantityType<Temperature> kelvinState = qtState.toUnit(Units.KELVIN);
final QuantityType<Temperature> kelvinOffset = offset.toUnit(Units.KELVIN);
final QuantityType<Temperature> kelvinOffset = offset.toUnitRelative(Units.KELVIN);
if (kelvinState == null || kelvinOffset == null) {
return null;
}

final QuantityType<Temperature> finalOffset;
if (SIUnits.CELSIUS.equals(offset.getUnit())) {
finalOffset = kelvinOffset.add(ZERO_CELSIUS_IN_KELVIN.negate());
} else if (ImperialUnits.FAHRENHEIT.equals(offset.getUnit())) {
finalOffset = kelvinOffset.add(ZERO_FAHRENHEIT_IN_KELVIN.negate());
} else {
// offset is already in Kelvin
finalOffset = offset;
}
return kelvinState.add(finalOffset).toUnit(qtState.getUnit());
return kelvinState.add(kelvinOffset).toUnit(qtState.getUnit());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,31 @@ public Dimension getDimension() {
return null;
}

/**
* Convert this QuantityType to a new {@link QuantityType} using the given target unit.
*
* Similar to {@link toUnit}, except that it treats the values as relative instead of absolute.
* This means that any offsets in the conversion of absolute values are ignored.
* This is useful when your quantity represents a delta, and not necessarily a measured
* value itself. For example, 32 °F, when converted with toUnit to Celsius, it will become 0 °C.
* But when converted with toUnitRelative, it will become 17.8 °C.
*
* @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 error.
*/
@SuppressWarnings("unchecked")
public @Nullable QuantityType<T> toUnitRelative(Unit<T> targetUnit) {
if (targetUnit.equals(getUnit())) {
return this;
}
if (!quantity.getUnit().isCompatible(targetUnit)) {
return null;
}
Quantity<?> result = quantity.to(targetUnit);

return new QuantityType<T>(result.getValue(), (Unit<T>) targetUnit);
}

public BigDecimal toBigDecimal() {
return new BigDecimal(quantity.getValue().toString());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import org.openhab.core.library.dimension.Density;
import org.openhab.core.library.dimension.Intensity;
import org.openhab.core.library.unit.BinaryPrefix;
import org.openhab.core.library.unit.ImperialUnits;
import org.openhab.core.library.unit.MetricPrefix;
import org.openhab.core.library.unit.SIUnits;
import org.openhab.core.library.unit.Units;
Expand Down Expand Up @@ -483,4 +484,11 @@ public void testMireds() {
QuantityType<?> andBack = mireds.toInvertibleUnit(Units.KELVIN);
assertEquals(2700, andBack.intValue());
}

@Test
public void testRelativeConversion() {
QuantityType<Temperature> c = new QuantityType("1 °C");
QuantityType<Temperature> f = c.toUnitRelative(ImperialUnits.FAHRENHEIT);
assertEquals(1.8, f.doubleValue());
}
}