mirror of
https://github.com/danieldemus/openhab-addons
synced 2026-07-29 12:34:21 +02:00
[roku] Fix jobs not starting if initial connection fails (#20214)
* Fix jobs not starting if initial connection fails Signed-off-by: Michael Lobstein <michael.lobstein@gmail.com>
This commit is contained in:
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2026 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.roku.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link RokuUnknownHostException} extends RokuHttpException
|
||||
*
|
||||
* @author Michael Lobstein - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class RokuUnknownHostException extends RokuHttpException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public RokuUnknownHostException(String errorMessage, Throwable t) {
|
||||
super(errorMessage, t);
|
||||
}
|
||||
|
||||
public RokuUnknownHostException(String errorMessage) {
|
||||
super(errorMessage);
|
||||
}
|
||||
}
|
||||
+26
-2
@@ -13,6 +13,8 @@
|
||||
package org.openhab.binding.roku.internal.communication;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@@ -29,6 +31,7 @@ import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.openhab.binding.roku.internal.RokuHttpException;
|
||||
import org.openhab.binding.roku.internal.RokuLimitedModeException;
|
||||
import org.openhab.binding.roku.internal.RokuUnknownHostException;
|
||||
import org.openhab.binding.roku.internal.dto.ActiveApp;
|
||||
import org.openhab.binding.roku.internal.dto.Apps;
|
||||
import org.openhab.binding.roku.internal.dto.Apps.App;
|
||||
@@ -37,6 +40,7 @@ import org.openhab.binding.roku.internal.dto.Player;
|
||||
import org.openhab.binding.roku.internal.dto.TvChannel;
|
||||
import org.openhab.binding.roku.internal.dto.TvChannels;
|
||||
import org.openhab.binding.roku.internal.dto.TvChannels.Channel;
|
||||
import org.openhab.core.net.NetUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -53,6 +57,7 @@ public class RokuCommunicator {
|
||||
private final Logger logger = LoggerFactory.getLogger(RokuCommunicator.class);
|
||||
private final HttpClient httpClient;
|
||||
|
||||
private final String host;
|
||||
private final String urlKeyPress;
|
||||
private final String urlLaunchApp;
|
||||
private final String urlLaunchTvChannel;
|
||||
@@ -65,6 +70,7 @@ public class RokuCommunicator {
|
||||
|
||||
public RokuCommunicator(HttpClient httpClient, String host, int port) {
|
||||
this.httpClient = httpClient;
|
||||
this.host = host;
|
||||
|
||||
final String baseUrl = "http://" + host + ":" + port;
|
||||
urlKeyPress = baseUrl + "/keypress/";
|
||||
@@ -285,7 +291,7 @@ public class RokuCommunicator {
|
||||
*/
|
||||
private String getCommand(String url) throws RokuHttpException {
|
||||
try {
|
||||
final String response = httpClient.newRequest(url).method(HttpMethod.GET)
|
||||
final String response = httpClient.newRequest(resolveHostName(url)).method(HttpMethod.GET)
|
||||
.timeout(REQUEST_TIMEOUT, TimeUnit.MILLISECONDS).send().getContentAsString();
|
||||
if (response != null && response.contains(LIMITED_MODE_RESPONSE)) {
|
||||
throw new RokuLimitedModeException(url + ": " + response);
|
||||
@@ -308,7 +314,8 @@ public class RokuCommunicator {
|
||||
private void postCommand(String url) throws RokuHttpException {
|
||||
try {
|
||||
logger.trace("Sending POST command: {}", url);
|
||||
httpClient.POST(url).method(HttpMethod.POST).timeout(REQUEST_TIMEOUT, TimeUnit.MILLISECONDS).send();
|
||||
httpClient.POST(resolveHostName(url)).method(HttpMethod.POST)
|
||||
.timeout(REQUEST_TIMEOUT, TimeUnit.MILLISECONDS).send();
|
||||
} catch (TimeoutException | ExecutionException e) {
|
||||
throw new RokuHttpException("Error executing POST command, URL: " + url, e);
|
||||
} catch (InterruptedException e) {
|
||||
@@ -316,4 +323,21 @@ public class RokuCommunicator {
|
||||
throw new RokuHttpException("InterruptedException executing POST command for URL: " + url, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the host name with the resolved IP address (if required) to use for the HTTP request.
|
||||
* Because if the host name was to be used, a Host header with the IP would be required in the request
|
||||
*/
|
||||
private String resolveHostName(String url) throws RokuUnknownHostException {
|
||||
if (NetUtil.isValidIPConfig(host)) {
|
||||
return url;
|
||||
} else {
|
||||
try {
|
||||
return url.replaceAll("(http:\\/\\/)([^:\\/]+)(:(\\d+)(\\/.*))",
|
||||
"$1" + InetAddress.getByName(host).getHostAddress() + "$3");
|
||||
} catch (UnknownHostException e) {
|
||||
throw new RokuUnknownHostException("UnknownHostException: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+25
-37
@@ -15,8 +15,6 @@ package org.openhab.binding.roku.internal.handler;
|
||||
import static org.openhab.binding.roku.internal.RokuBindingConstants.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -32,6 +30,7 @@ import org.openhab.binding.roku.internal.RokuConfiguration;
|
||||
import org.openhab.binding.roku.internal.RokuHttpException;
|
||||
import org.openhab.binding.roku.internal.RokuLimitedModeException;
|
||||
import org.openhab.binding.roku.internal.RokuStateDescriptionOptionProvider;
|
||||
import org.openhab.binding.roku.internal.RokuUnknownHostException;
|
||||
import org.openhab.binding.roku.internal.communication.RokuCommunicator;
|
||||
import org.openhab.binding.roku.internal.dto.Apps.App;
|
||||
import org.openhab.binding.roku.internal.dto.DeviceInfo;
|
||||
@@ -45,7 +44,6 @@ import org.openhab.core.library.types.PercentType;
|
||||
import org.openhab.core.library.types.PlayPauseType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.net.NetUtil;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
@@ -80,6 +78,7 @@ public class RokuHandler extends BaseThingHandler {
|
||||
private RokuCommunicator communicator;
|
||||
private DeviceInfo deviceInfo = new DeviceInfo();
|
||||
private int refreshInterval = DEFAULT_REFRESH_PERIOD_SEC;
|
||||
private boolean deviceInfoLoaded = false;
|
||||
private boolean tvActive = false;
|
||||
private int limitedMode = -1;
|
||||
private Map<String, String> appMap = new HashMap<>();
|
||||
@@ -102,8 +101,10 @@ public class RokuHandler extends BaseThingHandler {
|
||||
|
||||
final @Nullable String host = config.hostName;
|
||||
|
||||
if (host == null || EMPTY.equals(host)) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Host Name must be specified");
|
||||
if (host != null && !host.isBlank()) {
|
||||
this.communicator = new RokuCommunicator(httpClient, host, config.port);
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Host name must be specified");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -113,37 +114,8 @@ public class RokuHandler extends BaseThingHandler {
|
||||
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
|
||||
scheduler.execute(() -> {
|
||||
try {
|
||||
String resolvedHost = host;
|
||||
|
||||
if (!NetUtil.isValidIPConfig(host)) {
|
||||
resolvedHost = InetAddress.getByName(host).getHostAddress();
|
||||
}
|
||||
|
||||
this.communicator = new RokuCommunicator(httpClient, resolvedHost, config.port);
|
||||
|
||||
deviceInfo = communicator.getDeviceInfo();
|
||||
thing.setProperty(PROPERTY_MODEL_NAME, deviceInfo.getModelName());
|
||||
thing.setProperty(PROPERTY_MODEL_NUMBER, deviceInfo.getModelNumber());
|
||||
thing.setProperty(PROPERTY_DEVICE_LOCAITON, deviceInfo.getUserDeviceLocation());
|
||||
thing.setProperty(PROPERTY_SERIAL_NUMBER, deviceInfo.getSerialNumber());
|
||||
thing.setProperty(PROPERTY_DEVICE_ID, deviceInfo.getDeviceId());
|
||||
thing.setProperty(PROPERTY_SOFTWARE_VERSION, deviceInfo.getSoftwareVersion());
|
||||
thing.setProperty(PROPERTY_UUID, deviceInfo.getSerialNumber().toLowerCase());
|
||||
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
|
||||
startAutomaticRefresh();
|
||||
startAppListRefresh();
|
||||
} catch (UnknownHostException e) {
|
||||
logger.debug("Unable to resolve host", e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Cannot resolve hostname");
|
||||
} catch (RokuHttpException e) {
|
||||
logger.debug("Unable to retrieve Roku device-info. Exception: {}", e.getMessage(), e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Cannot connect to device");
|
||||
}
|
||||
});
|
||||
startAutomaticRefresh();
|
||||
startAppListRefresh();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -164,12 +136,23 @@ public class RokuHandler extends BaseThingHandler {
|
||||
synchronized (sequenceLock) {
|
||||
String activeAppId = ROKU_HOME_ID;
|
||||
try {
|
||||
if (thingTypeUID.equals(THING_TYPE_ROKU_TV)) {
|
||||
if (thingTypeUID.equals(THING_TYPE_ROKU_TV) || !deviceInfoLoaded) {
|
||||
try {
|
||||
deviceInfo = communicator.getDeviceInfo();
|
||||
String powerMode = deviceInfo.getPowerMode();
|
||||
updateState(POWER_STATE, new StringType(powerMode));
|
||||
updateState(POWER, OnOffType.from(POWER_ON.equalsIgnoreCase(powerMode)));
|
||||
|
||||
if (!deviceInfoLoaded) {
|
||||
thing.setProperty(PROPERTY_MODEL_NAME, deviceInfo.getModelName());
|
||||
thing.setProperty(PROPERTY_MODEL_NUMBER, deviceInfo.getModelNumber());
|
||||
thing.setProperty(PROPERTY_DEVICE_LOCAITON, deviceInfo.getUserDeviceLocation());
|
||||
thing.setProperty(PROPERTY_SERIAL_NUMBER, deviceInfo.getSerialNumber());
|
||||
thing.setProperty(PROPERTY_DEVICE_ID, deviceInfo.getDeviceId());
|
||||
thing.setProperty(PROPERTY_SOFTWARE_VERSION, deviceInfo.getSoftwareVersion());
|
||||
thing.setProperty(PROPERTY_UUID, deviceInfo.getSerialNumber().toLowerCase());
|
||||
deviceInfoLoaded = true;
|
||||
}
|
||||
} catch (RokuHttpException e) {
|
||||
logger.debug("Unable to retrieve Roku device-info.", e);
|
||||
}
|
||||
@@ -198,8 +181,13 @@ public class RokuHandler extends BaseThingHandler {
|
||||
}
|
||||
tvActive = false;
|
||||
}
|
||||
} catch (RokuUnknownHostException e) {
|
||||
logger.debug("Unable to resolve hostname: {}", e.getMessage(), e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Unable to resolve host name");
|
||||
return;
|
||||
} catch (RokuHttpException e) {
|
||||
logger.debug("Unable to retrieve Roku active-app info. Exception: {}", e.getMessage(), e);
|
||||
deviceInfoLoaded = false;
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user