* Get active program of device.
*
* @param haId home appliance id
- * @return {@link Data} or null if there is no active program
+ * @return {@link Program} or null if there is no active program
* @throws CommunicationException API communication exception
* @throws AuthorizationException oAuth authorization exception
* @throws ApplianceOfflineException appliance is not connected to the cloud
* Get selected program of device.
*
* @param haId home appliance id
- * @return {@link Data} or null if there is no selected program
+ * @return {@link Program} or null if there is no selected program
* @throws CommunicationException API communication exception
* @throws AuthorizationException oAuth authorization exception
* @throws ApplianceOfflineException appliance is not connected to the cloud
return getAvailablePrograms(haId, BASE_PATH + haId + "/programs/available");
}
- public List<AvailableProgramOption> getProgramOptions(String haId, String programKey)
+ /**
+ * Get the available options of a program.
+ *
+ * @param haId home appliance id
+ * @param programKey program id
+ * @return list of {@link AvailableProgramOption} or null if the program is unsupported by the API
+ * @throws CommunicationException API communication exception
+ * @throws AuthorizationException oAuth authorization exception
+ * @throws ApplianceOfflineException appliance is not connected to the cloud
+ */
+ public @Nullable List<AvailableProgramOption> getProgramOptions(String haId, String programKey)
throws CommunicationException, AuthorizationException, ApplianceOfflineException {
Request request = createRequest(HttpMethod.GET, BASE_PATH + haId + "/programs/available/" + programKey);
try {
responseBody == null ? "" : responseBody);
}
- return response.getStatus() == HttpStatus.OK_200 ? mapToAvailableProgramOption(responseBody, haId)
- : List.of();
+ return response.getStatus() == HttpStatus.OK_200 ? mapToAvailableProgramOption(responseBody, haId) : null;
} catch (InterruptedException | TimeoutException | ExecutionException e) {
logger.warn("Failed to get program options! haId={}, programKey={}, error={}", haId, programKey,
e.getMessage());
updateState(channel.getUID(), UnDefType.UNDEF);
}
});
-
}
return OnOffType.from(enabled);
} else {
}
protected void updateProgramOptionsStateDescriptions(String programKey)
- throws CommunicationException, AuthorizationException, ApplianceOfflineException {
+ throws AuthorizationException, ApplianceOfflineException {
Optional<HomeConnectApiClient> apiClient = getApiClient();
if (apiClient.isPresent()) {
+ boolean cacheToSet = false;
List<AvailableProgramOption> availableProgramOptions;
if (availableProgramOptionsCache.containsKey(programKey)) {
- logger.debug("Returning cached options for '{}'.", programKey);
+ logger.debug("Returning cached options for program '{}'.", programKey);
availableProgramOptions = availableProgramOptionsCache.get(programKey);
availableProgramOptions = availableProgramOptions != null ? availableProgramOptions
: Collections.emptyList();
} else {
- availableProgramOptions = apiClient.get().getProgramOptions(getThingHaId(), programKey);
- availableProgramOptionsCache.put(programKey, availableProgramOptions);
+ // Depending on the current program operation state, the APi request could trigger a
+ // CommunicationException exception due to returned status code 409
+ 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);
+ availableProgramOptionsCache.put(programKey, availableProgramOptions);
+ } else {
+ cacheToSet = true;
+ }
+ } catch (CommunicationException e) {
+ availableProgramOptions = emptyList();
+ }
}
Optional<Channel> channelSpinSpeed = getThingChannel(CHANNEL_WASHER_SPIN_SPEED);
Optional<Channel> channelTemperature = getThingChannel(CHANNEL_WASHER_TEMPERATURE);
Optional<Channel> channelDryingTarget = getThingChannel(CHANNEL_DRYER_DRYING_TARGET);
- if (availableProgramOptions.isEmpty()) {
- channelSpinSpeed.ifPresent(
- channel -> dynamicStateDescriptionProvider.setStateOptions(channel.getUID(), emptyList()));
- channelTemperature.ifPresent(
- channel -> dynamicStateDescriptionProvider.setStateOptions(channel.getUID(), emptyList()));
- channelDryingTarget.ifPresent(
- channel -> dynamicStateDescriptionProvider.setStateOptions(channel.getUID(), emptyList()));
+ Optional<AvailableProgramOption> optionsSpinSpeed = availableProgramOptions.stream()
+ .filter(option -> OPTION_WASHER_SPIN_SPEED.equals(option.getKey())).findFirst();
+ Optional<AvailableProgramOption> optionsTemperature = availableProgramOptions.stream()
+ .filter(option -> OPTION_WASHER_TEMPERATURE.equals(option.getKey())).findFirst();
+ Optional<AvailableProgramOption> optionsDryingTarget = availableProgramOptions.stream()
+ .filter(option -> OPTION_DRYER_DRYING_TARGET.equals(option.getKey())).findFirst();
+
+ // Save options in cache only if we got options for all expected channels
+ if (cacheToSet && (!channelSpinSpeed.isPresent() || optionsSpinSpeed.isPresent())
+ && (!channelTemperature.isPresent() || optionsTemperature.isPresent())
+ && (!channelDryingTarget.isPresent() || optionsDryingTarget.isPresent())) {
+ logger.debug("Saving options in cache for program '{}'.", programKey);
+ availableProgramOptionsCache.put(programKey, availableProgramOptions);
}
- availableProgramOptions.forEach(option -> {
- switch (option.getKey()) {
- case OPTION_WASHER_SPIN_SPEED: {
- channelSpinSpeed
- .ifPresent(channel -> dynamicStateDescriptionProvider.setStateOptions(channel.getUID(),
- createStateOptions(option, this::convertWasherSpinSpeed)));
- break;
- }
- case OPTION_WASHER_TEMPERATURE: {
- channelTemperature
- .ifPresent(channel -> dynamicStateDescriptionProvider.setStateOptions(channel.getUID(),
- createStateOptions(option, this::convertWasherTemperature)));
- break;
- }
- case OPTION_DRYER_DRYING_TARGET: {
- channelDryingTarget.ifPresent(channel -> dynamicStateDescriptionProvider
- .setStateOptions(channel.getUID(), createStateOptions(option, this::mapStringType)));
- break;
- }
- }
- });
+ channelSpinSpeed.ifPresent(channel -> optionsSpinSpeed.ifPresentOrElse(
+ option -> dynamicStateDescriptionProvider.setStateOptions(channel.getUID(),
+ createStateOptions(option, this::convertWasherSpinSpeed)),
+ () -> dynamicStateDescriptionProvider.setStateOptions(channel.getUID(), emptyList())));
+ channelTemperature.ifPresent(channel -> optionsTemperature.ifPresentOrElse(
+ option -> dynamicStateDescriptionProvider.setStateOptions(channel.getUID(),
+ createStateOptions(option, this::convertWasherTemperature)),
+ () -> dynamicStateDescriptionProvider.setStateOptions(channel.getUID(), emptyList())));
+ channelDryingTarget.ifPresent(channel -> optionsDryingTarget.ifPresentOrElse(
+ option -> dynamicStateDescriptionProvider.setStateOptions(channel.getUID(),
+ createStateOptions(option, this::mapStringType)),
+ () -> dynamicStateDescriptionProvider.setStateOptions(channel.getUID(), emptyList())));
}
}