Added config settings page and refactored backup handling and bridge

settings and cotntrol. Next is to add the editing to the config screen.
This commit is contained in:
Admin
2016-02-11 16:51:11 -06:00
parent 20328b15d8
commit e6da9950d6
25 changed files with 739 additions and 466 deletions

View File

@@ -5,7 +5,7 @@
<groupId>com.bwssystems.HABridge</groupId>
<artifactId>ha-bridge</artifactId>
<version>1.3.8b</version>
<version>1.3.8c</version>
<packaging>jar</packaging>
<name>HA Bridge</name>

View File

@@ -4,19 +4,12 @@ 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;
@@ -24,146 +17,139 @@ import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
public class BridgeSettings {
private String upnpconfigaddress;
private String serverport;
private String upnpresponseport;
private String upnpdevicedb;
private IpList veraaddress;
private IpList harmonyaddress;
private String harmonyuser;
private String harmonypwd;
private Integer buttonsleep;
private boolean upnpstrict;
private boolean traceupnp;
private boolean devmode;
private String nestuser;
private String nestpwd;
private boolean veraconfigured;
private boolean harmonyconfigured;
private boolean nestconfigured;
private String configfile;
private boolean restart;
public class BridgeSettings extends BackupHandler {
private BridgeSettingsDescriptor theBridgeSettings;
private boolean reinit;
private boolean stop;
public BridgeSettings() {
super();
this.upnpstrict = true;
this.devmode = false;
this.traceupnp = false;
this.restart = false;
this.reinit = false;
this.stop = false;
this.nestconfigured = false;
this.veraconfigured = false;
this.harmonyconfigured = false;
theBridgeSettings = new BridgeSettingsDescriptor();
theBridgeSettings.setUpnpStrict(true);
theBridgeSettings.setDevMode(false);
theBridgeSettings.setTraceupnp(false);
theBridgeSettings.setNestConfigured(false);
theBridgeSettings.setVeraconfigured(false);
theBridgeSettings.setHarmonyconfigured(false);
}
public BridgeSettingsDescriptor getBridgeSettingsDescriptor() {
return theBridgeSettings;
}
public String getUpnpConfigAddress() {
return upnpconfigaddress;
return theBridgeSettings.getUpnpConfigAddress();
}
public void setUpnpConfigAddress(String upnpConfigAddress) {
this.upnpconfigaddress = upnpConfigAddress;
theBridgeSettings.setUpnpConfigAddress(upnpConfigAddress);
}
public String getServerPort() {
return serverport;
return theBridgeSettings.getServerPort();
}
public void setServerPort(String serverPort) {
this.serverport = serverPort;
theBridgeSettings.setServerPort(serverPort);
}
public String getUpnpResponsePort() {
return upnpresponseport;
return theBridgeSettings.getUpnpResponsePort();
}
public void setUpnpResponsePort(String upnpResponsePort) {
this.upnpresponseport = upnpResponsePort;
theBridgeSettings.setUpnpResponsePort(upnpResponsePort);
}
public String getUpnpDeviceDb() {
return upnpdevicedb;
return theBridgeSettings.getUpnpDeviceDb();
}
public void setUpnpDeviceDb(String upnpDeviceDb) {
this.upnpdevicedb = upnpDeviceDb;
theBridgeSettings.setUpnpDeviceDb(upnpDeviceDb);
}
public IpList getVeraAddress() {
return veraaddress;
return theBridgeSettings.getVeraAddress();
}
public void setVeraAddress(IpList veraAddress) {
this.veraaddress = veraAddress;
theBridgeSettings.setVeraAddress(veraAddress);
}
public IpList getHarmonyAddress() {
return harmonyaddress;
return theBridgeSettings.getHarmonyAddress();
}
public void setHarmonyAddress(IpList harmonyaddress) {
this.harmonyaddress = harmonyaddress;
theBridgeSettings.setHarmonyAddress(harmonyaddress);
}
public String getHarmonyUser() {
return harmonyuser;
return theBridgeSettings.getHarmonyUser();
}
public void setHarmonyUser(String harmonyuser) {
this.harmonyuser = harmonyuser;
theBridgeSettings.setHarmonyUser(harmonyuser);
}
public String getHarmonyPwd() {
return harmonypwd;
return theBridgeSettings.getHarmonyPwd();
}
public void setHarmonyPwd(String harmonypwd) {
this.harmonypwd = harmonypwd;
theBridgeSettings.setHarmonyPwd(harmonypwd);
}
public boolean isUpnpStrict() {
return upnpstrict;
return theBridgeSettings.isUpnpStrict();
}
public void setUpnpStrict(boolean upnpStrict) {
this.upnpstrict = upnpStrict;
theBridgeSettings.setUpnpStrict(upnpStrict);
}
public boolean isTraceupnp() {
return traceupnp;
return theBridgeSettings.isTraceupnp();
}
public void setTraceupnp(boolean traceupnp) {
this.traceupnp = traceupnp;
theBridgeSettings.setTraceupnp(traceupnp);
}
public boolean isDevMode() {
return devmode;
return theBridgeSettings.isDevMode();
}
public void setDevMode(boolean devmode) {
this.devmode = devmode;
theBridgeSettings.setDevMode(devmode);
}
public String getNestuser() {
return nestuser;
return theBridgeSettings.getNestuser();
}
public void setNestuser(String nestuser) {
this.nestuser = nestuser;
theBridgeSettings.setNestuser(nestuser);
}
public String getNestpwd() {
return nestpwd;
return theBridgeSettings.getNestpwd();
}
public void setNestpwd(String nestpwd) {
this.nestpwd = nestpwd;
theBridgeSettings.setNestpwd(nestpwd);
}
public boolean isVeraconfigured() {
return veraconfigured;
return theBridgeSettings.isVeraconfigured();
}
public void setVeraconfigured(boolean veraconfigured) {
this.veraconfigured = veraconfigured;
theBridgeSettings.setVeraconfigured(veraconfigured);
}
public boolean isHarmonyconfigured() {
return harmonyconfigured;
return theBridgeSettings.isHarmonyconfigured();
}
public void setHarmonyconfigured(boolean harmonyconfigured) {
this.harmonyconfigured = harmonyconfigured;
theBridgeSettings.setHarmonyconfigured(harmonyconfigured);
}
public boolean isNestConfigured() {
return nestconfigured;
return theBridgeSettings.isNestConfigured();
}
public void setNestConfigured(boolean isNestConfigured) {
this.nestconfigured = isNestConfigured;
theBridgeSettings.setNestConfigured(isNestConfigured);
}
public Integer getButtonsleep() {
return buttonsleep;
return theBridgeSettings.getButtonsleep();
}
public void setButtonsleep(Integer buttonsleep) {
this.buttonsleep = buttonsleep;
theBridgeSettings.setButtonsleep(buttonsleep);
}
public boolean isRestart() {
return restart;
public String getConfigfile() {
return theBridgeSettings.getConfigfile();
}
public void setRestart(boolean restart) {
this.restart = restart;
public void setConfigfile(String configfile) {
theBridgeSettings.setConfigfile(configfile);
}
public boolean isReinit() {
return reinit;
}
public void setReinit(boolean reinit) {
this.reinit = reinit;
}
public boolean isStop() {
return stop;
@@ -171,39 +157,6 @@ public class BridgeSettings {
public void setStop(boolean stop) {
this.stop = stop;
}
public String getConfigfile() {
return configfile;
}
public void setConfigfile(String configfile) {
this.configfile = configfile;
}
public Boolean isValidVera() {
if(this.veraaddress == null)
return false;
List<NamedIP> 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<NamedIP> 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.harmonyuser == null || this.harmonyuser == "")
return false;
return true;
}
public Boolean isValidNest() {
if(this.nestpwd == null || this.nestpwd == "")
return false;
if(this.nestuser == null || this.nestuser == "")
return false;
return true;
}
public void buildSettings() {
Logger log = LoggerFactory.getLogger(BridgeSettings.class);
InetAddress address = null;
@@ -314,8 +267,17 @@ public class BridgeSettings {
if(this.getButtonsleep() <= 0)
this.setButtonsleep(Integer.parseInt(Configuration.DFAULT_BUTTON_SLEEP));
this.setVeraconfigured(theBridgeSettings.isValidVera());
this.setHarmonyconfigured(theBridgeSettings.isValidHarmony());
this.setNestConfigured(theBridgeSettings.isValidNest());
setupParams(Paths.get(getConfigfile()), ".cfgbk", "habridge.config-");
}
public void loadConfig() {
if(getConfigfile() != null)
_loadConfig();
}
private void _loadConfig() {
Path configPath = Paths.get(getConfigfile());
_loadConfig(configPath);
@@ -323,7 +285,7 @@ public class BridgeSettings {
private void _loadConfig(Path aPath) {
String jsonContent = configReader(aPath);
BridgeSettings aBridgeSettings = new Gson().fromJson(jsonContent, BridgeSettings.class);
BridgeSettingsDescriptor aBridgeSettings = new Gson().fromJson(jsonContent, BridgeSettingsDescriptor.class);
this.setButtonsleep(aBridgeSettings.getButtonsleep());
this.setUpnpConfigAddress(aBridgeSettings.getUpnpConfigAddress());
this.setServerPort(aBridgeSettings.getServerPort());
@@ -338,18 +300,19 @@ public class BridgeSettings {
this.setDevMode(aBridgeSettings.isDevMode());
this.setNestuser(aBridgeSettings.getNestuser());
this.setNestpwd(aBridgeSettings.getNestpwd());
this.setVeraconfigured(aBridgeSettings.isVeraconfigured());
this.setHarmonyconfigured(aBridgeSettings.isHarmonyconfigured());
this.setNestConfigured(aBridgeSettings.isNestConfigured());
this.setVeraconfigured(aBridgeSettings.isValidVera());
this.setHarmonyconfigured(aBridgeSettings.isValidHarmony());
this.setNestConfigured(aBridgeSettings.isValidNest());
}
public void save() {
public void save(BridgeSettings newBridgeSettings) {
Logger log = LoggerFactory.getLogger(BridgeSettings.class);
log.debug("Save HA Bridge settings.");
Path configPath = Paths.get(getConfigfile());
JsonTransformer aRenderer = new JsonTransformer();
String jsonValue = aRenderer.render(this);
String jsonValue = aRenderer.render(newBridgeSettings);
configWriter(jsonValue, configPath);
log.debug("Save HA Bridge settings.");
_loadConfig(configPath);
}
@@ -371,7 +334,7 @@ public class BridgeSettings {
try {
Path target = null;
if(Files.exists(filePath)) {
target = FileSystems.getDefault().getPath(filePath.getParent().toString(), "device.db.old");
target = FileSystems.getDefault().getPath(filePath.getParent().toString(), "habridge.config.old");
Files.move(filePath, target);
}
Files.write(filePath, content.getBytes(), StandardOpenOption.CREATE);
@@ -400,72 +363,4 @@ public class BridgeSettings {
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<String> getConfigBackups() {
Logger log = LoggerFactory.getLogger(BridgeSettings.class);
Path configPath = Paths.get(getConfigfile());
List<String> theFilenames = new ArrayList<String>();
Path dir = configPath.getParent();
try (DirectoryStream<Path> 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;
}
}

View File

@@ -0,0 +1,170 @@
package com.bwssystems.HABridge;
import java.util.List;
public class BridgeSettingsDescriptor {
private String upnpconfigaddress;
private String serverport;
private String upnpresponseport;
private String upnpdevicedb;
private IpList veraaddress;
private IpList harmonyaddress;
private String harmonyuser;
private String harmonypwd;
private Integer buttonsleep;
private boolean upnpstrict;
private boolean traceupnp;
private boolean devmode;
private String nestuser;
private String nestpwd;
private boolean veraconfigured;
private boolean harmonyconfigured;
private boolean nestconfigured;
private String configfile;
public BridgeSettingsDescriptor() {
super();
this.upnpstrict = true;
this.devmode = false;
this.traceupnp = false;
this.nestconfigured = false;
this.veraconfigured = false;
this.harmonyconfigured = false;
}
public String getUpnpConfigAddress() {
return upnpconfigaddress;
}
public void setUpnpConfigAddress(String upnpConfigAddress) {
this.upnpconfigaddress = upnpConfigAddress;
}
public String getServerPort() {
return serverport;
}
public void setServerPort(String serverPort) {
this.serverport = serverPort;
}
public String getUpnpResponsePort() {
return upnpresponseport;
}
public void setUpnpResponsePort(String upnpResponsePort) {
this.upnpresponseport = upnpResponsePort;
}
public String getUpnpDeviceDb() {
return upnpdevicedb;
}
public void setUpnpDeviceDb(String upnpDeviceDb) {
this.upnpdevicedb = upnpDeviceDb;
}
public IpList getVeraAddress() {
return veraaddress;
}
public void setVeraAddress(IpList veraAddress) {
this.veraaddress = veraAddress;
}
public IpList getHarmonyAddress() {
return harmonyaddress;
}
public void setHarmonyAddress(IpList harmonyaddress) {
this.harmonyaddress = harmonyaddress;
}
public String getHarmonyUser() {
return harmonyuser;
}
public void setHarmonyUser(String harmonyuser) {
this.harmonyuser = harmonyuser;
}
public String getHarmonyPwd() {
return harmonypwd;
}
public void setHarmonyPwd(String harmonypwd) {
this.harmonypwd = harmonypwd;
}
public boolean isUpnpStrict() {
return upnpstrict;
}
public void setUpnpStrict(boolean upnpStrict) {
this.upnpstrict = upnpStrict;
}
public boolean isTraceupnp() {
return traceupnp;
}
public void setTraceupnp(boolean traceupnp) {
this.traceupnp = traceupnp;
}
public boolean isDevMode() {
return devmode;
}
public void setDevMode(boolean devmode) {
this.devmode = devmode;
}
public String getNestuser() {
return nestuser;
}
public void setNestuser(String nestuser) {
this.nestuser = nestuser;
}
public String getNestpwd() {
return nestpwd;
}
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;
}
public void setNestConfigured(boolean isNestConfigured) {
this.nestconfigured = isNestConfigured;
}
public Integer getButtonsleep() {
return buttonsleep;
}
public void setButtonsleep(Integer buttonsleep) {
this.buttonsleep = buttonsleep;
}
public String getConfigfile() {
return configfile;
}
public void setConfigfile(String configfile) {
this.configfile = configfile;
}
public Boolean isValidVera() {
if(this.getVeraAddress() == null)
return false;
List<NamedIP> devicesList = this.getVeraAddress().getDevices();
if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS))
return false;
return true;
}
public Boolean isValidHarmony() {
if(this.getHarmonyAddress() == null)
return false;
List<NamedIP> devicesList = this.getHarmonyAddress().getDevices();
if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS))
return false;
if(this.getHarmonyPwd() == null || this.getHarmonyPwd() == "")
return false;
if(this.getHarmonyUser() == null || this.getHarmonyUser() == "")
return false;
return true;
}
public Boolean isValidNest() {
if(this.getNestpwd() == null || this.getNestpwd() == "")
return false;
if(this.getNestuser() == null || this.getNestuser() == "")
return false;
return true;
}
}

View File

@@ -7,9 +7,6 @@ public class Configuration {
public final static String DEFAULT_ADDRESS = "1.1.1.1";
public final static String LOOP_BACK_ADDRESS = "127.0.0.1";
public final static String LOOP_BACK_INTERFACE = "lo";
public final static String DEFAULT_HARMONY_ADDRESS_LIST = "{devices:[{name:default,ip:1.1.1.1}]}";
public final static String DEFAULT_USER = "";
public final static String DEFAULT_PWD = "";
public final static String DFAULT_WEB_PORT = "8080";
public final static String DFAULT_BUTTON_SLEEP = "100";
public static final int UPNP_DISCOVERY_PORT = 1900;

View File

@@ -37,6 +37,7 @@ public class HABridge {
HueMulator theHueMulator;
UpnpSettingsResource theSettingResponder;
UpnpListener theUpnpListener;
SystemControl theSystem;
BridgeSettings bridgeSettings;
Version theVersion;
@@ -45,7 +46,7 @@ public class HABridge {
log.info("HA Bridge (v" + theVersion.getVersion() + ") starting....");
bridgeSettings = new BridgeSettings();
bridgeSettings.setRestart(false);
bridgeSettings.setReinit(false);
bridgeSettings.setStop(false);
while(!bridgeSettings.isStop()) {
bridgeSettings.buildSettings();
@@ -56,17 +57,20 @@ public class HABridge {
port(Integer.valueOf(bridgeSettings.getServerPort()));
// sparkjava config directive to set html static file location for Jetty
staticFileLocation("/public");
// setup system control api first
theSystem = new SystemControl(bridgeSettings, theVersion);
theSystem.setupServer();
//setup the harmony connection if available
harmonyHome = new HarmonyHome(bridgeSettings);
harmonyHome = new HarmonyHome(bridgeSettings.getBridgeSettingsDescriptor());
//setup the nest connection if available
nestHome = new NestHome(bridgeSettings);
nestHome = new NestHome(bridgeSettings.getBridgeSettingsDescriptor());
// setup the class to handle the resource setup rest api
theResources = new DeviceResource(bridgeSettings, theVersion, harmonyHome, nestHome);
theResources = new DeviceResource(bridgeSettings.getBridgeSettingsDescriptor(), harmonyHome, nestHome);
// setup the class to handle the hue emulator rest api
theHueMulator = new HueMulator(bridgeSettings, theResources.getDeviceRepository(), harmonyHome, nestHome);
theHueMulator = new HueMulator(bridgeSettings.getBridgeSettingsDescriptor(), theResources.getDeviceRepository(), harmonyHome, nestHome);
theHueMulator.setupServer();
// setup the class to handle the upnp response rest api
theSettingResponder = new UpnpSettingsResource(bridgeSettings);
theSettingResponder = new UpnpSettingsResource(bridgeSettings.getBridgeSettingsDescriptor());
theSettingResponder.setupServer();
// wait for the sparkjava initialization of the rest api classes to be complete
awaitInitialization();
@@ -76,7 +80,7 @@ public class HABridge {
if(theUpnpListener.startListening())
log.info("HA Bridge (v" + theVersion.getVersion() + ") reinitialization requessted....");
bridgeSettings.setRestart(false);
bridgeSettings.setReinit(false);
stop();
}
log.info("HA Bridge (v" + theVersion.getVersion() + ") exiting....");

View File

@@ -0,0 +1,173 @@
package com.bwssystems.HABridge;
import static spark.Spark.get;
import static spark.Spark.options;
import static spark.Spark.post;
import static spark.Spark.put;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import org.apache.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.bwssystems.HABridge.dao.BackupFilename;
import com.google.gson.Gson;
public class SystemControl {
private static final Logger log = LoggerFactory.getLogger(SystemControl.class);
private static final String SYSTEM_CONTEXT = "/system";
private BridgeSettings bridgeSettings;
private Version version;
public SystemControl(BridgeSettings theBridgeSettings, Version theVersion) {
this.bridgeSettings = theBridgeSettings;
this.version = theVersion;
}
// This function sets up the sparkjava rest calls for the hue api
public void setupServer() {
log.info("Hue emulator service started....");
// http://ip_address:port/system/habridge/version gets the version of this bridge instance
get (SYSTEM_CONTEXT + "/habridge/version", "application/json", (request, response) -> {
log.debug("Get HA Bridge version: v" + version.getVersion());
response.status(HttpStatus.SC_OK);
return "{\"version\":\"" + version.getVersion() + "\"}";
});
// http://ip_address:port/system/settings which returns the bridge configuration settings
get(SYSTEM_CONTEXT + "/settings", "application/json", (request, response) -> {
log.debug("bridge settings requested from " + request.ip());
response.status(200);
return bridgeSettings;
}, new JsonTransformer());
// http://ip_address:port/system/control/reinit CORS request
options(SYSTEM_CONTEXT + "/control/reinit", "application/json", (request, response) -> {
response.status(HttpStatus.SC_OK);
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
response.header("Access-Control-Allow-Methods", "GET, POST, PUT");
response.header("Access-Control-Allow-Headers", request.headers("Access-Control-Request-Headers"));
response.header("Content-Type", "text/html; charset=utf-8");
return "";
});
// http://ip_address:port/system/control/reinit sets the parameter reinit the server
put(SYSTEM_CONTEXT + "/control/reinit", "application/json", (request, response) -> {
return reinit();
});
// http://ip_address:port/system/control/stop CORS request
options(SYSTEM_CONTEXT + "/control/stop", "application/json", (request, response) -> {
response.status(HttpStatus.SC_OK);
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
response.header("Access-Control-Allow-Methods", "GET, POST, PUT");
response.header("Access-Control-Allow-Headers", request.headers("Access-Control-Request-Headers"));
response.header("Content-Type", "text/html; charset=utf-8");
return "";
});
// http://ip_address:port/system/control/stop sets the parameter stop the server
put(SYSTEM_CONTEXT + "/control/stop", "application/json", (request, response) -> {
return stop();
});
// http://ip_address:port/system/backup/available returns a list of config backup filenames
get (SYSTEM_CONTEXT + "/backup/available", "application/json", (request, response) -> {
log.debug("Get backup filenames");
response.status(HttpStatus.SC_OK);
return bridgeSettings.getBackups();
}, new JsonTransformer());
// http://ip_address:port/system/backup/create CORS request
options(SYSTEM_CONTEXT + "/backup/create", "application/json", (request, response) -> {
response.status(HttpStatus.SC_OK);
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
response.header("Access-Control-Allow-Methods", "PUT");
response.header("Access-Control-Allow-Headers", request.headers("Access-Control-Request-Headers"));
response.header("Content-Type", "text/html; charset=utf-8");
return "";
});
put (SYSTEM_CONTEXT + "/backup/create", "application/json", (request, response) -> {
log.debug("Create backup: " + request.body());
BackupFilename aFilename = new Gson().fromJson(request.body(), BackupFilename.class);
BackupFilename returnFilename = new BackupFilename();
returnFilename.setFilename(bridgeSettings.backup(aFilename.getFilename()));
return returnFilename;
}, new JsonTransformer());
// http://ip_address:port/system/backup/delete CORS request
options(SYSTEM_CONTEXT + "/backup/delete", "application/json", (request, response) -> {
response.status(HttpStatus.SC_OK);
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
response.header("Access-Control-Allow-Methods", "POST");
response.header("Access-Control-Allow-Headers", request.headers("Access-Control-Request-Headers"));
response.header("Content-Type", "text/html; charset=utf-8");
return "";
});
post (SYSTEM_CONTEXT + "/backup/delete", "application/json", (request, response) -> {
log.debug("Delete backup: " + request.body());
BackupFilename aFilename = new Gson().fromJson(request.body(), BackupFilename.class);
if(aFilename != null)
bridgeSettings.deleteBackup(aFilename.getFilename());
else
log.warn("No filename given for delete backup.");
return null;
}, new JsonTransformer());
// http://ip_address:port/system/backup/restore CORS request
options(SYSTEM_CONTEXT + "/backup/restore", "application/json", (request, response) -> {
response.status(HttpStatus.SC_OK);
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
response.header("Access-Control-Allow-Methods", "POST");
response.header("Access-Control-Allow-Headers", request.headers("Access-Control-Request-Headers"));
response.header("Content-Type", "text/html; charset=utf-8");
return "";
});
post (SYSTEM_CONTEXT + "/backup/restore", "application/json", (request, response) -> {
log.debug("Restore backup: " + request.body());
BackupFilename aFilename = new Gson().fromJson(request.body(), BackupFilename.class);
if(aFilename != null) {
bridgeSettings.restoreBackup(aFilename.getFilename());
bridgeSettings.loadConfig();
}
else
log.warn("No filename given for restore backup.");
return null;
}, new JsonTransformer());
}
protected void pingListener() {
try {
byte[] buf = new byte[256];
String testData = "M-SEARCH * HTTP/1.1\nHOST: " + Configuration.UPNP_MULTICAST_ADDRESS + ":" + Configuration.UPNP_DISCOVERY_PORT + "ST: urn:schemas-upnp-org:device:CloudProxy:1\nMAN: \"ssdp:discover\"\nMX: 3";
buf = testData.getBytes();
MulticastSocket socket = new MulticastSocket(Configuration.UPNP_DISCOVERY_PORT);
InetAddress group = InetAddress.getByName(Configuration.UPNP_MULTICAST_ADDRESS);
DatagramPacket packet;
packet = new DatagramPacket(buf, buf.length, group, Configuration.UPNP_DISCOVERY_PORT);
socket.send(packet);
socket.close();
}
catch (IOException e) {
log.warn("Error pinging listener.", e);
}
}
public String reinit() {
bridgeSettings.setReinit(true);
pingListener();
return "{\"control\":\"reiniting\"}";
}
public String stop() {
bridgeSettings.setStop(true);
pingListener();
return "{\"control\":\"stopping\"}";
}
}

View File

@@ -3,23 +3,19 @@ package com.bwssystems.HABridge.dao;
import java.io.IOException;
import java.io.StringReader;
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.HashMap;
import java.util.Map;
import java.util.Random;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.bwssystems.HABridge.BackupHandler;
import com.bwssystems.HABridge.JsonTransformer;
import com.bwssystems.HABridge.dao.DeviceDescriptor;
import com.google.gson.stream.JsonReader;
@@ -30,7 +26,7 @@ import java.util.ListIterator;
* This is an in memory list to manage the configured devices and saves the list as a JSON string to a file for later
* loading.
*/
public class DeviceRepository {
public class DeviceRepository extends BackupHandler {
Map<String, DeviceDescriptor> devices;
Path repositoryPath;
final Random random = new Random();
@@ -38,14 +34,16 @@ public class DeviceRepository {
public DeviceRepository(String deviceDb) {
super();
_loadRepository(deviceDb);
repositoryPath = null;
repositoryPath = Paths.get(deviceDb);
setupParams(repositoryPath, ".bk", "device.db-");
_loadRepository(repositoryPath);
}
private void _loadRepository(String aFilePath){
repositoryPath = Paths.get(aFilePath);
_loadRepository(repositoryPath);
public void loadRepository() {
if(repositoryPath != null)
_loadRepository(repositoryPath);
}
private void _loadRepository(Path aPath){
String jsonContent = repositoryReader(aPath);
devices = new HashMap<String, DeviceDescriptor>();
@@ -93,66 +91,6 @@ public class DeviceRepository {
log.debug("Save device: " + aDescriptor.getName());
}
public String backup(String aFilename) {
if(aFilename == null || aFilename.equalsIgnoreCase("")) {
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
aFilename = "devicedb-" + dateFormat.format(Calendar.getInstance().getTime()) + ".bk";
}
else
aFilename = aFilename + ".bk";
try {
Files.copy(repositoryPath, FileSystems.getDefault().getPath(repositoryPath.getParent().toString(), aFilename), StandardCopyOption.COPY_ATTRIBUTES);
} catch (IOException e) {
log.error("Could not backup to file: " + aFilename + " message: " + e.getMessage(), e);
}
log.debug("Backup repository: " + aFilename);
return aFilename;
}
public String deleteBackup(String aFilename) {
log.debug("Delete backup repository: " + aFilename);
try {
Files.delete(FileSystems.getDefault().getPath(repositoryPath.getParent().toString(), aFilename));
} catch (IOException e) {
log.error("Could not delete file: " + aFilename + " message: " + e.getMessage(), e);
}
return aFilename;
}
public String restoreBackup(String aFilename) {
log.debug("Restore backup repository: " + aFilename);
try {
Path target = null;
if(Files.exists(repositoryPath)) {
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
target = FileSystems.getDefault().getPath(repositoryPath.getParent().toString(), "devicedb-" + dateFormat.format(Calendar.getInstance().getTime()) + ".bk");
Files.move(repositoryPath, target);
}
Files.copy(FileSystems.getDefault().getPath(repositoryPath.getParent().toString(), aFilename), repositoryPath, StandardCopyOption.COPY_ATTRIBUTES);
} catch (IOException e) {
log.error("Error restoring the file: " + aFilename + " message: " + e.getMessage(), e);
return null;
}
_loadRepository(repositoryPath);
return aFilename;
}
public List<String> getBackups() {
List<String> theFilenames = new ArrayList<String>();
Path dir = repositoryPath.getParent();
try (DirectoryStream<Path> 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 direcotyr listing for backups - " + x.getMessage());
}
return theFilenames;
}
public String delete(DeviceDescriptor aDescriptor) {
if (aDescriptor != null) {
devices.remove(aDescriptor.getId());

View File

@@ -16,8 +16,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.bwssystems.HABridge.BridgeSettings;
import com.bwssystems.HABridge.BridgeSettingsDescriptor;
import com.bwssystems.HABridge.JsonTransformer;
import com.bwssystems.HABridge.Version;
import com.bwssystems.HABridge.dao.BackupFilename;
import com.bwssystems.HABridge.dao.DeviceDescriptor;
import com.bwssystems.HABridge.dao.DeviceRepository;
@@ -35,12 +35,11 @@ public class DeviceResource {
private DeviceRepository deviceRepository;
private VeraHome veraHome;
private Version version;
private HarmonyHome myHarmonyHome;
private NestHome nestHome;
private static final Set<String> supportedVerbs = new HashSet<>(Arrays.asList("get", "put", "post"));
public DeviceResource(BridgeSettings theSettings, Version theVersion, HarmonyHome theHarmonyHome, NestHome aNestHome) {
public DeviceResource(BridgeSettingsDescriptor theSettings, HarmonyHome theHarmonyHome, NestHome aNestHome) {
this.deviceRepository = new DeviceRepository(theSettings.getUpnpDeviceDb());
if(theSettings.isValidVera())
@@ -58,7 +57,6 @@ public class DeviceResource {
else
this.nestHome = null;
this.version = theVersion;
setupEndpoints();
}
@@ -172,12 +170,6 @@ public class DeviceResource {
return null;
}, new JsonTransformer());
get (API_CONTEXT + "/habridge/version", "application/json", (request, response) -> {
log.debug("Get HA Bridge version: v" + version.getVersion());
response.status(HttpStatus.SC_OK);
return "{\"version\":\"" + version.getVersion() + "\"}";
});
get (API_CONTEXT + "/vera/devices", "application/json", (request, response) -> {
log.debug("Get vera devices");
if(veraHome == null){
@@ -293,8 +285,10 @@ public class DeviceResource {
post (API_CONTEXT + "/backup/restore", "application/json", (request, response) -> {
log.debug("Restore backup: " + request.body());
BackupFilename aFilename = new Gson().fromJson(request.body(), BackupFilename.class);
if(aFilename != null)
if(aFilename != null) {
deviceRepository.restoreBackup(aFilename.getFilename());
deviceRepository.loadRepository();
}
else
log.warn("No filename given for restore backup.");
return null;

View File

@@ -1,7 +1,6 @@
package com.bwssystems.HABridge.hue;
import com.bwssystems.HABridge.BridgeSettings;
import com.bwssystems.HABridge.Configuration;
import com.bwssystems.HABridge.BridgeSettingsDescriptor;
import com.bwssystems.HABridge.JsonTransformer;
import com.bwssystems.HABridge.api.UserCreateRequest;
import com.bwssystems.HABridge.api.hue.DeviceResponse;
@@ -46,7 +45,6 @@ import java.math.BigDecimal;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -71,11 +69,11 @@ public class HueMulator {
private Nest theNest;
private HttpClient httpClient;
private ObjectMapper mapper;
private BridgeSettings bridgeSettings;
private BridgeSettingsDescriptor bridgeSettings;
private byte[] sendData;
public HueMulator(BridgeSettings theBridgeSettings, DeviceRepository aDeviceRepository, HarmonyHome theHarmonyHome, NestHome aNestHome){
public HueMulator(BridgeSettingsDescriptor theBridgeSettings, DeviceRepository aDeviceRepository, HarmonyHome theHarmonyHome, NestHome aNestHome){
httpClient = HttpClients.createDefault();
mapper = new ObjectMapper(); //armzilla: work around Echo incorrect content type and breaking mapping. Map manually
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
@@ -441,38 +439,6 @@ public class HueMulator {
return responseString;
});
// http://ip_address:port/api/control/restart CORS request
options(HUE_CONTEXT + "/control/restart", "application/json", (request, response) -> {
response.status(HttpStatus.SC_OK);
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
response.header("Access-Control-Allow-Methods", "GET, POST, PUT");
response.header("Access-Control-Allow-Headers", request.headers("Access-Control-Request-Headers"));
response.header("Content-Type", "text/html; charset=utf-8");
return "";
});
// http://ip_address:port/api//control/restart sets the parameter restart the server
put(HUE_CONTEXT + "/control/restart", "application/json", (request, response) -> {
bridgeSettings.setRestart(true);
pingListener();
return "{\"control\":\"restarting\"}";
});
// http://ip_address:port/api/control/stop CORS request
options(HUE_CONTEXT + "/control/stop", "application/json", (request, response) -> {
response.status(HttpStatus.SC_OK);
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
response.header("Access-Control-Allow-Methods", "GET, POST, PUT");
response.header("Access-Control-Allow-Headers", request.headers("Access-Control-Request-Headers"));
response.header("Content-Type", "text/html; charset=utf-8");
return "";
});
// http://ip_address:port/api//control/stop sets the parameter stop the server
put(HUE_CONTEXT + "/control/stop", "application/json", (request, response) -> {
bridgeSettings.setStop(true);
pingListener();
return "{\"control\":\"stopping\"}";
});
}
/* light weight templating here, was going to use free marker but it was a bit too
@@ -544,23 +510,4 @@ public class HueMulator {
}
return false;
}
protected void pingListener() {
try {
byte[] buf = new byte[256];
String testData = "M-SEARCH * HTTP/1.1\nHOST: " + Configuration.UPNP_MULTICAST_ADDRESS + ":" + Configuration.UPNP_DISCOVERY_PORT + "ST: urn:schemas-upnp-org:device:CloudProxy:1\nMAN: \"ssdp:discover\"\nMX: 3";
buf = testData.getBytes();
MulticastSocket socket = new MulticastSocket(Configuration.UPNP_DISCOVERY_PORT);
InetAddress group = InetAddress.getByName(Configuration.UPNP_MULTICAST_ADDRESS);
DatagramPacket packet;
packet = new DatagramPacket(buf, buf.length, group, Configuration.UPNP_DISCOVERY_PORT);
socket.send(packet);
socket.close();
}
catch (IOException e) {
log.warn("Error pinging listener.", e);
}
}
}

View File

@@ -80,21 +80,27 @@ public class UpnpListener {
if(isSSDPDiscovery(packet)){
sendUpnpResponse(responseSocket, packet.getAddress(), packet.getPort());
}
if(bridgeSettings.isRestart() || bridgeSettings.isStop())
if(bridgeSettings.isReinit() || bridgeSettings.isStop()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// noop
}
loopControl = false;
}
}
upnpMulticastSocket.close();
responseSocket.close();
} catch (IOException e) {
log.error("UpnpListener encountered an error opening sockets. Shutting down", e);
}
if(bridgeSettings.isRestart())
if(bridgeSettings.isReinit())
log.info("UPNP Discovery Listener - ended, restart found");
if(bridgeSettings.isStop())
log.info("UPNP Discovery Listener - ended, stop found");
if(!bridgeSettings.isStop()&& !bridgeSettings.isRestart())
if(!bridgeSettings.isStop()&& !bridgeSettings.isReinit())
log.info("UPNP Discovery Listener - ended, error found");
return bridgeSettings.isRestart();
return bridgeSettings.isReinit();
}
/**

View File

@@ -3,8 +3,7 @@ package com.bwssystems.HABridge.upnp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.bwssystems.HABridge.BridgeSettings;
import com.bwssystems.HABridge.JsonTransformer;
import com.bwssystems.HABridge.BridgeSettingsDescriptor;
import static spark.Spark.get;
@@ -12,11 +11,9 @@ import static spark.Spark.get;
*
*/
public class UpnpSettingsResource {
private static final String UPNP_CONTEXT = "/upnp";
private Logger log = LoggerFactory.getLogger(UpnpSettingsResource.class);
private BridgeSettings theSettings;
private BridgeSettingsDescriptor theSettings;
private String hueTemplate = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" + "<root xmlns=\"urn:schemas-upnp-org:device-1-0\">\n"
+ "<specVersion>\n" + "<major>1</major>\n" + "<minor>0</minor>\n" + "</specVersion>\n"
@@ -40,22 +37,9 @@ public class UpnpSettingsResource {
+ "<depth>24</depth>\n" + "<url>hue_logo_3.png</url>\n" + "</icon>\n" + "</iconList>\n" + "</device>\n"
+ "</root>\n";
public UpnpSettingsResource(BridgeSettings theBridgeSettings) {
public UpnpSettingsResource(BridgeSettingsDescriptor theBridgeSettings) {
super();
this.theSettings = new BridgeSettings();
this.theSettings.setDevMode(theBridgeSettings.isDevMode());
this.theSettings.setHarmonyAddress(theBridgeSettings.getHarmonyAddress());
this.theSettings.setServerPort(theBridgeSettings.getServerPort());
this.theSettings.setTraceupnp(theBridgeSettings.isTraceupnp());
this.theSettings.setUpnpConfigAddress(theBridgeSettings.getUpnpConfigAddress());
this.theSettings.setUpnpDeviceDb(theBridgeSettings.getUpnpDeviceDb());
this.theSettings.setButtonsleep(theBridgeSettings.getButtonsleep());
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());
this.theSettings = theBridgeSettings;
}
public void setupServer() {
@@ -88,14 +72,5 @@ public class UpnpSettingsResource {
return filledTemplate;
} );
// http://ip_address:port/upnp/settings which returns the bridge configuration settings
get(UPNP_CONTEXT + "/settings", "application/json", (request, response) -> {
log.debug("bridge settings requested from " + request.ip());
response.status(200);
return theSettings;
}, new JsonTransformer());
}
}

View File

@@ -8,7 +8,7 @@ import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.bwssystems.HABridge.BridgeSettings;
import com.bwssystems.HABridge.BridgeSettingsDescriptor;
import com.bwssystems.nest.controller.Home;
import com.bwssystems.nest.controller.Nest;
import com.bwssystems.nest.controller.NestSession;
@@ -23,7 +23,7 @@ public class NestHome {
private Nest theNest;
private ArrayList<NestItem> nestItems;
public NestHome(BridgeSettings bridgeSettings) {
public NestHome(BridgeSettingsDescriptor bridgeSettings) {
theSession = null;
theNest = null;
nestItems = null;

View File

@@ -11,6 +11,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.bwssystems.HABridge.BridgeSettings;
import com.bwssystems.HABridge.BridgeSettingsDescriptor;
import com.bwssystems.HABridge.IpList;
import com.bwssystems.HABridge.NamedIP;
@@ -21,7 +22,7 @@ public class HarmonyHome {
private static final Logger log = LoggerFactory.getLogger(HarmonyHome.class);
private Map<String, HarmonyServer> hubs;
public HarmonyHome(BridgeSettings bridgeSettings) {
public HarmonyHome(BridgeSettingsDescriptor bridgeSettings) {
super();
hubs = new HashMap<String, HarmonyServer>();
if(!bridgeSettings.isValidHarmony() && !bridgeSettings.isDevMode())

View File

@@ -7,7 +7,7 @@ import javax.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.bwssystems.HABridge.BridgeSettings;
import com.bwssystems.HABridge.BridgeSettingsDescriptor;
import com.bwssystems.HABridge.NamedIP;
import com.google.inject.Guice;
import com.google.inject.Injector;
@@ -36,7 +36,7 @@ public class HarmonyServer {
myNameAndIP = theHarmonyAddress;
}
public static HarmonyServer setup(BridgeSettings bridgeSettings, NamedIP theHarmonyAddress) throws Exception {
public static HarmonyServer setup(BridgeSettingsDescriptor bridgeSettings, NamedIP theHarmonyAddress) throws Exception {
if(!bridgeSettings.isValidHarmony() && !bridgeSettings.isDevMode()) {
return new HarmonyServer(theHarmonyAddress);
}
@@ -50,7 +50,7 @@ public class HarmonyServer {
return mainObject;
}
private void execute(BridgeSettings mySettings) throws Exception {
private void execute(BridgeSettingsDescriptor mySettings) throws Exception {
Boolean noopCalls = Boolean.parseBoolean(System.getProperty("noop.calls", "false"));
String modeString = "";
if(dummyProvider != null)

View File

@@ -9,7 +9,7 @@ import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.bwssystems.HABridge.BridgeSettings;
import com.bwssystems.HABridge.BridgeSettingsDescriptor;
import com.bwssystems.HABridge.NamedIP;
import com.bwssystems.luupRequests.Device;
import com.bwssystems.luupRequests.Scene;
@@ -18,7 +18,7 @@ public class VeraHome {
private static final Logger log = LoggerFactory.getLogger(VeraHome.class);
private Map<String, VeraInfo> veras;
public VeraHome(BridgeSettings bridgeSettings) {
public VeraHome(BridgeSettingsDescriptor bridgeSettings) {
veras = new HashMap<String, VeraInfo>();
if(!bridgeSettings.isValidVera())
return;

View File

@@ -4,6 +4,9 @@ app.config(function ($routeProvider) {
$routeProvider.when('/#', {
templateUrl: 'views/configuration.html',
controller: 'ViewingController'
}).when('/system', {
templateUrl: 'views/system.html',
controller: 'SystemController'
}).when('/editor', {
templateUrl: 'views/editor.html',
controller: 'AddingController'
@@ -38,7 +41,7 @@ app.run( function (bridgeService) {
app.service('bridgeService', function ($http, $window, ngToast) {
var self = this;
this.state = {base: window.location.origin + "/api/devices", upnpbase: window.location.origin + "/upnp/settings", huebase: window.location.origin + "/api", backups: [], devices: [], device: [], settings: [], olddevicename: "", error: "", showVera: false, showHarmony: false, showNest: false, habridgeversion: ""};
this.state = {base: window.location.origin + "/api/devices", systemsbase: window.location.origin + "/system", huebase: window.location.origin + "/api", configs: [], backups: [], devices: [], device: [], settings: [], olddevicename: "", error: "", showVera: false, showHarmony: false, showNest: false, habridgeversion: ""};
this.viewDevices = function () {
this.state.error = "";
@@ -59,7 +62,7 @@ app.service('bridgeService', function ($http, $window, ngToast) {
this.getHABridgeVersion = function () {
this.state.error = "";
return $http.get(this.state.base + "/habridge/version").then(
return $http.get(this.state.systemsbase + "/habridge/version").then(
function (response) {
self.state.habridgeversion = response.data.version;
},
@@ -96,7 +99,7 @@ app.service('bridgeService', function ($http, $window, ngToast) {
this.loadBridgeSettings = function () {
this.state.error = "";
return $http.get(this.state.upnpbase).then(
return $http.get(this.state.systemsbase + "/settings").then(
function (response) {
self.state.settings = response.data;
self.updateShowVera();
@@ -130,6 +133,22 @@ app.service('bridgeService', function ($http, $window, ngToast) {
);
};
this.viewConfigs = function () {
this.state.error = "";
return $http.get(this.state.systemsbase + "/backup/available").then(
function (response) {
self.state.configs = response.data;
},
function (error) {
if (error.data) {
$window.alert("Get Configs Error: " + error.data.message);
} else {
$window.alert("Get Configs Error: unknown");
}
}
);
};
this.viewNestItems = function () {
this.state.error = "";
if(!this.state.showNest)
@@ -344,7 +363,59 @@ app.service('bridgeService', function ($http, $window, ngToast) {
if (error.data) {
self.state.error = error.data.message;
}
self.state.error = "Backup Db File Error: unknown";
self.state.error = "Delete Backup Db File Error: unknown";
}
);
};
this.backupSettings = function (afilename) {
this.state.error = "";
return $http.put(this.state.systemsbase + "/backup/create", {
filename: afilename
}).then(
function (response) {
self.viewConfigs();
},
function (error) {
if (error.data) {
self.state.error = error.data.message;
}
self.state.error = "Backup Settings Error: unknown";
}
);
};
this.restoreSettings = function (afilename) {
this.state.error = "";
return $http.post(this.state.systemsbase + "/backup/restore", {
filename: afilename
}).then(
function (response) {
self.viewConfigs();
self.viewDevices();
},
function (error) {
if (error.data) {
self.state.error = error.data.message;
}
self.state.error = "Backup Settings Restore Error: unknown";
}
);
};
this.deleteSettingsBackup = function (afilename) {
this.state.error = "";
return $http.post(this.state.systemsbase + "/backup/delete", {
filename: afilename
}).then(
function (response) {
self.viewConfigs();
},
function (error) {
if (error.data) {
self.state.error = error.data.message;
}
self.state.error = "Delete Backup Settings File Error: unknown";
}
);
};
@@ -410,6 +481,46 @@ app.service('bridgeService', function ($http, $window, ngToast) {
};
});
app.controller('SystemController', function ($scope, $location, $http, $window, bridgeService) {
bridgeService.viewConfigs();
$scope.bridge = bridgeService.state;
$scope.optionalbackupname = "";
$scope.visible = false;
$scope.imgUrl = "glyphicon glyphicon-plus";
$scope.visibleBk = false;
$scope.imgBkUrl = "glyphicon glyphicon-plus";
$scope.setBridgeUrl = function (url) {
bridgeService.state.base = url;
bridgeService.viewDevices();
};
$scope.goBridgeUrl = function (url) {
window.open(url, "_blank");
};
$scope.backupSettings = function (optionalbackupname) {
bridgeService.backupSettings(optionalbackupname);
};
$scope.restoreSettings = function (backupname) {
bridgeService.restoreSettings(backupname);
};
$scope.deleteSettingsBackup = function (backupname) {
bridgeService.deleteSettingsBackup(backupname);
};
$scope.toggle = function () {
$scope.visible = !$scope.visible;
if($scope.visible)
$scope.imgUrl = "glyphicon glyphicon-minus";
else
$scope.imgUrl = "glyphicon glyphicon-plus";
};
$scope.toggleBk = function () {
$scope.visibleBk = !$scope.visibleBk;
if($scope.visibleBk)
$scope.imgBkUrl = "glyphicon glyphicon-minus";
else
$scope.imgBkUrl = "glyphicon glyphicon-plus";
};
});
app.controller('ViewingController', function ($scope, $location, $http, $window, bridgeService) {
bridgeService.viewDevices();
@@ -432,13 +543,6 @@ app.controller('ViewingController', function ($scope, $location, $http, $window,
$scope.testUrl = function (device, type) {
bridgeService.testUrl(device, type);
};
$scope.setBridgeUrl = function (url) {
bridgeService.state.base = url;
bridgeService.viewDevices();
};
$scope.goBridgeUrl = function (url) {
window.open(url, "_blank");
};
$scope.editDevice = function (device) {
bridgeService.editDevice(device);
$location.path('/editdevice');

View File

@@ -1,5 +1,6 @@
<ul class="nav nav-pills" role="tablist">
<li role="presentation" class="active"><a href="#">Configuration</a></li>
<li role="presentation" class="active"><a href="#">Bridge Devices</a></li>
<li role="presentation"><a href="#/system">Bridge Control</a></li>
<li ng-if="bridge.showVera" role="presentation"><a href="#/veradevices">Vera Devices</a></li>
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>
@@ -64,82 +65,6 @@
</tr>
</table>
</div>
<div class="panel panel-default bridgeServer">
<div class="panel-heading">
<h1 class="panel-title">Bridge Settings <a ng-click="toggle()"><span class={{imgUrl}} aria-hidden="true"></a></h1>
</div>
<div ng-if="visible" class="animate-if" class="panel-body">
<form class="form-horizontal">
<div class="form-group">
<label class="col-xs-12 col-sm-2 control-label" for="bridge-base">Bridge
server</label>
<div class="col-xs-8 col-sm-7">
<input id="bridge-base" class="form-control" type="text"
ng-model="bridge.base" placeholder="URL to bridge">
</div>
<button type="submit" class="col-xs-2 col-sm-1 btn btn-primary"
ng-click="setBridgeUrl(bridge.base)">Load</button>
<button type="submit" class="col-xs-2 col-sm-1 btn btn-primary"
ng-click="goBridgeUrl(bridge.base)">Go</button>
</div>
</form>
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th>Setting</th>
<th>Value</th>
</tr>
</thead>
<tr>
<td>upnp.config.address</td>
<td>{{bridge.settings.upnpconfigaddress}}</td>
</tr>
<tr>
<td>server.port</td>
<td>{{bridge.settings.serverport}}</td>
</tr>
<tr>
<td>upnp.devices.db</td>
<td>{{bridge.settings.upnpdevicedb}}</td>
</tr>
<tr>
<td>upnp.response.port</td>
<td>{{bridge.settings.upnpresponseport}}</td>
</tr>
<tr>
<td>vera.address</td>
<td>{{bridge.settings.veraaddress}}</td>
</tr>
<tr>
<td>harmony.address</td>
<td>{{bridge.settings.harmonyaddress}}</td>
</tr>
<tr>
<td>upnp.strict</td>
<td>{{bridge.settings.upnpstrict}}</td>
</tr>
<tr>
<td>trace.upnp</td>
<td>{{bridge.settings.traceupnp}}</td>
</tr>
<tr>
<td>dev.mode</td>
<td>{{bridge.settings.devmode}}</td>
</tr>
<tr>
<td>nest.configured</td>
<td>{{bridge.settings.nestconfigured}}</td>
</tr>
<tr>
<td>button.sleep</td>
<td>{{bridge.settings.buttonsleep}} ms</td>
</tr>
</table>
</div>
</div>
<div class="panel panel-default backup">
<div class="panel-heading">
<h1 class="panel-title">Bridge Device DB Backup <a ng-click="toggleBk()"><span class={{imgBkUrl}} aria-hidden="true"></a></h1>

View File

@@ -1,5 +1,6 @@
<ul class="nav nav-pills" role="tablist">
<li role="presentation"><a href="#">Configuration</a></li>
<li role="presentation"><a href="#">Bridge Devices</a></li>
<li role="presentation"><a href="#/system">Bridge Control</a></li>
<li ng-if="bridge.showVera" role="presentation"><a href="#/veradevices">Vera Devices</a></li>
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>

View File

@@ -1,5 +1,6 @@
<ul class="nav nav-pills" role="tablist">
<li role="presentation"><a href="#">Configuration</a></li>
<li role="presentation"><a href="#">Bridge Devices</a></li>
<li role="presentation"><a href="#/system">Bridge Control</a></li>
<li ng-if="bridge.showVera" role="presentation"><a href="#/veradevices">Vera Devices</a></li>
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>

View File

@@ -1,5 +1,6 @@
<ul class="nav nav-pills" role="tablist">
<li role="presentation"><a href="#">Configuration</a></li>
<li role="presentation"><a href="#">Bridge Devices</a></li>
<li role="presentation"><a href="#/system">Bridge Control</a></li>
<li ng-if="bridge.showVera" role="presentation"><a href="#/veradevices">Vera Devices</a></li>
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
<li role="presentation" class="active"><a href="#/harmonyactivities">Harmony Activities</a></li>

View File

@@ -1,5 +1,6 @@
<ul class="nav nav-pills" role="tablist">
<li role="presentation"><a href="#">Configuration</a></li>
<li role="presentation"><a href="#">Bridge Devices</a></li>
<li role="presentation"><a href="#/system">Bridge Control</a></li>
<li ng-if="bridge.showVera" role="presentation"><a href="#/veradevices">Vera Devices</a></li>
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
<li role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>

View File

@@ -1,5 +1,6 @@
<ul class="nav nav-pills" role="tablist">
<li role="presentation"><a href="#">Configuration</a></li>
<li role="presentation"><a href="#">Bridge Devices</a></li>
<li role="presentation"><a href="#/system">Bridge Control</a></li>
<li ng-if="bridge.showVera" role="presentation"><a href="#/veradevices">Vera Devices</a></li>
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>

View File

@@ -0,0 +1,137 @@
<ul class="nav nav-pills" role="tablist">
<li role="presentation"><a href="#">Bridge Devices</a></li>
<li role="presentation" class="active"><a href="#/system">Bridge Control</a></li>
<li ng-if="bridge.showVera" role="presentation"><a href="#/veradevices">Vera Devices</a></li>
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonydevices">Harmony Devices</a></li>
<li ng-if="bridge.showNest" role="presentation"><a href="#/nest">Nest</a></li>
<li role="presentation"><a href="#/editor">Manual Add</a></li>
</ul>
<div ng-controller="ErrorsController">
<div ng-if="bridge.error"
class="alert alert-warning alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert"
aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
<h2 ng-show='bridge.error != ""'>ERROR</h2>
<div ng-show='bridge.error != ""'>{{bridge.error}}</div>
</div>
</div>
<div class="panel panel-default bridgeServer">
<div class="panel-heading">
<h1 class="panel-title">Bridge Settings</h1>
</div>
<div class="panel-body">
<form class="form-horizontal">
<div class="form-group">
<label class="col-xs-12 col-sm-2 control-label" for="bridge-base">Bridge
server</label>
<div class="col-xs-8 col-sm-7">
<input id="bridge-base" class="form-control" type="text"
ng-model="bridge.base" placeholder="URL to bridge">
</div>
<button type="submit" class="col-xs-2 col-sm-1 btn btn-primary"
ng-click="setBridgeUrl(bridge.base)">Load</button>
<button type="submit" class="col-xs-2 col-sm-1 btn btn-primary"
ng-click="goBridgeUrl(bridge.base)">Go</button>
</div>
</form>
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th>Setting</th>
<th>Value</th>
</tr>
</thead>
<tr>
<td>upnp.config.address</td>
<td>{{bridge.settings.upnpconfigaddress}}</td>
</tr>
<tr>
<td>server.port</td>
<td>{{bridge.settings.serverport}}</td>
</tr>
<tr>
<td>upnp.devices.db</td>
<td>{{bridge.settings.upnpdevicedb}}</td>
</tr>
<tr>
<td>upnp.response.port</td>
<td>{{bridge.settings.upnpresponseport}}</td>
</tr>
<tr>
<td>vera.address</td>
<td>{{bridge.settings.veraaddress}}</td>
</tr>
<tr>
<td>harmony.address</td>
<td>{{bridge.settings.harmonyaddress}}</td>
</tr>
<tr>
<td>upnp.strict</td>
<td>{{bridge.settings.upnpstrict}}</td>
</tr>
<tr>
<td>trace.upnp</td>
<td>{{bridge.settings.traceupnp}}</td>
</tr>
<tr>
<td>dev.mode</td>
<td>{{bridge.settings.devmode}}</td>
</tr>
<tr>
<td>nest.configured</td>
<td>{{bridge.settings.nestconfigured}}</td>
</tr>
<tr>
<td>button.sleep</td>
<td>{{bridge.settings.buttonsleep}} ms</td>
</tr>
</table>
</div>
</div>
<div class="panel panel-default backup">
<div class="panel-heading">
<h1 class="panel-title">Bridge Settings Backup <a ng-click="toggleBk()"><span class={{imgBkUrl}} aria-hidden="true"></a></h1>
</div>
<div ng-if="visibleBk" class="animate-if" class="panel-body">
<form class="form-horizontal">
<div class="form-group">
<label class="col-xs-12 col-sm-2 control-label" for="backup-name">Backup Settings File Name</label>
<div class="col-xs-8 col-sm-7">
<input id="backup-name" class="form-control" type="text"
ng-model="optionalbackupname" placeholder="Optional">
</div>
<button type="submit" class="btn btn-primary"
ng-click="backupSettings(optionalbackupname)">Backup Settings</button>
</div>
</form>
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th>Filename</th>
<th>Actions</th>
</tr>
</thead>
<tr ng-repeat="backup in bridge.configs">
<td>{{backup}}</td>
<td>
<button class="btn btn-danger" type="submit"
ng-click="restoreSettings(backup)">Restore</button>
<button class="btn btn-warning" type="submit"
ng-click="deleteSettingsBackup(backup)">Delete</button>
</td>
</tr>
</table>
</div>
</div>

View File

@@ -1,5 +1,6 @@
<ul class="nav nav-pills" role="tablist">
<li role="presentation"><a href="#">Configuration</a></li>
<li role="presentation"><a href="#">Bridge Devices</a></li>
<li role="presentation"><a href="#/system">Bridge Control</a></li>
<li role="presentation" class="active"><a href="#/veradevices">Vera Devices</a></li>
<li role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>

View File

@@ -1,5 +1,6 @@
<ul class="nav nav-pills" role="tablist">
<li role="presentation"><a href="#">Configuration</a></li>
<li role="presentation"><a href="#">Bridge Devices</a></li>
<li role="presentation"><a href="#/system">Bridge Control</a></li>
<li role="presentation"><a href="#/veradevices">Vera Devices</a></li>
<li role="presentation" class="active"><a href="#/verascenes">Vera Scenes</a></li>
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>