fix Fahrenheit conversion (#12024)
Signed-off-by: Eugen Freiter <freiter@gmx.de>
This commit is contained in:
parent
67ccf858f8
commit
843ca55c68
@ -12,8 +12,6 @@
|
||||
*/
|
||||
package org.openhab.io.homekit.internal.accessories;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@ -22,9 +20,6 @@ import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import javax.measure.Quantity;
|
||||
import javax.measure.Unit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.items.GenericItem;
|
||||
@ -32,8 +27,6 @@ import org.openhab.core.items.Item;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.OpenClosedType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.library.unit.ImperialUnits;
|
||||
import org.openhab.core.library.unit.SIUnits;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
|
||||
import org.openhab.io.homekit.internal.HomekitCharacteristicType;
|
||||
@ -282,32 +275,13 @@ abstract class AbstractHomekitAccessoryImpl implements HomekitAccessory {
|
||||
characteristics.add(characteristic);
|
||||
}
|
||||
|
||||
@NonNullByDefault
|
||||
private <T extends Quantity<T>> double convertAndRound(double value, Unit<T> from, Unit<T> to) {
|
||||
double rawValue = from.equals(to) ? value : from.getConverterTo(to).convert(value);
|
||||
return new BigDecimal(rawValue).setScale(1, RoundingMode.HALF_UP).doubleValue();
|
||||
}
|
||||
|
||||
@NonNullByDefault
|
||||
protected double convertToCelsius(double degrees) {
|
||||
return convertAndRound(degrees,
|
||||
getSettings().useFahrenheitTemperature ? ImperialUnits.FAHRENHEIT : SIUnits.CELSIUS, SIUnits.CELSIUS);
|
||||
}
|
||||
|
||||
@NonNullByDefault
|
||||
protected double convertFromCelsius(double degrees) {
|
||||
return convertAndRound(degrees,
|
||||
getSettings().useFahrenheitTemperature ? SIUnits.CELSIUS : ImperialUnits.FAHRENHEIT,
|
||||
ImperialUnits.FAHRENHEIT);
|
||||
}
|
||||
|
||||
/**
|
||||
* create boolean reader with ON state mapped to trueOnOffValue or trueOpenClosedValue depending of item type
|
||||
*
|
||||
* @param characteristicType characteristic id
|
||||
* @param trueOnOffValue ON value for switch
|
||||
* @param trueOpenClosedValue ON value for contact
|
||||
* @return boolean readed
|
||||
* @return boolean read
|
||||
* @throws IncompleteAccessoryException
|
||||
*/
|
||||
@NonNullByDefault
|
||||
|
||||
@ -15,6 +15,7 @@ package org.openhab.io.homekit.internal.accessories;
|
||||
import static org.openhab.io.homekit.internal.HomekitCharacteristicType.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@ -22,6 +23,9 @@ import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.measure.Quantity;
|
||||
import javax.measure.Unit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.items.GenericItem;
|
||||
@ -35,13 +39,18 @@ import org.openhab.core.library.types.HSBType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.OpenClosedType;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
import org.openhab.core.library.unit.ImperialUnits;
|
||||
import org.openhab.core.library.unit.SIUnits;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
import org.openhab.io.homekit.Homekit;
|
||||
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
|
||||
import org.openhab.io.homekit.internal.HomekitCharacteristicType;
|
||||
import org.openhab.io.homekit.internal.HomekitCommandType;
|
||||
import org.openhab.io.homekit.internal.HomekitException;
|
||||
import org.openhab.io.homekit.internal.HomekitImpl;
|
||||
import org.openhab.io.homekit.internal.HomekitTaggedItem;
|
||||
import org.osgi.framework.FrameworkUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -170,6 +179,12 @@ public class HomekitCharacteristicFactory {
|
||||
// METHODS TO CREATE SINGLE CHARACTERISTIC FROM OH ITEM
|
||||
|
||||
// supporting methods
|
||||
|
||||
public static boolean useFahrenheit() {
|
||||
return FrameworkUtil.getBundle(HomekitImpl.class).getBundleContext()
|
||||
.getServiceReference(Homekit.class.getName()).getProperty("useFahrenheitTemperature") == Boolean.TRUE;
|
||||
}
|
||||
|
||||
private static <T extends CharacteristicEnum> CompletableFuture<T> getEnumFromItem(HomekitTaggedItem item,
|
||||
T offEnum, T onEnum, T defaultEnum) {
|
||||
final State state = item.getItem().getState();
|
||||
@ -239,6 +254,19 @@ public class HomekitCharacteristicFactory {
|
||||
return value;
|
||||
}
|
||||
|
||||
private static <T extends Quantity<T>> double convertAndRound(double value, Unit<T> from, Unit<T> to) {
|
||||
double rawValue = from.equals(to) ? value : from.getConverterTo(to).convert(value);
|
||||
return new BigDecimal(rawValue).setScale(1, RoundingMode.HALF_UP).doubleValue();
|
||||
}
|
||||
|
||||
public static double convertToCelsius(double degrees) {
|
||||
return convertAndRound(degrees, useFahrenheit() ? ImperialUnits.FAHRENHEIT : SIUnits.CELSIUS, SIUnits.CELSIUS);
|
||||
}
|
||||
|
||||
public static double convertFromCelsius(double degrees) {
|
||||
return convertAndRound(degrees, SIUnits.CELSIUS, useFahrenheit() ? ImperialUnits.FAHRENHEIT : SIUnits.CELSIUS);
|
||||
}
|
||||
|
||||
private static Supplier<CompletableFuture<Integer>> getAngleSupplier(HomekitTaggedItem taggedItem,
|
||||
int defaultValue) {
|
||||
return () -> CompletableFuture.completedFuture(getAngleFromItem(taggedItem, defaultValue));
|
||||
@ -305,6 +333,26 @@ public class HomekitCharacteristicFactory {
|
||||
};
|
||||
}
|
||||
|
||||
private static Supplier<CompletableFuture<Double>> getTemperatureSupplier(HomekitTaggedItem taggedItem,
|
||||
double defaultValue) {
|
||||
return () -> {
|
||||
final @Nullable DecimalType value = taggedItem.getItem().getStateAs(DecimalType.class);
|
||||
return CompletableFuture
|
||||
.completedFuture(value != null ? convertToCelsius(value.doubleValue()) : defaultValue);
|
||||
};
|
||||
}
|
||||
|
||||
private static ExceptionalConsumer<Double> setTemperatureConsumer(HomekitTaggedItem taggedItem) {
|
||||
return (value) -> {
|
||||
if (taggedItem.getItem() instanceof NumberItem) {
|
||||
((NumberItem) taggedItem.getItem()).send(new DecimalType(convertFromCelsius(value)));
|
||||
} else {
|
||||
logger.warn("Item type {} is not supported for {}. Only Number type is supported.",
|
||||
taggedItem.getItem().getType(), taggedItem.getName());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected static Consumer<HomekitCharacteristicChangeCallback> getSubscriber(HomekitTaggedItem taggedItem,
|
||||
HomekitCharacteristicType key, HomekitAccessoryUpdater updater) {
|
||||
return (callback) -> updater.subscribe((GenericItem) taggedItem.getItem(), key.getTag(), callback);
|
||||
@ -631,10 +679,10 @@ public class HomekitCharacteristicFactory {
|
||||
CoolingThresholdTemperatureCharacteristic.DEFAULT_MAX_VALUE),
|
||||
taggedItem.getConfigurationAsDouble(HomekitTaggedItem.STEP,
|
||||
CoolingThresholdTemperatureCharacteristic.DEFAULT_STEP),
|
||||
getDoubleSupplier(taggedItem,
|
||||
getTemperatureSupplier(taggedItem,
|
||||
taggedItem.getConfigurationAsDouble(HomekitTaggedItem.MIN_VALUE,
|
||||
CoolingThresholdTemperatureCharacteristic.DEFAULT_MIN_VALUE)),
|
||||
setDoubleConsumer(taggedItem), getSubscriber(taggedItem, COOLING_THRESHOLD_TEMPERATURE, updater),
|
||||
setTemperatureConsumer(taggedItem), getSubscriber(taggedItem, COOLING_THRESHOLD_TEMPERATURE, updater),
|
||||
getUnsubscriber(taggedItem, COOLING_THRESHOLD_TEMPERATURE, updater));
|
||||
}
|
||||
|
||||
@ -647,10 +695,10 @@ public class HomekitCharacteristicFactory {
|
||||
HeatingThresholdTemperatureCharacteristic.DEFAULT_MAX_VALUE),
|
||||
taggedItem.getConfigurationAsDouble(HomekitTaggedItem.STEP,
|
||||
HeatingThresholdTemperatureCharacteristic.DEFAULT_STEP),
|
||||
getDoubleSupplier(taggedItem,
|
||||
getTemperatureSupplier(taggedItem,
|
||||
taggedItem.getConfigurationAsDouble(HomekitTaggedItem.MIN_VALUE,
|
||||
HeatingThresholdTemperatureCharacteristic.DEFAULT_MIN_VALUE)),
|
||||
setDoubleConsumer(taggedItem), getSubscriber(taggedItem, HEATING_THRESHOLD_TEMPERATURE, updater),
|
||||
setTemperatureConsumer(taggedItem), getSubscriber(taggedItem, HEATING_THRESHOLD_TEMPERATURE, updater),
|
||||
getUnsubscriber(taggedItem, HEATING_THRESHOLD_TEMPERATURE, updater));
|
||||
}
|
||||
|
||||
|
||||
@ -108,9 +108,12 @@ public class HomekitHeaterCoolerImpl extends AbstractHomekitAccessoryImpl implem
|
||||
public CompletableFuture<Double> getCurrentTemperature() {
|
||||
final @Nullable DecimalType state = getStateAs(HomekitCharacteristicType.CURRENT_TEMPERATURE,
|
||||
DecimalType.class);
|
||||
return CompletableFuture.completedFuture(state != null ? convertToCelsius(state.doubleValue())
|
||||
return CompletableFuture.completedFuture(state != null
|
||||
? HomekitCharacteristicFactory.convertToCelsius(state.doubleValue())
|
||||
: getAccessoryConfiguration(HomekitCharacteristicType.CURRENT_TEMPERATURE, HomekitTaggedItem.MIN_VALUE,
|
||||
BigDecimal.valueOf(CurrentTemperatureCharacteristic.DEFAULT_MIN_VALUE)).doubleValue());
|
||||
BigDecimal.valueOf(HomekitCharacteristicFactory
|
||||
.convertFromCelsius(CurrentTemperatureCharacteristic.DEFAULT_MIN_VALUE)))
|
||||
.doubleValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -151,7 +154,7 @@ public class HomekitHeaterCoolerImpl extends AbstractHomekitAccessoryImpl implem
|
||||
|
||||
public CompletableFuture<TemperatureDisplayUnitEnum> getTemperatureDisplayUnit() {
|
||||
return CompletableFuture
|
||||
.completedFuture(getSettings().useFahrenheitTemperature ? TemperatureDisplayUnitEnum.FAHRENHEIT
|
||||
.completedFuture(HomekitCharacteristicFactory.useFahrenheit() ? TemperatureDisplayUnitEnum.FAHRENHEIT
|
||||
: TemperatureDisplayUnitEnum.CELSIUS);
|
||||
}
|
||||
|
||||
|
||||
@ -25,6 +25,7 @@ import org.openhab.io.homekit.internal.HomekitTaggedItem;
|
||||
|
||||
import io.github.hapjava.accessories.TemperatureSensorAccessory;
|
||||
import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
|
||||
import io.github.hapjava.characteristics.impl.thermostat.CurrentTemperatureCharacteristic;
|
||||
import io.github.hapjava.characteristics.impl.thermostat.TargetTemperatureCharacteristic;
|
||||
import io.github.hapjava.services.impl.TemperatureSensorService;
|
||||
|
||||
@ -46,7 +47,8 @@ class HomekitTemperatureSensorImpl extends AbstractHomekitAccessoryImpl implemen
|
||||
final @Nullable DecimalType state = getStateAs(HomekitCharacteristicType.CURRENT_TEMPERATURE,
|
||||
DecimalType.class);
|
||||
return CompletableFuture
|
||||
.completedFuture(state != null ? convertToCelsius(state.doubleValue()) : getMinCurrentTemperature());
|
||||
.completedFuture(state != null ? HomekitCharacteristicFactory.convertToCelsius(state.doubleValue())
|
||||
: getMinCurrentTemperature());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -56,16 +58,23 @@ class HomekitTemperatureSensorImpl extends AbstractHomekitAccessoryImpl implemen
|
||||
|
||||
@Override
|
||||
public double getMinCurrentTemperature() {
|
||||
return convertToCelsius(
|
||||
// Apple defines default values in Celsius. We need to convert them to Fahrenheit if openHAB is using Fahrenheit
|
||||
// convertToCelsius and convertFromCelsius are only converting if useFahrenheit is set to true, so no additional
|
||||
// check here needed
|
||||
return HomekitCharacteristicFactory.convertToCelsius(
|
||||
getAccessoryConfiguration(HomekitCharacteristicType.CURRENT_TEMPERATURE, HomekitTaggedItem.MIN_VALUE,
|
||||
BigDecimal.valueOf(TargetTemperatureCharacteristic.DEFAULT_MIN_VALUE)).doubleValue());
|
||||
BigDecimal.valueOf(HomekitCharacteristicFactory
|
||||
.convertFromCelsius(CurrentTemperatureCharacteristic.DEFAULT_MIN_VALUE)))
|
||||
.doubleValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getMaxCurrentTemperature() {
|
||||
return convertToCelsius(
|
||||
return HomekitCharacteristicFactory.convertToCelsius(
|
||||
getAccessoryConfiguration(HomekitCharacteristicType.CURRENT_TEMPERATURE, HomekitTaggedItem.MAX_VALUE,
|
||||
BigDecimal.valueOf(TargetTemperatureCharacteristic.DEFAULT_MAX_VALUE)).doubleValue());
|
||||
BigDecimal.valueOf(HomekitCharacteristicFactory
|
||||
.convertFromCelsius(CurrentTemperatureCharacteristic.DEFAULT_MAX_VALUE)))
|
||||
.doubleValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -37,6 +37,7 @@ import org.slf4j.LoggerFactory;
|
||||
import io.github.hapjava.accessories.ThermostatAccessory;
|
||||
import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
|
||||
import io.github.hapjava.characteristics.impl.thermostat.CurrentHeatingCoolingStateEnum;
|
||||
import io.github.hapjava.characteristics.impl.thermostat.CurrentTemperatureCharacteristic;
|
||||
import io.github.hapjava.characteristics.impl.thermostat.TargetHeatingCoolingStateEnum;
|
||||
import io.github.hapjava.characteristics.impl.thermostat.TargetTemperatureCharacteristic;
|
||||
import io.github.hapjava.characteristics.impl.thermostat.TemperatureDisplayUnitEnum;
|
||||
@ -106,21 +107,31 @@ class HomekitThermostatImpl extends AbstractHomekitAccessoryImpl implements Ther
|
||||
@Override
|
||||
public CompletableFuture<Double> getCurrentTemperature() {
|
||||
DecimalType state = getStateAs(HomekitCharacteristicType.CURRENT_TEMPERATURE, DecimalType.class);
|
||||
return CompletableFuture.completedFuture(state != null ? convertToCelsius(state.doubleValue()) : 0.0);
|
||||
return CompletableFuture
|
||||
.completedFuture(state != null ? HomekitCharacteristicFactory.convertToCelsius(state.doubleValue())
|
||||
: getMinCurrentTemperature());
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getMinCurrentTemperature() {
|
||||
return convertToCelsius(
|
||||
// Apple defines default values in Celsius. We need to convert them to Fahrenheit if openHAB is using Fahrenheit
|
||||
// convertToCelsius and convertFromCelsius are only converting if useFahrenheit is set to true, so no additional
|
||||
// check here needed
|
||||
|
||||
return HomekitCharacteristicFactory.convertToCelsius(
|
||||
getAccessoryConfiguration(HomekitCharacteristicType.CURRENT_TEMPERATURE, HomekitTaggedItem.MIN_VALUE,
|
||||
BigDecimal.valueOf(TargetTemperatureCharacteristic.DEFAULT_MIN_VALUE)).doubleValue());
|
||||
BigDecimal.valueOf(HomekitCharacteristicFactory
|
||||
.convertFromCelsius(CurrentTemperatureCharacteristic.DEFAULT_MIN_VALUE)))
|
||||
.doubleValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getMaxCurrentTemperature() {
|
||||
return convertToCelsius(
|
||||
return HomekitCharacteristicFactory.convertToCelsius(
|
||||
getAccessoryConfiguration(HomekitCharacteristicType.CURRENT_TEMPERATURE, HomekitTaggedItem.MAX_VALUE,
|
||||
BigDecimal.valueOf(TargetTemperatureCharacteristic.DEFAULT_MAX_VALUE)).doubleValue());
|
||||
BigDecimal.valueOf(HomekitCharacteristicFactory
|
||||
.convertFromCelsius(CurrentTemperatureCharacteristic.DEFAULT_MAX_VALUE)))
|
||||
.doubleValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -138,7 +149,7 @@ class HomekitThermostatImpl extends AbstractHomekitAccessoryImpl implements Ther
|
||||
@Override
|
||||
public CompletableFuture<TemperatureDisplayUnitEnum> getTemperatureDisplayUnit() {
|
||||
return CompletableFuture
|
||||
.completedFuture(getSettings().useFahrenheitTemperature ? TemperatureDisplayUnitEnum.FAHRENHEIT
|
||||
.completedFuture(HomekitCharacteristicFactory.useFahrenheit() ? TemperatureDisplayUnitEnum.FAHRENHEIT
|
||||
: TemperatureDisplayUnitEnum.CELSIUS);
|
||||
}
|
||||
|
||||
@ -150,7 +161,8 @@ class HomekitThermostatImpl extends AbstractHomekitAccessoryImpl implements Ther
|
||||
@Override
|
||||
public CompletableFuture<Double> getTargetTemperature() {
|
||||
DecimalType state = getStateAs(HomekitCharacteristicType.TARGET_TEMPERATURE, DecimalType.class);
|
||||
return CompletableFuture.completedFuture(state != null ? convertToCelsius(state.doubleValue()) : 0.0);
|
||||
return CompletableFuture.completedFuture(
|
||||
state != null ? HomekitCharacteristicFactory.convertToCelsius(state.doubleValue()) : 0.0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -165,7 +177,7 @@ class HomekitThermostatImpl extends AbstractHomekitAccessoryImpl implements Ther
|
||||
HomekitCharacteristicType.TARGET_TEMPERATURE);
|
||||
if (characteristic.isPresent()) {
|
||||
((NumberItem) characteristic.get().getItem())
|
||||
.send(new DecimalType(BigDecimal.valueOf(convertFromCelsius(value))));
|
||||
.send(new DecimalType(BigDecimal.valueOf(HomekitCharacteristicFactory.convertFromCelsius(value))));
|
||||
} else {
|
||||
logger.warn("Missing mandatory characteristic {}", HomekitCharacteristicType.TARGET_TEMPERATURE);
|
||||
}
|
||||
@ -173,16 +185,24 @@ class HomekitThermostatImpl extends AbstractHomekitAccessoryImpl implements Ther
|
||||
|
||||
@Override
|
||||
public double getMinTargetTemperature() {
|
||||
return convertToCelsius(
|
||||
getAccessoryConfiguration(HomekitCharacteristicType.TARGET_TEMPERATURE, HomekitTaggedItem.MIN_VALUE,
|
||||
BigDecimal.valueOf(TargetTemperatureCharacteristic.DEFAULT_MIN_VALUE)).doubleValue());
|
||||
return HomekitCharacteristicFactory
|
||||
.convertToCelsius(
|
||||
getAccessoryConfiguration(HomekitCharacteristicType.TARGET_TEMPERATURE,
|
||||
HomekitTaggedItem.MIN_VALUE,
|
||||
BigDecimal.valueOf(HomekitCharacteristicFactory
|
||||
.convertFromCelsius(TargetTemperatureCharacteristic.DEFAULT_MIN_VALUE)))
|
||||
.doubleValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getMaxTargetTemperature() {
|
||||
return convertToCelsius(
|
||||
getAccessoryConfiguration(HomekitCharacteristicType.TARGET_TEMPERATURE, HomekitTaggedItem.MAX_VALUE,
|
||||
BigDecimal.valueOf(TargetTemperatureCharacteristic.DEFAULT_MAX_VALUE)).doubleValue());
|
||||
return HomekitCharacteristicFactory
|
||||
.convertToCelsius(
|
||||
getAccessoryConfiguration(HomekitCharacteristicType.TARGET_TEMPERATURE,
|
||||
HomekitTaggedItem.MAX_VALUE,
|
||||
BigDecimal.valueOf(HomekitCharacteristicFactory
|
||||
.convertFromCelsius(TargetTemperatureCharacteristic.DEFAULT_MAX_VALUE)))
|
||||
.doubleValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user