Skip to content

Commit

Permalink
[homeconnect] Catch exception when appropriate (openhab#10929)
Browse files Browse the repository at this point in the history
* [homeconnect] Catch exception when appropriate

Fix openhab#10904

Signed-off-by: Laurent Garnier <lg.hc@free.fr>
  • Loading branch information
lolodomo committed Jul 11, 2021
1 parent 9b3c136 commit fcae878
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,7 @@ public boolean isLocalControlActive(String haId)
* 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
Expand All @@ -562,7 +562,7 @@ public boolean isLocalControlActive(String haId)
* 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
Expand Down Expand Up @@ -627,7 +627,17 @@ public List<AvailableProgram> getAvailablePrograms(String haId)
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 {
Expand All @@ -644,8 +654,7 @@ public List<AvailableProgramOption> getProgramOptions(String haId, String progra
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());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1026,7 +1026,6 @@ protected ChannelUpdateHandler defaultAmbientLightChannelUpdateHandler() {
updateState(channel.getUID(), UnDefType.UNDEF);
}
});

}
return OnOffType.from(enabled);
} else {
Expand Down Expand Up @@ -1458,54 +1457,66 @@ protected String convertWasherSpinSpeed(String value) {
}

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())));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ protected void updateSelectedProgramStateDescription() {
try {
List<AvailableProgramOption> availableProgramOptions = apiClient.get()
.getProgramOptions(getThingHaId(), PROGRAM_HOOD_VENTING);
if (availableProgramOptions.isEmpty()) {
if (availableProgramOptions == null || availableProgramOptions.isEmpty()) {
throw new CommunicationException("Program " + PROGRAM_HOOD_VENTING + " is unsupported");
}
availableProgramOptions.forEach(option -> {
Expand Down

0 comments on commit fcae878

Please sign in to comment.