Skip to content

Commit

Permalink
fix(18062): 🛠️ work in progress ...
Browse files Browse the repository at this point in the history
Signed-off-by: Patrik Gfeller <[email protected]>
  • Loading branch information
pgfeller committed Jan 24, 2025
1 parent a1fd18e commit 116e8ce
Show file tree
Hide file tree
Showing 8 changed files with 200 additions and 135 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@
*/
@NonNullByDefault
public class HueSyncConstants {
public static class EXCEPTION_TYPES {
public static class CONNECTION {
public static final String UNAUTHORIZED_401 = "invalidLogin";
public static final String NOT_FOUND_404 = "notFound";
public static final String INTERNAL_SERVER_ERROR_500 = "deviceError";
}
}

public static class ENDPOINTS {
public static final String DEVICE = "device";
public static final String REGISTRATIONS = "registrations";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,25 +102,21 @@ public void updateAuthentication(String id, String token) {

// #region protected
protected @Nullable <T> T executeRequest(HttpMethod method, String endpoint, String payload,
@Nullable Class<T> type) {
@Nullable Class<T> type) throws Exception {
try {
return this.processedResponse(this.executeRequest(method, endpoint, payload), type);
} catch (ExecutionException e) {
this.handleExecutionException(e);
} catch (InterruptedException | TimeoutException e) {
this.logger.warn("{}", e.getMessage());
} catch (ExecutionException | InterruptedException | TimeoutException e) {
this.handleException(e);
}

return null;
}

protected @Nullable <T> T executeGetRequest(String endpoint, Class<T> type) {
protected @Nullable <T> T executeGetRequest(String endpoint, Class<T> type) throws Exception {
try {
return this.processedResponse(this.executeGetRequest(endpoint), type);
} catch (ExecutionException e) {
this.handleExecutionException(e);
} catch (InterruptedException | TimeoutException e) {
this.logger.warn("{}", e.getMessage());
} catch (ExecutionException | InterruptedException | TimeoutException e) {
this.handleException(e);
}

return null;
Expand Down Expand Up @@ -151,39 +147,40 @@ protected void dispose() {
// #endregion

// #region private
private @Nullable <T> T processedResponse(Response response, @Nullable Class<T> type) {
private @Nullable <T> T processedResponse(Response response, @Nullable Class<T> type)
throws HueSyncConnectionException {
int status = response.getStatus();
try {
/*
* 400 Invalid State: Registration in progress
*
* 401 Authentication failed: If credentials are missing or invalid, errors out. If
* credentials are missing, continues on to GET only the Configuration state when
* unauthenticated, to allow for device identification.
*
* 404 Invalid URI Path: Accessing URI path which is not supported
*
* 500 Internal: Internal errors like out of memory
*/
switch (status) {
case HttpStatus.OK_200 -> {
return (type != null && (response instanceof ContentResponse))
? this.deserialize(((ContentResponse) response).getContentAsString(), type)
: null;
}
case HttpStatus.BAD_REQUEST_400 -> this.logger.debug("registration in progress: no token received yet");
case HttpStatus.UNAUTHORIZED_401 -> {
this.authentication = Optional.empty();
throw new HueSyncConnectionException("@text/connection.invalid-login");
}
case HttpStatus.NOT_FOUND_404 -> this.logger.warn("invalid device URI or API endpoint");
case HttpStatus.INTERNAL_SERVER_ERROR_500 -> this.logger.warn("hue sync box server problem");
default -> this.logger.warn("unexpected HTTP status: {}", status);
String exceptionMessage;
/*
* 400 Invalid State: Registration in progress
*
* 401 Authentication failed: If credentials are missing or invalid, errors out. If
* credentials are missing, continues on to GET only the Configuration state when
* unauthenticated, to allow for device identification.
*
* 404 Invalid URI Path: Accessing URI path which is not supported
*
* 500 Internal: Internal errors like out of memory
*/
switch (status) {
case HttpStatus.OK_200 -> {
return (type != null && (response instanceof ContentResponse))
? this.deserialize(((ContentResponse) response).getContentAsString(), type)
: null;
}
case HttpStatus.BAD_REQUEST_400 -> {
this.logger.debug("registration in progress: no token received yet");
return null;
}
} catch (HueSyncConnectionException e) {
this.logger.warn("{}", e.getMessage());
case HttpStatus.UNAUTHORIZED_401 -> exceptionMessage = "@text/connection.invalid-login";
case HttpStatus.NOT_FOUND_404 -> exceptionMessage = "@text/connection.generic-error";
default -> exceptionMessage = "@text/connection.generic-error";
}
return null;

var exception = new HueSyncConnectionException(exceptionMessage);

this.logger.warn("{}", exception.getMessage());
throw (exception);
}

private @Nullable <T> T deserialize(String json, Class<T> type) {
Expand Down Expand Up @@ -226,12 +223,14 @@ private ContentResponse executeRequest(HttpMethod method, String endpoint, Strin
return request.send();
}

private void handleExecutionException(ExecutionException e) {
this.logger.warn("{}", e.getMessage());
private void handleException(Exception e) throws Exception {
this.logger.warn("Exception: {}, Client State: {}", e.getMessage(), this.httpClient.getState());

Throwable cause = e.getCause();
if (cause != null && cause instanceof HttpResponseException) {
processedResponse(((HttpResponseException) cause).getResponse(), null);
this.processedResponse(((HttpResponseException) cause).getResponse(), null);
} else {
throw e;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
import org.openhab.binding.huesync.internal.api.dto.registration.HueSyncRegistration;
import org.openhab.binding.huesync.internal.api.dto.registration.HueSyncRegistrationRequest;
import org.openhab.binding.huesync.internal.config.HueSyncConfiguration;
import org.openhab.binding.huesync.internal.exceptions.HueSyncConnectionException;
import org.openhab.binding.huesync.internal.types.HueSyncExceptionHandler;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.types.StringType;
Expand All @@ -55,11 +55,14 @@ public class HueSyncDeviceConnection {
private final Logger logger = LoggerFactory.getLogger(HueSyncDeviceConnection.class);

private final HueSyncConnection connection;
private final HueSyncExceptionHandler exceptionHandler;

private final Map<String, Consumer<Command>> deviceCommandExecutors = new HashMap<>();

public HueSyncDeviceConnection(HttpClient httpClient, HueSyncConfiguration configuration)
throws CertificateException, IOException, URISyntaxException {
public HueSyncDeviceConnection(HttpClient httpClient, HueSyncConfiguration configuration,
HueSyncExceptionHandler exceptionHandler) throws CertificateException, IOException, URISyntaxException {

this.exceptionHandler = exceptionHandler;
this.connection = new HueSyncConnection(httpClient, configuration.host, configuration.port);

registerCommandHandlers();
Expand Down Expand Up @@ -109,7 +112,11 @@ private void execute(String key, Command command) {

String json = String.format("{ \"%s\": %s }", key, value);

this.connection.executeRequest(HttpMethod.PUT, ENDPOINTS.EXECUTION, json, null);
try {
this.connection.executeRequest(HttpMethod.PUT, ENDPOINTS.EXECUTION, json, null);
} catch (Exception exception) {
exceptionHandler.handle(exception);
}
}

// #endregion
Expand All @@ -131,29 +138,29 @@ public void executeCommand(Channel channel, Command command) {
}
}

public @Nullable HueSyncDevice getDeviceInfo() {
public @Nullable HueSyncDevice getDeviceInfo() throws Exception {
return this.connection.executeGetRequest(ENDPOINTS.DEVICE, HueSyncDevice.class);
}

public @Nullable HueSyncDeviceDetailed getDetailedDeviceInfo() {
public @Nullable HueSyncDeviceDetailed getDetailedDeviceInfo() throws Exception {
return this.connection.isRegistered()
? this.connection.executeRequest(HttpMethod.GET, ENDPOINTS.DEVICE, "", HueSyncDeviceDetailed.class)
: null;
}

public @Nullable HueSyncHdmi getHdmiInfo() {
public @Nullable HueSyncHdmi getHdmiInfo() throws Exception {
return this.connection.isRegistered()
? this.connection.executeRequest(HttpMethod.GET, ENDPOINTS.HDMI, "", HueSyncHdmi.class)
: null;
}

public @Nullable HueSyncExecution getExecutionInfo() {
public @Nullable HueSyncExecution getExecutionInfo() throws Exception {
return this.connection.isRegistered()
? this.connection.executeRequest(HttpMethod.GET, ENDPOINTS.EXECUTION, "", HueSyncExecution.class)
: null;
}

public @Nullable HueSyncRegistration registerDevice(String id) throws HueSyncConnectionException {
public @Nullable HueSyncRegistration registerDevice(String id) throws Exception {
if (!id.isBlank()) {
try {
HueSyncRegistrationRequest dto = new HueSyncRegistrationRequest();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@
*/
package org.openhab.binding.huesync.internal.factory;

import java.io.IOException;
import java.net.URISyntaxException;
import java.security.cert.CertificateException;
import java.util.Collections;
import java.util.Set;

Expand All @@ -31,8 +28,6 @@
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* The {@link HueSyncHandlerFactory} is responsible for creating things and
Expand All @@ -44,9 +39,7 @@
@NonNullByDefault
@Component(configurationPid = "binding.huesync", service = ThingHandlerFactory.class)
public class HueSyncHandlerFactory extends BaseThingHandlerFactory {

private final HttpClientFactory httpClientFactory;
private final Logger logger = LoggerFactory.getLogger(HueSyncHandlerFactory.class);

@Activate
public HueSyncHandlerFactory(@Reference final HttpClientFactory httpClientFactory) throws Exception {
Expand All @@ -66,12 +59,7 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();

if (HueSyncConstants.THING_TYPE_UID.equals(thingTypeUID)) {
try {
return new HueSyncHandler(thing, this.httpClientFactory);
} catch (IOException | URISyntaxException | CertificateException e) {
this.logger.warn("It was not possible to create a handler for {}: {}", thingTypeUID.getId(),
e.getMessage());
}
return new HueSyncHandler(thing, this.httpClientFactory);
}

return null;
Expand Down
Loading

0 comments on commit 116e8ce

Please sign in to comment.