[homekit] Unify all enum handling (#14036)

* [homekit] unify all enum handling

regardless of if it's a required or optional characteristic,
or even "boolean" enums

then allow number or switch items to be linked with enums

then update the docs listing the numeric value for enums

as part of this, global configuration of thermostat enum values
is no longer supported; you must use metadata.
in particular, for GarageDoorOpener, the global settings didn't
even actually work, so they should work now.

Fixes #13595

* [homekit] default-invert boolean items for garage door states

this was previously handled explicitly by the switch statement.
so need to set the inverted flag now that we're building a
mapping instead

* [homekit] document that CurrentDoorState can be linked to a Contact item
* [homekit] improve docs on invert param to createMapping

also fix a new helper method not properly passing through the inverted
param

Signed-off-by: Cody Cutrer <cody@cutrer.us>
This commit is contained in:
Cody Cutrer
2023-03-22 06:58:12 -06:00
committed by GitHub
parent 72254b820d
commit d9ceb63b82
23 changed files with 536 additions and 842 deletions

View File

@@ -34,20 +34,6 @@ public class HomekitSettings {
public boolean useFahrenheitTemperature = false;
public boolean useOHmDNS = false;
public boolean blockUserDeletion = false;
public String thermostatTargetModeHeat = "HeatOn";
public String thermostatTargetModeCool = "CoolOn";
public String thermostatTargetModeAuto = "Auto";
public String thermostatTargetModeOff = "Off";
public String thermostatCurrentModeHeating = "HeatOn";
public String thermostatCurrentModeCooling = "CoolOn";
public String thermostatCurrentModeOff = "Off";
public String doorCurrentStateOpen = "OPEN";
public String doorCurrentStateOpening = "OPENING";
public String doorCurrentStateClosed = "CLOSED";
public String doorCurrentStateClosing = "CLOSING";
public String doorCurrentStateStopped = "STOPPED";
public String doorTargetStateClosed = "CLOSED";
public String doorTargetStateOpen = "OPEN";
public String networkInterface;
@Override
@@ -57,10 +43,6 @@ public class HomekitSettings {
result = prime * result + ((pin == null) ? 0 : pin.hashCode());
result = prime * result + ((setupId == null) ? 0 : setupId.hashCode());
result = prime * result + port;
result = prime * result + ((thermostatTargetModeAuto == null) ? 0 : thermostatTargetModeAuto.hashCode());
result = prime * result + ((thermostatTargetModeCool == null) ? 0 : thermostatTargetModeCool.hashCode());
result = prime * result + ((thermostatTargetModeHeat == null) ? 0 : thermostatTargetModeHeat.hashCode());
result = prime * result + ((thermostatTargetModeOff == null) ? 0 : thermostatTargetModeOff.hashCode());
result = prime * result + (useFahrenheitTemperature ? 1231 : 1237);
result = prime * result + (useDummyAccessories ? 1249 : 1259);
return result;
@@ -98,34 +80,6 @@ public class HomekitSettings {
if (instances != other.instances) {
return false;
}
if (thermostatTargetModeAuto == null) {
if (other.thermostatTargetModeAuto != null) {
return false;
}
} else if (!thermostatTargetModeAuto.equals(other.thermostatTargetModeAuto)) {
return false;
}
if (thermostatTargetModeCool == null) {
if (other.thermostatTargetModeCool != null) {
return false;
}
} else if (!thermostatTargetModeCool.equals(other.thermostatTargetModeCool)) {
return false;
}
if (thermostatTargetModeHeat == null) {
if (other.thermostatTargetModeHeat != null) {
return false;
}
} else if (!thermostatTargetModeHeat.equals(other.thermostatTargetModeHeat)) {
return false;
}
if (thermostatTargetModeOff == null) {
if (other.thermostatTargetModeOff != null) {
return false;
}
} else if (!thermostatTargetModeOff.equals(other.thermostatTargetModeOff)) {
return false;
}
if (useFahrenheitTemperature != other.useFahrenheitTemperature) {
return false;
}

View File

@@ -43,6 +43,7 @@ import org.slf4j.LoggerFactory;
import io.github.hapjava.accessories.HomekitAccessory;
import io.github.hapjava.characteristics.Characteristic;
import io.github.hapjava.characteristics.CharacteristicEnum;
import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
import io.github.hapjava.characteristics.impl.base.BaseCharacteristic;
import io.github.hapjava.services.Service;
@@ -267,29 +268,38 @@ public abstract class AbstractHomekitAccessoryImpl implements HomekitAccessory {
.map(homekitTaggedItem -> homekitTaggedItem.getConfiguration(key, defaultValue)).orElse(defaultValue);
}
/**
* update mapping with values from item configuration.
* it checks for all keys from the mapping whether there is configuration at item with the same key and if yes,
* replace the value.
*
* @param characteristicType characteristicType to identify item
* @param map mapping to update
* @param customEnumList list to store custom state enumeration
*/
@NonNullByDefault
public <T> void updateMapping(HomekitCharacteristicType characteristicType, Map<T, String> map,
@Nullable List<T> customEnumList) {
getCharacteristic(characteristicType).ifPresent(c -> {
final Map<String, Object> configuration = c.getConfiguration();
if (configuration != null) {
HomekitCharacteristicFactory.updateMapping(configuration, map, customEnumList);
}
});
protected <T extends Enum<T> & CharacteristicEnum> Map<T, String> createMapping(
HomekitCharacteristicType characteristicType, Class<T> klazz) {
return createMapping(characteristicType, klazz, null, false);
}
@NonNullByDefault
public <T> void updateMapping(HomekitCharacteristicType characteristicType, Map<T, String> map) {
updateMapping(characteristicType, map, null);
protected <T extends Enum<T> & CharacteristicEnum> Map<T, String> createMapping(
HomekitCharacteristicType characteristicType, Class<T> klazz, boolean inverted) {
return createMapping(characteristicType, klazz, null, inverted);
}
@NonNullByDefault
protected <T extends Enum<T> & CharacteristicEnum> Map<T, String> createMapping(
HomekitCharacteristicType characteristicType, Class<T> klazz, @Nullable List<T> customEnumList) {
return createMapping(characteristicType, klazz, customEnumList, false);
}
/**
* create mapping with values from item configuration
*
* @param characteristicType to identify item; must be present
* @param customEnumList list to store custom state enumeration
* @param inverted if ON/OFF and OPEN/CLOSED should be inverted by default (inverted on the item will double-invert)
* @return mapping of enum values to custom string values
*/
@NonNullByDefault
protected <T extends Enum<T> & CharacteristicEnum> Map<T, String> createMapping(
HomekitCharacteristicType characteristicType, Class<T> klazz, @Nullable List<T> customEnumList,
boolean inverted) {
HomekitTaggedItem item = getCharacteristic(characteristicType).get();
return HomekitCharacteristicFactory.createMapping(item, klazz, customEnumList, inverted);
}
/**

View File

@@ -16,7 +16,6 @@ import static org.openhab.io.homekit.internal.HomekitCharacteristicType.CURRENT_
import static org.openhab.io.homekit.internal.HomekitCharacteristicType.POSITION_STATE;
import static org.openhab.io.homekit.internal.HomekitCharacteristicType.TARGET_POSITION;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -68,11 +67,7 @@ abstract class AbstractHomekitPositionAccessoryImpl extends AbstractHomekitAcces
false);
closedPosition = inverted ? 0 : 100;
openPosition = inverted ? 100 : 0;
positionStateMapping = new EnumMap<>(PositionStateEnum.class);
positionStateMapping.put(PositionStateEnum.DECREASING, "DECREASING");
positionStateMapping.put(PositionStateEnum.INCREASING, "INCREASING");
positionStateMapping.put(PositionStateEnum.STOPPED, "STOPPED");
updateMapping(POSITION_STATE, positionStateMapping);
positionStateMapping = createMapping(POSITION_STATE, PositionStateEnum.class);
}
public CompletableFuture<Integer> getCurrentPosition() {

View File

@@ -14,7 +14,6 @@ package org.openhab.io.homekit.internal.accessories;
import static org.openhab.io.homekit.internal.HomekitCharacteristicType.AIR_QUALITY;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
@@ -34,22 +33,12 @@ import io.github.hapjava.services.impl.AirQualityService;
* @author Eugen Freiter - Initial contribution
*/
public class HomekitAirQualitySensorImpl extends AbstractHomekitAccessoryImpl implements AirQualityAccessory {
private final Map<AirQualityEnum, String> qualityStateMapping = new EnumMap<AirQualityEnum, String>(
AirQualityEnum.class) {
{
put(AirQualityEnum.UNKNOWN, "UNKNOWN");
put(AirQualityEnum.EXCELLENT, "EXCELLENT");
put(AirQualityEnum.GOOD, "GOOD");
put(AirQualityEnum.FAIR, "FAIR");
put(AirQualityEnum.INFERIOR, "INFERIOR");
put(AirQualityEnum.POOR, "POOR");
}
};
private final Map<AirQualityEnum, String> qualityStateMapping;
public HomekitAirQualitySensorImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
super(taggedItem, mandatoryCharacteristics, updater, settings);
updateMapping(AIR_QUALITY, qualityStateMapping);
qualityStateMapping = createMapping(AIR_QUALITY, AirQualityEnum.class);
getServices().add(new AirQualityService(this));
}

View File

@@ -15,6 +15,7 @@ package org.openhab.io.homekit.internal.accessories;
import static org.openhab.io.homekit.internal.HomekitCharacteristicType.CARBON_DIOXIDE_DETECTED_STATE;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
@@ -32,21 +33,20 @@ import io.github.hapjava.services.impl.CarbonDioxideSensorService;
*/
public class HomekitCarbonDioxideSensorImpl extends AbstractHomekitAccessoryImpl
implements CarbonDioxideSensorAccessory {
private final BooleanItemReader carbonDioxideDetectedReader;
private final Map<CarbonDioxideDetectedEnum, String> mapping;
public HomekitCarbonDioxideSensorImpl(HomekitTaggedItem taggedItem,
List<HomekitTaggedItem> mandatoryCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
throws IncompleteAccessoryException {
super(taggedItem, mandatoryCharacteristics, updater, settings);
carbonDioxideDetectedReader = createBooleanReader(CARBON_DIOXIDE_DETECTED_STATE);
mapping = createMapping(CARBON_DIOXIDE_DETECTED_STATE, CarbonDioxideDetectedEnum.class);
getServices().add(new CarbonDioxideSensorService(this));
}
@Override
public CompletableFuture<CarbonDioxideDetectedEnum> getCarbonDioxideDetectedState() {
return CompletableFuture
.completedFuture(carbonDioxideDetectedReader.getValue() ? CarbonDioxideDetectedEnum.ABNORMAL
: CarbonDioxideDetectedEnum.NORMAL);
return CompletableFuture.completedFuture(
getKeyFromMapping(CARBON_DIOXIDE_DETECTED_STATE, mapping, CarbonDioxideDetectedEnum.NORMAL));
}
@Override

View File

@@ -15,6 +15,7 @@ package org.openhab.io.homekit.internal.accessories;
import static org.openhab.io.homekit.internal.HomekitCharacteristicType.CARBON_MONOXIDE_DETECTED_STATE;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
@@ -32,21 +33,20 @@ import io.github.hapjava.services.impl.CarbonMonoxideSensorService;
*/
public class HomekitCarbonMonoxideSensorImpl extends AbstractHomekitAccessoryImpl
implements CarbonMonoxideSensorAccessory {
private final BooleanItemReader carbonMonoxideDetectedReader;
private final Map<CarbonMonoxideDetectedEnum, String> mapping;
public HomekitCarbonMonoxideSensorImpl(HomekitTaggedItem taggedItem,
List<HomekitTaggedItem> mandatoryCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings)
throws IncompleteAccessoryException {
super(taggedItem, mandatoryCharacteristics, updater, settings);
carbonMonoxideDetectedReader = createBooleanReader(CARBON_MONOXIDE_DETECTED_STATE);
mapping = createMapping(CARBON_MONOXIDE_DETECTED_STATE, CarbonMonoxideDetectedEnum.class);
getServices().add(new CarbonMonoxideSensorService(this));
}
@Override
public CompletableFuture<CarbonMonoxideDetectedEnum> getCarbonMonoxideDetectedState() {
return CompletableFuture
.completedFuture(carbonMonoxideDetectedReader.getValue() ? CarbonMonoxideDetectedEnum.ABNORMAL
: CarbonMonoxideDetectedEnum.NORMAL);
return CompletableFuture.completedFuture(
getKeyFromMapping(CARBON_MONOXIDE_DETECTED_STATE, mapping, CarbonMonoxideDetectedEnum.NORMAL));
}
@Override

View File

@@ -20,6 +20,7 @@ import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiFunction;
import java.util.function.Consumer;
@@ -260,42 +261,86 @@ public class HomekitCharacteristicFactory {
"Unsupported optional characteristic. Characteristic type \"" + type.getTag() + "\"");
}
public static <T extends Enum<T>> Map<T, String> createMapping(HomekitTaggedItem item, Class<T> klazz) {
/**
* Create an EnumMap for a particular CharacteristicEnum.
*
* By default, the map will simply be from the Enum value to the string version of its value.
* If the item is a Number item, though, the values will the be underlying integer code
* for the item, as a String.
* Then the item's metadata will be inspected, applying any custom mappings.
* Finally, if customEnumList is supplied, it will be filled out with those mappings
* that are actually referenced in the metadata.
*
* @param item
* @param klazz The HAP-Java Enum for the characteristic.
* @param customEnumList Optional output list of which enums are explicitly mentioned.
* @param inverted Default-invert the 0/1 values of the HAP enum when linked to a Switch or Contact item.
* This is set by the addon when creating mappings for specific characteristics where the 0 and 1
* values for the enum do not map naturally to 0/OFF/CLOSED and 1/ON/OPEN of openHAB items.
* Note that this is separate from the inverted item-level metadata configuration, which can be
* thought of independently as applying on top of this setting. It essentially "multiplies" out,
* but can also be thought of as simply swapping whichever value OFF/CLOSED and ON/OPEN are
* associated with, which has already been set.
* @return
*/
public static <T extends Enum<T> & CharacteristicEnum> Map<T, String> createMapping(HomekitTaggedItem item,
Class<T> klazz, @Nullable List<T> customEnumList, boolean inverted) {
EnumMap<T, String> map = new EnumMap(klazz);
var dataTypes = item.getBaseItem().getAcceptedDataTypes();
boolean switchType = dataTypes.contains(OnOffType.class);
boolean contactType = dataTypes.contains(OpenClosedType.class);
boolean percentType = dataTypes.contains(PercentType.class);
boolean numberType = dataTypes.contains(DecimalType.class) || percentType || switchType || contactType;
if (item.isInverted()) {
inverted = !inverted;
}
String onValue = switchType ? OnOffType.ON.toString() : OpenClosedType.OPEN.toString();
String offValue = switchType ? OnOffType.OFF.toString() : OpenClosedType.CLOSED.toString();
for (var k : klazz.getEnumConstants()) {
map.put(k, k.toString());
if (numberType) {
int code = k.getCode();
if ((switchType || contactType) && code == 0) {
map.put(k, inverted ? onValue : offValue);
} else if ((switchType || contactType) && code == 1) {
map.put(k, inverted ? offValue : onValue);
} else if (percentType && code == 0) {
map.put(k, "OFF");
} else if (percentType && code == 1) {
map.put(k, "ON");
} else {
map.put(k, Integer.toString(code));
}
} else {
map.put(k, k.toString());
}
}
var configuration = item.getConfiguration();
if (configuration != null) {
updateMapping(configuration, map);
map.forEach((k, current_value) -> {
final Object newValue = configuration.get(k.toString());
if (newValue instanceof String || newValue instanceof Number) {
map.put(k, newValue.toString());
if (customEnumList != null) {
customEnumList.add(k);
}
}
});
}
logger.debug("Created {} mapping for item {} ({}): {}", klazz.getSimpleName(), item.getName(),
item.getBaseItem().getClass().getSimpleName(), map);
return map;
}
/**
* Update mapping with values from item configuration.
* It checks for all keys from the mapping whether there is configuration at item with the same key and if yes,
* replace the value.
*
* @param configuration tagged item configuration
* @param map mapping to update
* @param customEnumList list to store custom state enumeration
*/
public static <T> void updateMapping(Map<String, Object> configuration, Map<T, String> map,
@Nullable List<T> customEnumList) {
map.forEach((k, current_value) -> {
final Object new_value = configuration.get(k.toString());
if (new_value instanceof String) {
map.put(k, (String) new_value);
if (customEnumList != null) {
customEnumList.add(k);
}
}
});
public static <T extends Enum<T> & CharacteristicEnum> Map<T, String> createMapping(HomekitTaggedItem item,
Class<T> klazz) {
return createMapping(item, klazz, null, false);
}
public static <T> void updateMapping(Map<String, Object> configuration, Map<T, String> map) {
updateMapping(configuration, map, null);
public static <T extends Enum<T> & CharacteristicEnum> Map<T, String> createMapping(HomekitTaggedItem item,
Class<T> klazz, boolean inverted) {
return createMapping(item, klazz, null, inverted);
}
/**
@@ -312,17 +357,34 @@ public class HomekitCharacteristicFactory {
final State state = item.getItem().getState();
logger.trace("getKeyFromMapping: characteristic {}, state {}, mapping {}", item.getAccessoryType().getTag(),
state, mapping);
if (state instanceof StringType) {
return mapping.entrySet().stream().filter(entry -> state.toString().equalsIgnoreCase(entry.getValue()))
.findAny().map(Map.Entry::getKey).orElseGet(() -> {
logger.warn(
"Wrong value {} for {} characteristic of the item {}. Expected one of following {}. Returning {}.",
state.toString(), item.getAccessoryType().getTag(), item.getName(), mapping.values(),
defaultValue);
return defaultValue;
});
String value;
if (state instanceof UnDefType) {
return defaultValue;
} else if (state instanceof StringType || state instanceof OnOffType || state instanceof OpenClosedType) {
value = state.toString();
} else if (state.getClass().equals(PercentType.class)) {
// We specifically want PercentType, but _not_ HSBType, so don't use instanceof
value = state.as(OnOffType.class).toString();
} else if (state.getClass().equals(DecimalType.class)) {
// We specifically want DecimalType, but _not_ PercentType or HSBType, so don't use instanceof
value = Integer.toString(((DecimalType) state).intValue());
} else {
logger.warn(
"Wrong value type {} ({}) for {} characteristic of the item {}. Expected StringItem, NumberItem, or SwitchItem.",
state.toString(), state.getClass().getSimpleName(), item.getAccessoryType().getTag(),
item.getName());
return defaultValue;
}
return defaultValue;
return mapping.entrySet().stream().filter(entry -> value.equalsIgnoreCase(entry.getValue())).findAny()
.map(Map.Entry::getKey).orElseGet(() -> {
logger.warn(
"Wrong value {} for {} characteristic of the item {}. Expected one of following {}. Returning {}.",
state.toString(), item.getAccessoryType().getTag(), item.getName(), mapping.values(),
defaultValue);
return defaultValue;
});
}
// METHODS TO CREATE SINGLE CHARACTERISTIC FROM OH ITEM
@@ -339,47 +401,13 @@ public class HomekitCharacteristicFactory {
return CompletableFuture.completedFuture(getKeyFromMapping(item, mapping, defaultValue));
}
private static <T extends CharacteristicEnum> CompletableFuture<T> getEnumFromItem(HomekitTaggedItem item,
T offEnum, T onEnum, T defaultEnum) {
final State state = item.getItem().getState();
if (state instanceof OnOffType) {
return CompletableFuture
.completedFuture(state.equals(item.isInverted() ? OnOffType.ON : OnOffType.OFF) ? offEnum : onEnum);
} else if (state instanceof OpenClosedType) {
return CompletableFuture.completedFuture(
state.equals(item.isInverted() ? OpenClosedType.OPEN : OpenClosedType.CLOSED) ? offEnum : onEnum);
} else if (state instanceof DecimalType) {
return CompletableFuture.completedFuture(((DecimalType) state).intValue() == 0 ? offEnum : onEnum);
} else if (state instanceof UnDefType) {
return CompletableFuture.completedFuture(defaultEnum);
}
logger.warn(
"Item state {} is not supported. Only OnOffType,OpenClosedType and Decimal (0/1) are supported. Ignore item {}",
state, item.getName());
return CompletableFuture.completedFuture(defaultEnum);
}
private static <T extends Enum<T>> void setValueFromEnum(HomekitTaggedItem taggedItem, T value,
Map<T, String> map) {
taggedItem.send(new StringType(map.get(value)));
}
private static void setValueFromEnum(HomekitTaggedItem taggedItem, CharacteristicEnum value,
CharacteristicEnum offEnum, CharacteristicEnum onEnum) {
if (taggedItem.getBaseItem() instanceof SwitchItem) {
if (value.equals(offEnum)) {
taggedItem.send(taggedItem.isInverted() ? OnOffType.ON : OnOffType.OFF);
} else if (value.equals(onEnum)) {
taggedItem.send(taggedItem.isInverted() ? OnOffType.OFF : OnOffType.ON);
} else {
logger.warn("Enum value {} is not supported for {}. Only following values are supported: {},{}", value,
taggedItem.getName(), offEnum, onEnum);
}
} else if (taggedItem.getBaseItem() instanceof NumberItem) {
taggedItem.send(new DecimalType(value.getCode()));
public static <T extends Enum<T>> void setValueFromEnum(HomekitTaggedItem taggedItem, T value, Map<T, String> map) {
if (taggedItem.getBaseItem() instanceof NumberItem) {
taggedItem.send(new DecimalType(Objects.requireNonNull(map.get(value))));
} else if (taggedItem.getBaseItem() instanceof SwitchItem) {
taggedItem.send(OnOffType.from(Objects.requireNonNull(map.get(value))));
} else {
logger.warn("Item {} of type {} is not supported. Only Switch and Number item types are supported.",
taggedItem.getName(), taggedItem.getBaseItem().getType());
taggedItem.send(new StringType(map.get(value)));
}
}
@@ -568,17 +596,15 @@ public class HomekitCharacteristicFactory {
private static StatusFaultCharacteristic createStatusFaultCharacteristic(HomekitTaggedItem taggedItem,
HomekitAccessoryUpdater updater) {
return new StatusFaultCharacteristic(
() -> getEnumFromItem(taggedItem, StatusFaultEnum.NO_FAULT, StatusFaultEnum.GENERAL_FAULT,
StatusFaultEnum.NO_FAULT),
var map = createMapping(taggedItem, StatusFaultEnum.class);
return new StatusFaultCharacteristic(() -> getEnumFromItem(taggedItem, map, StatusFaultEnum.NO_FAULT),
getSubscriber(taggedItem, FAULT_STATUS, updater), getUnsubscriber(taggedItem, FAULT_STATUS, updater));
}
private static StatusTamperedCharacteristic createStatusTamperedCharacteristic(HomekitTaggedItem taggedItem,
HomekitAccessoryUpdater updater) {
return new StatusTamperedCharacteristic(
() -> getEnumFromItem(taggedItem, StatusTamperedEnum.NOT_TAMPERED, StatusTamperedEnum.TAMPERED,
StatusTamperedEnum.NOT_TAMPERED),
var map = createMapping(taggedItem, StatusTamperedEnum.class);
return new StatusTamperedCharacteristic(() -> getEnumFromItem(taggedItem, map, StatusTamperedEnum.NOT_TAMPERED),
getSubscriber(taggedItem, TAMPERED_STATUS, updater),
getUnsubscriber(taggedItem, TAMPERED_STATUS, updater));
}
@@ -840,59 +866,46 @@ public class HomekitCharacteristicFactory {
private static CurrentFanStateCharacteristic createCurrentFanStateCharacteristic(HomekitTaggedItem taggedItem,
HomekitAccessoryUpdater updater) {
return new CurrentFanStateCharacteristic(() -> {
final @Nullable DecimalType value = taggedItem.getItem().getStateAs(DecimalType.class);
@Nullable
CurrentFanStateEnum currentFanStateEnum = value != null ? CurrentFanStateEnum.fromCode(value.intValue())
: null;
if (currentFanStateEnum == null) {
currentFanStateEnum = CurrentFanStateEnum.INACTIVE;
}
return CompletableFuture.completedFuture(currentFanStateEnum);
}, getSubscriber(taggedItem, CURRENT_FAN_STATE, updater),
var map = createMapping(taggedItem, CurrentFanStateEnum.class);
return new CurrentFanStateCharacteristic(() -> getEnumFromItem(taggedItem, map, CurrentFanStateEnum.INACTIVE),
getSubscriber(taggedItem, CURRENT_FAN_STATE, updater),
getUnsubscriber(taggedItem, CURRENT_FAN_STATE, updater));
}
private static TargetFanStateCharacteristic createTargetFanStateCharacteristic(HomekitTaggedItem taggedItem,
HomekitAccessoryUpdater updater) {
return new TargetFanStateCharacteristic(
() -> getEnumFromItem(taggedItem, TargetFanStateEnum.MANUAL, TargetFanStateEnum.AUTO,
TargetFanStateEnum.AUTO),
(targetState) -> setValueFromEnum(taggedItem, targetState, TargetFanStateEnum.MANUAL,
TargetFanStateEnum.AUTO),
var map = createMapping(taggedItem, TargetFanStateEnum.class);
return new TargetFanStateCharacteristic(() -> getEnumFromItem(taggedItem, map, TargetFanStateEnum.AUTO),
(targetState) -> setValueFromEnum(taggedItem, targetState, map),
getSubscriber(taggedItem, TARGET_FAN_STATE, updater),
getUnsubscriber(taggedItem, TARGET_FAN_STATE, updater));
}
private static RotationDirectionCharacteristic createRotationDirectionCharacteristic(HomekitTaggedItem taggedItem,
HomekitAccessoryUpdater updater) {
var map = createMapping(taggedItem, RotationDirectionEnum.class);
return new RotationDirectionCharacteristic(
() -> getEnumFromItem(taggedItem, RotationDirectionEnum.CLOCKWISE,
RotationDirectionEnum.COUNTER_CLOCKWISE, RotationDirectionEnum.CLOCKWISE),
(value) -> setValueFromEnum(taggedItem, value, RotationDirectionEnum.CLOCKWISE,
RotationDirectionEnum.COUNTER_CLOCKWISE),
() -> getEnumFromItem(taggedItem, map, RotationDirectionEnum.CLOCKWISE),
(value) -> setValueFromEnum(taggedItem, value, map),
getSubscriber(taggedItem, ROTATION_DIRECTION, updater),
getUnsubscriber(taggedItem, ROTATION_DIRECTION, updater));
}
private static SwingModeCharacteristic createSwingModeCharacteristic(HomekitTaggedItem taggedItem,
HomekitAccessoryUpdater updater) {
return new SwingModeCharacteristic(
() -> getEnumFromItem(taggedItem, SwingModeEnum.SWING_DISABLED, SwingModeEnum.SWING_ENABLED,
SwingModeEnum.SWING_DISABLED),
(value) -> setValueFromEnum(taggedItem, value, SwingModeEnum.SWING_DISABLED,
SwingModeEnum.SWING_ENABLED),
getSubscriber(taggedItem, SWING_MODE, updater), getUnsubscriber(taggedItem, SWING_MODE, updater));
var map = createMapping(taggedItem, SwingModeEnum.class);
return new SwingModeCharacteristic(() -> getEnumFromItem(taggedItem, map, SwingModeEnum.SWING_DISABLED),
(value) -> setValueFromEnum(taggedItem, value, map), getSubscriber(taggedItem, SWING_MODE, updater),
getUnsubscriber(taggedItem, SWING_MODE, updater));
}
private static LockPhysicalControlsCharacteristic createLockPhysicalControlsCharacteristic(
HomekitTaggedItem taggedItem, HomekitAccessoryUpdater updater) {
var map = createMapping(taggedItem, LockPhysicalControlsEnum.class);
return new LockPhysicalControlsCharacteristic(
() -> getEnumFromItem(taggedItem, LockPhysicalControlsEnum.CONTROL_LOCK_DISABLED,
LockPhysicalControlsEnum.CONTROL_LOCK_ENABLED, LockPhysicalControlsEnum.CONTROL_LOCK_DISABLED),
(value) -> setValueFromEnum(taggedItem, value, LockPhysicalControlsEnum.CONTROL_LOCK_DISABLED,
LockPhysicalControlsEnum.CONTROL_LOCK_ENABLED),
getSubscriber(taggedItem, LOCK_CONTROL, updater), getUnsubscriber(taggedItem, LOCK_CONTROL, updater));
() -> getEnumFromItem(taggedItem, map, LockPhysicalControlsEnum.CONTROL_LOCK_DISABLED),
(value) -> setValueFromEnum(taggedItem, value, map), getSubscriber(taggedItem, LOCK_CONTROL, updater),
getUnsubscriber(taggedItem, LOCK_CONTROL, updater));
}
private static RotationSpeedCharacteristic createRotationSpeedCharacteristic(HomekitTaggedItem item,
@@ -1049,10 +1062,10 @@ public class HomekitCharacteristicFactory {
private static ActiveCharacteristic createActiveCharacteristic(HomekitTaggedItem taggedItem,
HomekitAccessoryUpdater updater) {
return new ActiveCharacteristic(
() -> getEnumFromItem(taggedItem, ActiveEnum.INACTIVE, ActiveEnum.ACTIVE, ActiveEnum.INACTIVE),
(value) -> setValueFromEnum(taggedItem, value, ActiveEnum.INACTIVE, ActiveEnum.ACTIVE),
getSubscriber(taggedItem, ACTIVE, updater), getUnsubscriber(taggedItem, ACTIVE, updater));
var map = createMapping(taggedItem, ActiveEnum.class, false);
return new ActiveCharacteristic(() -> getEnumFromItem(taggedItem, map, ActiveEnum.INACTIVE),
(value) -> setValueFromEnum(taggedItem, value, map), getSubscriber(taggedItem, ACTIVE, updater),
getUnsubscriber(taggedItem, ACTIVE, updater));
}
private static ConfiguredNameCharacteristic createConfiguredNameCharacteristic(HomekitTaggedItem taggedItem,
@@ -1081,25 +1094,24 @@ public class HomekitCharacteristicFactory {
private static SleepDiscoveryModeCharacteristic createSleepDiscoveryModeCharacteristic(HomekitTaggedItem taggedItem,
HomekitAccessoryUpdater updater) {
var map = createMapping(taggedItem, SleepDiscoveryModeEnum.class);
return new SleepDiscoveryModeCharacteristic(
() -> getEnumFromItem(taggedItem, SleepDiscoveryModeEnum.NOT_DISCOVERABLE,
SleepDiscoveryModeEnum.ALWAYS_DISCOVERABLE, SleepDiscoveryModeEnum.ALWAYS_DISCOVERABLE),
() -> getEnumFromItem(taggedItem, map, SleepDiscoveryModeEnum.ALWAYS_DISCOVERABLE),
getSubscriber(taggedItem, SLEEP_DISCOVERY_MODE, updater),
getUnsubscriber(taggedItem, SLEEP_DISCOVERY_MODE, updater));
}
private static PowerModeCharacteristic createPowerModeCharacteristic(HomekitTaggedItem taggedItem,
HomekitAccessoryUpdater updater) {
return new PowerModeCharacteristic(
(value) -> setValueFromEnum(taggedItem, value, PowerModeEnum.HIDE, PowerModeEnum.SHOW));
var map = createMapping(taggedItem, PowerModeEnum.class, true);
return new PowerModeCharacteristic((value) -> setValueFromEnum(taggedItem, value, map));
}
private static ClosedCaptionsCharacteristic createClosedCaptionsCharacteristic(HomekitTaggedItem taggedItem,
HomekitAccessoryUpdater updater) {
return new ClosedCaptionsCharacteristic(
() -> getEnumFromItem(taggedItem, ClosedCaptionsEnum.DISABLED, ClosedCaptionsEnum.ENABLED,
ClosedCaptionsEnum.DISABLED),
(value) -> setValueFromEnum(taggedItem, value, ClosedCaptionsEnum.DISABLED, ClosedCaptionsEnum.ENABLED),
var map = createMapping(taggedItem, ClosedCaptionsEnum.class);
return new ClosedCaptionsCharacteristic(() -> getEnumFromItem(taggedItem, map, ClosedCaptionsEnum.DISABLED),
(value) -> setValueFromEnum(taggedItem, value, map),
getSubscriber(taggedItem, CLOSED_CAPTIONS, updater),
getUnsubscriber(taggedItem, CLOSED_CAPTIONS, updater));
}
@@ -1114,12 +1126,10 @@ public class HomekitCharacteristicFactory {
private static IsConfiguredCharacteristic createIsConfiguredCharacteristic(HomekitTaggedItem taggedItem,
HomekitAccessoryUpdater updater) {
return new IsConfiguredCharacteristic(
() -> getEnumFromItem(taggedItem, IsConfiguredEnum.NOT_CONFIGURED, IsConfiguredEnum.CONFIGURED,
IsConfiguredEnum.NOT_CONFIGURED),
(value) -> setValueFromEnum(taggedItem, value, IsConfiguredEnum.NOT_CONFIGURED,
IsConfiguredEnum.CONFIGURED),
getSubscriber(taggedItem, CONFIGURED, updater), getUnsubscriber(taggedItem, CONFIGURED, updater));
var map = createMapping(taggedItem, IsConfiguredEnum.class);
return new IsConfiguredCharacteristic(() -> getEnumFromItem(taggedItem, map, IsConfiguredEnum.NOT_CONFIGURED),
(value) -> setValueFromEnum(taggedItem, value, map), getSubscriber(taggedItem, CONFIGURED, updater),
getUnsubscriber(taggedItem, CONFIGURED, updater));
}
private static InputSourceTypeCharacteristic createInputSourceTypeCharacteristic(HomekitTaggedItem taggedItem,
@@ -1132,9 +1142,9 @@ public class HomekitCharacteristicFactory {
private static CurrentVisibilityStateCharacteristic createCurrentVisibilityStateCharacteristic(
HomekitTaggedItem taggedItem, HomekitAccessoryUpdater updater) {
var map = createMapping(taggedItem, CurrentVisibilityStateEnum.class, true);
return new CurrentVisibilityStateCharacteristic(
() -> getEnumFromItem(taggedItem, CurrentVisibilityStateEnum.HIDDEN, CurrentVisibilityStateEnum.SHOWN,
CurrentVisibilityStateEnum.HIDDEN),
() -> getEnumFromItem(taggedItem, map, CurrentVisibilityStateEnum.HIDDEN),
getSubscriber(taggedItem, CURRENT_VISIBILITY, updater),
getUnsubscriber(taggedItem, CURRENT_VISIBILITY, updater));
}
@@ -1146,19 +1156,18 @@ public class HomekitCharacteristicFactory {
private static InputDeviceTypeCharacteristic createInputDeviceTypeCharacteristic(HomekitTaggedItem taggedItem,
HomekitAccessoryUpdater updater) {
var mapping = createMapping(taggedItem, InputDeviceTypeEnum.class);
return new InputDeviceTypeCharacteristic(() -> getEnumFromItem(taggedItem, mapping, InputDeviceTypeEnum.OTHER),
var map = createMapping(taggedItem, InputDeviceTypeEnum.class);
return new InputDeviceTypeCharacteristic(() -> getEnumFromItem(taggedItem, map, InputDeviceTypeEnum.OTHER),
getSubscriber(taggedItem, INPUT_DEVICE_TYPE, updater),
getUnsubscriber(taggedItem, INPUT_DEVICE_TYPE, updater));
}
private static TargetVisibilityStateCharacteristic createTargetVisibilityStateCharacteristic(
HomekitTaggedItem taggedItem, HomekitAccessoryUpdater updater) {
var map = createMapping(taggedItem, TargetVisibilityStateEnum.class, true);
return new TargetVisibilityStateCharacteristic(
() -> getEnumFromItem(taggedItem, TargetVisibilityStateEnum.HIDDEN, TargetVisibilityStateEnum.SHOWN,
TargetVisibilityStateEnum.HIDDEN),
(value) -> setValueFromEnum(taggedItem, value, TargetVisibilityStateEnum.HIDDEN,
TargetVisibilityStateEnum.SHOWN),
() -> getEnumFromItem(taggedItem, map, TargetVisibilityStateEnum.HIDDEN),
(value) -> setValueFromEnum(taggedItem, value, map),
getSubscriber(taggedItem, TARGET_VISIBILITY_STATE, updater),
getUnsubscriber(taggedItem, TARGET_VISIBILITY_STATE, updater));
}

View File

@@ -15,6 +15,7 @@ package org.openhab.io.homekit.internal.accessories;
import static org.openhab.io.homekit.internal.HomekitCharacteristicType.CONTACT_SENSOR_STATE;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
@@ -31,19 +32,19 @@ import io.github.hapjava.services.impl.ContactSensorService;
* @author Philipp Arndt - Initial contribution
*/
public class HomekitContactSensorImpl extends AbstractHomekitAccessoryImpl implements ContactSensorAccessory {
private final BooleanItemReader contactSensedReader;
private final Map<ContactStateEnum, String> mapping;
public HomekitContactSensorImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
super(taggedItem, mandatoryCharacteristics, updater, settings);
contactSensedReader = createBooleanReader(CONTACT_SENSOR_STATE);
mapping = createMapping(CONTACT_SENSOR_STATE, ContactStateEnum.class);
getServices().add(new ContactSensorService(this));
}
@Override
public CompletableFuture<ContactStateEnum> getCurrentState() {
return CompletableFuture.completedFuture(
contactSensedReader.getValue() ? ContactStateEnum.NOT_DETECTED : ContactStateEnum.DETECTED);
return CompletableFuture
.completedFuture(getKeyFromMapping(CONTACT_SENSOR_STATE, mapping, ContactStateEnum.DETECTED));
}
@Override

View File

@@ -15,6 +15,7 @@ package org.openhab.io.homekit.internal.accessories;
import static org.openhab.io.homekit.internal.HomekitCharacteristicType.FILTER_CHANGE_INDICATION;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
@@ -32,20 +33,19 @@ import io.github.hapjava.services.impl.FilterMaintenanceService;
* @author Eugen Freiter - Initial contribution
*/
public class HomekitFilterMaintenanceImpl extends AbstractHomekitAccessoryImpl implements FilterMaintenanceAccessory {
private BooleanItemReader filterChangeIndication;
private final Map<FilterChangeIndicationEnum, String> mapping;
public HomekitFilterMaintenanceImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
super(taggedItem, mandatoryCharacteristics, updater, settings);
filterChangeIndication = createBooleanReader(FILTER_CHANGE_INDICATION);
mapping = createMapping(FILTER_CHANGE_INDICATION, FilterChangeIndicationEnum.class);
getServices().add(new FilterMaintenanceService(this));
}
@Override
public CompletableFuture<FilterChangeIndicationEnum> getFilterChangeIndication() {
return CompletableFuture
.completedFuture(filterChangeIndication.getValue() ? FilterChangeIndicationEnum.CHANGE_NEEDED
: FilterChangeIndicationEnum.NO_CHANGE_NEEDED);
return CompletableFuture.completedFuture(
getKeyFromMapping(FILTER_CHANGE_INDICATION, mapping, FilterChangeIndicationEnum.NO_CHANGE_NEEDED));
}
@Override

View File

@@ -17,16 +17,10 @@ import static org.openhab.io.homekit.internal.HomekitCharacteristicType.OBSTRUCT
import static org.openhab.io.homekit.internal.HomekitCharacteristicType.TARGET_DOOR_STATE;
import java.util.List;
import java.util.Optional;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import org.openhab.core.items.Item;
import org.openhab.core.library.items.StringItem;
import org.openhab.core.library.items.SwitchItem;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.StringType;
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
import org.openhab.io.homekit.internal.HomekitOHItemProxy;
import org.openhab.io.homekit.internal.HomekitSettings;
import org.openhab.io.homekit.internal.HomekitTaggedItem;
import org.slf4j.Logger;
@@ -46,83 +40,29 @@ import io.github.hapjava.services.impl.GarageDoorOpenerService;
public class HomekitGarageDoorOpenerImpl extends AbstractHomekitAccessoryImpl implements GarageDoorOpenerAccessory {
private final Logger logger = LoggerFactory.getLogger(HomekitGarageDoorOpenerImpl.class);
private final BooleanItemReader obstructionReader;
private final Map<CurrentDoorStateEnum, String> currentDoorStateMapping;
private final Map<TargetDoorStateEnum, String> targetDoorStateMapping;
public HomekitGarageDoorOpenerImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
super(taggedItem, mandatoryCharacteristics, updater, settings);
obstructionReader = createBooleanReader(OBSTRUCTION_STATUS);
currentDoorStateMapping = createMapping(CURRENT_DOOR_STATE, CurrentDoorStateEnum.class, true);
targetDoorStateMapping = createMapping(TARGET_DOOR_STATE, TargetDoorStateEnum.class, true);
getServices().add(new GarageDoorOpenerService(this));
}
@Override
public CompletableFuture<CurrentDoorStateEnum> getCurrentDoorState() {
final Optional<HomekitTaggedItem> characteristic = getCharacteristic(CURRENT_DOOR_STATE);
final HomekitSettings settings = getSettings();
String stringValue = settings.doorCurrentStateClosed;
if (characteristic.isPresent()) {
stringValue = characteristic.get().getItem().getState().toString();
} else {
logger.warn("Missing mandatory characteristic {}", CURRENT_DOOR_STATE);
}
CurrentDoorStateEnum mode;
if (stringValue.equalsIgnoreCase(settings.doorCurrentStateClosed)) {
mode = CurrentDoorStateEnum.CLOSED;
} else if (stringValue.equalsIgnoreCase(settings.doorCurrentStateClosing)) {
mode = CurrentDoorStateEnum.CLOSING;
} else if (stringValue.equalsIgnoreCase(settings.doorCurrentStateOpen)) {
mode = CurrentDoorStateEnum.OPEN;
} else if (stringValue.equalsIgnoreCase(settings.doorCurrentStateOpening)) {
mode = CurrentDoorStateEnum.OPENING;
} else if (stringValue.equalsIgnoreCase(settings.doorCurrentStateStopped)) {
mode = CurrentDoorStateEnum.STOPPED;
} else if (stringValue.equals("UNDEF") || stringValue.equals("NULL")) {
logger.warn("Current door state not available. Relaying value of CLOSED to HomeKit");
mode = CurrentDoorStateEnum.CLOSED;
} else {
logger.warn("Unrecognized current door state: {}. Expected {}, {}, {}, {} or {} strings in value.",
stringValue, settings.doorCurrentStateClosed, settings.doorCurrentStateClosing,
settings.doorCurrentStateOpen, settings.doorCurrentStateOpening, settings.doorCurrentStateStopped);
mode = CurrentDoorStateEnum.CLOSED;
}
return CompletableFuture.completedFuture(mode);
return CompletableFuture.completedFuture(
getKeyFromMapping(CURRENT_DOOR_STATE, currentDoorStateMapping, CurrentDoorStateEnum.CLOSED));
}
@Override
public CompletableFuture<TargetDoorStateEnum> getTargetDoorState() {
final Optional<HomekitTaggedItem> characteristic = getCharacteristic(TARGET_DOOR_STATE);
Item item;
if (characteristic.isPresent()) {
item = characteristic.get().getItem();
} else {
logger.warn("Missing mandatory characteristic {}", TARGET_DOOR_STATE);
return CompletableFuture.completedFuture(TargetDoorStateEnum.CLOSED);
}
TargetDoorStateEnum mode;
final Item baseItem = HomekitOHItemProxy.getBaseItem(item);
if (baseItem instanceof SwitchItem) {
mode = item.getState() == OnOffType.ON ? TargetDoorStateEnum.OPEN : TargetDoorStateEnum.CLOSED;
} else if (baseItem instanceof StringItem) {
final HomekitSettings settings = getSettings();
final String stringValue = item.getState().toString();
if (stringValue.equalsIgnoreCase(settings.doorTargetStateClosed)) {
mode = TargetDoorStateEnum.CLOSED;
} else if (stringValue.equalsIgnoreCase(settings.doorTargetStateOpen)) {
mode = TargetDoorStateEnum.OPEN;
} else {
logger.warn(
"Unsupported value {} for {}. Only {} and {} supported. Check HomeKit settings if you want to change the mapping",
stringValue, item.getName(), settings.doorTargetStateClosed, settings.doorTargetStateOpen);
mode = TargetDoorStateEnum.CLOSED;
}
} else {
logger.warn("Unsupported item type {} for {}. Only Switch and String are supported", baseItem.getType(),
item.getName());
mode = TargetDoorStateEnum.CLOSED;
}
return CompletableFuture.completedFuture(mode);
return CompletableFuture.completedFuture(
getKeyFromMapping(TARGET_DOOR_STATE, targetDoorStateMapping, TargetDoorStateEnum.CLOSED));
}
@Override
@@ -132,26 +72,8 @@ public class HomekitGarageDoorOpenerImpl extends AbstractHomekitAccessoryImpl im
@Override
public CompletableFuture<Void> setTargetDoorState(TargetDoorStateEnum targetDoorStateEnum) {
final Optional<HomekitTaggedItem> characteristic = getCharacteristic(TARGET_DOOR_STATE);
final HomekitTaggedItem taggedItem;
if (characteristic.isPresent()) {
taggedItem = characteristic.get();
} else {
logger.warn("Missing mandatory characteristic {}", TARGET_DOOR_STATE);
return CompletableFuture.completedFuture(null);
}
if (taggedItem.getBaseItem() instanceof SwitchItem) {
taggedItem.send(OnOffType.from(targetDoorStateEnum == TargetDoorStateEnum.OPEN));
} else if (taggedItem.getBaseItem() instanceof StringItem) {
final HomekitSettings settings = getSettings();
taggedItem
.send(new StringType(targetDoorStateEnum == TargetDoorStateEnum.OPEN ? settings.doorTargetStateOpen
: settings.doorTargetStateClosed));
} else {
logger.warn("Unsupported item type {} for {}. Only Switch and String are supported",
taggedItem.getBaseItem().getType(), taggedItem.getName());
}
HomekitCharacteristicFactory.setValueFromEnum(getCharacteristic(TARGET_DOOR_STATE).get(), targetDoorStateEnum,
targetDoorStateMapping);
return CompletableFuture.completedFuture(null);
}

View File

@@ -18,18 +18,14 @@ import static org.openhab.io.homekit.internal.HomekitCharacteristicType.TARGET_H
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
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.OnOffType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.library.types.StringType;
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
import org.openhab.io.homekit.internal.HomekitCharacteristicType;
import org.openhab.io.homekit.internal.HomekitSettings;
@@ -55,23 +51,8 @@ import io.github.hapjava.services.impl.HeaterCoolerService;
public class HomekitHeaterCoolerImpl extends AbstractHomekitAccessoryImpl implements HeaterCoolerAccessory {
private final Logger logger = LoggerFactory.getLogger(HomekitHeaterCoolerImpl.class);
private final BooleanItemReader activeReader;
private final Map<CurrentHeaterCoolerStateEnum, String> currentStateMapping = new EnumMap<CurrentHeaterCoolerStateEnum, String>(
CurrentHeaterCoolerStateEnum.class) {
{
put(CurrentHeaterCoolerStateEnum.INACTIVE, "INACTIVE");
put(CurrentHeaterCoolerStateEnum.IDLE, "IDLE");
put(CurrentHeaterCoolerStateEnum.HEATING, "HEATING");
put(CurrentHeaterCoolerStateEnum.COOLING, "COOLING");
}
};
private final Map<TargetHeaterCoolerStateEnum, String> targetStateMapping = new EnumMap<TargetHeaterCoolerStateEnum, String>(
TargetHeaterCoolerStateEnum.class) {
{
put(TargetHeaterCoolerStateEnum.AUTO, "AUTO");
put(TargetHeaterCoolerStateEnum.HEAT, "HEAT");
put(TargetHeaterCoolerStateEnum.COOL, "COOL");
}
};
private final Map<CurrentHeaterCoolerStateEnum, String> currentStateMapping;
private final Map<TargetHeaterCoolerStateEnum, String> targetStateMapping;
private final List<CurrentHeaterCoolerStateEnum> customCurrentStateList = new ArrayList<>();
private final List<TargetHeaterCoolerStateEnum> customTargetStateList = new ArrayList<>();
@@ -81,8 +62,10 @@ public class HomekitHeaterCoolerImpl extends AbstractHomekitAccessoryImpl implem
super(taggedItem, mandatoryCharacteristics, updater, settings);
activeReader = new BooleanItemReader(getItem(ACTIVE_STATUS, GenericItem.class)
.orElseThrow(() -> new IncompleteAccessoryException(ACTIVE_STATUS)), OnOffType.ON, OpenClosedType.OPEN);
updateMapping(CURRENT_HEATER_COOLER_STATE, currentStateMapping, customCurrentStateList);
updateMapping(TARGET_HEATER_COOLER_STATE, targetStateMapping, customTargetStateList);
currentStateMapping = createMapping(CURRENT_HEATER_COOLER_STATE, CurrentHeaterCoolerStateEnum.class,
customCurrentStateList);
targetStateMapping = createMapping(TARGET_HEATER_COOLER_STATE, TargetHeaterCoolerStateEnum.class,
customTargetStateList);
final HeaterCoolerService service = new HeaterCoolerService(this);
service.addOptionalCharacteristic(new TemperatureDisplayUnitCharacteristic(this::getTemperatureDisplayUnit,
this::setTemperatureDisplayUnit, this::subscribeTemperatureDisplayUnit,
@@ -138,14 +121,9 @@ public class HomekitHeaterCoolerImpl extends AbstractHomekitAccessoryImpl implem
@Override
public CompletableFuture<Void> setTargetHeaterCoolerState(TargetHeaterCoolerStateEnum state) {
final Optional<HomekitTaggedItem> characteristic = getCharacteristic(
HomekitCharacteristicType.TARGET_HEATER_COOLER_STATE);
if (characteristic.isPresent()) {
((StringItem) characteristic.get().getItem()).send(new StringType(targetStateMapping.get(state)));
} else {
logger.warn("Missing mandatory characteristic {}",
HomekitCharacteristicType.TARGET_HEATING_COOLING_STATE.getTag());
}
HomekitCharacteristicFactory.setValueFromEnum(
getCharacteristic(HomekitCharacteristicType.TARGET_HEATER_COOLER_STATE).get(), state,
targetStateMapping);
return CompletableFuture.completedFuture(null);
}

View File

@@ -44,14 +44,14 @@ import io.github.hapjava.services.impl.ServiceLabelService;
*/
@NonNullByDefault({})
public class HomekitIrrigationSystemImpl extends AbstractHomekitAccessoryImpl implements IrrigationSystemAccessory {
private BooleanItemReader inUseReader;
private Map<InUseEnum, String> inUseMapping;
private Map<ProgramModeEnum, String> programModeMap;
private static final String SERVICE_LABEL = "ServiceLabel";
public HomekitIrrigationSystemImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
super(taggedItem, mandatoryCharacteristics, updater, settings);
inUseReader = createBooleanReader(HomekitCharacteristicType.INUSE_STATUS);
inUseMapping = createMapping(HomekitCharacteristicType.INUSE_STATUS, InUseEnum.class);
programModeMap = HomekitCharacteristicFactory
.createMapping(getCharacteristic(HomekitCharacteristicType.PROGRAM_MODE).get(), ProgramModeEnum.class);
getServices().add(new IrrigationSystemService(this));
@@ -89,7 +89,8 @@ public class HomekitIrrigationSystemImpl extends AbstractHomekitAccessoryImpl im
@Override
public CompletableFuture<InUseEnum> getInUse() {
return CompletableFuture.completedFuture(inUseReader.getValue() ? InUseEnum.IN_USE : InUseEnum.NOT_IN_USE);
return CompletableFuture.completedFuture(
getKeyFromMapping(HomekitCharacteristicType.INUSE_STATUS, inUseMapping, InUseEnum.NOT_IN_USE));
}
@Override

View File

@@ -15,6 +15,7 @@ package org.openhab.io.homekit.internal.accessories;
import static org.openhab.io.homekit.internal.HomekitCharacteristicType.LEAK_DETECTED_STATE;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
@@ -31,19 +32,19 @@ import io.github.hapjava.services.impl.LeakSensorService;
* @author Tim Harper - Initial contribution
*/
public class HomekitLeakSensorImpl extends AbstractHomekitAccessoryImpl implements LeakSensorAccessory {
private final BooleanItemReader leakDetectedReader;
private final Map<LeakDetectedStateEnum, String> mapping;
public HomekitLeakSensorImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
super(taggedItem, mandatoryCharacteristics, updater, settings);
leakDetectedReader = createBooleanReader(LEAK_DETECTED_STATE);
mapping = createMapping(LEAK_DETECTED_STATE, LeakDetectedStateEnum.class);
getServices().add(new LeakSensorService(this));
}
@Override
public CompletableFuture<LeakDetectedStateEnum> getLeakDetected() {
return CompletableFuture.completedFuture(leakDetectedReader.getValue() ? LeakDetectedStateEnum.LEAK_DETECTED
: LeakDetectedStateEnum.LEAK_NOT_DETECTED);
return CompletableFuture.completedFuture(
getKeyFromMapping(LEAK_DETECTED_STATE, mapping, LeakDetectedStateEnum.LEAK_NOT_DETECTED));
}
@Override

View File

@@ -13,15 +13,9 @@
package org.openhab.io.homekit.internal.accessories;
import java.util.List;
import java.util.Optional;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.items.GenericItem;
import org.openhab.core.library.items.SwitchItem;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.types.State;
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
import org.openhab.io.homekit.internal.HomekitCharacteristicType;
import org.openhab.io.homekit.internal.HomekitSettings;
@@ -40,62 +34,34 @@ import io.github.hapjava.services.impl.LockMechanismService;
*
*/
public class HomekitLockImpl extends AbstractHomekitAccessoryImpl implements LockMechanismAccessory {
final OnOffType securedState;
final OnOffType unsecuredState;
final Map<LockCurrentStateEnum, String> currentStateMapping;
final Map<LockTargetStateEnum, String> targetStateMapping;
public HomekitLockImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
HomekitAccessoryUpdater updater, HomekitSettings settings) {
super(taggedItem, mandatoryCharacteristics, updater, settings);
securedState = taggedItem.isInverted() ? OnOffType.OFF : OnOffType.ON;
unsecuredState = taggedItem.isInverted() ? OnOffType.ON : OnOffType.OFF;
currentStateMapping = createMapping(HomekitCharacteristicType.LOCK_CURRENT_STATE, LockCurrentStateEnum.class);
targetStateMapping = createMapping(HomekitCharacteristicType.LOCK_TARGET_STATE, LockTargetStateEnum.class);
getServices().add(new LockMechanismService(this));
}
@Override
public CompletableFuture<LockCurrentStateEnum> getLockCurrentState() {
final Optional<GenericItem> item = getItem(HomekitCharacteristicType.LOCK_CURRENT_STATE, GenericItem.class);
LockCurrentStateEnum lockState = LockCurrentStateEnum.UNKNOWN;
if (item.isPresent()) {
final State state = item.get().getState();
if (state instanceof DecimalType) {
lockState = LockCurrentStateEnum.fromCode(((DecimalType) state).intValue());
} else if (state instanceof OnOffType) {
lockState = state.equals(securedState) ? LockCurrentStateEnum.SECURED : LockCurrentStateEnum.UNSECURED;
}
}
return CompletableFuture.completedFuture(lockState);
return CompletableFuture.completedFuture(getKeyFromMapping(HomekitCharacteristicType.LOCK_CURRENT_STATE,
currentStateMapping, LockCurrentStateEnum.UNKNOWN));
}
@Override
public CompletableFuture<LockTargetStateEnum> getLockTargetState() {
final @Nullable OnOffType state = getStateAs(HomekitCharacteristicType.LOCK_TARGET_STATE, OnOffType.class);
if (state != null) {
return CompletableFuture.completedFuture(
state == securedState ? LockTargetStateEnum.SECURED : LockTargetStateEnum.UNSECURED);
}
return CompletableFuture.completedFuture(LockTargetStateEnum.UNSECURED);
// Apple HAP specification has only SECURED and UNSECURED values for lock target state.
// unknown does not supported for target state.
return CompletableFuture.completedFuture(getKeyFromMapping(HomekitCharacteristicType.LOCK_TARGET_STATE,
targetStateMapping, LockTargetStateEnum.UNSECURED));
}
@Override
public CompletableFuture<Void> setLockTargetState(LockTargetStateEnum state) {
getItem(HomekitCharacteristicType.LOCK_TARGET_STATE, SwitchItem.class).ifPresent(item -> {
switch (state) {
case SECURED:
if (item instanceof SwitchItem) {
item.send(securedState);
}
break;
case UNSECURED:
if (item instanceof SwitchItem) {
item.send(unsecuredState);
}
break;
default:
break;
}
});
HomekitCharacteristicFactory.setValueFromEnum(
getCharacteristic(HomekitCharacteristicType.LOCK_TARGET_STATE).get(), state, targetStateMapping);
return CompletableFuture.completedFuture(null);
}

View File

@@ -15,6 +15,7 @@ package org.openhab.io.homekit.internal.accessories;
import static org.openhab.io.homekit.internal.HomekitCharacteristicType.OCCUPANCY_DETECTED_STATE;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
@@ -31,19 +32,19 @@ import io.github.hapjava.services.impl.OccupancySensorService;
* @author Tim Harper - Initial contribution
*/
public class HomekitOccupancySensorImpl extends AbstractHomekitAccessoryImpl implements OccupancySensorAccessory {
private final BooleanItemReader occupancySensedReader;
private final Map<OccupancyDetectedEnum, String> mapping;
public HomekitOccupancySensorImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
super(taggedItem, mandatoryCharacteristics, updater, settings);
occupancySensedReader = createBooleanReader(OCCUPANCY_DETECTED_STATE);
mapping = createMapping(OCCUPANCY_DETECTED_STATE, OccupancyDetectedEnum.class);
getServices().add(new OccupancySensorService(this));
}
@Override
public CompletableFuture<OccupancyDetectedEnum> getOccupancyDetected() {
return CompletableFuture.completedFuture(
occupancySensedReader.getValue() ? OccupancyDetectedEnum.DETECTED : OccupancyDetectedEnum.NOT_DETECTED);
getKeyFromMapping(OCCUPANCY_DETECTED_STATE, mapping, OccupancyDetectedEnum.NOT_DETECTED));
}
@Override

View File

@@ -16,13 +16,10 @@ import static org.openhab.io.homekit.internal.HomekitCharacteristicType.SECURITY
import static org.openhab.io.homekit.internal.HomekitCharacteristicType.SECURITY_SYSTEM_TARGET_STATE;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import org.openhab.core.library.items.StringItem;
import org.openhab.core.library.types.StringType;
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
import org.openhab.io.homekit.internal.HomekitCharacteristicType;
import org.openhab.io.homekit.internal.HomekitSettings;
@@ -44,35 +41,18 @@ import io.github.hapjava.services.impl.SecuritySystemService;
* @author Cody Cutrer - Initial contribution
*/
public class HomekitSecuritySystemImpl extends AbstractHomekitAccessoryImpl implements SecuritySystemAccessory {
private final Map<CurrentSecuritySystemStateEnum, String> currentStateMapping = new EnumMap<CurrentSecuritySystemStateEnum, String>(
CurrentSecuritySystemStateEnum.class) {
{
put(CurrentSecuritySystemStateEnum.DISARMED, "DISARMED");
put(CurrentSecuritySystemStateEnum.AWAY_ARM, "AWAY_ARM");
put(CurrentSecuritySystemStateEnum.STAY_ARM, "STAY_ARM");
put(CurrentSecuritySystemStateEnum.NIGHT_ARM, "NIGHT_ARM");
put(CurrentSecuritySystemStateEnum.TRIGGERED, "TRIGGERED");
}
};
private final Map<TargetSecuritySystemStateEnum, String> targetStateMapping = new EnumMap<TargetSecuritySystemStateEnum, String>(
TargetSecuritySystemStateEnum.class) {
{
put(TargetSecuritySystemStateEnum.DISARM, "DISARM");
put(TargetSecuritySystemStateEnum.AWAY_ARM, "AWAY_ARM");
put(TargetSecuritySystemStateEnum.STAY_ARM, "STAY_ARM");
put(TargetSecuritySystemStateEnum.NIGHT_ARM, "NIGHT_ARM");
}
};
private final List<CurrentSecuritySystemStateEnum> customCurrentStateList;
private final List<TargetSecuritySystemStateEnum> customTargetStateList;
private final Map<CurrentSecuritySystemStateEnum, String> currentStateMapping;
private final Map<TargetSecuritySystemStateEnum, String> targetStateMapping;
private final List<CurrentSecuritySystemStateEnum> customCurrentStateList = new ArrayList<>();
private final List<TargetSecuritySystemStateEnum> customTargetStateList = new ArrayList<>();
public HomekitSecuritySystemImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
HomekitAccessoryUpdater updater, HomekitSettings settings) {
super(taggedItem, mandatoryCharacteristics, updater, settings);
customCurrentStateList = new ArrayList<>();
customTargetStateList = new ArrayList<>();
updateMapping(SECURITY_SYSTEM_CURRENT_STATE, currentStateMapping, customCurrentStateList);
updateMapping(SECURITY_SYSTEM_TARGET_STATE, targetStateMapping, customTargetStateList);
currentStateMapping = createMapping(SECURITY_SYSTEM_CURRENT_STATE, CurrentSecuritySystemStateEnum.class,
customCurrentStateList);
targetStateMapping = createMapping(SECURITY_SYSTEM_TARGET_STATE, TargetSecuritySystemStateEnum.class,
customTargetStateList);
getServices().add(new SecuritySystemService(this));
}
@@ -98,8 +78,9 @@ public class HomekitSecuritySystemImpl extends AbstractHomekitAccessoryImpl impl
@Override
public void setTargetSecuritySystemState(TargetSecuritySystemStateEnum state) {
getItem(HomekitCharacteristicType.SECURITY_SYSTEM_TARGET_STATE, StringItem.class)
.ifPresent(item -> item.send(new StringType(targetStateMapping.get(state))));
HomekitCharacteristicFactory.setValueFromEnum(
getCharacteristic(HomekitCharacteristicType.SECURITY_SYSTEM_TARGET_STATE).get(), state,
targetStateMapping);
}
@Override

View File

@@ -14,7 +14,6 @@ package org.openhab.io.homekit.internal.accessories;
import static org.openhab.io.homekit.internal.HomekitCharacteristicType.CURRENT_SLAT_STATE;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
@@ -43,11 +42,7 @@ public class HomekitSlatImpl extends AbstractHomekitAccessoryImpl implements Sla
super(taggedItem, mandatoryCharacteristics, updater, settings);
final String slatTypeConfig = getAccessoryConfiguration(CONFIG_TYPE, "horizontal");
slatType = "horizontal".equalsIgnoreCase(slatTypeConfig) ? SlatTypeEnum.HORIZONTAL : SlatTypeEnum.VERTICAL;
currentSlatStateMapping = new EnumMap<>(CurrentSlatStateEnum.class);
currentSlatStateMapping.put(CurrentSlatStateEnum.FIXED, "FIXED");
currentSlatStateMapping.put(CurrentSlatStateEnum.SWINGING, "SWINGING");
currentSlatStateMapping.put(CurrentSlatStateEnum.JAMMED, "JAMMED");
updateMapping(CURRENT_SLAT_STATE, currentSlatStateMapping);
currentSlatStateMapping = createMapping(CURRENT_SLAT_STATE, CurrentSlatStateEnum.class);
getServices().add(new SlatService(this));
}

View File

@@ -15,13 +15,10 @@ package org.openhab.io.homekit.internal.accessories;
import static org.openhab.io.homekit.internal.HomekitCharacteristicType.CURRENT_MEDIA_STATE;
import static org.openhab.io.homekit.internal.HomekitCharacteristicType.TARGET_MEDIA_STATE;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import org.openhab.core.library.items.StringItem;
import org.openhab.core.library.types.StringType;
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
import org.openhab.io.homekit.internal.HomekitSettings;
import org.openhab.io.homekit.internal.HomekitTaggedItem;
@@ -43,18 +40,8 @@ public class HomekitSmartSpeakerImpl extends AbstractHomekitAccessoryImpl implem
public HomekitSmartSpeakerImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
HomekitAccessoryUpdater updater, HomekitSettings settings) {
super(taggedItem, mandatoryCharacteristics, updater, settings);
currentMediaState = new EnumMap<>(CurrentMediaStateEnum.class);
currentMediaState.put(CurrentMediaStateEnum.STOP, "STOP");
currentMediaState.put(CurrentMediaStateEnum.PLAY, "PLAY");
currentMediaState.put(CurrentMediaStateEnum.PAUSE, "PAUSE");
currentMediaState.put(CurrentMediaStateEnum.UNKNOWN, "UNKNOWN");
updateMapping(CURRENT_MEDIA_STATE, currentMediaState);
targetMediaState = new EnumMap<>(TargetMediaStateEnum.class);
targetMediaState.put(TargetMediaStateEnum.STOP, "STOP");
targetMediaState.put(TargetMediaStateEnum.PLAY, "PLAY");
targetMediaState.put(TargetMediaStateEnum.PAUSE, "PAUSE");
updateMapping(TARGET_MEDIA_STATE, targetMediaState);
currentMediaState = createMapping(CURRENT_MEDIA_STATE, CurrentMediaStateEnum.class);
targetMediaState = createMapping(TARGET_MEDIA_STATE, TargetMediaStateEnum.class);
getServices().add(new SmartSpeakerService(this));
}
@@ -82,8 +69,8 @@ public class HomekitSmartSpeakerImpl extends AbstractHomekitAccessoryImpl implem
@Override
public CompletableFuture<Void> setTargetMediaState(final TargetMediaStateEnum targetState) {
getItem(TARGET_MEDIA_STATE, StringItem.class)
.ifPresent(item -> item.send(new StringType(targetMediaState.get(targetState))));
HomekitCharacteristicFactory.setValueFromEnum(getCharacteristic(TARGET_MEDIA_STATE).get(), targetState,
targetMediaState);
return CompletableFuture.completedFuture(null);
}

View File

@@ -15,6 +15,7 @@ package org.openhab.io.homekit.internal.accessories;
import static org.openhab.io.homekit.internal.HomekitCharacteristicType.SMOKE_DETECTED_STATE;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
@@ -31,19 +32,19 @@ import io.github.hapjava.services.impl.SmokeSensorService;
* @author Cody Cutrer - Initial contribution
*/
public class HomekitSmokeSensorImpl extends AbstractHomekitAccessoryImpl implements SmokeSensorAccessory {
private final BooleanItemReader smokeDetectedReader;
private final Map<SmokeDetectedStateEnum, String> mapping;
public HomekitSmokeSensorImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
super(taggedItem, mandatoryCharacteristics, updater, settings);
smokeDetectedReader = createBooleanReader(SMOKE_DETECTED_STATE);
mapping = createMapping(SMOKE_DETECTED_STATE, SmokeDetectedStateEnum.class);
this.getServices().add(new SmokeSensorService(this));
}
@Override
public CompletableFuture<SmokeDetectedStateEnum> getSmokeDetectedState() {
return CompletableFuture.completedFuture(
smokeDetectedReader.getValue() ? SmokeDetectedStateEnum.DETECTED : SmokeDetectedStateEnum.NOT_DETECTED);
return CompletableFuture
.completedFuture(getKeyFromMapping(SMOKE_DETECTED_STATE, mapping, SmokeDetectedStateEnum.NOT_DETECTED));
}
@Override

View File

@@ -17,16 +17,13 @@ import static org.openhab.io.homekit.internal.HomekitCharacteristicType.TARGET_H
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import org.openhab.core.library.items.NumberItem;
import org.openhab.core.library.items.StringItem;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.StringType;
import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
import org.openhab.io.homekit.internal.HomekitCharacteristicType;
import org.openhab.io.homekit.internal.HomekitSettings;
@@ -64,23 +61,12 @@ class HomekitThermostatImpl extends AbstractHomekitAccessoryImpl implements Ther
public HomekitThermostatImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
HomekitAccessoryUpdater updater, HomekitSettings settings) {
super(taggedItem, mandatoryCharacteristics, updater, settings);
currentHeatingCoolingStateMapping = new EnumMap<>(CurrentHeatingCoolingStateEnum.class);
currentHeatingCoolingStateMapping.put(CurrentHeatingCoolingStateEnum.OFF, settings.thermostatCurrentModeOff);
currentHeatingCoolingStateMapping.put(CurrentHeatingCoolingStateEnum.COOL,
settings.thermostatCurrentModeCooling);
currentHeatingCoolingStateMapping.put(CurrentHeatingCoolingStateEnum.HEAT,
settings.thermostatCurrentModeHeating);
targetHeatingCoolingStateMapping = new EnumMap<>(TargetHeatingCoolingStateEnum.class);
targetHeatingCoolingStateMapping.put(TargetHeatingCoolingStateEnum.OFF, settings.thermostatTargetModeOff);
targetHeatingCoolingStateMapping.put(TargetHeatingCoolingStateEnum.COOL, settings.thermostatTargetModeCool);
targetHeatingCoolingStateMapping.put(TargetHeatingCoolingStateEnum.HEAT, settings.thermostatTargetModeHeat);
targetHeatingCoolingStateMapping.put(TargetHeatingCoolingStateEnum.AUTO, settings.thermostatTargetModeAuto);
customCurrentHeatingCoolingStateList = new ArrayList<>();
customTargetHeatingCoolingStateList = new ArrayList<>();
updateMapping(CURRENT_HEATING_COOLING_STATE, currentHeatingCoolingStateMapping,
customCurrentHeatingCoolingStateList);
updateMapping(TARGET_HEATING_COOLING_STATE, targetHeatingCoolingStateMapping,
customTargetHeatingCoolingStateList);
currentHeatingCoolingStateMapping = createMapping(CURRENT_HEATING_COOLING_STATE,
CurrentHeatingCoolingStateEnum.class, customCurrentHeatingCoolingStateList);
targetHeatingCoolingStateMapping = createMapping(TARGET_HEATING_COOLING_STATE,
TargetHeatingCoolingStateEnum.class, customTargetHeatingCoolingStateList);
this.getServices().add(new ThermostatService(this));
}
@@ -165,8 +151,8 @@ class HomekitThermostatImpl extends AbstractHomekitAccessoryImpl implements Ther
@Override
public void setTargetState(TargetHeatingCoolingStateEnum mode) {
getItem(TARGET_HEATING_COOLING_STATE, StringItem.class)
.ifPresent(item -> item.send(new StringType(targetHeatingCoolingStateMapping.get(mode))));
HomekitCharacteristicFactory.setValueFromEnum(getCharacteristic(TARGET_HEATING_COOLING_STATE).get(), mode,
targetHeatingCoolingStateMapping);
}
@Override

View File

@@ -20,16 +20,6 @@
<description>Advanced network settings.</description>
<advanced>true</advanced>
</parameter-group>
<parameter-group name="thermostatTargetHeatingCooling">
<label>Thermostat Target Heating/Cooling Mapping</label>
<description>String values used by your thermostat to set different target heating/cooling modes.</description>
<advanced>true</advanced>
</parameter-group>
<parameter-group name="thermostatCurrentHeatingCooling">
<label>Thermostat Current Heating/Cooling Mapping</label>
<description>String values used by your thermostat to set different current heating/cooling modes.</description>
<advanced>true</advanced>
</parameter-group>
<parameter name="name" type="text" required="false" groupName="core">
<label>Bridge name</label>
<description>Name of the HomeKit bridge.</description>
@@ -79,58 +69,6 @@
<description>Defines whether or not to direct HomeKit clients to use fahrenheit temperatures instead of celsius.</description>
<default>false</default>
</parameter>
<parameter name="thermostatTargetModeCool" type="text" required="true"
groupName="thermostatTargetHeatingCooling">
<label>Cool Value</label>
<description>Word used to set the target heatingCoolingMode to COOL (if a thermostat is defined).</description>
<default>CoolOn</default>
<advanced>true</advanced>
</parameter>
<parameter name="thermostatTargetModeHeat" type="text" required="true"
groupName="thermostatTargetHeatingCooling">
<label>Heat Value</label>
<description>Word used to set the target heatingCoolingMode to HEAT (if a thermostat is defined).</description>
<default>HeatOn</default>
<advanced>true</advanced>
</parameter>
<parameter name="thermostatTargetModeAuto" type="text" required="true"
groupName="thermostatTargetHeatingCooling">
<label>Auto Value</label>
<description>Word used to set the target heatingCoolingMode to AUTO (if a thermostat is defined).</description>
<default>Auto</default>
<advanced>true</advanced>
</parameter>
<parameter name="thermostatTargetModeOff" type="text" required="true"
groupName="thermostatTargetHeatingCooling">
<label>Off Value</label>
<description>Word used to set the target heatingCoolingMode to OFF (if a thermostat is defined).</description>
<default>Off</default>
<advanced>true</advanced>
</parameter>
<parameter name="thermostatCurrentModeHeating" type="text" required="true"
groupName="thermostatCurrentHeatingCooling">
<label>Heating Value</label>
<description>Value for setting target heatingCoolingCurrentMode to HEAT (IE: indicating that the heater is currently
warming the home).</description>
<default>Heating</default>
<advanced>true</advanced>
</parameter>
<parameter name="thermostatCurrentModeCooling" type="text" required="true"
groupName="thermostatCurrentHeatingCooling">
<label>Cooling Value</label>
<description>Value for setting target heatingCoolingCurrentMode to COOL (IE: indicating that the air condition is
currently cooling the home).</description>
<default>Cooling</default>
<advanced>true</advanced>
</parameter>
<parameter name="thermostatCurrentModeOff" type="text" required="true"
groupName="thermostatCurrentHeatingCooling">
<label>Off Value</label>
<description>Value for setting target heatingCoolingCurrentMode to OFF (IE: the hvac is currently idle, because the
target temperature has been reached per the mode).</description>
<default>Off</default>
<advanced>true</advanced>
</parameter>
<parameter name="useOHmDNS" type="boolean" required="false" groupName="network">
<label>Use openHAB mDNS service</label>
<description>Defines whether mDNS service of openHAB or a separate instance of mDNS should be used.</description>

View File

@@ -5,10 +5,6 @@ io.config.homekit.group.network.label = Network Settings
io.config.homekit.group.network.description = Advanced network settings.
io.config.homekit.group.thermostat.label = Thermostat Settings
io.config.homekit.group.thermostat.description = Advanced thermostat settings.
io.config.homekit.group.thermostatCurrentHeatingCooling.label = Thermostat Current Heating/Cooling Mapping
io.config.homekit.group.thermostatCurrentHeatingCooling.description = String values used by your thermostat to set different current heating/cooling modes.
io.config.homekit.group.thermostatTargetHeatingCooling.label = Thermostat Target Heating/Cooling Mapping
io.config.homekit.group.thermostatTargetHeatingCooling.description = String values used by your thermostat to set different target heating/cooling modes.
io.config.homekit.instances.label = Instances
io.config.homekit.instances.description = Defines how many bridges to expose. Necessary if you have more than 149 accessories. Accessories must be assigned to additional instances via metadata. Additional bridges will use incrementing port numbers.
io.config.homekit.name.label = Bridge name
@@ -23,20 +19,6 @@ io.config.homekit.qrCode.label = HomeKit QR Code
io.config.homekit.qrCode.description = Scan QR code with home app to add openHAB as HomeKit bridge.
io.config.homekit.setupId.label = Setup ID
io.config.homekit.setupId.description = Setup ID used for pairing using QR Code. Alphanumeric code of length 4.
io.config.homekit.thermostatCurrentModeCooling.label = Cooling Value
io.config.homekit.thermostatCurrentModeCooling.description = Value for setting target heatingCoolingCurrentMode to COOL (IE: indicating that the air condition is currently cooling the home).
io.config.homekit.thermostatCurrentModeHeating.label = Heating Value
io.config.homekit.thermostatCurrentModeHeating.description = Value for setting target heatingCoolingCurrentMode to HEAT (IE: indicating that the heater is currently warming the home).
io.config.homekit.thermostatCurrentModeOff.label = Off Value
io.config.homekit.thermostatCurrentModeOff.description = Value for setting target heatingCoolingCurrentMode to OFF (IE: the hvac is currently idle, because the target temperature has been reached per the mode).
io.config.homekit.thermostatTargetModeAuto.label = Auto Value
io.config.homekit.thermostatTargetModeAuto.description = Word used to set the target heatingCoolingMode to AUTO (if a thermostat is defined).
io.config.homekit.thermostatTargetModeCool.label = Cool Value
io.config.homekit.thermostatTargetModeCool.description = Word used to set the target heatingCoolingMode to COOL (if a thermostat is defined).
io.config.homekit.thermostatTargetModeHeat.label = Heat Value
io.config.homekit.thermostatTargetModeHeat.description = Word used to set the target heatingCoolingMode to HEAT (if a thermostat is defined).
io.config.homekit.thermostatTargetModeOff.label = Off Value
io.config.homekit.thermostatTargetModeOff.description = Word used to set the target heatingCoolingMode to OFF (if a thermostat is defined).
io.config.homekit.useDummyAccessories.label = Use Dummy Accessories
io.config.homekit.useDummyAccessories.description = Create dummy accessories when an item is missing. See <a href="https://www.openhab.org/addons/integrations/homekit/#dummy-accessories">the documentation</a> for more information.
io.config.homekit.useFahrenheitTemperature.label = Use Fahrenheit Temperature