diff --git a/pom.xml b/pom.xml
index 623a4ea..93df6ba 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
com.bwssystems.HABridge
ha-bridge
- 1.3.8a
+ 1.3.8b
jar
HA Bridge
diff --git a/src/main/java/com/bwssystems/HABridge/BridgeSettings.java b/src/main/java/com/bwssystems/HABridge/BridgeSettings.java
index f931859..7a63c3c 100644
--- a/src/main/java/com/bwssystems/HABridge/BridgeSettings.java
+++ b/src/main/java/com/bwssystems/HABridge/BridgeSettings.java
@@ -1,7 +1,29 @@
package com.bwssystems.HABridge;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.nio.file.StandardOpenOption;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Enumeration;
import java.util.List;
+import org.apache.http.conn.util.InetAddressUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.Gson;
+
public class BridgeSettings {
private String upnpconfigaddress;
private String serverport;
@@ -17,11 +39,24 @@ public class BridgeSettings {
private boolean devmode;
private String nestuser;
private String nestpwd;
+ private boolean veraconfigured;
+ private boolean harmonyconfigured;
private boolean nestconfigured;
private String configfile;
private boolean restart;
private boolean stop;
+ public BridgeSettings() {
+ super();
+ this.upnpstrict = true;
+ this.devmode = false;
+ this.traceupnp = false;
+ this.restart = false;
+ this.stop = false;
+ this.nestconfigured = false;
+ this.veraconfigured = false;
+ this.harmonyconfigured = false;
+ }
public String getUpnpConfigAddress() {
return upnpconfigaddress;
}
@@ -100,6 +135,18 @@ public class BridgeSettings {
public void setNestpwd(String nestpwd) {
this.nestpwd = nestpwd;
}
+ public boolean isVeraconfigured() {
+ return veraconfigured;
+ }
+ public void setVeraconfigured(boolean veraconfigured) {
+ this.veraconfigured = veraconfigured;
+ }
+ public boolean isHarmonyconfigured() {
+ return harmonyconfigured;
+ }
+ public void setHarmonyconfigured(boolean harmonyconfigured) {
+ this.harmonyconfigured = harmonyconfigured;
+ }
public boolean isNestConfigured() {
return nestconfigured;
}
@@ -131,16 +178,19 @@ public class BridgeSettings {
this.configfile = configfile;
}
public Boolean isValidVera() {
+ if(this.veraaddress == null)
+ return false;
List devicesList = this.veraaddress.getDevices();
if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS))
return false;
return true;
}
public Boolean isValidHarmony() {
+ if(this.harmonyaddress == null)
+ return false;
List devicesList = this.harmonyaddress.getDevices();
if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS))
- return false;
- if(this.harmonypwd == null || this.harmonypwd == "")
+ return false; if(this.harmonypwd == null || this.harmonypwd == "")
return false;
if(this.harmonyuser == null || this.harmonyuser == "")
return false;
@@ -153,4 +203,269 @@ public class BridgeSettings {
return false;
return true;
}
+
+ public void buildSettings() {
+ Logger log = LoggerFactory.getLogger(BridgeSettings.class);
+ InetAddress address = null;
+ String addressString = null;
+ String theVeraAddress = null;
+ String theHarmonyAddress = null;
+ String configFileProperty = System.getProperty("config.file");
+ if(configFileProperty == null) {
+ Path filePath = Paths.get(Configuration.CONFIG_FILE);
+ if(Files.exists(filePath) && Files.isReadable(filePath))
+ configFileProperty = Configuration.CONFIG_FILE;
+ }
+ if(configFileProperty != null)
+ {
+ log.info("reading from config file: " + configFileProperty);
+ setConfigfile(configFileProperty);
+ _loadConfig();
+ }
+ else
+ {
+ log.info("reading from system properties");
+ setConfigfile(Configuration.CONFIG_FILE);
+ setServerPort(System.getProperty("server.port"));
+ setUpnpConfigAddress(System.getProperty("upnp.config.address"));
+ setUpnpDeviceDb(System.getProperty("upnp.device.db"));
+ setUpnpResponsePort(System.getProperty("upnp.response.port"));
+
+ theVeraAddress = System.getProperty("vera.address");
+ IpList theVeraList = null;
+ if(theVeraAddress != null) {
+ try {
+ theVeraList = new Gson().fromJson(theVeraAddress, IpList.class);
+ } catch (Exception e) {
+ try {
+ theVeraList = new Gson().fromJson("{devices:[{name:default,ip:" + theVeraAddress + "}]}", IpList.class);
+ } catch (Exception et) {
+ log.error("Cannot parse vera.address, not set with message: " + e.getMessage(), e);
+ theVeraList = null;
+ }
+ }
+ }
+ setVeraAddress(theVeraList);
+
+ theHarmonyAddress = System.getProperty("harmony.address");
+ IpList theHarmonyList = null;
+ if(theHarmonyAddress != null) {
+ try {
+ theHarmonyList = new Gson().fromJson(theHarmonyAddress, IpList.class);
+ } catch (Exception e) {
+ try {
+ theHarmonyList = new Gson().fromJson("{devices:[{name:default,ip:" + theHarmonyAddress + "}]}", IpList.class);
+ } catch (Exception et) {
+ log.error("Cannot parse harmony.address, not set with message: " + e.getMessage(), e);
+ theHarmonyList = null;
+ }
+ }
+ }
+ setHarmonyAddress(theHarmonyList);
+ setHarmonyUser(System.getProperty("harmony.user"));
+ setHarmonyPwd(System.getProperty("harmony.pwd"));
+ setUpnpStrict(Boolean.parseBoolean(System.getProperty("upnp.strict", "true")));
+ setTraceupnp(Boolean.parseBoolean(System.getProperty("trace.upnp", "false")));
+ setDevMode(Boolean.parseBoolean(System.getProperty("dev.mode", "false")));
+ setButtonsleep(Integer.parseInt(System.getProperty("button.sleep", Configuration.DFAULT_BUTTON_SLEEP)));
+ setNestuser(System.getProperty("nest.user"));
+ setNestpwd(System.getProperty("nest.pwd"));
+ }
+
+ if(getUpnpConfigAddress() == null) {
+ try {
+ log.info("Getting an IP address for this host....");
+ Enumeration ifs = NetworkInterface.getNetworkInterfaces();
+
+ while (ifs.hasMoreElements() && addressString == null) {
+ NetworkInterface xface = ifs.nextElement();
+ Enumeration addrs = xface.getInetAddresses();
+ String name = xface.getName();
+ int IPsPerNic = 0;
+
+ while (addrs.hasMoreElements() && IPsPerNic == 0) {
+ address = addrs.nextElement();
+ if (InetAddressUtils.isIPv4Address(address.getHostAddress())) {
+ log.debug(name + " ... has IPV4 addr " + address);
+ if(!name.equalsIgnoreCase(Configuration.LOOP_BACK_INTERFACE)|| !address.getHostAddress().equalsIgnoreCase(Configuration.LOOP_BACK_ADDRESS)) {
+ IPsPerNic++;
+ addressString = address.getHostAddress();
+ log.info("Adding " + addressString + " from interface " + name + " as our default upnp config address.");
+ }
+ }
+ }
+ }
+ } catch (SocketException e) {
+ log.error("Cannot get ip address of this host, Exiting with message: " + e.getMessage(), e);
+ return;
+ }
+
+ setUpnpConfigAddress(addressString);
+ }
+
+ if(this.getUpnpResponsePort() == null)
+ this.setUpnpResponsePort(Configuration.UPNP_RESPONSE_PORT);
+
+ if(this.getServerPort() == null)
+ this.setServerPort(Configuration.DFAULT_WEB_PORT);
+
+ if(this.getUpnpDeviceDb() == null)
+ this.setUpnpDeviceDb(Configuration.DEVICE_DB_DIRECTORY);
+
+ if(this.getButtonsleep() <= 0)
+ this.setButtonsleep(Integer.parseInt(Configuration.DFAULT_BUTTON_SLEEP));
+ }
+
+ private void _loadConfig() {
+ Path configPath = Paths.get(getConfigfile());
+ _loadConfig(configPath);
+ }
+
+ private void _loadConfig(Path aPath) {
+ String jsonContent = configReader(aPath);
+ BridgeSettings aBridgeSettings = new Gson().fromJson(jsonContent, BridgeSettings.class);
+ this.setButtonsleep(aBridgeSettings.getButtonsleep());
+ this.setUpnpConfigAddress(aBridgeSettings.getUpnpConfigAddress());
+ this.setServerPort(aBridgeSettings.getServerPort());
+ this.setUpnpResponsePort(aBridgeSettings.getUpnpResponsePort());
+ this.setUpnpDeviceDb(aBridgeSettings.getUpnpDeviceDb());
+ this.setVeraAddress(aBridgeSettings.getVeraAddress());
+ this.setHarmonyAddress(aBridgeSettings.getHarmonyAddress());
+ this.setHarmonyUser(aBridgeSettings.getHarmonyUser());
+ this.setHarmonyPwd(aBridgeSettings.getHarmonyPwd());
+ this.setUpnpStrict(aBridgeSettings.isUpnpStrict());
+ this.setTraceupnp(aBridgeSettings.isTraceupnp());
+ this.setDevMode(aBridgeSettings.isDevMode());
+ this.setNestuser(aBridgeSettings.getNestuser());
+ this.setNestpwd(aBridgeSettings.getNestpwd());
+ this.setVeraconfigured(aBridgeSettings.isVeraconfigured());
+ this.setHarmonyconfigured(aBridgeSettings.isHarmonyconfigured());
+ this.setNestConfigured(aBridgeSettings.isNestConfigured());
+ }
+
+ public void save() {
+ Logger log = LoggerFactory.getLogger(BridgeSettings.class);
+ Path configPath = Paths.get(getConfigfile());
+ JsonTransformer aRenderer = new JsonTransformer();
+ String jsonValue = aRenderer.render(this);
+ configWriter(jsonValue, configPath);
+ log.debug("Save HA Bridge settings.");
+ }
+
+
+ private void configWriter(String content, Path filePath) {
+ Logger log = LoggerFactory.getLogger(BridgeSettings.class);
+ if(Files.exists(filePath) && !Files.isWritable(filePath)){
+ log.error("Error file is not writable: " + filePath);
+ return;
+ }
+
+ if(Files.notExists(filePath.getParent())) {
+ try {
+ Files.createDirectories(filePath.getParent());
+ } catch (IOException e) {
+ log.error("Error creating the directory: " + filePath + " message: " + e.getMessage(), e);
+ }
+ }
+
+ try {
+ Path target = null;
+ if(Files.exists(filePath)) {
+ target = FileSystems.getDefault().getPath(filePath.getParent().toString(), "device.db.old");
+ Files.move(filePath, target);
+ }
+ Files.write(filePath, content.getBytes(), StandardOpenOption.CREATE);
+ if(target != null)
+ Files.delete(target);
+ } catch (IOException e) {
+ log.error("Error writing the file: " + filePath + " message: " + e.getMessage(), e);
+ }
+ }
+
+ private String configReader(Path filePath) {
+ Logger log = LoggerFactory.getLogger(BridgeSettings.class);
+
+ String content = null;
+ if(Files.notExists(filePath) || !Files.isReadable(filePath)){
+ log.warn("Error reading the file: " + filePath + " - Does not exist or is not readable. continuing...");
+ return null;
+ }
+
+
+ try {
+ content = new String(Files.readAllBytes(filePath));
+ } catch (IOException e) {
+ log.error("Error reading the file: " + filePath + " message: " + e.getMessage(), e);
+ }
+
+ return content;
+ }
+
+ public String backupConfig(String aFilename) {
+ Logger log = LoggerFactory.getLogger(BridgeSettings.class);
+ Path configPath = Paths.get(getConfigfile());
+ if(aFilename == null || aFilename.equalsIgnoreCase("")) {
+ DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
+ aFilename = "habridge.config-" + dateFormat.format(Calendar.getInstance().getTime()) + ".bk";
+ }
+ else
+ aFilename = aFilename + ".bk";
+ try {
+ Files.copy(configPath, FileSystems.getDefault().getPath(configPath.getParent().toString(), aFilename), StandardCopyOption.COPY_ATTRIBUTES);
+ } catch (IOException e) {
+ log.error("Could not backup to file: " + aFilename + " message: " + e.getMessage(), e);
+ }
+ log.debug("Backup config: " + aFilename);
+ return aFilename;
+ }
+
+ public String deleteConfigBackup(String aFilename) {
+ Logger log = LoggerFactory.getLogger(BridgeSettings.class);
+ Path configPath = Paths.get(getConfigfile());
+ log.debug("Delete backup config: " + aFilename);
+ try {
+ Files.delete(FileSystems.getDefault().getPath(configPath.getParent().toString(), aFilename));
+ } catch (IOException e) {
+ log.error("Could not delete file: " + aFilename + " message: " + e.getMessage(), e);
+ }
+ return aFilename;
+ }
+
+ public String restoreConfigBackup(String aFilename) {
+ Logger log = LoggerFactory.getLogger(BridgeSettings.class);
+ Path configPath = Paths.get(getConfigfile());
+ log.debug("Restore backup config: " + aFilename);
+ try {
+ Path target = null;
+ if(Files.exists(configPath)) {
+ DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
+ target = FileSystems.getDefault().getPath(configPath.getParent().toString(), "habridge.config-" + dateFormat.format(Calendar.getInstance().getTime()) + ".bk");
+ Files.move(configPath, target);
+ }
+ Files.copy(FileSystems.getDefault().getPath(configPath.getParent().toString(), aFilename), configPath, StandardCopyOption.COPY_ATTRIBUTES);
+ } catch (IOException e) {
+ log.error("Error restoring the file: " + aFilename + " message: " + e.getMessage(), e);
+ return null;
+ }
+ _loadConfig(configPath);
+ return aFilename;
+ }
+
+ public List getConfigBackups() {
+ Logger log = LoggerFactory.getLogger(BridgeSettings.class);
+ Path configPath = Paths.get(getConfigfile());
+ List theFilenames = new ArrayList();
+ Path dir = configPath.getParent();
+ try (DirectoryStream stream =
+ Files.newDirectoryStream(dir, "*.{bk}")) {
+ for (Path entry: stream) {
+ theFilenames.add(entry.getFileName().toString());
+ }
+ } catch (IOException x) {
+ // IOException can never be thrown by the iteration.
+ // In this snippet, it can // only be thrown by newDirectoryStream.
+ log.error("Issue getting directory listing for config backups - " + x.getMessage());
+ }
+ return theFilenames;
+ }
}
diff --git a/src/main/java/com/bwssystems/HABridge/HABridge.java b/src/main/java/com/bwssystems/HABridge/HABridge.java
index 6818ce3..210f808 100644
--- a/src/main/java/com/bwssystems/HABridge/HABridge.java
+++ b/src/main/java/com/bwssystems/HABridge/HABridge.java
@@ -2,12 +2,6 @@ package com.bwssystems.HABridge;
import static spark.Spark.*;
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
-import java.util.Enumeration;
-
-import org.apache.http.conn.util.InetAddressUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -17,7 +11,6 @@ import com.bwssystems.HABridge.upnp.UpnpListener;
import com.bwssystems.HABridge.upnp.UpnpSettingsResource;
import com.bwssystems.NestBridge.NestHome;
import com.bwssystems.harmony.HarmonyHome;
-import com.google.gson.Gson;
public class HABridge {
@@ -44,8 +37,6 @@ public class HABridge {
HueMulator theHueMulator;
UpnpSettingsResource theSettingResponder;
UpnpListener theUpnpListener;
- InetAddress address = null;
- String addressString = null;
BridgeSettings bridgeSettings;
Version theVersion;
@@ -57,77 +48,7 @@ public class HABridge {
bridgeSettings.setRestart(false);
bridgeSettings.setStop(false);
while(!bridgeSettings.isStop()) {
- bridgeSettings.setConfigfile(System.getProperty("config.file", Configuration.CONFIG_FILE));
- bridgeSettings.setServerPort(System.getProperty("server.port", Configuration.DFAULT_WEB_PORT));
- bridgeSettings.setUpnpConfigAddress(System.getProperty("upnp.config.address", Configuration.DEFAULT_ADDRESS));
- if(bridgeSettings.getUpnpConfigAddress().equalsIgnoreCase(Configuration.DEFAULT_ADDRESS)) {
- try {
- log.info("HA Bridge (v" + theVersion.getVersion() + ") Getting an IP address for this host....");
- Enumeration ifs = NetworkInterface.getNetworkInterfaces();
-
- while (ifs.hasMoreElements() && addressString == null) {
- NetworkInterface xface = ifs.nextElement();
- Enumeration addrs = xface.getInetAddresses();
- String name = xface.getName();
- int IPsPerNic = 0;
-
- while (addrs.hasMoreElements() && IPsPerNic == 0) {
- address = addrs.nextElement();
- if (InetAddressUtils.isIPv4Address(address.getHostAddress())) {
- log.debug(name + " ... has IPV4 addr " + address);
- if(!name.equalsIgnoreCase(Configuration.LOOP_BACK_INTERFACE)|| !address.getHostAddress().equalsIgnoreCase(Configuration.LOOP_BACK_ADDRESS)) {
- IPsPerNic++;
- addressString = address.getHostAddress();
- log.info("HA Bridge (v" + theVersion.getVersion() + ") Adding " + addressString + " from interface " + name + " as our default upnp config address.");
- }
- }
- }
- }
- } catch (SocketException e) {
- log.error("Cannot get ip address of this host, Exiting with message: " + e.getMessage(), e);
- return;
- }
-
- bridgeSettings.setUpnpConfigAddress(addressString);
- }
-
- bridgeSettings.setUpnpDeviceDb(System.getProperty("upnp.device.db", Configuration.DEVICE_DB_DIRECTORY));
- bridgeSettings.setUpnpResponsePort(System.getProperty("upnp.response.port", Configuration.UPNP_RESPONSE_PORT));
- IpList theVeraList;
-
- try {
- theVeraList = new Gson().fromJson(System.getProperty("vera.address", Configuration.DEFAULT_HARMONY_ADDRESS_LIST), IpList.class);
- } catch (Exception e) {
- try {
- theVeraList = new Gson().fromJson("{devices:[{name:default,ip:" + System.getProperty("vera.address", Configuration.DEFAULT_ADDRESS) + "}]}", IpList.class);
- } catch (Exception et) {
- log.error("Cannot parse vera.address, Exiting with message: " + e.getMessage(), e);
- return;
- }
- }
- bridgeSettings.setVeraAddress(theVeraList);
- IpList theHarmonyList;
-
- try {
- theHarmonyList = new Gson().fromJson(System.getProperty("harmony.address", Configuration.DEFAULT_HARMONY_ADDRESS_LIST), IpList.class);
- } catch (Exception e) {
- try {
- theHarmonyList = new Gson().fromJson("{devices:[{name:default,ip:" + System.getProperty("harmony.address", Configuration.DEFAULT_ADDRESS) + "}]}", IpList.class);
- } catch (Exception et) {
- log.error("Cannot parse harmony.address, Exiting with message: " + e.getMessage(), e);
- return;
- }
- }
- bridgeSettings.setHarmonyAddress(theHarmonyList);
- bridgeSettings.setHarmonyUser(System.getProperty("harmony.user", Configuration.DEFAULT_USER));
- bridgeSettings.setHarmonyPwd(System.getProperty("harmony.pwd", Configuration.DEFAULT_PWD));
- bridgeSettings.setUpnpStrict(Boolean.parseBoolean(System.getProperty("upnp.strict", "true")));
- bridgeSettings.setTraceupnp(Boolean.parseBoolean(System.getProperty("trace.upnp", "false")));
- bridgeSettings.setDevMode(Boolean.parseBoolean(System.getProperty("dev.mode", "false")));
- bridgeSettings.setButtonsleep(Integer.parseInt(System.getProperty("button.sleep", Configuration.DFAULT_BUTTON_SLEEP)));
- bridgeSettings.setNestuser(System.getProperty("nest.user", Configuration.DEFAULT_USER));
- bridgeSettings.setNestpwd(System.getProperty("nest.pwd", Configuration.DEFAULT_PWD));
-
+ bridgeSettings.buildSettings();
log.info("HA Bridge (v" + theVersion.getVersion() + ") initializing....");
// sparkjava config directive to set ip address for the web server to listen on
// ipAddress("0.0.0.0"); // not used
diff --git a/src/main/java/com/bwssystems/HABridge/upnp/UpnpSettingsResource.java b/src/main/java/com/bwssystems/HABridge/upnp/UpnpSettingsResource.java
index dbcfb41..a613eb2 100644
--- a/src/main/java/com/bwssystems/HABridge/upnp/UpnpSettingsResource.java
+++ b/src/main/java/com/bwssystems/HABridge/upnp/UpnpSettingsResource.java
@@ -53,6 +53,8 @@ public class UpnpSettingsResource {
this.theSettings.setUpnpResponsePort(theBridgeSettings.getUpnpResponsePort());
this.theSettings.setUpnpStrict(theBridgeSettings.isUpnpStrict());
this.theSettings.setVeraAddress(theBridgeSettings.getVeraAddress());
+ this.theSettings.setVeraconfigured(theBridgeSettings.isValidVera());
+ this.theSettings.setHarmonyconfigured(theBridgeSettings.isValidHarmony());
this.theSettings.setNestConfigured(theBridgeSettings.isValidNest());
}
diff --git a/src/main/resources/public/scripts/app.js b/src/main/resources/public/scripts/app.js
index 18feb09..ccbd851 100644
--- a/src/main/resources/public/scripts/app.js
+++ b/src/main/resources/public/scripts/app.js
@@ -79,31 +79,18 @@ app.service('bridgeService', function ($http, $window, ngToast) {
}
this.updateShowVera = function () {
- if(this.aContainsB(self.state.settings.veraaddress.devices[0].ip, "1.1.1.1") || self.state.settings.veraaddress == "" || self.state.settings.veraaddress == null)
- this.state.showVera = false;
- else
- this.state.showVera = true;
+ this.state.showVera = self.state.settings.veraconfigured;
return;
}
this.updateShowNest = function () {
- if(self.state.settings.nestconfigured == true)
- this.state.showNest = true;
- else
- this.state.showNest = false;
+ this.state.showNest = self.state.settings.nestconfigured;
return;
}
this.updateShowHarmony = function () {
- if(self.state.settings.harmonyaddress.devices) {
- if(this.aContainsB(self.state.settings.harmonyaddress.devices[0].ip, "1.1.1.1") || self.state.settings.harmonyaddress == "" || self.state.settings.harmonyaddress == null)
- this.state.showHarmony = false;
- else
- this.state.showHarmony = true;
- }
- else
- this.state.showHarmony = false;
- return;
+ this.state.showHarmony = self.state.settings.harmonyconfigured;
+ return;
}