From a5ee0aafc8c735a40aab375f4761725bfe35872e Mon Sep 17 00:00:00 2001 From: BWS Systems Date: Tue, 2 Jul 2019 10:57:46 -0500 Subject: [PATCH] Update upnp original to be like v3.5.1 --- .../HABridge/upnp/UpnpListener.java | 28 ++++------------- .../HABridge/upnp/UpnpSettingsResource.java | 29 +++++++++++++++--- src/main/resources/public/hue_logo_0.png | Bin 0 -> 4718 bytes src/main/resources/public/hue_logo_3.png | Bin 0 -> 15791 bytes 4 files changed, 31 insertions(+), 26 deletions(-) create mode 100644 src/main/resources/public/hue_logo_0.png create mode 100644 src/main/resources/public/hue_logo_3.png diff --git a/src/main/java/com/bwssystems/HABridge/upnp/UpnpListener.java b/src/main/java/com/bwssystems/HABridge/upnp/UpnpListener.java index f7f331a..67f691e 100644 --- a/src/main/java/com/bwssystems/HABridge/upnp/UpnpListener.java +++ b/src/main/java/com/bwssystems/HABridge/upnp/UpnpListener.java @@ -12,8 +12,8 @@ import com.bwssystems.HABridge.util.UDPDatagramSender; import java.io.IOException; import java.net.*; -import java.time.Instant; -import java.time.temporal.ChronoUnit; +// import java.time.Instant; +// import java.time.temporal.ChronoUnit; import java.util.Enumeration; import org.apache.http.conn.util.*; @@ -63,7 +63,7 @@ public class UpnpListener { "ST: urn:schemas-upnp-org:device:basic:1\r\n" + "USN: uuid:" + HueConstants.UUID_PREFIX + "%s\r\n\r\n"; - private String notifyTemplate = "NOTIFY * HTTP/1.1\r\n" + + private String notifyTemplate1 = "NOTIFY * HTTP/1.1\r\n" + "HOST: %s:%s\r\n" + "CACHE-CONTROL: max-age=100\r\n" + "LOCATION: http://%s:%s/description.xml\r\n" + @@ -202,8 +202,8 @@ public class UpnpListener { } catch (SocketException e1) { log.warn("Could not sent soTimeout on multi-cast socket"); } - Instant current, previous; - previous = Instant.now(); +// Instant current, previous; +// previous = Instant.now(); while (loopControl) { // trigger shutdown here byte[] buf = new byte[1024]; DatagramPacket packet = new DatagramPacket(buf, buf.length); @@ -379,7 +379,7 @@ public class UpnpListener { // noop } - notifyData = String.format(notifyTemplate, Configuration.UPNP_MULTICAST_ADDRESS, + notifyData = String.format(notifyTemplate1, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, upnpConfigIP, httpServerPort, bridgeId, bridgeSNUUID, bridgeSNUUID); if (traceupnp) { log.info("Traceupnp: sendUpnpNotify notifyTemplate1"); @@ -416,22 +416,6 @@ public class UpnpListener { sendUDPResponse(notifyData.getBytes(), aSocketAddress, Configuration.UPNP_DISCOVERY_PORT); } - public void sendNotifyDatagram(String notifyData, InetAddress aSocketAddress, String templateNumber) { - if (traceupnp) { - log.info("Traceupnp: sendUpnpNotify {}", templateNumber); - } - log.debug("sendUpnpNotify {} is <<<{}>>>", templateNumber, notifyData); - DatagramPacket notifyPacket = new DatagramPacket(notifyData.getBytes(), notifyData.length(), aSocketAddress, - Configuration.UPNP_DISCOVERY_PORT); - try { - upnpMulticastSocket.send(notifyPacket); - } catch (IOException e1) { - log.warn("UpnpListener encountered an error sending upnp {}. IP: {} with message: {}", templateNumber, - notifyPacket.getAddress().getHostAddress(), e1.getMessage()); - log.debug("UpnpListener send {} exception: ", templateNumber, e1); - } - } - // added by https://github.com/pvint // Ruthlessly stolen from // https://stackoverflow.com/questions/22045165/java-datagrampacket-receive-how-to-determine-local-ip-interface diff --git a/src/main/java/com/bwssystems/HABridge/upnp/UpnpSettingsResource.java b/src/main/java/com/bwssystems/HABridge/upnp/UpnpSettingsResource.java index 4eec674..b62d84e 100644 --- a/src/main/java/com/bwssystems/HABridge/upnp/UpnpSettingsResource.java +++ b/src/main/java/com/bwssystems/HABridge/upnp/UpnpSettingsResource.java @@ -24,7 +24,7 @@ public class UpnpSettingsResource { private BridgeSettingsDescriptor theSettings; private BridgeSettings bridgeSettings; - private String hueTemplate = "\n" + private String hueTemplate_pre = "\n" + "\n" + "\n" + "1\n" @@ -41,8 +41,9 @@ public class UpnpSettingsResource { + "" + HueConstants.MODEL_ID + "\n" + "http://www.meethue.com\n" + "%s\n" - + "uuid:" + HueConstants.UUID_PREFIX + "%s\n" - + "index.html\n" + + "uuid:" + HueConstants.UUID_PREFIX + "%s\n"; + + private String hueTemplate_post = "index.html\n" + "\n" + "\n" + "image/png\n" @@ -62,6 +63,17 @@ public class UpnpSettingsResource { + "\n" + "\n"; + private String hueTemplate_mid_orig = "\n" + + "\n" + + "(null)\n" + + "(null)\n" + + "(null)\n" + + "(null)\n" + + "(null)\n" + + "\n" + + "\n"; + + public UpnpSettingsResource(BridgeSettings theBridgeSettings) { super(); this.bridgeSettings = theBridgeSettings; @@ -80,7 +92,16 @@ public class UpnpSettingsResource { String portNumber = Integer.toString(request.port()); String filledTemplate = null; - String httpLocationAddr = getOutboundAddress(request.ip(), request.port()).getHostAddress(); + String httpLocationAddr = null; + String hueTemplate = null; + if(theSettings.isUpnporiginal()) { + httpLocationAddr = theSettings.getUpnpConfigAddress(); + hueTemplate = hueTemplate_pre + hueTemplate_mid_orig + hueTemplate_post; + } else { + httpLocationAddr = getOutboundAddress(request.ip(), request.port()).getHostAddress(); + hueTemplate = hueTemplate_pre + hueTemplate_post; + } + String bridgeIdMac = HuePublicConfig.createConfig("temp", httpLocationAddr, HueConstants.HUB_VERSION, theSettings.getHubmac()).getSNUUIDFromMac(); filledTemplate = String.format(hueTemplate, httpLocationAddr, portNumber, httpLocationAddr, bridgeIdMac, bridgeIdMac); if(theSettings.isTraceupnp()) diff --git a/src/main/resources/public/hue_logo_0.png b/src/main/resources/public/hue_logo_0.png new file mode 100644 index 0000000000000000000000000000000000000000..0e435a393b6f6a47f089d603063af6750d0a5765 GIT binary patch literal 4718 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 c0*LEdQlB2z