diff --git a/pom.xml b/pom.xml
index 88faba8..623a4ea 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
com.bwssystems.HABridge
ha-bridge
- 1.3.8
+ 1.3.8a
jar
HA Bridge
diff --git a/src/main/java/com/bwssystems/HABridge/BridgeSettings.java b/src/main/java/com/bwssystems/HABridge/BridgeSettings.java
index eeb0846..f931859 100644
--- a/src/main/java/com/bwssystems/HABridge/BridgeSettings.java
+++ b/src/main/java/com/bwssystems/HABridge/BridgeSettings.java
@@ -18,6 +18,9 @@ public class BridgeSettings {
private String nestuser;
private String nestpwd;
private boolean nestconfigured;
+ private String configfile;
+ private boolean restart;
+ private boolean stop;
public String getUpnpConfigAddress() {
return upnpconfigaddress;
@@ -109,6 +112,24 @@ public class BridgeSettings {
public void setButtonsleep(Integer buttonsleep) {
this.buttonsleep = buttonsleep;
}
+ public boolean isRestart() {
+ return restart;
+ }
+ public void setRestart(boolean restart) {
+ this.restart = restart;
+ }
+ public boolean isStop() {
+ return stop;
+ }
+ public void setStop(boolean stop) {
+ this.stop = stop;
+ }
+ public String getConfigfile() {
+ return configfile;
+ }
+ public void setConfigfile(String configfile) {
+ this.configfile = configfile;
+ }
public Boolean isValidVera() {
List devicesList = this.veraaddress.getDevices();
if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS))
diff --git a/src/main/java/com/bwssystems/HABridge/Configuration.java b/src/main/java/com/bwssystems/HABridge/Configuration.java
index 26b3bac..5c0c0bd 100644
--- a/src/main/java/com/bwssystems/HABridge/Configuration.java
+++ b/src/main/java/com/bwssystems/HABridge/Configuration.java
@@ -12,4 +12,7 @@ public class Configuration {
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;
+ public static final String UPNP_MULTICAST_ADDRESS = "239.255.255.250";
+ public static final String CONFIG_FILE = "data/habridge.config";
}
diff --git a/src/main/java/com/bwssystems/HABridge/HABridge.java b/src/main/java/com/bwssystems/HABridge/HABridge.java
index d1c9b50..6818ce3 100644
--- a/src/main/java/com/bwssystems/HABridge/HABridge.java
+++ b/src/main/java/com/bwssystems/HABridge/HABridge.java
@@ -51,102 +51,114 @@ public class HABridge {
theVersion = new Version();
- log.info("HA Bridge (v" + theVersion.getVersion() + ") starting setup....");
+ log.info("HA Bridge (v" + theVersion.getVersion() + ") starting....");
bridgeSettings = new BridgeSettings();
- 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("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.");
+ 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;
}
- } catch (SocketException e) {
- log.error("Cannot get ip address of this host, Exiting with message: " + e.getMessage(), e);
- return;
- }
+
+ bridgeSettings.setUpnpConfigAddress(addressString);
+ }
- 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.setUpnpDeviceDb(System.getProperty("upnp.device.db", Configuration.DEVICE_DB_DIRECTORY));
- bridgeSettings.setUpnpResponsePort(System.getProperty("upnp.response.port", Configuration.UPNP_RESPONSE_PORT));
- IpList theVeraList;
+ 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
+ // sparkjava config directive to set port for the web server to listen on
+ port(Integer.valueOf(bridgeSettings.getServerPort()));
+ // sparkjava config directive to set html static file location for Jetty
+ staticFileLocation("/public");
+ //setup the harmony connection if available
+ harmonyHome = new HarmonyHome(bridgeSettings);
+ //setup the nest connection if available
+ nestHome = new NestHome(bridgeSettings);
+ // setup the class to handle the resource setup rest api
+ theResources = new DeviceResource(bridgeSettings, theVersion, harmonyHome, nestHome);
+ // setup the class to handle the hue emulator rest api
+ theHueMulator = new HueMulator(bridgeSettings, theResources.getDeviceRepository(), harmonyHome, nestHome);
+ theHueMulator.setupServer();
+ // setup the class to handle the upnp response rest api
+ theSettingResponder = new UpnpSettingsResource(bridgeSettings);
+ theSettingResponder.setupServer();
+ // wait for the sparkjava initialization of the rest api classes to be complete
+ awaitInitialization();
+
+ // start the upnp ssdp discovery listener
+ theUpnpListener = new UpnpListener(bridgeSettings);
+ if(theUpnpListener.startListening())
+ log.info("HA Bridge (v" + theVersion.getVersion() + ") reinitialization requessted....");
- 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.setRestart(false);
+ stop();
}
- 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));
-
- // sparkjava config directive to set ip address for the web server to listen on
- // ipAddress("0.0.0.0"); // not used
- // sparkjava config directive to set port for the web server to listen on
- port(Integer.valueOf(bridgeSettings.getServerPort()));
- // sparkjava config directive to set html static file location for Jetty
- staticFileLocation("/public");
- //setup the harmony connection if available
- harmonyHome = new HarmonyHome(bridgeSettings);
- //setup the nest connection if available
- nestHome = new NestHome(bridgeSettings);
- // setup the class to handle the resource setup rest api
- theResources = new DeviceResource(bridgeSettings, theVersion, harmonyHome, nestHome);
- // setup the class to handle the hue emulator rest api
- theHueMulator = new HueMulator(bridgeSettings, theResources.getDeviceRepository(), harmonyHome, nestHome);
- theHueMulator.setupServer();
- // setup the class to handle the upnp response rest api
- theSettingResponder = new UpnpSettingsResource(bridgeSettings);
- theSettingResponder.setupServer();
- // wait for the sparkjava initialization of the rest api classes to be complete
- awaitInitialization();
-
- // start the upnp ssdp discovery listener
- theUpnpListener = new UpnpListener(bridgeSettings);
- theUpnpListener.startListening();
+ log.info("HA Bridge (v" + theVersion.getVersion() + ") exiting....");
+ System.exit(0);
}
}
diff --git a/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java b/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java
index 1fe6c8b..f350be4 100644
--- a/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java
+++ b/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java
@@ -23,9 +23,7 @@ import com.bwssystems.HABridge.dao.DeviceDescriptor;
import com.bwssystems.HABridge.dao.DeviceRepository;
import com.bwssystems.NestBridge.NestHome;
import com.bwssystems.harmony.HarmonyHome;
-import com.bwssystems.luupRequests.Sdata;
import com.bwssystems.vera.VeraHome;
-import com.bwssystems.vera.VeraInfo;
import com.google.gson.Gson;
/**
diff --git a/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java b/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java
index a68dde6..ba5c81f 100644
--- a/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java
+++ b/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java
@@ -1,6 +1,7 @@
package com.bwssystems.HABridge.hue;
import com.bwssystems.HABridge.BridgeSettings;
+import com.bwssystems.HABridge.Configuration;
import com.bwssystems.HABridge.JsonTransformer;
import com.bwssystems.HABridge.api.UserCreateRequest;
import com.bwssystems.HABridge.api.hue.DeviceResponse;
@@ -45,6 +46,7 @@ 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;
@@ -439,6 +441,38 @@ 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
@@ -510,4 +544,23 @@ 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);
+ }
+ }
}
diff --git a/src/main/java/com/bwssystems/HABridge/upnp/UpnpListener.java b/src/main/java/com/bwssystems/HABridge/upnp/UpnpListener.java
index 531fc6e..7567db3 100644
--- a/src/main/java/com/bwssystems/HABridge/upnp/UpnpListener.java
+++ b/src/main/java/com/bwssystems/HABridge/upnp/UpnpListener.java
@@ -4,6 +4,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.bwssystems.HABridge.BridgeSettings;
+import com.bwssystems.HABridge.Configuration;
import java.io.IOException;
import java.net.*;
@@ -14,8 +15,6 @@ import org.apache.http.conn.util.*;
public class UpnpListener {
private Logger log = LoggerFactory.getLogger(UpnpListener.class);
- private static final int UPNP_DISCOVERY_PORT = 1900;
- private static final String UPNP_MULTICAST_ADDRESS = "239.255.255.250";
private int upnpResponsePort;
@@ -26,6 +25,7 @@ public class UpnpListener {
private boolean strict;
private boolean traceupnp;
+ private BridgeSettings bridgeSettings;
public UpnpListener(BridgeSettings theSettings) {
super();
@@ -34,14 +34,15 @@ public class UpnpListener {
responseAddress = theSettings.getUpnpConfigAddress();
strict = theSettings.isUpnpStrict();
traceupnp = theSettings.isTraceupnp();
+ bridgeSettings = theSettings;
}
- public void startListening(){
+ public boolean startListening(){
log.info("UPNP Discovery Listener starting....");
try (DatagramSocket responseSocket = new DatagramSocket(upnpResponsePort);
- MulticastSocket upnpMulticastSocket = new MulticastSocket(UPNP_DISCOVERY_PORT);) {
- InetSocketAddress socketAddress = new InetSocketAddress(UPNP_MULTICAST_ADDRESS, UPNP_DISCOVERY_PORT);
+ MulticastSocket upnpMulticastSocket = new MulticastSocket(Configuration.UPNP_DISCOVERY_PORT);) {
+ InetSocketAddress socketAddress = new InetSocketAddress(Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT);
Enumeration ifs = NetworkInterface.getNetworkInterfaces();
while (ifs.hasMoreElements()) {
@@ -71,22 +72,29 @@ public class UpnpListener {
}
log.info("UPNP Discovery Listener running and ready....");
-
- while(true){ //trigger shutdown here
+ boolean loopControl = true;
+ while(loopControl){ //trigger shutdown here
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
upnpMulticastSocket.receive(packet);
if(isSSDPDiscovery(packet)){
sendUpnpResponse(responseSocket, packet.getAddress(), packet.getPort());
}
+ if(bridgeSettings.isRestart() || bridgeSettings.isStop())
+ loopControl = false;
}
-
+ upnpMulticastSocket.close();
+ responseSocket.close();
} catch (IOException e) {
log.error("UpnpListener encountered an error opening sockets. Shutting down", e);
-
}
- log.info("UPNP Discovery Listener Stopped");
-
+ if(bridgeSettings.isRestart())
+ log.info("UPNP Discovery Listener - ended, restart found");
+ if(bridgeSettings.isStop())
+ log.info("UPNP Discovery Listener - ended, stop found");
+ if(!bridgeSettings.isStop()&& !bridgeSettings.isRestart())
+ log.info("UPNP Discovery Listener - ended, error found");
+ return bridgeSettings.isRestart();
}
/**