[homekit] make sure to convert step values to Celsius (#13796)
otherwise if your step is 1.0 in fahrenheit, then your values will get rounded to 1.0 celsius, and you might not even notice you've lost precision in the Home app. Signed-off-by: Cody Cutrer <cody@cutrer.us>
This commit is contained in:
parent
446be35ac5
commit
826fc9e8d7
|
@ -18,6 +18,8 @@ import java.math.BigDecimal;
|
|||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.measure.Unit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.items.GroupItem;
|
||||
|
@ -415,14 +417,34 @@ public class HomekitTaggedItem {
|
|||
* @param defaultValue default value
|
||||
* @return value
|
||||
*/
|
||||
public QuantityType getConfigurationAsQuantity(String key, QuantityType defaultValue) {
|
||||
public QuantityType<?> getConfigurationAsQuantity(String key, QuantityType defaultValue,
|
||||
boolean relativeConversion) {
|
||||
String stringValue = getConfiguration(key, new String());
|
||||
if (stringValue.isEmpty()) {
|
||||
return defaultValue;
|
||||
}
|
||||
var parsedValue = new QuantityType(stringValue);
|
||||
var convertedValue = parsedValue.toInvertibleUnit(defaultValue.getUnit());
|
||||
// not convertible? just assume it's in the expected unit
|
||||
QuantityType<?> convertedValue;
|
||||
|
||||
if (relativeConversion) {
|
||||
convertedValue = parsedValue.toUnitRelative(defaultValue.getUnit());
|
||||
} else {
|
||||
convertedValue = parsedValue.toInvertibleUnit(defaultValue.getUnit());
|
||||
}
|
||||
// not convertible? just assume it's in the item's unit
|
||||
if (convertedValue == null) {
|
||||
Unit unit;
|
||||
if (getBaseItem() instanceof NumberItem && (unit = ((NumberItem) getBaseItem()).getUnit()) != null) {
|
||||
var bdValue = new BigDecimal(stringValue);
|
||||
parsedValue = new QuantityType(bdValue, unit);
|
||||
if (relativeConversion) {
|
||||
convertedValue = parsedValue.toUnitRelative(defaultValue.getUnit());
|
||||
} else {
|
||||
convertedValue = parsedValue.toInvertibleUnit(defaultValue.getUnit());
|
||||
}
|
||||
}
|
||||
}
|
||||
// still not convertible? just assume it's in the default's unit
|
||||
if (convertedValue == null) {
|
||||
return new QuantityType(parsedValue.toBigDecimal(), defaultValue.getUnit());
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ import java.math.BigDecimal;
|
|||
import java.math.RoundingMode;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
|
@ -303,6 +302,11 @@ public class HomekitCharacteristicFactory {
|
|||
return convertAndRound(degrees, SIUnits.CELSIUS, useFahrenheit() ? ImperialUnits.FAHRENHEIT : SIUnits.CELSIUS);
|
||||
}
|
||||
|
||||
public static double getTemperatureStep(HomekitTaggedItem taggedItem, double defaultValue) {
|
||||
return taggedItem.getConfigurationAsQuantity(HomekitTaggedItem.STEP,
|
||||
new QuantityType(defaultValue, SIUnits.CELSIUS), true).doubleValue();
|
||||
}
|
||||
|
||||
private static Supplier<CompletableFuture<Integer>> getAngleSupplier(HomekitTaggedItem taggedItem,
|
||||
int defaultValue) {
|
||||
return () -> CompletableFuture.completedFuture(getAngleFromItem(taggedItem, defaultValue));
|
||||
|
@ -616,34 +620,16 @@ public class HomekitCharacteristicFactory {
|
|||
|
||||
private static ColorTemperatureCharacteristic createColorTemperatureCharacteristic(HomekitTaggedItem taggedItem,
|
||||
HomekitAccessoryUpdater updater) {
|
||||
// Check if units are expressed in Kelvin, not mireds, and adjust
|
||||
// the min/max appropriately
|
||||
Unit unit = null;
|
||||
var numberItem = taggedItem.getBaseItem();
|
||||
if (numberItem instanceof NumberItem) {
|
||||
unit = ((NumberItem) numberItem).getUnit();
|
||||
}
|
||||
if (unit == null) {
|
||||
unit = Units.MIRED;
|
||||
}
|
||||
final Unit finalUnit = unit;
|
||||
|
||||
final boolean inverted = taggedItem.isInverted();
|
||||
|
||||
if (!unit.equals(Units.KELVIN) && !unit.equals(Units.MIRED)) {
|
||||
logger.warn("Item {} must be in either K or mired. Given {}.", taggedItem.getName(), unit);
|
||||
return new ColorTemperatureCharacteristic(null, null, null, null);
|
||||
}
|
||||
|
||||
var minValueQt = taggedItem.getConfigurationAsQuantity(HomekitTaggedItem.MIN_VALUE,
|
||||
Objects.requireNonNull(new QuantityType(ColorTemperatureCharacteristic.DEFAULT_MIN_VALUE, Units.MIRED)
|
||||
.toInvertibleUnit(unit)));
|
||||
var maxValueQt = taggedItem.getConfigurationAsQuantity(HomekitTaggedItem.MAX_VALUE,
|
||||
Objects.requireNonNull(new QuantityType(ColorTemperatureCharacteristic.DEFAULT_MAX_VALUE, Units.MIRED)
|
||||
.toInvertibleUnit(unit)));
|
||||
|
||||
int minValue = minValueQt.toInvertibleUnit(Units.MIRED).intValue();
|
||||
int maxValue = maxValueQt.toInvertibleUnit(Units.MIRED).intValue();
|
||||
int minValue = taggedItem
|
||||
.getConfigurationAsQuantity(HomekitTaggedItem.MIN_VALUE,
|
||||
new QuantityType(ColorTemperatureCharacteristic.DEFAULT_MIN_VALUE, Units.MIRED), false)
|
||||
.intValue();
|
||||
int maxValue = taggedItem
|
||||
.getConfigurationAsQuantity(HomekitTaggedItem.MAX_VALUE,
|
||||
new QuantityType(ColorTemperatureCharacteristic.DEFAULT_MAX_VALUE, Units.MIRED), false)
|
||||
.intValue();
|
||||
|
||||
// It's common to swap these if you're providing in Kelvin instead of mired
|
||||
if (minValue > maxValue) {
|
||||
|
@ -804,9 +790,8 @@ public class HomekitCharacteristicFactory {
|
|||
HomekitTaggedItem.MIN_VALUE, CoolingThresholdTemperatureCharacteristic.DEFAULT_MIN_VALUE));
|
||||
double maxValue = HomekitCharacteristicFactory.convertToCelsius(taggedItem.getConfigurationAsDouble(
|
||||
HomekitTaggedItem.MAX_VALUE, CoolingThresholdTemperatureCharacteristic.DEFAULT_MAX_VALUE));
|
||||
return new CoolingThresholdTemperatureCharacteristic(minValue, maxValue,
|
||||
taggedItem.getConfigurationAsDouble(HomekitTaggedItem.STEP,
|
||||
CoolingThresholdTemperatureCharacteristic.DEFAULT_STEP),
|
||||
double step = getTemperatureStep(taggedItem, CoolingThresholdTemperatureCharacteristic.DEFAULT_STEP);
|
||||
return new CoolingThresholdTemperatureCharacteristic(minValue, maxValue, step,
|
||||
getTemperatureSupplier(taggedItem, minValue), setTemperatureConsumer(taggedItem),
|
||||
getSubscriber(taggedItem, COOLING_THRESHOLD_TEMPERATURE, updater),
|
||||
getUnsubscriber(taggedItem, COOLING_THRESHOLD_TEMPERATURE, updater));
|
||||
|
@ -818,9 +803,8 @@ public class HomekitCharacteristicFactory {
|
|||
HomekitTaggedItem.MIN_VALUE, HeatingThresholdTemperatureCharacteristic.DEFAULT_MIN_VALUE));
|
||||
double maxValue = HomekitCharacteristicFactory.convertToCelsius(taggedItem.getConfigurationAsDouble(
|
||||
HomekitTaggedItem.MAX_VALUE, HeatingThresholdTemperatureCharacteristic.DEFAULT_MAX_VALUE));
|
||||
return new HeatingThresholdTemperatureCharacteristic(minValue, maxValue,
|
||||
taggedItem.getConfigurationAsDouble(HomekitTaggedItem.STEP,
|
||||
HeatingThresholdTemperatureCharacteristic.DEFAULT_STEP),
|
||||
double step = getTemperatureStep(taggedItem, HeatingThresholdTemperatureCharacteristic.DEFAULT_STEP);
|
||||
return new HeatingThresholdTemperatureCharacteristic(minValue, maxValue, step,
|
||||
getTemperatureSupplier(taggedItem, minValue), setTemperatureConsumer(taggedItem),
|
||||
getSubscriber(taggedItem, HEATING_THRESHOLD_TEMPERATURE, updater),
|
||||
getUnsubscriber(taggedItem, HEATING_THRESHOLD_TEMPERATURE, updater));
|
||||
|
|
|
@ -75,8 +75,9 @@ class HomekitTemperatureSensorImpl extends AbstractHomekitAccessoryImpl implemen
|
|||
|
||||
@Override
|
||||
public double getMinStepCurrentTemperature() {
|
||||
return getAccessoryConfiguration(HomekitCharacteristicType.CURRENT_TEMPERATURE, HomekitTaggedItem.STEP,
|
||||
BigDecimal.valueOf(TargetTemperatureCharacteristic.DEFAULT_STEP)).doubleValue();
|
||||
return HomekitCharacteristicFactory.getTemperatureStep(
|
||||
getCharacteristic(HomekitCharacteristicType.CURRENT_TEMPERATURE).get(),
|
||||
TargetTemperatureCharacteristic.DEFAULT_STEP);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -134,8 +134,9 @@ class HomekitThermostatImpl extends AbstractHomekitAccessoryImpl implements Ther
|
|||
|
||||
@Override
|
||||
public double getMinStepCurrentTemperature() {
|
||||
return getAccessoryConfiguration(HomekitCharacteristicType.CURRENT_TEMPERATURE, HomekitTaggedItem.STEP,
|
||||
BigDecimal.valueOf(TargetTemperatureCharacteristic.DEFAULT_STEP)).doubleValue();
|
||||
return HomekitCharacteristicFactory.getTemperatureStep(
|
||||
getCharacteristic(HomekitCharacteristicType.CURRENT_TEMPERATURE).get(),
|
||||
TargetTemperatureCharacteristic.DEFAULT_STEP);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -204,8 +205,9 @@ class HomekitThermostatImpl extends AbstractHomekitAccessoryImpl implements Ther
|
|||
|
||||
@Override
|
||||
public double getMinStepTargetTemperature() {
|
||||
return getAccessoryConfiguration(HomekitCharacteristicType.TARGET_TEMPERATURE, HomekitTaggedItem.STEP,
|
||||
BigDecimal.valueOf(TargetTemperatureCharacteristic.DEFAULT_STEP)).doubleValue();
|
||||
return HomekitCharacteristicFactory.getTemperatureStep(
|
||||
getCharacteristic(HomekitCharacteristicType.TARGET_TEMPERATURE).get(),
|
||||
TargetTemperatureCharacteristic.DEFAULT_STEP);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in New Issue