diff --git a/pom.xml b/pom.xml
index 8cf2371..45f78a9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
com.bwssystems.HABridge
ha-bridge
- 3.1.0k
+ 3.1.0l
jar
HA Bridge
diff --git a/src/main/java/com/bwssystems/HABridge/api/hue/HueConfig.java b/src/main/java/com/bwssystems/HABridge/api/hue/HueConfig.java
index 705e1c5..6389d73 100644
--- a/src/main/java/com/bwssystems/HABridge/api/hue/HueConfig.java
+++ b/src/main/java/com/bwssystems/HABridge/api/hue/HueConfig.java
@@ -40,10 +40,10 @@ public class HueConfig
SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("UTC"));
aConfig.setMac(HueConfig.getMacAddress(ipaddress));
- aConfig.setApiversion("1.14.0");
+ aConfig.setApiversion("1.15.0");
aConfig.setPortalservices(false);
aConfig.setGateway(ipaddress);
- aConfig.setSwversion("01033989");
+ aConfig.setSwversion("01035934");
aConfig.setLinkbutton(true);
aConfig.setIpaddress(ipaddress);
aConfig.setProxyport(0);
@@ -56,7 +56,7 @@ public class HueConfig
aConfig.setLocaltime(dateFormat.format(new Date()));
aConfig.setTimezone(TimeZone.getDefault().getID());
aConfig.setZigbeechannel("6");
- aConfig.setBridgeid(HuePublicConfig.getBridgeIdFromMac(aConfig.getMac(), ipaddress));
+ aConfig.setBridgeid(HuePublicConfig.createConfig(name, ipaddress).getHueBridgeIdFromMac());
aConfig.setModelid("BSB002");
aConfig.setFactorynew(false);
aConfig.setReplacesbridgeid(null);
diff --git a/src/main/java/com/bwssystems/HABridge/api/hue/HuePublicConfig.java b/src/main/java/com/bwssystems/HABridge/api/hue/HuePublicConfig.java
index c955cf7..9492ba9 100644
--- a/src/main/java/com/bwssystems/HABridge/api/hue/HuePublicConfig.java
+++ b/src/main/java/com/bwssystems/HABridge/api/hue/HuePublicConfig.java
@@ -1,13 +1,11 @@
package com.bwssystems.HABridge.api.hue;
-import java.math.BigInteger;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.StringTokenizer;
-import javax.xml.bind.DatatypeConverter;
public class HuePublicConfig
{
@@ -23,10 +21,10 @@ public class HuePublicConfig
public static HuePublicConfig createConfig(String name, String ipaddress) {
HuePublicConfig aConfig = new HuePublicConfig();
aConfig.setMac(HuePublicConfig.getMacAddress(ipaddress));
- aConfig.setApiversion("1.14.0");
- aConfig.setSwversion("01033989");
+ aConfig.setApiversion("1.15.0");
+ aConfig.setSwversion("01035934");
aConfig.setName(name);
- aConfig.setBridgeid(HuePublicConfig.getBridgeIdFromMac(aConfig.getMac(), ipaddress));
+ aConfig.setBridgeid(aConfig.getHueBridgeIdFromMac());
aConfig.setModelid("BSB002");
aConfig.setFactorynew(false);
aConfig.setReplacesbridgeid(null);
@@ -67,24 +65,22 @@ public class HuePublicConfig
return sb.toString();
}
- protected static String getBridgeIdFromMac(String macAddr, String ipAddr)
+ public String getSNUUIDFromMac()
{
- StringTokenizer st = new StringTokenizer(macAddr, ":");
- String bridgeId = "";
-// String port = null;
+ StringTokenizer st = new StringTokenizer(this.getMac(), ":");
+ String bridgeUUID = "";
while(st.hasMoreTokens()) {
- bridgeId = bridgeId + st.nextToken();
+ bridgeUUID = bridgeUUID + st.nextToken();
}
-// if(ipAddr.contains(":")) {
-// port = ipAddr.substring(ipAddr.indexOf(":"));
-// BigInteger bigInt = BigInteger.valueOf(Integer.getInteger(port).intValue());
-// byte[] theBytes = bigInt.toByteArray();
-// bridgeId = bridgeId + DatatypeConverter.printHexBinary(theBytes);
-// }
-// else
-// bridgeId = bridgeId + "0800";
- bridgeId = bridgeId.toLowerCase();
- return bridgeId;
+ bridgeUUID = bridgeUUID.toLowerCase();
+ return bridgeUUID.toLowerCase();
+ }
+
+ protected String getHueBridgeIdFromMac()
+ {
+ String cleanMac = this.getSNUUIDFromMac();
+ String bridgeId = cleanMac.substring(0, 6) + "FFFE" + cleanMac.substring(6);
+ return bridgeId.toUpperCase();
}
public String getMac() {
diff --git a/src/main/java/com/bwssystems/HABridge/upnp/UpnpListener.java b/src/main/java/com/bwssystems/HABridge/upnp/UpnpListener.java
index dba4225..bff33cb 100644
--- a/src/main/java/com/bwssystems/HABridge/upnp/UpnpListener.java
+++ b/src/main/java/com/bwssystems/HABridge/upnp/UpnpListener.java
@@ -24,75 +24,34 @@ public class UpnpListener {
private boolean strict;
private boolean traceupnp;
private BridgeControlDescriptor bridgeControl;
- private boolean discoveryTemplateLatest;
- private String discoveryTemplate = "HTTP/1.1 200 OK\r\n" +
- "CACHE-CONTROL: max-age=86400\r\n" +
- "EXT:\r\n" +
- "LOCATION: http://%s:%s/description.xml\r\n" +
- "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/1.14.0\r\n" +
- "ST: urn:schemas-upnp-org:device:basic:1\r\n" +
- "USN: uuid:2f402f80-da50-11e1-9b23-%s\r\n\r\n";
-/*
- private String discoveryTemplate = "NOTIFY * HTTP/1.1\r\n" +
+ private String responseTemplate1 = "HTTP/1.1 200 OK\r\n" +
"HOST: %s:%s\r\n" +
"CACHE-CONTROL: max-age=100\r\n" +
+ "EXT:\r\n" +
"LOCATION: http://%s:%s/description.xml\r\n" +
- "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/1.14.0\r\n" +
- "NTS: ssdp:alive\r\n" +
+ "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/1.15.0\r\n" +
"hue-bridgeid: %s\r\n" +
- "NT: uuid:2f402f80-da50-11e1-9b23-%s\r\n" +
- "USN: uuid:2f402f80-da50-11e1-9b23-%s\r\n\r\n";
- discoveryResponse = String.format(discoveryTemplate, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, responseAddress, httpServerPort, bridgeIdMac, bridgeIdMac, bridgeIdMac);
-*/
-/*
- private String discoveryTemplate = "HTTP/1.1 200 OK\r\n" +
- "CACHE-CONTROL: max-age=86400\r\n" +
- "EXT:\r\n" +
- "LOCATION: http://%s:%s/description.xml\r\n" +
- "SERVER: FreeRTOS/7.4.2 UPnP/1.0 IpBridge/1.10.0\r\n" +
- "ST: urn:schemas-upnp-org:device:basic:1\r\n" +
- "USN: uuid:2f402f80-da50-11e1-9b23-001788102201::urn:schemas-upnp-org:device:basic:1\r\n\r\n";
- discoveryResponse = String.format(discoveryTemplate, responseAddress, httpServerPort);
-*/
-/*
- private String discoveryTemplate = "HTTP/1.1 200 OK\r\n" +
- "CACHE-CONTROL: max-age=86400\r\n" +
- "EXT:\r\n" +
- "LOCATION: http://%s:%s/description.xml\r\n" +
- "SERVER: FreeRTOS/7.4.2 UPnP/1.0 IpBridge/1.10.0\r\n" +
"ST: upnp:rootdevice\r\n" +
- "USN: uuid:2f402f80-da50-11e1-9b23-001788102201\r\n\r\n";
-*/
-/*
- private String discoveryTemplate = "HTTP/1.1 200 OK\r\n" +
+ "USN: uuid:2f402f80-da50-11e1-9b23-%s::upnp:rootdevice\r\n\r\n";
+ private String responseTemplate2 = "HTTP/1.1 200 OK\r\n" +
"HOST: %s:%s\r\n" +
- "CACHE-CONTROL: max-age=86400\r\n" +
+ "CACHE-CONTROL: max-age=100\r\n" +
"EXT:\r\n" +
"LOCATION: http://%s:%s/description.xml\r\n" +
- "SERVER: FreeRTOS/7.4.2 UPnP/1.0 IpBridge/1.10.0\r\n" +
+ "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/1.15.0\r\n" +
"hue-bridgeid: %s\r\n" +
- "ST: upnp:rootdevice\r\n" +
- "USN: uuid:2f402f80-da50-11e1-9b23-001788102201\r\n\r\n";
-
- discoveryResponse = String.format(discoveryTemplate, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, responseAddress, httpServerPort, HuePublicConfig.createConfig("temp", responseAddress).getBridgeid());
-*/
- private String discoveryTemplate091516 = "HTTP/1.1 200 OK\r\n" +
- "CACHE-CONTROL: max-age=86400\r\n" +
+ "ST: uuid:2f402f80-da50-11e1-9b23-%s\r\n" +
+ "USN: uuid:2f402f80-da50-11e1-9b23-%s\r\n\r\n";
+ private String responseTemplate3 = "HTTP/1.1 200 OK\r\n" +
+ "HOST: %s:%s\r\n" +
+ "CACHE-CONTROL: max-age=100\r\n" +
"EXT:\r\n" +
"LOCATION: http://%s:%s/description.xml\r\n" +
- "SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/1.10.0\r\n" +
+ "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/1.15.0\r\n" +
+ "hue-bridgeid: %s\r\n" +
"ST: urn:schemas-upnp-org:device:basic:1\r\n" +
- "USN: uuid:Socket-1_0-221438K0100073::urn:schemas-upnp-org:device:basic:1\r\n\r\n";
-/*
- private String discoveryTemplateOld = "HTTP/1.1 200 OK\r\n" +
- "CACHE-CONTROL: max-age=86400\r\n" +
- "EXT:\r\n" +
- "LOCATION: http://%s:%s/upnp/amazon-ha-bridge/setup.xml\r\n" +
- "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n" +
- "01-NLS: %s\r\n" +
- "ST: urn:schemas-upnp-org:device:basic:1\r\n" +
- "USN: uuid:Socket-1_0-221438K0100073::urn:Belkin:device:**\r\n\r\n";
-*/
+ "USN: uuid:2f402f80-da50-11e1-9b23-%s\r\n\r\n";
+
public UpnpListener(BridgeSettingsDescriptor theSettings, BridgeControlDescriptor theControl, UDPDatagramSender aUdpDatagramSender) {
super();
theUDPDatagramSender = aUdpDatagramSender;
@@ -101,7 +60,6 @@ public class UpnpListener {
strict = theSettings.isUpnpStrict();
traceupnp = theSettings.isTraceupnp();
bridgeControl = theControl;
- discoveryTemplateLatest = true;
}
@SuppressWarnings("resource")
@@ -243,19 +201,33 @@ public class UpnpListener {
protected void sendUpnpResponse(InetAddress requester, int sourcePort) throws IOException {
String discoveryResponse = null;
- String bridgeIdMac = null;
- if(discoveryTemplateLatest) {
- bridgeIdMac = HuePublicConfig.createConfig("temp", responseAddress).getBridgeid();
- discoveryResponse = String.format(discoveryTemplate, responseAddress, httpServerPort, bridgeIdMac);
- }
- else
- discoveryResponse = String.format(discoveryTemplate091516, responseAddress, httpServerPort);
+ String bridgeId = null;
+ String bridgeSNUUID = null;
+ HuePublicConfig aHueConfig = HuePublicConfig.createConfig("temp", responseAddress);
+ bridgeId = aHueConfig.getBridgeid();
+ bridgeSNUUID = aHueConfig.getSNUUIDFromMac();
+ discoveryResponse = String.format(responseTemplate1, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, responseAddress, httpServerPort, bridgeId, bridgeSNUUID);
if(traceupnp) {
- log.info("Traceupnp: sendUpnpResponse discovery template with address: " + responseAddress + " and port: " + httpServerPort);
- log.info("Traceupnp: discoveryResponse is <<<" + discoveryResponse + ">>>");
+ log.info("Traceupnp: sendUpnpResponse discovery responseTemplate1 is <<<" + discoveryResponse + ">>>");
}
else
- log.debug("sendUpnpResponse discovery template with address: " + responseAddress + " and port: " + httpServerPort);
+ log.debug("sendUpnpResponse discovery responseTemplate1 is <<<" + discoveryResponse + ">>>");
+ theUDPDatagramSender.sendUDPResponse(discoveryResponse, requester, sourcePort);
+
+ discoveryResponse = String.format(responseTemplate2, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, responseAddress, httpServerPort, bridgeId, bridgeSNUUID, bridgeSNUUID);
+ if(traceupnp) {
+ log.info("Traceupnp: sendUpnpResponse discovery responseTemplate2 is <<<" + discoveryResponse + ">>>");
+ }
+ else
+ log.debug("sendUpnpResponse discovery responseTemplate2 is <<<" + discoveryResponse + ">>>");
+ theUDPDatagramSender.sendUDPResponse(discoveryResponse, requester, sourcePort);
+
+ discoveryResponse = String.format(responseTemplate3, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, responseAddress, httpServerPort, bridgeId, bridgeSNUUID);
+ if(traceupnp) {
+ log.info("Traceupnp: sendUpnpResponse discovery responseTemplate3 is <<<" + discoveryResponse + ">>>");
+ }
+ else
+ log.debug("sendUpnpResponse discovery responseTemplate3 is <<<" + discoveryResponse + ">>>");
theUDPDatagramSender.sendUDPResponse(discoveryResponse, requester, sourcePort);
}
}
diff --git a/src/main/java/com/bwssystems/HABridge/upnp/UpnpSettingsResource.java b/src/main/java/com/bwssystems/HABridge/upnp/UpnpSettingsResource.java
index 789653c..528b4e9 100644
--- a/src/main/java/com/bwssystems/HABridge/upnp/UpnpSettingsResource.java
+++ b/src/main/java/com/bwssystems/HABridge/upnp/UpnpSettingsResource.java
@@ -78,7 +78,7 @@ public class UpnpSettingsResource {
log.debug("upnp device settings requested: " + " from " + request.ip() + ":" + request.port());
String portNumber = Integer.toString(request.port());
String filledTemplate = null;
- String bridgeIdMac = HuePublicConfig.createConfig("temp", theSettings.getUpnpConfigAddress()).getBridgeid();
+ String bridgeIdMac = HuePublicConfig.createConfig("temp", theSettings.getUpnpConfigAddress()).getSNUUIDFromMac();
filledTemplate = String.format(hueTemplate, theSettings.getUpnpConfigAddress(), portNumber, theSettings.getUpnpConfigAddress(), bridgeIdMac, bridgeIdMac);
if(theSettings.isTraceupnp())
log.info("Traceupnp: upnp device settings template filled with address: " + theSettings.getUpnpConfigAddress() + " and port: " + portNumber);
diff --git a/src/main/java/com/bwssystems/util/UDPDatagramSender.java b/src/main/java/com/bwssystems/util/UDPDatagramSender.java
new file mode 100644
index 0000000..62b2931
--- /dev/null
+++ b/src/main/java/com/bwssystems/util/UDPDatagramSender.java
@@ -0,0 +1,72 @@
+package com.bwssystems.util;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.SocketException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class UDPDatagramSender {
+ private Logger log = LoggerFactory.getLogger(UDPDatagramSender.class);
+ private DatagramSocket responseSocket = null;
+ private int udpResponsePort;
+
+ public UDPDatagramSender() {
+ super();
+ udpResponsePort = 0;
+ }
+
+ public static UDPDatagramSender createUDPDatagramSender(int udpResponsePort) {
+ UDPDatagramSender aDatagramSender = new UDPDatagramSender();
+ if(aDatagramSender.initializeSocket(udpResponsePort))
+ return aDatagramSender;
+ else
+ return null;
+ }
+
+ private boolean initializeSocket(int port) {
+ log.info("Initializing UDP response Seocket...");
+ udpResponsePort = port;
+ boolean portLoopControl = true;
+ int retryCount = 0;
+ while(portLoopControl) {
+ try {
+ responseSocket = new DatagramSocket(udpResponsePort);
+ portLoopControl = false;
+ } catch(SocketException e) {
+ if(retryCount == 0)
+ log.warn("UDP Response Port is in use, starting loop to find open port for 20 tries - configured port is: " + udpResponsePort);
+ if(retryCount >= 20) {
+ portLoopControl = false;
+ log.error("UDP Response Port issue, could not find open port - last port tried: " + udpResponsePort + " with message: " + e.getMessage());
+ return false;
+ }
+ }
+ if(portLoopControl) {
+ retryCount++;
+ udpResponsePort++;
+ }
+ }
+ log.info("UDP response Seocket initialized to: " + udpResponsePort);
+ return true;
+ }
+
+ public int getUdpResponsePort() {
+ return udpResponsePort;
+ }
+
+ public void closeResponseSocket() {
+ responseSocket.close();
+ }
+
+ public void sendUDPResponse(String udpResponse, InetAddress requester, int sourcePort) throws IOException {
+ log.debug("Sending response string: <<<" + udpResponse + ">>>");
+ if(responseSocket == null)
+ throw new IOException("Socket not initialized");
+ DatagramPacket response = new DatagramPacket(udpResponse.getBytes(), udpResponse.length(), requester, sourcePort);
+ responseSocket.send(response);
+ }
+}