Skip to content

Commit

Permalink
Allow the onewire binding to retry failed connections.
Browse files Browse the repository at this point in the history
  • Loading branch information
9037568 committed Dec 8, 2016
1 parent 97a2c92 commit 7067461
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 89 deletions.
Expand Up @@ -112,7 +112,7 @@ public void updated(Dictionary<String, ?> pvConfig) throws ConfigurationExceptio

@Override
protected void internalReceiveCommand(String pvItemName, Command pvCommand) {
logger.debug("received command " + pvCommand.toString() + " for item " + pvItemName);
logger.debug("received command {} for item {}", pvCommand.toString(), pvItemName);

OneWireBindingConfig lvBindigConfig = getBindingConfig(pvItemName);

Expand All @@ -126,8 +126,7 @@ protected void internalReceiveCommand(String pvItemName, Command pvCommand) {
AbstractOneWireControlBindingConfig lvControlBindingConfig = (AbstractOneWireControlBindingConfig) lvBindigConfig;
lvControlBindingConfig.executeControl(this, pvCommand);
} else {
logger.debug("received command " + pvCommand.toString() + " for item " + pvItemName
+ " which is not writable or executable");
logger.debug("received command {} for item {} which is not writable or executable", pvCommand.toString(), pvItemName);
}
}

Expand Down Expand Up @@ -223,8 +222,7 @@ public void bindingChanged(BindingProvider pvProvider, String pvItemName) {
logger.warn("Couldn't add to OneWireUpdate scheduler", lvDeviceBindingConfig);
}
} else {
logger.debug("Didn't add to OneWireUpdate scheduler, because refresh is <= 0: "
+ lvDeviceBindingConfig.toString());
logger.debug("Didn't add to OneWireUpdate scheduler, because refresh is <= 0: {}", lvDeviceBindingConfig.toString());
}
}
}
Expand All @@ -242,7 +240,7 @@ public void bindingChanged(BindingProvider pvProvider, String pvItemName) {
public void devicePropertyWantsUpdate(OneWireDevicePropertyWantsUpdateEvent pvWantsUpdateEvent) {
String lvItemName = pvWantsUpdateEvent.getItemName();

logger.debug("Item " + lvItemName + " wants update!");
logger.debug("Item {} wants update!", lvItemName);

updateItemFromOneWire(lvItemName);
}
Expand Down Expand Up @@ -284,8 +282,7 @@ public void updateItemFromOneWire(String pvItemName) {
pvItemName);

if (pvBindingConfig == null) {
logger.error("no bindingConfig found for itemName=" + pvItemName
+ " cannot update! It will be removed from scheduler");
logger.error("no bindingConfig found for itemName={} cannot update! It will be removed from scheduler", pvItemName);
ivOneWireReaderScheduler.removeItem(pvItemName);
return;
}
Expand All @@ -298,7 +295,7 @@ public void updateItemFromOneWire(String pvItemName) {
if (lvItem != null) {
postUpdate(lvItem, lvNewType);
} else {
logger.error("There is no Item for ItemName=" + pvItemName);
logger.error("There is no Item for ItemName={}", pvItemName);
}
} else {
String lvLogText = "Set Item for itemName=" + pvItemName
Expand All @@ -323,8 +320,7 @@ private void postUpdate(Item pvItem, Type pvNewType) {
ivCacheItemStates.put(pvItem.getName(), lvNewState);
eventPublisher.postUpdate(pvItem.getName(), lvNewState);
} else {
logger.debug("didn't post update to eventPublisher, because state did not change for item "
+ pvItem.getName());
logger.debug("didn't post update to eventPublisher, because state did not change for item {}", pvItem.getName());
}
}
}
Expand Down
Expand Up @@ -42,7 +42,7 @@ public class OneWireBindingConfigFactory {
*/
public static OneWireBindingConfig createOneWireDeviceProperty(Item pvItem, String pvBindingConfig)
throws BindingConfigParseException {
logger.debug("createOneWireDeviceProperty: " + pvItem.getName() + " - bindingConfig:" + pvBindingConfig);
logger.debug("createOneWireDeviceProperty: {} - bindingConfig:{}", pvItem.getName(), pvBindingConfig);

OneWireBindingConfig lvNewBindingConfig = null;
if (OneWireClearCacheControlBindingConfig.isBindingConfigToCreate(pvItem, pvBindingConfig)) {
Expand All @@ -63,7 +63,7 @@ public static OneWireBindingConfig createOneWireDeviceProperty(Item pvItem, Stri
"the item-type " + pvItem.getClass() + " cannot be a onewire device");
}

logger.debug("created newBindingConfig: " + lvNewBindingConfig.toString());
logger.debug("created newBindingConfig: {}", lvNewBindingConfig.toString());

return lvNewBindingConfig;
}
Expand All @@ -80,8 +80,8 @@ public static boolean isValidItemType(Item pvItem, String pvBindingConfig) throw
|| (pvItem instanceof SwitchItem) || (pvItem instanceof StringItem));

if (!lvIsValidItem) {
logger.error("Item " + pvItem.getName() + " of type " + pvItem.getClass().getSimpleName()
+ " with configuration " + pvBindingConfig + " is not a valid onewire ItemType!");
logger.error("Item {} of type {} with configuration {} is not a valid onewire ItemType!",
pvItem.getName(), pvItem.getClass().getSimpleName(), pvBindingConfig);
}

return lvIsValidItem;
Expand Down
Expand Up @@ -54,7 +54,7 @@ public String getBindingType() {
*/
@Override
public void validateItemType(Item pvItem, String pvBindingConfig) throws BindingConfigParseException {
logger.debug("validateItemType: " + pvItem.getName() + " - bindingConfig:" + pvBindingConfig);
logger.debug("validateItemType: {} - bindingConfig:{}", pvItem.getName(), pvBindingConfig);

if (OneWireBindingConfigFactory.isValidItemType(pvItem, pvBindingConfig)) {
return;
Expand Down
Expand Up @@ -10,6 +10,7 @@

import java.io.IOException;
import java.util.Dictionary;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.openhab.binding.onewire.internal.deviceproperties.AbstractOneWireDevicePropertyBindingConfig;
Expand Down Expand Up @@ -60,6 +61,18 @@ public class OneWireConnection {
*/
private static int cvRetry = 3;

/**
* The number of retries that will be attempted after a failed connection attempt.
* Optional, defaults to 3. 0 means no retries will be attempted.
*/
private static int cvServerRetries = 3;

/**
* The time to wait between connection attempts. Optional, defaults to 60 seconds.
* May not be less than 5 seconds.
*/
private static int cvServerRetryInterval = 60;

/**
* signals that the connection is established
*/
Expand All @@ -85,31 +98,66 @@ public static synchronized OwfsConnection getConnection() {
* @return true if connection was established, false otherwise
*/
public static synchronized boolean connect() {
if (cvIp != null && cvPort > 0) {
OwfsConnectionFactory owfsConnectorFactory = new OwfsConnectionFactory(cvIp, cvPort);
OwfsConnectionConfig owConnectionConfig = new OwfsConnectionConfig(cvIp, cvPort);
owConnectionConfig.setTemperatureScale(cvTempScale);
owConnectionConfig.setPersistence(OwPersistence.ON);
owConnectionConfig.setBusReturn(OwBusReturn.ON);
owfsConnectorFactory.setConnectionConfig(owConnectionConfig);
OwfsConnectionFactory owfsConnectorFactory = new OwfsConnectionFactory(cvIp, cvPort);
OwfsConnectionConfig owConnectionConfig = new OwfsConnectionConfig(cvIp, cvPort);
owConnectionConfig.setTemperatureScale(cvTempScale);
owConnectionConfig.setPersistence(OwPersistence.ON);
owConnectionConfig.setBusReturn(OwBusReturn.ON);
owfsConnectorFactory.setConnectionConfig(owConnectionConfig);

try {
cvOwConnection = owfsConnectorFactory.createNewConnection();
cvOwConnection.listDirectory("/");
logger.info("Connected to owserver [IP '" + cvIp + "' Port '" + cvPort + "']");
cvIsEstablished = true;
return true;
} catch (Exception exception) {
logger.error("Couldn't connect to owserver [IP '" + cvIp + "' Port '" + cvPort + "']: ",
exception.getLocalizedMessage());
cvOwConnection = owfsConnectorFactory.createNewConnection();

boolean connected = false;
int attempts = 0, retriesRemaining = cvServerRetries;
List<String> result = null;

try {
result = cvOwConnection.listDirectory("/");
if (result != null) {
connected = true;
}
else {
cvIsEstablished = false;
return false;
}
} else {
logger.warn("Couldn't connect to owserver because of missing connection parameters [IP '{}' Port '{}'].",
cvIp, cvPort);
} catch (OwfsException oe) {
logger.warn("Unexpected owfs exception: {}", oe.getMessage(), oe);
} catch (IOException e) {
logger.warn("Unexpected connection failure.", e);
}

while (!connected && retriesRemaining > 0) {
logger.warn("Connection failed. Will retry in {} seconds.", cvServerRetryInterval);
synchronized (cvOwConnection) {
try {
cvOwConnection.wait(cvServerRetryInterval * 1000L);
} catch (InterruptedException e) {
logger.debug("Wait was interrupted.");
}
}
attempts++;
retriesRemaining--;
logger.info("Retrying failed connection...");
try {
result = cvOwConnection.listDirectory("/");
if (result != null) {
connected = true;
}
} catch (OwfsException oe) {
logger.warn("Unexpected owfs exception: {}", oe.getMessage(), oe);
} catch (IOException e) {
logger.warn("Unexpected connection failure.", e);
}
}

if (!connected) {
logger.error("Couldn't connect to owserver [IP '{}' Port '{}']", cvIp, cvPort);
cvIsEstablished = false;
return false;
}

logger.info("Connected to owserver [IP '{}' Port '{}']", cvIp, cvPort);
cvIsEstablished = true;
return true;
}

/**
Expand All @@ -122,50 +170,79 @@ public static synchronized boolean reconnect() {
try {
cvOwConnection.disconnect();
} catch (Exception lvException) {
logger.error("Error while disconnecting from owserver: " + lvException, lvException);
logger.error("Error while disconnecting from owserver: ", lvException);
}
cvOwConnection = null;
cvIsEstablished = false;
return connect();
}

public static synchronized void updated(Dictionary<String, ?> pvConfig) throws ConfigurationException {
if (pvConfig != null) {
logger.debug("OneWire configuration present. Setting up owserver connection.");
cvIp = (String) pvConfig.get("ip");
if (pvConfig == null) {
logger.info(
"OneWireBinding configuration is not present. Please check your configuration file or if not needed remove the OneWireBinding addon.");
return;
}

String lvPortConfig = (String) pvConfig.get("port");
if (StringUtils.isNotBlank(lvPortConfig)) {
cvPort = Integer.parseInt(lvPortConfig);
}
logger.debug("OneWire configuration present. Setting up owserver connection.");
cvIp = (String) pvConfig.get("ip");
if (StringUtils.isBlank(cvIp)) {
logger.error("owserver IP address was configured as an empty string.");
throw new ConfigurationException("onewire:ip", "owserver IP address was configured as an empty string.");
}

String lvTempScaleString = (String) pvConfig.get("tempscale");
if (StringUtils.isNotBlank(lvTempScaleString)) {
try {
cvTempScale = OwTemperatureScale.valueOf(lvTempScaleString);
} catch (IllegalArgumentException iae) {
String lvFehlertext = "Unknown temperature scale '" + lvTempScaleString
+ "'. Valid values are CELSIUS, FAHRENHEIT, KELVIN or RANKINE.";
logger.error(lvFehlertext, iae);
throw new ConfigurationException("onewire:tempscale", lvFehlertext);
}
String lvPortConfig = (String) pvConfig.get("port");
if (StringUtils.isNotBlank(lvPortConfig)) {
cvPort = Integer.parseInt(lvPortConfig);
}
if (cvPort < 1) {
logger.error("owserver port was configured with an invalid value: {}", cvPort);
throw new ConfigurationException("onewire:port",
"owserver port was configured with an invalid value: " + cvPort);
}
logger.debug("owserver ip:port = {}:{}", cvIp, cvPort);

String lvTempScaleString = (String) pvConfig.get("tempscale");
if (StringUtils.isNotBlank(lvTempScaleString)) {
try {
cvTempScale = OwTemperatureScale.valueOf(lvTempScaleString);
} catch (IllegalArgumentException iae) {
String lvFehlertext = "Unknown temperature scale '" + lvTempScaleString
+ "'. Valid values are CELSIUS, FAHRENHEIT, KELVIN or RANKINE.";
logger.error(lvFehlertext, iae);
throw new ConfigurationException("onewire:tempscale", lvFehlertext);
}
}

String lvRetryString = (String) pvConfig.get("retry");
if (StringUtils.isNotBlank(lvRetryString)) {
cvRetry = Integer.parseInt(lvRetryString);
}
logger.debug("onewire:retry = {}", cvRetry);

String lvRetryString = (String) pvConfig.get("retry");
if (StringUtils.isNotBlank(lvRetryString)) {
cvRetry = Integer.parseInt(lvRetryString);
String lvServerRetries = (String) pvConfig.get("server_retries");
if( StringUtils.isNotBlank(lvServerRetries)) {
cvServerRetries = Integer.parseInt(lvServerRetries);
}
logger.debug("onewire:server_retries = {}", cvServerRetries);

String lvRetryIntervalString = (String) pvConfig.get("server_retryInterval");
if (StringUtils.isNotBlank(lvRetryIntervalString)) {
cvServerRetryInterval = Integer.parseInt(lvRetryIntervalString);
if( cvServerRetryInterval < 5 && cvServerRetryInterval > 0 ) {
logger.info("server_retryInterval was set to {}. Using the minimum allowed value of 5 instead.", cvServerRetryInterval);
cvServerRetryInterval = 5;
}
}
logger.debug("onewire:server_retryInterval = {} seconds", cvServerRetryInterval);

if (cvOwConnection == null) {
logger.debug("Not connected to owserver yet. Trying to connect...");
if (!connect()) {
logger.warn("Initial connection to owserver failed!");
} else {
logger.debug("Success: connected to owserver.");
}
if (cvOwConnection == null) {
logger.debug("Not connected to owserver yet. Trying to connect...");
if (!connect()) {
logger.warn("Connection to owserver failed!");
} else {
logger.debug("Success: connected to owserver.");
}
} else {
logger.info(
"OneWireBinding configuration is not present. Please check your configuration file or if not needed remove the OneWireBinding addon.");
}
}

Expand Down Expand Up @@ -217,8 +294,7 @@ public static synchronized String readFromOneWire(AbstractOneWireDevicePropertyB
if (pvBindingConfig.isIgnore85CPowerOnResetValues()) {
double lvReadDouble = Double.parseDouble(lvReadValue);
if (lvReadDouble == 85.0) {
logger.debug("reading from path " + lvDevicePropertyPath + " attempt " + lvAttempt
+ " Ignoring 85°C value");
logger.debug("reading from path '{}' attempt {}. Ignoring 85C value", lvDevicePropertyPath, lvAttempt);
} else {
return lvReadValue;
}
Expand All @@ -239,8 +315,8 @@ public static synchronized String readFromOneWire(AbstractOneWireDevicePropertyB
reconnect();
}
} catch (IOException ioe) {
logger.error("couldn't establish network connection while read attempt " + lvAttempt + " '"
+ lvDevicePropertyPath + "' ip:port=" + cvIp + ":" + cvPort, ioe);
logger.error("couldn't establish network connection while read attempt {} '{}'"
+" ip:port={}:{}", lvAttempt, lvDevicePropertyPath, cvIp, cvPort, ioe);
reconnect();
} catch (NumberFormatException lvNumberFormatException) {
logger.error(
Expand All @@ -263,22 +339,22 @@ public static synchronized void writeToOneWire(String pvDevicePropertyPath, Stri
int lvAttempt = 1;
while (lvAttempt <= cvRetry) {
try {
logger.debug("trying to write '{}' to '{}', write attempt={}",
logger.debug("Trying to write '{}' to '{}', write attempt={}",
new Object[] { pvValue, pvDevicePropertyPath, lvAttempt });
if (checkIfDeviceExists(pvDevicePropertyPath)) {
OneWireConnection.getConnection().write(pvDevicePropertyPath, pvValue);
return; // Success, exit
} else {
logger.info("there is no device for path {}, write attempt={}",
logger.info("There is no device for path {}, write attempt={}",
new Object[] { pvDevicePropertyPath, lvAttempt });
}
} catch (OwfsException oe) {
logger.error("writing " + pvValue + " to path " + pvDevicePropertyPath + " attempt " + lvAttempt
+ " throws exception", oe);
logger.error("Writing {} to path {} attempt {} threw an exception",
pvValue, pvDevicePropertyPath, lvAttempt, oe);
reconnect();
} catch (IOException ioe) {
logger.error("couldn't establish network connection while write attempt " + lvAttempt + " to '"
+ pvDevicePropertyPath + "' ip:port=" + cvIp + ":" + cvPort, ioe);
logger.error("Couldn't establish network connection while write attempt {} to '{}'"
+" ip:port={}:{}", lvAttempt, pvDevicePropertyPath, cvIp, cvPort, ioe);
reconnect();
} finally {
lvAttempt++;
Expand Down

0 comments on commit 7067461

Please sign in to comment.