[homeconnect] Fix update of channels linked to program options (#10990)

Fix #10955

Signed-off-by: Laurent Garnier <lg.hc@free.fr>
This commit is contained in:
lolodomo 2021-08-04 15:52:56 +02:00 committed by GitHub
parent f09dfa0f93
commit ebb2662870
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -75,6 +75,7 @@ import org.openhab.core.thing.binding.BaseThingHandler;
import org.openhab.core.thing.binding.BridgeHandler; import org.openhab.core.thing.binding.BridgeHandler;
import org.openhab.core.types.Command; import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType; import org.openhab.core.types.RefreshType;
import org.openhab.core.types.State;
import org.openhab.core.types.StateOption; import org.openhab.core.types.StateOption;
import org.openhab.core.types.UnDefType; import org.openhab.core.types.UnDefType;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -473,6 +474,21 @@ public abstract class AbstractHomeConnectThingHandler extends BaseThingHandler i
} }
} }
/**
* Get thing linked channel by given channel id.
*
* @param channelId channel id
* @return channel if linked
*/
protected Optional<Channel> getLinkedChannel(String channelId) {
Channel channel = getThing().getChannel(channelId);
if (channel == null || !isLinked(channelId)) {
return Optional.empty();
} else {
return Optional.of(channel);
}
}
/** /**
* Configure channel update handlers. Classes which extend {@link AbstractHomeConnectThingHandler} must implement * Configure channel update handlers. Classes which extend {@link AbstractHomeConnectThingHandler} must implement
* this class and add handlers. * this class and add handlers.
@ -1334,109 +1350,95 @@ public abstract class AbstractHomeConnectThingHandler extends BaseThingHandler i
} }
} }
private Optional<Option> getOption(List<Option> options, String optionKey) {
return options.stream().filter(option -> optionKey.equals(option.getKey())).findFirst();
}
private void setStringChannelFromOption(String channelId, List<Option> options, String optionKey,
@Nullable State defaultState) {
setStringChannelFromOption(channelId, options, optionKey, value -> value, defaultState);
}
private void setStringChannelFromOption(String channelId, List<Option> options, String optionKey,
Function<String, String> mappingFunc, @Nullable State defaultState) {
getLinkedChannel(channelId)
.ifPresent(channel -> getOption(options, optionKey).map(option -> option.getValue()).ifPresentOrElse(
value -> updateState(channel.getUID(), new StringType(mappingFunc.apply(value))), () -> {
if (defaultState != null) {
updateState(channel.getUID(), defaultState);
}
}));
}
private void setQuantityChannelFromOption(String channelId, List<Option> options, String optionKey,
Function<@Nullable String, Unit<?>> unitMappingFunc, @Nullable State defaultState) {
getLinkedChannel(channelId).ifPresent(channel -> getOption(options, optionKey) //
.ifPresentOrElse(
option -> updateState(channel.getUID(),
new QuantityType<>(option.getValueAsInt(), unitMappingFunc.apply(option.getUnit()))),
() -> {
if (defaultState != null) {
updateState(channel.getUID(), defaultState);
}
}));
}
private void setOnOffChannelFromOption(String channelId, List<Option> options, String optionKey,
@Nullable State defaultState) {
getLinkedChannel(channelId)
.ifPresent(channel -> getOption(options, optionKey).map(option -> option.getValueAsBoolean())
.ifPresentOrElse(value -> updateState(channel.getUID(), OnOffType.from(value)), () -> {
if (defaultState != null) {
updateState(channel.getUID(), defaultState);
}
}));
}
protected void processProgramOptions(List<Option> options) { protected void processProgramOptions(List<Option> options) {
options.forEach(option -> { String operationState = getOperationState();
String key = option.getKey();
if (key != null) { Map.of(CHANNEL_WASHER_TEMPERATURE, OPTION_WASHER_TEMPERATURE, CHANNEL_WASHER_SPIN_SPEED,
switch (key) { OPTION_WASHER_SPIN_SPEED, CHANNEL_WASHER_IDOS1_LEVEL, OPTION_WASHER_IDOS_1_DOSING_LEVEL,
case OPTION_WASHER_TEMPERATURE: CHANNEL_WASHER_IDOS2_LEVEL, OPTION_WASHER_IDOS_2_DOSING_LEVEL, CHANNEL_DRYER_DRYING_TARGET,
getThingChannel(CHANNEL_WASHER_TEMPERATURE) OPTION_DRYER_DRYING_TARGET)
.ifPresent(channel -> updateState(channel.getUID(), new StringType(option.getValue()))); .forEach((channel, option) -> setStringChannelFromOption(channel, options, option, UnDefType.UNDEF));
break;
case OPTION_WASHER_SPIN_SPEED: Map.of(CHANNEL_WASHER_IDOS1, OPTION_WASHER_IDOS_1_ACTIVE, CHANNEL_WASHER_IDOS2, OPTION_WASHER_IDOS_2_ACTIVE,
getThingChannel(CHANNEL_WASHER_SPIN_SPEED) CHANNEL_WASHER_LESS_IRONING, OPTION_WASHER_LESS_IRONING, CHANNEL_WASHER_PRE_WASH,
.ifPresent(channel -> updateState(channel.getUID(), new StringType(option.getValue()))); OPTION_WASHER_PRE_WASH, CHANNEL_WASHER_SOAK, OPTION_WASHER_SOAK)
break; .forEach((channel, option) -> setOnOffChannelFromOption(channel, options, option, OnOffType.OFF));
case OPTION_WASHER_IDOS_1_DOSING_LEVEL:
getThingChannel(CHANNEL_WASHER_IDOS1_LEVEL) setStringChannelFromOption(CHANNEL_HOOD_INTENSIVE_LEVEL, options, OPTION_HOOD_INTENSIVE_LEVEL,
.ifPresent(channel -> updateState(channel.getUID(), new StringType(option.getValue()))); value -> mapStageStringType(value), UnDefType.UNDEF);
break; setStringChannelFromOption(CHANNEL_HOOD_VENTING_LEVEL, options, OPTION_HOOD_VENTING_LEVEL,
case OPTION_WASHER_IDOS_2_DOSING_LEVEL: value -> mapStageStringType(value), UnDefType.UNDEF);
getThingChannel(CHANNEL_WASHER_IDOS2_LEVEL) setQuantityChannelFromOption(CHANNEL_SETPOINT_TEMPERATURE, options, OPTION_SETPOINT_TEMPERATURE,
.ifPresent(channel -> updateState(channel.getUID(), new StringType(option.getValue()))); unit -> mapTemperature(unit), UnDefType.UNDEF);
break; setQuantityChannelFromOption(CHANNEL_DURATION, options, OPTION_DURATION, unit -> SECOND, UnDefType.UNDEF);
case OPTION_DRYER_DRYING_TARGET: // The channel remaining_program_time_state depends on two program options: FinishInRelative and
getThingChannel(CHANNEL_DRYER_DRYING_TARGET) // RemainingProgramTime. When the start of the program is delayed, the two options are returned by the API with
.ifPresent(channel -> updateState(channel.getUID(), new StringType(option.getValue()))); // different values. In this case, we consider the value of the option FinishInRelative.
break; setQuantityChannelFromOption(CHANNEL_REMAINING_PROGRAM_TIME_STATE, options,
case OPTION_HOOD_INTENSIVE_LEVEL: getOption(options, OPTION_FINISH_IN_RELATIVE).isPresent() ? OPTION_FINISH_IN_RELATIVE
String hoodIntensiveLevelValue = option.getValue(); : OPTION_REMAINING_PROGRAM_TIME,
if (hoodIntensiveLevelValue != null) { unit -> SECOND, UnDefType.UNDEF);
getThingChannel(CHANNEL_HOOD_INTENSIVE_LEVEL) setQuantityChannelFromOption(CHANNEL_ELAPSED_PROGRAM_TIME, options, OPTION_ELAPSED_PROGRAM_TIME, unit -> SECOND,
.ifPresent(channel -> updateState(channel.getUID(), new QuantityType<>(0, SECOND));
new StringType(mapStageStringType(hoodIntensiveLevelValue)))); setQuantityChannelFromOption(CHANNEL_PROGRAM_PROGRESS_STATE, options, OPTION_PROGRAM_PROGRESS, unit -> PERCENT,
} new QuantityType<>(0, PERCENT));
break; // When the program is not in ready state, the vario perfect option is not always provided by the API returning
case OPTION_HOOD_VENTING_LEVEL: // the options of the current active program. So in this case we avoid updating the channel (to the default
String hoodVentingLevel = option.getValue(); // state) by passing a null value as parameter.to setStringChannelFromOption.
if (hoodVentingLevel != null) { setStringChannelFromOption(CHANNEL_WASHER_VARIO_PERFECT, options, OPTION_WASHER_VARIO_PERFECT,
getThingChannel(CHANNEL_HOOD_VENTING_LEVEL) OPERATION_STATE_READY.equals(operationState)
.ifPresent(channel -> updateState(channel.getUID(), ? new StringType("LaundryCare.Common.EnumType.VarioPerfect.Off")
new StringType(mapStageStringType(hoodVentingLevel)))); : null);
} setStringChannelFromOption(CHANNEL_WASHER_RINSE_PLUS, options, OPTION_WASHER_RINSE_PLUS,
break; new StringType("LaundryCare.Washer.EnumType.RinsePlus.Off"));
case OPTION_SETPOINT_TEMPERATURE: setQuantityChannelFromOption(CHANNEL_PROGRAM_ENERGY, options, OPTION_WASHER_ENERGY_FORECAST, unit -> PERCENT,
getThingChannel(CHANNEL_SETPOINT_TEMPERATURE).ifPresent(channel -> updateState(channel.getUID(), UnDefType.UNDEF);
new QuantityType<>(option.getValueAsInt(), mapTemperature(option.getUnit())))); setQuantityChannelFromOption(CHANNEL_PROGRAM_WATER, options, OPTION_WASHER_WATER_FORECAST, unit -> PERCENT,
break; UnDefType.UNDEF);
case OPTION_DURATION:
getThingChannel(CHANNEL_DURATION).ifPresent(channel -> updateState(channel.getUID(),
new QuantityType<>(option.getValueAsInt(), SECOND)));
break;
case OPTION_FINISH_IN_RELATIVE:
case OPTION_REMAINING_PROGRAM_TIME:
getThingChannel(CHANNEL_REMAINING_PROGRAM_TIME_STATE)
.ifPresent(channel -> updateState(channel.getUID(),
new QuantityType<>(option.getValueAsInt(), SECOND)));
break;
case OPTION_ELAPSED_PROGRAM_TIME:
getThingChannel(CHANNEL_ELAPSED_PROGRAM_TIME).ifPresent(channel -> updateState(channel.getUID(),
new QuantityType<>(option.getValueAsInt(), SECOND)));
break;
case OPTION_PROGRAM_PROGRESS:
getThingChannel(CHANNEL_PROGRAM_PROGRESS_STATE)
.ifPresent(channel -> updateState(channel.getUID(),
new QuantityType<>(option.getValueAsInt(), PERCENT)));
break;
case OPTION_WASHER_IDOS_1_ACTIVE:
getThingChannel(CHANNEL_WASHER_IDOS1).ifPresent(
channel -> updateState(channel.getUID(), OnOffType.from(option.getValueAsBoolean())));
break;
case OPTION_WASHER_IDOS_2_ACTIVE:
getThingChannel(CHANNEL_WASHER_IDOS2).ifPresent(
channel -> updateState(channel.getUID(), OnOffType.from(option.getValueAsBoolean())));
break;
case OPTION_WASHER_VARIO_PERFECT:
getThingChannel(CHANNEL_WASHER_VARIO_PERFECT)
.ifPresent(channel -> updateState(channel.getUID(), new StringType(option.getValue())));
break;
case OPTION_WASHER_LESS_IRONING:
getThingChannel(CHANNEL_WASHER_LESS_IRONING).ifPresent(
channel -> updateState(channel.getUID(), OnOffType.from(option.getValueAsBoolean())));
break;
case OPTION_WASHER_PRE_WASH:
getThingChannel(CHANNEL_WASHER_PRE_WASH).ifPresent(
channel -> updateState(channel.getUID(), OnOffType.from(option.getValueAsBoolean())));
break;
case OPTION_WASHER_RINSE_PLUS:
getThingChannel(CHANNEL_WASHER_RINSE_PLUS)
.ifPresent(channel -> updateState(channel.getUID(), new StringType(option.getValue())));
break;
case OPTION_WASHER_SOAK:
getThingChannel(CHANNEL_WASHER_SOAK).ifPresent(
channel -> updateState(channel.getUID(), OnOffType.from(option.getValueAsBoolean())));
break;
case OPTION_WASHER_ENERGY_FORECAST:
getThingChannel(CHANNEL_PROGRAM_ENERGY).ifPresent(channel -> updateState(channel.getUID(),
new QuantityType<>(option.getValueAsInt(), PERCENT)));
break;
case OPTION_WASHER_WATER_FORECAST:
getThingChannel(CHANNEL_PROGRAM_WATER).ifPresent(channel -> updateState(channel.getUID(),
new QuantityType<>(option.getValueAsInt(), PERCENT)));
break;
}
}
});
} }
protected String convertWasherTemperature(String value) { protected String convertWasherTemperature(String value) {