Changed handling of upnp rsponses from the upnp listener and the

huemulator udp calls to use the same response port.
This commit is contained in:
Admin
2016-10-07 16:29:55 -05:00
parent e90e0f69ef
commit 004276d3ea
4 changed files with 37 additions and 54 deletions

View File

@@ -5,7 +5,7 @@
<groupId>com.bwssystems.HABridge</groupId> <groupId>com.bwssystems.HABridge</groupId>
<artifactId>ha-bridge</artifactId> <artifactId>ha-bridge</artifactId>
<version>3.1.0j</version> <version>3.1.0k</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>HA Bridge</name> <name>HA Bridge</name>

View File

@@ -13,6 +13,7 @@ import com.bwssystems.NestBridge.NestHome;
import com.bwssystems.hal.HalHome; import com.bwssystems.hal.HalHome;
import com.bwssystems.harmony.HarmonyHome; import com.bwssystems.harmony.HarmonyHome;
import com.bwssystems.hue.HueHome; import com.bwssystems.hue.HueHome;
import com.bwssystems.util.UDPDatagramSender;
public class HABridge { public class HABridge {
@@ -39,6 +40,7 @@ public class HABridge {
HueHome hueHome; HueHome hueHome;
HalHome halHome; HalHome halHome;
HueMulator theHueMulator; HueMulator theHueMulator;
UDPDatagramSender udpSender;
UpnpSettingsResource theSettingResponder; UpnpSettingsResource theSettingResponder;
UpnpListener theUpnpListener; UpnpListener theUpnpListener;
SystemControl theSystem; SystemControl theSystem;
@@ -72,29 +74,37 @@ public class HABridge {
halHome = new HalHome(bridgeSettings.getBridgeSettingsDescriptor()); halHome = new HalHome(bridgeSettings.getBridgeSettingsDescriptor());
// setup the class to handle the resource setup rest api // setup the class to handle the resource setup rest api
theResources = new DeviceResource(bridgeSettings.getBridgeSettingsDescriptor(), harmonyHome, nestHome, hueHome, halHome); theResources = new DeviceResource(bridgeSettings.getBridgeSettingsDescriptor(), harmonyHome, nestHome, hueHome, halHome);
// setup the class to handle the hue emulator rest api
theHueMulator = new HueMulator(bridgeSettings.getBridgeSettingsDescriptor(), theResources.getDeviceRepository(), harmonyHome, nestHome, hueHome);
theHueMulator.setupServer();
// setup the class to handle the upnp response rest api // setup the class to handle the upnp response rest api
theSettingResponder = new UpnpSettingsResource(bridgeSettings.getBridgeSettingsDescriptor()); theSettingResponder = new UpnpSettingsResource(bridgeSettings.getBridgeSettingsDescriptor());
theSettingResponder.setupServer(); theSettingResponder.setupServer();
// setup the UDP Datagram socket to be used by the HueMulator and the upnpListener
udpSender = UDPDatagramSender.createUDPDatagramSender(bridgeSettings.getBridgeSettingsDescriptor().getUpnpResponsePort());
if(udpSender == null) {
bridgeSettings.getBridgeControl().setStop(true);
}
else {
// setup the class to handle the hue emulator rest api
theHueMulator = new HueMulator(bridgeSettings.getBridgeSettingsDescriptor(), theResources.getDeviceRepository(), harmonyHome, nestHome, hueHome, udpSender);
theHueMulator.setupServer();
// wait for the sparkjava initialization of the rest api classes to be complete // wait for the sparkjava initialization of the rest api classes to be complete
awaitInitialization(); awaitInitialization();
// start the upnp ssdp discovery listener // start the upnp ssdp discovery listener
theUpnpListener = new UpnpListener(bridgeSettings.getBridgeSettingsDescriptor(), bridgeSettings.getBridgeControl()); theUpnpListener = new UpnpListener(bridgeSettings.getBridgeSettingsDescriptor(), bridgeSettings.getBridgeControl(), udpSender);
if(theUpnpListener.startListening()) if(theUpnpListener.startListening())
log.info("HA Bridge (v" + theVersion.getVersion() + ") reinitialization requessted...."); log.info("HA Bridge (v" + theVersion.getVersion() + ") reinitialization requessted....");
else else
bridgeSettings.getBridgeControl().setStop(true); bridgeSettings.getBridgeControl().setStop(true);
if(bridgeSettings.getBridgeSettingsDescriptor().isSettingsChanged()) if(bridgeSettings.getBridgeSettingsDescriptor().isSettingsChanged())
bridgeSettings.save(bridgeSettings.getBridgeSettingsDescriptor()); bridgeSettings.save(bridgeSettings.getBridgeSettingsDescriptor());
}
bridgeSettings.getBridgeControl().setReinit(false); bridgeSettings.getBridgeControl().setReinit(false);
stop(); stop();
nestHome.closeTheNest(); nestHome.closeTheNest();
nestHome = null; nestHome = null;
harmonyHome.shutdownHarmonyHubs(); harmonyHome.shutdownHarmonyHubs();
harmonyHome = null; harmonyHome = null;
udpSender.closeResponseSocket();
} }
log.info("HA Bridge (v" + theVersion.getVersion() + ") exiting...."); log.info("HA Bridge (v" + theVersion.getVersion() + ") exiting....");
System.exit(0); System.exit(0);

View File

@@ -27,6 +27,7 @@ import com.bwssystems.hue.HueHome;
import com.bwssystems.hue.HueUtil; import com.bwssystems.hue.HueUtil;
import com.bwssystems.nest.controller.Nest; import com.bwssystems.nest.controller.Nest;
import com.bwssystems.util.JsonTransformer; import com.bwssystems.util.JsonTransformer;
import com.bwssystems.util.UDPDatagramSender;
import com.google.gson.Gson; import com.google.gson.Gson;
import net.java.dev.eval.Expression; import net.java.dev.eval.Expression;
@@ -60,8 +61,6 @@ import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.Socket; import java.net.Socket;
import java.nio.charset.Charset; import java.nio.charset.Charset;
@@ -99,12 +98,13 @@ public class HueMulator implements HueErrorStringSet {
private SSLConnectionSocketFactory sslsf; private SSLConnectionSocketFactory sslsf;
private RequestConfig globalConfig; private RequestConfig globalConfig;
private BridgeSettingsDescriptor bridgeSettings; private BridgeSettingsDescriptor bridgeSettings;
private UDPDatagramSender theUDPDatagramSender;
private byte[] sendData; private byte[] sendData;
private String hueUser; private String hueUser;
private String errorString; private String errorString;
public HueMulator(BridgeSettingsDescriptor theBridgeSettings, DeviceRepository aDeviceRepository, HarmonyHome theHarmonyHome, NestHome aNestHome, HueHome aHueHome){ public HueMulator(BridgeSettingsDescriptor theBridgeSettings, DeviceRepository aDeviceRepository, HarmonyHome theHarmonyHome, NestHome aNestHome, HueHome aHueHome, UDPDatagramSender aUdpDatagramSender) {
httpClient = HttpClients.createDefault(); httpClient = HttpClients.createDefault();
// Trust own CA and all self-signed certs // Trust own CA and all self-signed certs
sslcontext = SSLContexts.createDefault(); sslcontext = SSLContexts.createDefault();
@@ -136,6 +136,7 @@ public class HueMulator implements HueErrorStringSet {
else else
this.myHueHome = null; this.myHueHome = null;
bridgeSettings = theBridgeSettings; bridgeSettings = theBridgeSettings;
theUDPDatagramSender = aUdpDatagramSender;
hueUser = null; hueUser = null;
errorString = null; errorString = null;
} }
@@ -905,10 +906,7 @@ public class HueMulator implements HueErrorStringSet {
} }
if(callItems[i].getItem().contains("udp://")) { if(callItems[i].getItem().contains("udp://")) {
log.debug("executing HUE api request to UDP: " + callItems[i].getItem()); log.debug("executing HUE api request to UDP: " + callItems[i].getItem());
DatagramSocket responseSocket = new DatagramSocket(Integer.parseInt(port)); theUDPDatagramSender.sendUDPResponse(new String(sendData), IPAddress, Integer.parseInt(port));
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, Integer.parseInt(port));
responseSocket.send(sendPacket);
responseSocket.close();
} }
else if(callItems[i].getItem().contains("tcp://")) else if(callItems[i].getItem().contains("tcp://"))
{ {

View File

@@ -7,6 +7,7 @@ import com.bwssystems.HABridge.BridgeControlDescriptor;
import com.bwssystems.HABridge.BridgeSettingsDescriptor; import com.bwssystems.HABridge.BridgeSettingsDescriptor;
import com.bwssystems.HABridge.Configuration; import com.bwssystems.HABridge.Configuration;
import com.bwssystems.HABridge.api.hue.HuePublicConfig; import com.bwssystems.HABridge.api.hue.HuePublicConfig;
import com.bwssystems.util.UDPDatagramSender;
import java.io.IOException; import java.io.IOException;
import java.net.*; import java.net.*;
@@ -17,7 +18,7 @@ import org.apache.http.conn.util.*;
public class UpnpListener { public class UpnpListener {
private Logger log = LoggerFactory.getLogger(UpnpListener.class); private Logger log = LoggerFactory.getLogger(UpnpListener.class);
private int upnpResponsePort; private UDPDatagramSender theUDPDatagramSender;
private int httpServerPort; private int httpServerPort;
private String responseAddress; private String responseAddress;
private boolean strict; private boolean strict;
@@ -92,9 +93,9 @@ public class UpnpListener {
"ST: urn:schemas-upnp-org:device:basic:1\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:Socket-1_0-221438K0100073::urn:Belkin:device:**\r\n\r\n";
*/ */
public UpnpListener(BridgeSettingsDescriptor theSettings, BridgeControlDescriptor theControl) { public UpnpListener(BridgeSettingsDescriptor theSettings, BridgeControlDescriptor theControl, UDPDatagramSender aUdpDatagramSender) {
super(); super();
upnpResponsePort = theSettings.getUpnpResponsePort(); theUDPDatagramSender = aUdpDatagramSender;
httpServerPort = Integer.valueOf(theSettings.getServerPort()); httpServerPort = Integer.valueOf(theSettings.getServerPort());
responseAddress = theSettings.getUpnpConfigAddress(); responseAddress = theSettings.getUpnpConfigAddress();
strict = theSettings.isUpnpStrict(); strict = theSettings.isUpnpStrict();
@@ -106,33 +107,9 @@ public class UpnpListener {
@SuppressWarnings("resource") @SuppressWarnings("resource")
public boolean startListening(){ public boolean startListening(){
log.info("UPNP Discovery Listener starting...."); log.info("UPNP Discovery Listener starting....");
DatagramSocket responseSocket = null;
MulticastSocket upnpMulticastSocket = null; MulticastSocket upnpMulticastSocket = null;
Enumeration<NetworkInterface> ifs = null; Enumeration<NetworkInterface> ifs = null;
boolean portLoopControl = true;
int retryCount = 0;
while(portLoopControl) {
try {
responseSocket = new DatagramSocket(upnpResponsePort);
if(retryCount > 0)
log.info("Upnp Response Port issue, found open port: " + upnpResponsePort);
portLoopControl = false;
} catch(SocketException e) {
if(retryCount == 0)
log.warn("Upnp Response Port is in use, starting loop to find open port for 20 tries - configured port is: " + upnpResponsePort);
if(retryCount >= 20) {
portLoopControl = false;
log.error("Upnp Response Port issue, could not find open port - last port tried: " + upnpResponsePort + " with message: " + e.getMessage());
return false;
}
}
if(portLoopControl) {
retryCount++;
upnpResponsePort++;
}
}
try { try {
upnpMulticastSocket = new MulticastSocket(Configuration.UPNP_DISCOVERY_PORT); upnpMulticastSocket = new MulticastSocket(Configuration.UPNP_DISCOVERY_PORT);
} catch(IOException e){ } catch(IOException e){
@@ -189,7 +166,7 @@ public class UpnpListener {
upnpMulticastSocket.receive(packet); upnpMulticastSocket.receive(packet);
if (isSSDPDiscovery(packet)) { if (isSSDPDiscovery(packet)) {
try { try {
sendUpnpResponse(responseSocket, packet.getAddress(), packet.getPort()); sendUpnpResponse(packet.getAddress(), packet.getPort());
} catch (IOException e) { } catch (IOException e) {
if(e.getMessage().equalsIgnoreCase("Host is down")) if(e.getMessage().equalsIgnoreCase("Host is down"))
log.warn("UpnpListener encountered an error sending upnp response packet as requesting host is now not available. IP: " + packet.getAddress().getHostAddress()); log.warn("UpnpListener encountered an error sending upnp response packet as requesting host is now not available. IP: " + packet.getAddress().getHostAddress());
@@ -213,7 +190,6 @@ public class UpnpListener {
} }
} }
upnpMulticastSocket.close(); upnpMulticastSocket.close();
responseSocket.close();
if (bridgeControl.isReinit()) if (bridgeControl.isReinit())
log.info("UPNP Discovery Listener - ended, restart found"); log.info("UPNP Discovery Listener - ended, restart found");
if (bridgeControl.isStop()) if (bridgeControl.isStop())
@@ -265,7 +241,7 @@ public class UpnpListener {
return false; return false;
} }
protected void sendUpnpResponse(DatagramSocket socket, InetAddress requester, int sourcePort) throws IOException { protected void sendUpnpResponse(InetAddress requester, int sourcePort) throws IOException {
String discoveryResponse = null; String discoveryResponse = null;
String bridgeIdMac = null; String bridgeIdMac = null;
if(discoveryTemplateLatest) { if(discoveryTemplateLatest) {
@@ -280,7 +256,6 @@ public class UpnpListener {
} }
else else
log.debug("sendUpnpResponse discovery template with address: " + responseAddress + " and port: " + httpServerPort); log.debug("sendUpnpResponse discovery template with address: " + responseAddress + " and port: " + httpServerPort);
DatagramPacket response = new DatagramPacket(discoveryResponse.getBytes(), discoveryResponse.length(), requester, sourcePort); theUDPDatagramSender.sendUDPResponse(discoveryResponse, requester, sourcePort);
socket.send(response);
} }
} }