diff --git a/bundles/org.openhab.binding.homeconnect/src/main/java/org/openhab/binding/homeconnect/internal/client/HomeConnectApiClient.java b/bundles/org.openhab.binding.homeconnect/src/main/java/org/openhab/binding/homeconnect/internal/client/HomeConnectApiClient.java index c72a1cd0d..feba2087b 100644 --- a/bundles/org.openhab.binding.homeconnect/src/main/java/org/openhab/binding/homeconnect/internal/client/HomeConnectApiClient.java +++ b/bundles/org.openhab.binding.homeconnect/src/main/java/org/openhab/binding/homeconnect/internal/client/HomeConnectApiClient.java @@ -79,7 +79,6 @@ public class HomeConnectApiClient { private final Logger logger = LoggerFactory.getLogger(HomeConnectApiClient.class); private final HttpClient client; private final String apiUrl; - private final Map> availableProgramOptionsCache; private final Map> programsCache; private final OAuthClientService oAuthClientService; private final CircularQueue communicationQueue; @@ -91,7 +90,6 @@ public class HomeConnectApiClient { this.oAuthClientService = oAuthClientService; this.apiBridgeConfiguration = apiBridgeConfiguration; - availableProgramOptionsCache = new ConcurrentHashMap<>(); programsCache = new ConcurrentHashMap<>(); apiUrl = simulated ? API_SIMULATOR_BASE_URL : API_BASE_URL; communicationQueue = new CircularQueue<>(COMMUNICATION_QUEUE_SIZE); @@ -631,12 +629,6 @@ public class HomeConnectApiClient { public List getProgramOptions(String haId, String programKey) throws CommunicationException, AuthorizationException, ApplianceOfflineException { - if (availableProgramOptionsCache.containsKey(programKey)) { - logger.debug("Returning cached options for '{}'.", programKey); - List availableProgramOptions = availableProgramOptionsCache.get(programKey); - return availableProgramOptions != null ? availableProgramOptions : Collections.emptyList(); - } - Request request = createRequest(HttpMethod.GET, BASE_PATH + haId + "/programs/available/" + programKey); try { ContentResponse response = sendRequest(request, apiBridgeConfiguration.getClientId()); @@ -652,11 +644,8 @@ public class HomeConnectApiClient { responseBody == null ? "" : responseBody); } - List availableProgramOptions = response.getStatus() == HttpStatus.OK_200 - ? mapToAvailableProgramOption(responseBody, haId) + return response.getStatus() == HttpStatus.OK_200 ? mapToAvailableProgramOption(responseBody, haId) : List.of(); - availableProgramOptionsCache.put(programKey, availableProgramOptions); - return availableProgramOptions; } catch (InterruptedException | TimeoutException | ExecutionException e) { logger.warn("Failed to get program options! haId={}, programKey={}, error={}", haId, programKey, e.getMessage()); 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 344bf511e..f042a56d0 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 @@ -21,6 +21,7 @@ import static org.openhab.core.library.unit.Units.*; import static org.openhab.core.thing.ThingStatus.*; import java.time.Duration; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; @@ -96,6 +97,7 @@ public abstract class AbstractHomeConnectThingHandler extends BaseThingHandler i private @Nullable ScheduledFuture reinitializationFuture2; private @Nullable ScheduledFuture reinitializationFuture3; private boolean ignoreEventSourceClosedEvent; + private @Nullable String programOptionsDelayedUpdate; private final ConcurrentHashMap eventHandlers; private final ConcurrentHashMap channelUpdateHandlers; @@ -103,6 +105,7 @@ public abstract class AbstractHomeConnectThingHandler extends BaseThingHandler i private final ExpiringStateMap expiringStateMap; private final AtomicBoolean accessible; private final Logger logger = LoggerFactory.getLogger(AbstractHomeConnectThingHandler.class); + private final Map> availableProgramOptionsCache; public AbstractHomeConnectThingHandler(Thing thing, HomeConnectDynamicStateDescriptionProvider dynamicStateDescriptionProvider) { @@ -112,6 +115,7 @@ public abstract class AbstractHomeConnectThingHandler extends BaseThingHandler i this.dynamicStateDescriptionProvider = dynamicStateDescriptionProvider; expiringStateMap = new ExpiringStateMap(Duration.ofSeconds(CACHE_TTL_SEC)); accessible = new AtomicBoolean(false); + availableProgramOptionsCache = new ConcurrentHashMap<>(); configureEventHandlers(eventHandlers); configureChannelUpdateHandlers(channelUpdateHandlers); @@ -855,15 +859,41 @@ public abstract class AbstractHomeConnectThingHandler extends BaseThingHandler i }); } + protected EventHandler updateRemoteControlActiveAndProgramOptionsStateEventHandler() { + return event -> { + defaultBooleanEventHandler(CHANNEL_REMOTE_CONTROL_ACTIVE_STATE).handle(event); + + // update available program options if update was previously delayed and remote control is enabled + try { + String programKey = programOptionsDelayedUpdate; + if (programKey != null && Boolean.parseBoolean(event.getValue())) { + logger.debug("Delayed update of options for program {}", programKey); + updateProgramOptionsStateDescriptions(programKey, null); + programOptionsDelayedUpdate = null; + } + } catch (CommunicationException | ApplianceOfflineException | AuthorizationException e) { + logger.debug("Could not update program options. {}", e.getMessage()); + } + }; + } + protected EventHandler updateProgramOptionsAndSelectedProgramStateEventHandler() { return event -> { defaultSelectedProgramStateEventHandler().handle(event); // update available program options try { + Optional apiClient = getApiClient(); String programKey = event.getValue(); - if (programKey != null) { - updateProgramOptionsStateDescriptions(programKey, null); + if (apiClient.isPresent() && programKey != null) { + // Delay the update if options are not yet cached and remote control is disabled + if (availableProgramOptionsCache.get(programKey) == null + && !apiClient.get().isRemoteControlActive(getThingHaId())) { + logger.debug("Delay update of options for program {}", programKey); + programOptionsDelayedUpdate = programKey; + } else { + updateProgramOptionsStateDescriptions(programKey, null); + } } } catch (CommunicationException | ApplianceOfflineException | AuthorizationException e) { logger.debug("Could not update program options. {}", e.getMessage()); @@ -1322,8 +1352,16 @@ public abstract class AbstractHomeConnectThingHandler extends BaseThingHandler i throws CommunicationException, AuthorizationException, ApplianceOfflineException { Optional apiClient = getApiClient(); if (apiClient.isPresent()) { - List availableProgramOptions = apiClient.get().getProgramOptions(getThingHaId(), - programKey); + List availableProgramOptions; + if (availableProgramOptionsCache.containsKey(programKey)) { + logger.debug("Returning cached options for '{}'.", programKey); + availableProgramOptions = availableProgramOptionsCache.get(programKey); + availableProgramOptions = availableProgramOptions != null ? availableProgramOptions + : Collections.emptyList(); + } else { + availableProgramOptions = apiClient.get().getProgramOptions(getThingHaId(), programKey); + availableProgramOptionsCache.put(programKey, availableProgramOptions); + } Optional channelSpinSpeed = getThingChannel(CHANNEL_WASHER_SPIN_SPEED); Optional channelTemperature = getThingChannel(CHANNEL_WASHER_TEMPERATURE); diff --git a/bundles/org.openhab.binding.homeconnect/src/main/java/org/openhab/binding/homeconnect/internal/handler/HomeConnectDryerHandler.java b/bundles/org.openhab.binding.homeconnect/src/main/java/org/openhab/binding/homeconnect/internal/handler/HomeConnectDryerHandler.java index 2ec9c1697..cab3ad3e3 100644 --- a/bundles/org.openhab.binding.homeconnect/src/main/java/org/openhab/binding/homeconnect/internal/handler/HomeConnectDryerHandler.java +++ b/bundles/org.openhab.binding.homeconnect/src/main/java/org/openhab/binding/homeconnect/internal/handler/HomeConnectDryerHandler.java @@ -66,7 +66,7 @@ public class HomeConnectDryerHandler extends AbstractHomeConnectThingHandler { protected void configureEventHandlers(Map handlers) { // register default event handlers handlers.put(EVENT_DOOR_STATE, defaultDoorStateEventHandler()); - handlers.put(EVENT_REMOTE_CONTROL_ACTIVE, defaultBooleanEventHandler(CHANNEL_REMOTE_CONTROL_ACTIVE_STATE)); + handlers.put(EVENT_REMOTE_CONTROL_ACTIVE, updateRemoteControlActiveAndProgramOptionsStateEventHandler()); handlers.put(EVENT_REMOTE_CONTROL_START_ALLOWED, defaultBooleanEventHandler(CHANNEL_REMOTE_START_ALLOWANCE_STATE)); handlers.put(EVENT_FINISH_IN_RELATIVE, defaultRemainingProgramTimeEventHandler()); diff --git a/bundles/org.openhab.binding.homeconnect/src/main/java/org/openhab/binding/homeconnect/internal/handler/HomeConnectWasherDryerHandler.java b/bundles/org.openhab.binding.homeconnect/src/main/java/org/openhab/binding/homeconnect/internal/handler/HomeConnectWasherDryerHandler.java index 24a0afec9..9d1d97d2a 100644 --- a/bundles/org.openhab.binding.homeconnect/src/main/java/org/openhab/binding/homeconnect/internal/handler/HomeConnectWasherDryerHandler.java +++ b/bundles/org.openhab.binding.homeconnect/src/main/java/org/openhab/binding/homeconnect/internal/handler/HomeConnectWasherDryerHandler.java @@ -85,7 +85,7 @@ public class HomeConnectWasherDryerHandler extends AbstractHomeConnectThingHandl protected void configureEventHandlers(Map handlers) { // register default event handlers handlers.put(EVENT_DOOR_STATE, defaultDoorStateEventHandler()); - handlers.put(EVENT_REMOTE_CONTROL_ACTIVE, defaultBooleanEventHandler(CHANNEL_REMOTE_CONTROL_ACTIVE_STATE)); + handlers.put(EVENT_REMOTE_CONTROL_ACTIVE, updateRemoteControlActiveAndProgramOptionsStateEventHandler()); handlers.put(EVENT_REMOTE_CONTROL_START_ALLOWED, defaultBooleanEventHandler(CHANNEL_REMOTE_START_ALLOWANCE_STATE)); handlers.put(EVENT_FINISH_IN_RELATIVE, defaultRemainingProgramTimeEventHandler()); 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 3224d4a35..964d9bcad 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 @@ -85,7 +85,7 @@ public class HomeConnectWasherHandler extends AbstractHomeConnectThingHandler { protected void configureEventHandlers(Map handlers) { // register default event handlers handlers.put(EVENT_DOOR_STATE, defaultDoorStateEventHandler()); - handlers.put(EVENT_REMOTE_CONTROL_ACTIVE, defaultBooleanEventHandler(CHANNEL_REMOTE_CONTROL_ACTIVE_STATE)); + handlers.put(EVENT_REMOTE_CONTROL_ACTIVE, updateRemoteControlActiveAndProgramOptionsStateEventHandler()); handlers.put(EVENT_REMOTE_CONTROL_START_ALLOWED, defaultBooleanEventHandler(CHANNEL_REMOTE_START_ALLOWANCE_STATE)); handlers.put(EVENT_FINISH_IN_RELATIVE, defaultRemainingProgramTimeEventHandler());