diff --git a/README.md b/README.md index 753a077..b6a9256 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ The server defaults to the first available address on the host. Replace the -Dup The server defaults to running on port 8080. If you're already running a server (like openHAB) on 8080, -Dserver.port=`` on the command line. ### -Dupnp.device.db=`` The default location for the db to contain the devices as they are added is "data/devices.db". If you would like a different filename or directory, specify -Dupnp.devices.db=`/ or ` if it is the same directory. -### -Dupnp.resonse.port=`` +### -Dupnp.response.port=`` The upnp response port that will be used. The default is 50000. ### -Dupnp.strict=`` Upnp has been very closed on this platform to try and respond as a hue and there is now a setting to control if it is more open or strict, Add -Dupnp.strict=`` to your command line to have the emulator respond to what it thinks is an echo to a hue or any other device. The default is upnp.strict=false. diff --git a/pom.xml b/pom.xml index 1be264b..ec206d5 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.bwssystems.HABridge ha-bridge - 0.4.3 + 0.4.4 jar HA Bridge diff --git a/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java b/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java index 025aeb6..576ab23 100644 --- a/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java +++ b/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java @@ -100,6 +100,31 @@ public class HueMulator { return "[{\"success\":{\"username\":\"" + newUser + "\"}}]"; } ); + // http://ip_address:port/api/* with body of user request returns json object for a success of user add - This method is for Harmony Hub + post(HUE_CONTEXT + "/*", "application/json", (request, response) -> { + UserCreateRequest aNewUser = null; + String newUser = null; + String aDeviceType = null; + + log.info("HH trace: hue api user create requested: " + request.body() + " from " + request.ip()); + + if(request.body() != null && !request.body().isEmpty()) { + aNewUser = new Gson().fromJson(request.body(), UserCreateRequest.class); + newUser = aNewUser.getUsername(); + aDeviceType = aNewUser.getDevicetype(); + } + if(newUser == null) + newUser = "lightssystem"; + + if(aDeviceType == null) + aDeviceType = ""; + log.debug("HH trace: hue api user create requested for device type: " + aDeviceType + " and username: " + newUser); + + response.type("application/json; charset=utf-8"); + response.status(HttpStatus.SC_OK); + return "[{\"success\":{\"username\":\"" + newUser + "\"}}]"; + } ); + // http://ip_address:port/api/{userId} returns json objects for the full state get(HUE_CONTEXT + "/:userid", "application/json", (request, response) -> { String userId = request.params(":userid"); diff --git a/src/main/java/com/bwssystems/HABridge/upnp/UpnpListener.java b/src/main/java/com/bwssystems/HABridge/upnp/UpnpListener.java index bda8d30..71a1f97 100644 --- a/src/main/java/com/bwssystems/HABridge/upnp/UpnpListener.java +++ b/src/main/java/com/bwssystems/HABridge/upnp/UpnpListener.java @@ -40,7 +40,7 @@ public class UpnpListener { } public void startListening(){ - log.info("UPNP Discovery Listener started...."); + log.info("UPNP Discovery Listener starting...."); try (DatagramSocket responseSocket = new DatagramSocket(upnpResponsePort); MulticastSocket upnpMulticastSocket = new MulticastSocket(UPNP_DISCOVERY_PORT);) { @@ -55,7 +55,10 @@ public class UpnpListener { while (addrs.hasMoreElements()) { InetAddress addr = addrs.nextElement(); - log.debug(name + " ... has addr " + addr); + if(traceupnp) + log.info("Traceupnp: " + name + " ... has addr " + addr); + else + log.debug(name + " ... has addr " + addr); if (InetAddressUtils.isIPv4Address(addr.getHostAddress())) { IPsPerNic++; } @@ -63,10 +66,15 @@ public class UpnpListener { log.debug("Checking " + name + " to our interface set"); if (IPsPerNic > 0) { upnpMulticastSocket.joinGroup(socketAddress, xface); - log.debug("Adding " + name + " to our interface set"); + if(traceupnp) + log.info("Traceupnp: Adding " + name + " to our interface set"); + else + log.debug("Adding " + name + " to our interface set"); } } + log.info("UPNP Discovery Listener running and ready...."); + while(true){ //trigger shutdown here byte[] buf = new byte[1024]; DatagramPacket packet = new DatagramPacket(buf, buf.length); @@ -74,9 +82,9 @@ public class UpnpListener { String packetString = new String(packet.getData()); if(packetString != null && packetString.contains("M-SEARCH")) { if(traceupnp) - log.info("Trace SSDP packet from " + packet.getAddress().getHostAddress() + ":" + packet.getPort() + " body : " + packetString); + log.info("Traceupnp: SSDP packet from " + packet.getAddress().getHostAddress() + ":" + packet.getPort() + ", body: " + packetString); else - log.debug("Got SSDP packet from " + packet.getAddress().getHostAddress() + ":" + packet.getPort() + " body : " + packetString); + log.debug("Got SSDP packet from " + packet.getAddress().getHostAddress() + ":" + packet.getPort() + ", body: " + packetString); } if(isSSDPDiscovery(packetString)){ sendUpnpResponse(responseSocket, packet.getAddress(), packet.getPort()); @@ -84,7 +92,7 @@ public class UpnpListener { } } catch (IOException e) { - log.error("UpnpListener encountered an error. Shutting down", e); + log.error("UpnpListener encountered an error opening sockets. Shutting down", e); } log.info("UPNP Discovery Listener Stopped"); @@ -100,11 +108,23 @@ public class UpnpListener { // log.debug("Check if this is a MAN ssdp-discover packet for a upnp basic device: " + body); //Only respond to discover request for upnp basic device from echo, the others are for the wemo if(body != null && body.contains("M-SEARCH") && body.contains("\"ssdp:discover\"")){ - if(strict && body.startsWith("M-SEARCH * HTTP/1.1") && body.contains("MAN: \"ssdp:discover\"") && body.contains("ST: urn:schemas-upnp-org:device:basic:1")) + if(traceupnp) + log.info("Traceupnp: isSSDPDiscovery found message to be an M-SEARCH message."); + if(strict && body.startsWith("M-SEARCH * HTTP/1.1") && body.contains("MAN: \"ssdp:discover\"") && (body.contains("ST: urn:schemas-upnp-org:device:basic:1") || body.contains("ST: upnp:rootdevice") || body.contains("ST: ssdp:all"))) + { + if(traceupnp) + log.info("Traceupnp: isSSDPDiscovery found message to be valid under strict rules - strict: " + strict + ", vTwo.Compatibility: " + vTwoCompatibility); return true; + } else if (!strict || vTwoCompatibility) + { + if(traceupnp) + log.info("Traceupnp: isSSDPDiscovery found message to be valid under loose rules - strict: " + strict + ", vTwo.Compatibility: " + vTwoCompatibility); return true; + } } + if(traceupnp) + log.info("Traceupnp: isSSDPDiscovery found message to not be valid - strict: " + strict + ", vTwo.Compatibility: " + vTwoCompatibility); return false; } @@ -129,7 +149,10 @@ public class UpnpListener { discoveryResponse = String.format(discoveryTemplateVTwo, responseAddress, httpServerPort, getRandomUUIDString()); else discoveryResponse = String.format(discoveryTemplate, responseAddress, httpServerPort, getRandomUUIDString()); - log.debug("sndUpnpResponse: " + discoveryResponse); + if(traceupnp) + log.info("Traceupnp: sendUpnpResponse: " + discoveryResponse); + else + log.debug("sendUpnpResponse: " + discoveryResponse); DatagramPacket response = new DatagramPacket(discoveryResponse.getBytes(), discoveryResponse.length(), requester, sourcePort); socket.send(response); } diff --git a/src/main/java/com/bwssystems/HABridge/upnp/UpnpSettingsResource.java b/src/main/java/com/bwssystems/HABridge/upnp/UpnpSettingsResource.java index e90400c..e115976 100644 --- a/src/main/java/com/bwssystems/HABridge/upnp/UpnpSettingsResource.java +++ b/src/main/java/com/bwssystems/HABridge/upnp/UpnpSettingsResource.java @@ -15,6 +15,8 @@ public class UpnpSettingsResource { private static final String UPNP_CONTEXT = "/upnp"; private Logger log = LoggerFactory.getLogger(UpnpSettingsResource.class); + + private BridgeSettings theSettings; private String hueTemplate = "\n" + "\n" + "\n" + "1\n" + "0\n" + "\n" @@ -87,21 +89,28 @@ public class UpnpSettingsResource { public UpnpSettingsResource(BridgeSettings theSettings) { super(); - setupListener(theSettings); + this.theSettings = theSettings; + setupListener(this.theSettings); } private void setupListener (BridgeSettings theSettings) { log.info("Hue description service started...."); // http://ip_adress:port/description.xml which returns the xml configuration for the hue emulator get("/description.xml", "application/xml; charset=utf-8", (request, response) -> { - log.debug("upnp device settings requested: " + request.params(":id") + " from " + request.ip()); + if(theSettings.isTraceupnp()) + log.info("Traceupnp: upnp device settings requested: " + request.params(":id") + " from " + request.ip() + ":" + request.port()); + else + log.debug("upnp device settings requested: " + request.params(":id") + " from " + request.ip() + ":" + request.port()); String portNumber = Integer.toString(request.port()); String filledTemplate = null; if(theSettings.isVtwocompatibility()) filledTemplate = String.format(hueTemplateVTwo, theSettings.getUpnpConfigAddress(), portNumber, theSettings.getUpnpConfigAddress()); else filledTemplate = String.format(hueTemplate, theSettings.getUpnpConfigAddress(), portNumber, theSettings.getUpnpConfigAddress()); - log.debug("upnp device settings response: " + filledTemplate); + if(theSettings.isTraceupnp()) + log.info("Traceupnp: upnp device settings response: " + filledTemplate); + else + log.debug("upnp device settings response: " + filledTemplate); // response.header("Cache-Control", "no-store, no-cache, must-revalidate, post-check=0, pre-check=0"); // response.header("Pragma", "no-cache"); // response.header("Expires", "Mon, 1 Aug 2011 09:00:00 GMT"); diff --git a/src/main/resources/public/index.html b/src/main/resources/public/index.html index 7f11ed0..6a379cc 100644 --- a/src/main/resources/public/index.html +++ b/src/main/resources/public/index.html @@ -36,7 +36,7 @@