From ac46039e39b41069d6f71178768ce1f49e24eba0 Mon Sep 17 00:00:00 2001 From: Laurent Garnier Date: Tue, 6 Jul 2021 20:11:41 +0200 Subject: [PATCH] [homeconnect] Predefined temp / spin speeds options for unsupported washer programs Fix #10701 Signed-off-by: Laurent Garnier --- .../AbstractHomeConnectThingHandler.java | 28 ++++++- .../handler/HomeConnectWasherHandler.java | 73 +++++++++++++++++++ 2 files changed, 97 insertions(+), 4 deletions(-) diff --git a/bundles/org.openhab.binding.homeconnect/src/main/java/org/openhab/binding/homeconnect/internal/handler/AbstractHomeConnectThingHandler.java b/bundles/org.openhab.binding.homeconnect/src/main/java/org/openhab/binding/homeconnect/internal/handler/AbstractHomeConnectThingHandler.java index a12d73e3ff802..5b50e175cc6a3 100644 --- a/bundles/org.openhab.binding.homeconnect/src/main/java/org/openhab/binding/homeconnect/internal/handler/AbstractHomeConnectThingHandler.java +++ b/bundles/org.openhab.binding.homeconnect/src/main/java/org/openhab/binding/homeconnect/internal/handler/AbstractHomeConnectThingHandler.java @@ -106,6 +106,7 @@ public abstract class AbstractHomeConnectThingHandler extends BaseThingHandler i private final AtomicBoolean accessible; private final Logger logger = LoggerFactory.getLogger(AbstractHomeConnectThingHandler.class); private final Map> availableProgramOptionsCache; + private final Map> unsupportedProgramOptions; public AbstractHomeConnectThingHandler(Thing thing, HomeConnectDynamicStateDescriptionProvider dynamicStateDescriptionProvider) { @@ -116,9 +117,11 @@ public AbstractHomeConnectThingHandler(Thing thing, expiringStateMap = new ExpiringStateMap(Duration.ofSeconds(CACHE_TTL_SEC)); accessible = new AtomicBoolean(false); availableProgramOptionsCache = new ConcurrentHashMap<>(); + unsupportedProgramOptions = new ConcurrentHashMap<>(); configureEventHandlers(eventHandlers); configureChannelUpdateHandlers(channelUpdateHandlers); + configureUnsupportedProgramOptions(unsupportedProgramOptions); } @Override @@ -485,6 +488,9 @@ protected Optional getThingChannel(String channelId) { */ protected abstract void configureEventHandlers(final Map handlers); + protected void configureUnsupportedProgramOptions(final Map> programOptions) { + } + protected boolean isChannelLinkedToProgramOptionNotFullySupportedByApi() { return false; } @@ -1475,12 +1481,26 @@ protected void updateProgramOptionsStateDescriptions(String programKey) try { availableProgramOptions = apiClient.get().getProgramOptions(getThingHaId(), programKey); if (availableProgramOptions == null) { - // Program is unsupported, save in cache an empty list of options to avoid calling again the API - // for this program - availableProgramOptions = emptyList(); - logger.debug("Saving empty options in cache for unsupported program '{}'.", programKey); + // Program is unsupported, to avoid calling again the API for this program, save in cache either + // the predefined options provided by the binding if they exist, or an empty list of options + if (unsupportedProgramOptions.containsKey(programKey)) { + availableProgramOptions = unsupportedProgramOptions.get(programKey); + availableProgramOptions = availableProgramOptions != null ? availableProgramOptions + : emptyList(); + logger.debug("Saving predefined options in cache for unsupported program '{}'.", + programKey); + } else { + availableProgramOptions = emptyList(); + logger.debug("Saving empty options in cache for unsupported program '{}'.", programKey); + } availableProgramOptionsCache.put(programKey, availableProgramOptions); } else { + // If no options are returned by the API, using predefined options if available + if (availableProgramOptions.isEmpty() && unsupportedProgramOptions.containsKey(programKey)) { + availableProgramOptions = unsupportedProgramOptions.get(programKey); + availableProgramOptions = availableProgramOptions != null ? availableProgramOptions + : emptyList(); + } cacheToSet = true; } } catch (CommunicationException e) { diff --git a/bundles/org.openhab.binding.homeconnect/src/main/java/org/openhab/binding/homeconnect/internal/handler/HomeConnectWasherHandler.java b/bundles/org.openhab.binding.homeconnect/src/main/java/org/openhab/binding/homeconnect/internal/handler/HomeConnectWasherHandler.java index 4d62ede7d8749..4380a8e43356d 100644 --- a/bundles/org.openhab.binding.homeconnect/src/main/java/org/openhab/binding/homeconnect/internal/handler/HomeConnectWasherHandler.java +++ b/bundles/org.openhab.binding.homeconnect/src/main/java/org/openhab/binding/homeconnect/internal/handler/HomeConnectWasherHandler.java @@ -23,6 +23,7 @@ import org.openhab.binding.homeconnect.internal.client.exception.ApplianceOfflineException; import org.openhab.binding.homeconnect.internal.client.exception.AuthorizationException; import org.openhab.binding.homeconnect.internal.client.exception.CommunicationException; +import org.openhab.binding.homeconnect.internal.client.model.AvailableProgramOption; import org.openhab.binding.homeconnect.internal.type.HomeConnectDynamicStateDescriptionProvider; import org.openhab.core.library.types.StringType; import org.openhab.core.thing.ChannelUID; @@ -121,6 +122,78 @@ protected void configureEventHandlers(Map handlers) { event.getValue() == null ? UnDefType.UNDEF : new StringType(event.getValue())))); } + @Override + protected void configureUnsupportedProgramOptions(Map> programOptions) { + programOptions.put("LaundryCare.Washer.Program.Cotton.Eco4060", List.of( // + new AvailableProgramOption("LaundryCare.Washer.Option.Temperature", + List.of("LaundryCare.Washer.EnumType.Temperature.Auto")), + new AvailableProgramOption("LaundryCare.Washer.Option.SpinSpeed", // + List.of("LaundryCare.Washer.EnumType.SpinSpeed.RPM400", + "LaundryCare.Washer.EnumType.SpinSpeed.RPM600", + "LaundryCare.Washer.EnumType.SpinSpeed.RPM800", + "LaundryCare.Washer.EnumType.SpinSpeed.RPM1200", + "LaundryCare.Washer.EnumType.SpinSpeed.RPM1400")))); + + programOptions.put("LaundryCare.Washer.Program.Cotton.Colour", List.of( // + new AvailableProgramOption("LaundryCare.Washer.Option.Temperature", // + List.of("LaundryCare.Washer.EnumType.Temperature.Cold", + "LaundryCare.Washer.EnumType.Temperature.GC20", + "LaundryCare.Washer.EnumType.Temperature.GC30", + "LaundryCare.Washer.EnumType.Temperature.GC40", + "LaundryCare.Washer.EnumType.Temperature.GC60", + "LaundryCare.Washer.EnumType.Temperature.GC90")), + new AvailableProgramOption("LaundryCare.Washer.Option.SpinSpeed", // + List.of("LaundryCare.Washer.EnumType.SpinSpeed.RPM400", + "LaundryCare.Washer.EnumType.SpinSpeed.RPM600", + "LaundryCare.Washer.EnumType.SpinSpeed.RPM800", + "LaundryCare.Washer.EnumType.SpinSpeed.RPM1200", + "LaundryCare.Washer.EnumType.SpinSpeed.RPM1400")))); + + // Auto30 is provided by the API but with empty options, so we defined predefined values for this program + programOptions.put("LaundryCare.Washer.Program.Auto30", List.of( // + new AvailableProgramOption("LaundryCare.Washer.Option.Temperature", + List.of("LaundryCare.Washer.EnumType.Temperature.Auto")), + new AvailableProgramOption("LaundryCare.Washer.Option.SpinSpeed", + List.of("LaundryCare.Washer.EnumType.SpinSpeed.Auto")))); + + programOptions.put("LaundryCare.Washer.Program.Super153045.Super1530", List.of( // + new AvailableProgramOption("LaundryCare.Washer.Option.Temperature", // + List.of("LaundryCare.Washer.EnumType.Temperature.Cold", + "LaundryCare.Washer.EnumType.Temperature.GC20", + "LaundryCare.Washer.EnumType.Temperature.GC30", + "LaundryCare.Washer.EnumType.Temperature.GC40")), + new AvailableProgramOption("LaundryCare.Washer.Option.SpinSpeed", // + List.of("LaundryCare.Washer.EnumType.SpinSpeed.RPM400", + "LaundryCare.Washer.EnumType.SpinSpeed.RPM600", + "LaundryCare.Washer.EnumType.SpinSpeed.RPM800", + "LaundryCare.Washer.EnumType.SpinSpeed.RPM1200")))); + + programOptions.put("LaundryCare.Washer.Program.Rinse", List.of( // + new AvailableProgramOption("LaundryCare.Washer.Option.Temperature", List.of()), + new AvailableProgramOption("LaundryCare.Washer.Option.SpinSpeed", // + List.of("LaundryCare.Washer.EnumType.SpinSpeed.Off", + "LaundryCare.Washer.EnumType.SpinSpeed.RPM400", + "LaundryCare.Washer.EnumType.SpinSpeed.RPM600", + "LaundryCare.Washer.EnumType.SpinSpeed.RPM800", + "LaundryCare.Washer.EnumType.SpinSpeed.RPM1200", + "LaundryCare.Washer.EnumType.SpinSpeed.RPM1400")))); + + programOptions.put("LaundryCare.Washer.Program.Spin.SpinDrain", List.of( // + new AvailableProgramOption("LaundryCare.Washer.Option.Temperature", List.of()), + new AvailableProgramOption("LaundryCare.Washer.Option.SpinSpeed", // + List.of("LaundryCare.Washer.EnumType.SpinSpeed.Off", + "LaundryCare.Washer.EnumType.SpinSpeed.RPM400", + "LaundryCare.Washer.EnumType.SpinSpeed.RPM600", + "LaundryCare.Washer.EnumType.SpinSpeed.RPM800", + "LaundryCare.Washer.EnumType.SpinSpeed.RPM1200", + "LaundryCare.Washer.EnumType.SpinSpeed.RPM1400")))); + + programOptions.put("LaundryCare.Washer.Program.DrumClean", List.of( // + new AvailableProgramOption("LaundryCare.Washer.Option.Temperature", List.of()), + new AvailableProgramOption("LaundryCare.Washer.Option.SpinSpeed", + List.of("LaundryCare.Washer.EnumType.SpinSpeed.RPM1200")))); + } + @Override protected boolean isChannelLinkedToProgramOptionNotFullySupportedByApi() { return (getThingChannel(CHANNEL_WASHER_IDOS1).isPresent() && isLinked(CHANNEL_WASHER_IDOS1))