diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/connection/HueBridge.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/connection/HueBridge.java index fd82e49c5..58536ccd0 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/connection/HueBridge.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/connection/HueBridge.java @@ -72,6 +72,7 @@ import org.openhab.binding.hue.internal.dto.SuccessResponse; import org.openhab.binding.hue.internal.dto.Util; import org.openhab.binding.hue.internal.exceptions.ApiException; import org.openhab.binding.hue.internal.exceptions.DeviceOffException; +import org.openhab.binding.hue.internal.exceptions.EmptyResponseException; import org.openhab.binding.hue.internal.exceptions.EntityNotAvailableException; import org.openhab.binding.hue.internal.exceptions.GroupTableFullException; import org.openhab.binding.hue.internal.exceptions.InvalidCommandException; @@ -252,6 +253,10 @@ public class HueBridge { handleErrors(result); + if (result.body.isBlank()) { + throw new EmptyResponseException("GET request 'lights' returned an unexpected empty reponse"); + } + Map lightMap = safeFromJson(result.body, gsonType); List lights = new ArrayList<>(); lightMap.forEach((id, light) -> { @@ -275,6 +280,10 @@ public class HueBridge { handleErrors(result); + if (result.body.isBlank()) { + throw new EmptyResponseException("GET request 'sensors' returned an unexpected empty reponse"); + } + Map sensorMap = safeFromJson(result.body, FullSensor.GSON_TYPE); List sensors = new ArrayList<>(); sensorMap.forEach((id, sensor) -> { @@ -300,6 +309,10 @@ public class HueBridge { handleErrors(result); + if (result.body.isBlank()) { + throw new EmptyResponseException("GET request 'lights/new' returned an unexpected empty reponse"); + } + String lastScan = safeFromJson(result.body, NewLightsResponse.class).lastscan; switch (lastScan) { @@ -362,6 +375,11 @@ public class HueBridge { handleErrors(result); + if (result.body.isBlank()) { + throw new EmptyResponseException( + "GET request 'lights/" + enc(light.getId()) + "' returned an unexpected empty reponse"); + } + FullHueObject fullLight = safeFromJson(result.body, FullLight.class); fullLight.setId(light.getId()); return fullLight; @@ -386,6 +404,11 @@ public class HueBridge { handleErrors(result); + if (result.body.isBlank()) { + throw new EmptyResponseException( + "PUT request 'lights/" + enc(light.getId()) + "' returned an unexpected empty reponse"); + } + List entries = safeFromJson(result.body, SuccessResponse.GSON_TYPE); SuccessResponse response = entries.get(0); @@ -469,6 +492,10 @@ public class HueBridge { handleErrors(result); + if (result.body.isBlank()) { + throw new EmptyResponseException("GET request 'groups' returned an unexpected empty reponse"); + } + Map groupMap = safeFromJson(result.body, FullGroup.GSON_TYPE); List groups = new ArrayList<>(); if (groupMap.get("0") == null) { @@ -510,6 +537,10 @@ public class HueBridge { handleErrors(result); + if (result.body.isBlank()) { + throw new EmptyResponseException("POST request 'groups' returned an unexpected empty reponse"); + } + List entries = safeFromJson(result.body, SuccessResponse.GSON_TYPE); SuccessResponse response = entries.get(0); @@ -540,6 +571,10 @@ public class HueBridge { handleErrors(result); + if (result.body.isBlank()) { + throw new EmptyResponseException("POST request 'groups' returned an unexpected empty reponse"); + } + List entries = safeFromJson(result.body, SuccessResponse.GSON_TYPE); SuccessResponse response = entries.get(0); @@ -565,6 +600,11 @@ public class HueBridge { handleErrors(result); + if (result.body.isBlank()) { + throw new EmptyResponseException( + "GET request 'groups/" + enc(group.getId()) + "' returned an unexpected empty reponse"); + } + FullGroup fullGroup = safeFromJson(result.body, FullGroup.class); fullGroup.setId(group.getId()); return fullGroup; @@ -593,6 +633,11 @@ public class HueBridge { handleErrors(result); + if (result.body.isBlank()) { + throw new EmptyResponseException( + "PUT request 'groups/" + enc(group.getId()) + "' returned an unexpected empty reponse"); + } + List entries = safeFromJson(result.body, SuccessResponse.GSON_TYPE); SuccessResponse response = entries.get(0); @@ -648,6 +693,11 @@ public class HueBridge { handleErrors(result); + if (result.body.isBlank()) { + throw new EmptyResponseException( + "PUT request 'groups/" + enc(group.getId()) + "' returned an unexpected empty reponse"); + } + List entries = safeFromJson(result.body, SuccessResponse.GSON_TYPE); SuccessResponse response = entries.get(0); @@ -707,6 +757,10 @@ public class HueBridge { handleErrors(result); + if (result.body.isBlank()) { + throw new EmptyResponseException("GET request 'schedules' returned an unexpected empty reponse"); + } + Map scheduleMap = safeFromJson(result.body, Schedule.GSON_TYPE); List schedules = new ArrayList<>(); scheduleMap.forEach((id, schedule) -> { @@ -761,6 +815,10 @@ public class HueBridge { handleErrors(result); + if (result.body.isBlank()) { + throw new EmptyResponseException("GET request 'scenes' returned an unexpected empty reponse"); + } + Map sceneMap = safeFromJson(result.body, Scene.GSON_TYPE); return sceneMap.entrySet().stream()// .map(e -> { @@ -841,6 +899,10 @@ public class HueBridge { handleErrors(result); + if (result.body.isBlank()) { + throw new EmptyResponseException("POST request (link) returned an unexpected empty reponse"); + } + List entries = safeFromJson(result.body, SuccessResponse.GSON_TYPE); SuccessResponse response = entries.get(0); @@ -865,6 +927,10 @@ public class HueBridge { handleErrors(result); + if (result.body.isBlank()) { + throw new EmptyResponseException("GET request 'config' returned an unexpected empty reponse"); + } + return safeFromJson(result.body, Config.class); } @@ -912,6 +978,10 @@ public class HueBridge { handleErrors(result); + if (result.body.isBlank()) { + throw new EmptyResponseException("GET request (getFullConfig) returned an unexpected empty reponse"); + } + FullConfig fullConfig = gson.fromJson(result.body, FullConfig.class); return Objects.requireNonNull(fullConfig); } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/exceptions/EmptyResponseException.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/exceptions/EmptyResponseException.java new file mode 100644 index 000000000..7316cf291 --- /dev/null +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/exceptions/EmptyResponseException.java @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.hue.internal.exceptions; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * Thrown when API is returning an unexpected empty response. + * + * @author Laurent Garnier - Initial contribution + */ +@SuppressWarnings("serial") +@NonNullByDefault +public class EmptyResponseException extends ApiException { + public EmptyResponseException() { + } + + public EmptyResponseException(String message) { + super(message); + } +} diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueBridgeHandler.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueBridgeHandler.java index efda66507..7893572ee 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueBridgeHandler.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueBridgeHandler.java @@ -49,6 +49,7 @@ import org.openhab.binding.hue.internal.dto.State; import org.openhab.binding.hue.internal.dto.StateUpdate; import org.openhab.binding.hue.internal.exceptions.ApiException; import org.openhab.binding.hue.internal.exceptions.DeviceOffException; +import org.openhab.binding.hue.internal.exceptions.EmptyResponseException; import org.openhab.binding.hue.internal.exceptions.EntityNotAvailableException; import org.openhab.binding.hue.internal.exceptions.LinkButtonException; import org.openhab.binding.hue.internal.exceptions.UnauthorizedException; @@ -150,6 +151,9 @@ public class HueBridgeHandler extends ConfigStatusBridgeHandler implements HueCl lastBridgeConnectionState = false; onConnectionLost(); } + } catch (EmptyResponseException e) { + // Unexpected empty response is ignored + logger.debug("{}", e.getMessage()); } catch (ApiException | CommunicationException | IOException e) { if (hueBridge != null && lastBridgeConnectionState) { logger.debug("Connection to Hue Bridge {} lost: {}", hueBridge.getIPAddress(), e.getMessage(), e);