[homekit] use quantity type conversions for temperature characteristics (#12083)

if an Item associated with a temperature characteristic has a QuantityType
(of dimension Temperature) as its state, regardless of current unit,
use that to convert to celsius instead of any other configuration.

Note that this is only for supply values to HomeKit; commands coming from
HomeKit will still send a DecimalType with units according to the HomeKit-wide
useFahrenheit configuration.

Signed-off-by: Cody Cutrer <cody@cutrer.us>
This commit is contained in:
Cody Cutrer
2022-01-23 05:40:14 -07:00
committed by GitHub
parent 6bd37cb02a
commit d4fb20d529
6 changed files with 147 additions and 132 deletions

View File

@@ -140,19 +140,28 @@ abstract class AbstractHomekitAccessoryImpl implements HomekitAccessory {
}
}
protected @Nullable <T extends State> T getStateAs(HomekitCharacteristicType characteristic, Class<T> type) {
protected @Nullable State getState(HomekitCharacteristicType characteristic) {
final Optional<HomekitTaggedItem> taggedItem = getCharacteristic(characteristic);
if (taggedItem.isPresent()) {
final State state = taggedItem.get().getItem().getStateAs(type);
if (state != null) {
return state.as(type);
}
return taggedItem.get().getItem().getState();
}
logger.debug("State for characteristic {} at accessory {} cannot be retrieved.", characteristic,
accessory.getName());
return null;
}
protected @Nullable <T extends State> T getStateAs(HomekitCharacteristicType characteristic, Class<T> type) {
final State state = getState(characteristic);
if (state != null) {
return state.as(type);
}
return null;
}
protected @Nullable Double getStateAsTemperature(HomekitCharacteristicType characteristic) {
return HomekitCharacteristicFactory.stateAsTemperature(getState(characteristic));
}
@NonNullByDefault
protected <T extends Item> Optional<T> getItem(HomekitCharacteristicType characteristic, Class<T> type) {
final Optional<HomekitTaggedItem> taggedItem = getCharacteristic(characteristic);

View File

@@ -39,6 +39,7 @@ 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.types.QuantityType;
import org.openhab.core.library.unit.ImperialUnits;
import org.openhab.core.library.unit.SIUnits;
import org.openhab.core.types.State;
@@ -102,6 +103,7 @@ import io.github.hapjava.characteristics.impl.windowcovering.CurrentVerticalTilt
import io.github.hapjava.characteristics.impl.windowcovering.HoldPositionCharacteristic;
import io.github.hapjava.characteristics.impl.windowcovering.TargetHorizontalTiltAngleCharacteristic;
import io.github.hapjava.characteristics.impl.windowcovering.TargetVerticalTiltAngleCharacteristic;
import tech.units.indriya.unit.UnitDimension;
/**
* Creates a optional characteristics .
@@ -259,6 +261,21 @@ public class HomekitCharacteristicFactory {
return new BigDecimal(rawValue).setScale(1, RoundingMode.HALF_UP).doubleValue();
}
public static @Nullable Double stateAsTemperature(@Nullable State state) {
if (state == null) {
return null;
}
if (state instanceof QuantityType<?>) {
final QuantityType<?> qt = (QuantityType<?>) state;
if (qt.getDimension().equals(UnitDimension.TEMPERATURE)) {
return qt.toUnit(SIUnits.CELSIUS).doubleValue();
}
}
return convertToCelsius(state.as(DecimalType.class).doubleValue());
}
public static double convertToCelsius(double degrees) {
return convertAndRound(degrees, useFahrenheit() ? ImperialUnits.FAHRENHEIT : SIUnits.CELSIUS, SIUnits.CELSIUS);
}
@@ -336,9 +353,8 @@ 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);
final @Nullable Double value = stateAsTemperature(taggedItem.getItem().getState());
return CompletableFuture.completedFuture(value != null ? value : defaultValue);
};
}

View File

@@ -27,7 +27,6 @@ import java.util.concurrent.CompletableFuture;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.items.GenericItem;
import org.openhab.core.library.items.StringItem;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.library.types.StringType;
@@ -106,10 +105,8 @@ public class HomekitHeaterCoolerImpl extends AbstractHomekitAccessoryImpl implem
@Override
public CompletableFuture<Double> getCurrentTemperature() {
final @Nullable DecimalType state = getStateAs(HomekitCharacteristicType.CURRENT_TEMPERATURE,
DecimalType.class);
return CompletableFuture.completedFuture(state != null
? HomekitCharacteristicFactory.convertToCelsius(state.doubleValue())
final @Nullable Double state = getStateAsTemperature(HomekitCharacteristicType.CURRENT_TEMPERATURE);
return CompletableFuture.completedFuture(state != null ? state
: getAccessoryConfiguration(HomekitCharacteristicType.CURRENT_TEMPERATURE, HomekitTaggedItem.MIN_VALUE,
BigDecimal.valueOf(HomekitCharacteristicFactory
.convertFromCelsius(CurrentTemperatureCharacteristic.DEFAULT_MIN_VALUE)))

View File

@@ -17,7 +17,6 @@ import java.util.List;
import java.util.concurrent.CompletableFuture;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.library.types.DecimalType;
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
import org.openhab.io.homekit.internal.HomekitCharacteristicType;
import org.openhab.io.homekit.internal.HomekitSettings;
@@ -44,11 +43,8 @@ class HomekitTemperatureSensorImpl extends AbstractHomekitAccessoryImpl implemen
@Override
public CompletableFuture<Double> getCurrentTemperature() {
final @Nullable DecimalType state = getStateAs(HomekitCharacteristicType.CURRENT_TEMPERATURE,
DecimalType.class);
return CompletableFuture
.completedFuture(state != null ? HomekitCharacteristicFactory.convertToCelsius(state.doubleValue())
: getMinCurrentTemperature());
final @Nullable Double state = getStateAsTemperature(HomekitCharacteristicType.CURRENT_TEMPERATURE);
return CompletableFuture.completedFuture(state != null ? state : getMinCurrentTemperature());
}
@Override

View File

@@ -106,10 +106,8 @@ class HomekitThermostatImpl extends AbstractHomekitAccessoryImpl implements Ther
@Override
public CompletableFuture<Double> getCurrentTemperature() {
DecimalType state = getStateAs(HomekitCharacteristicType.CURRENT_TEMPERATURE, DecimalType.class);
return CompletableFuture
.completedFuture(state != null ? HomekitCharacteristicFactory.convertToCelsius(state.doubleValue())
: getMinCurrentTemperature());
Double state = getStateAsTemperature(HomekitCharacteristicType.CURRENT_TEMPERATURE);
return CompletableFuture.completedFuture(state != null ? state : getMinCurrentTemperature());
}
@Override
@@ -160,9 +158,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 ? HomekitCharacteristicFactory.convertToCelsius(state.doubleValue()) : 0.0);
Double state = getStateAsTemperature(HomekitCharacteristicType.TARGET_TEMPERATURE);
return CompletableFuture.completedFuture(state != null ? state : 0.0);
}
@Override