[homeconnect] Delay update of state options when not accessible (#10784)

* [homeconnect] Delay update of state options when not accessible

Fix #10705

Signed-off-by: Laurent Garnier <lg.hc@free.fr>

* Review comment: parseBoolean

Signed-off-by: Laurent Garnier <lg.hc@free.fr>
pull/10792/head^2
lolodomo 2021-06-05 19:30:43 +02:00 committed by GitHub
parent 3dc7b9ed25
commit 17eb0d5d78
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 46 additions and 19 deletions

View File

@ -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<String, List<AvailableProgramOption>> availableProgramOptionsCache;
private final Map<String, List<AvailableProgram>> programsCache;
private final OAuthClientService oAuthClientService;
private final CircularQueue<ApiRequest> 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<AvailableProgramOption> getProgramOptions(String haId, String programKey)
throws CommunicationException, AuthorizationException, ApplianceOfflineException {
if (availableProgramOptionsCache.containsKey(programKey)) {
logger.debug("Returning cached options for '{}'.", programKey);
List<AvailableProgramOption> 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<AvailableProgramOption> 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());

View File

@ -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<String, EventHandler> eventHandlers;
private final ConcurrentHashMap<String, ChannelUpdateHandler> 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<String, List<AvailableProgramOption>> 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<HomeConnectApiClient> 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<HomeConnectApiClient> apiClient = getApiClient();
if (apiClient.isPresent()) {
List<AvailableProgramOption> availableProgramOptions = apiClient.get().getProgramOptions(getThingHaId(),
programKey);
List<AvailableProgramOption> 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<Channel> channelSpinSpeed = getThingChannel(CHANNEL_WASHER_SPIN_SPEED);
Optional<Channel> channelTemperature = getThingChannel(CHANNEL_WASHER_TEMPERATURE);

View File

@ -66,7 +66,7 @@ public class HomeConnectDryerHandler extends AbstractHomeConnectThingHandler {
protected void configureEventHandlers(Map<String, EventHandler> 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());

View File

@ -85,7 +85,7 @@ public class HomeConnectWasherDryerHandler extends AbstractHomeConnectThingHandl
protected void configureEventHandlers(Map<String, EventHandler> 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());

View File

@ -85,7 +85,7 @@ public class HomeConnectWasherHandler extends AbstractHomeConnectThingHandler {
protected void configureEventHandlers(Map<String, EventHandler> 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());