Skip to content

Commit

Permalink
Merge pull request #81 from armzilla/development
Browse files Browse the repository at this point in the history
Development
  • Loading branch information
armzilla committed Sep 16, 2016
2 parents d6aebfb + 2717fb7 commit 0ab7872
Show file tree
Hide file tree
Showing 9 changed files with 118 additions and 18 deletions.
22 changes: 22 additions & 0 deletions src/main/java/com/armzilla/ha/ConfigChecker.java
@@ -0,0 +1,22 @@
package com.armzilla.ha;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
* Created by arm on 9/16/16.
*/
@Component
public class ConfigChecker implements InitializingBean {

@Value("${upnp.config.address}")
private String responseAddress;

@Override
public void afterPropertiesSet() throws Exception {
if(responseAddress == null || responseAddress.isEmpty() ){
throw new IllegalArgumentException("please provide the IP(v4) address of the interface you want the bridge to listen on using --upnp.config.address=<ipadress>");
}
}
}
9 changes: 9 additions & 0 deletions src/main/java/com/armzilla/ha/SpringbootEntry.java
@@ -1,10 +1,18 @@
package com.armzilla.ha;

import org.apache.catalina.connector.Connector;
import org.apache.coyote.http11.Http11NioProtocol;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;

import java.io.IOException;

@SpringBootApplication
@EnableScheduling
@ComponentScan
Expand All @@ -13,4 +21,5 @@ public class SpringbootEntry {
public static void main(String[] args) {
SpringApplication.run(SpringbootEntry.class, args);
}

}
45 changes: 45 additions & 0 deletions src/main/java/com/armzilla/ha/TomcatConnectorBean.java
@@ -0,0 +1,45 @@
package com.armzilla.ha;

import org.apache.catalina.connector.Connector;
import org.apache.coyote.http11.Http11NioProtocol;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import java.util.Set;

/**
* Created by arm on 9/12/15.
*/
@Component

public class TomcatConnectorBean {
@Value("${emulator.portbase}")
private int portBase;
@Value("${emulator.portcount}")
private int portCount;
@Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory tomcat = null;
for(int i = 0; i < portCount; i ++) {
if(tomcat == null){
tomcat = new TomcatEmbeddedServletContainerFactory(portBase + i);
}else{
tomcat.addAdditionalTomcatConnectors(createConnector(portBase + i));
}
}
return tomcat;
}

private Connector createConnector(int portNumber) {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
connector.setScheme("http");
connector.setPort(portNumber);
return connector;
}
}
20 changes: 15 additions & 5 deletions src/main/java/com/armzilla/ha/hue/HueMulator.java
Expand Up @@ -19,6 +19,7 @@
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.HttpHeaders;
Expand Down Expand Up @@ -50,6 +51,10 @@ public class HueMulator {
private HttpClient httpClient;
private ObjectMapper mapper;

@Value("${emulator.portbase}")
private int portBase;
@Value("${emulator.portcount}")
private int portCount;

public HueMulator(){
httpClient = HttpClients.createDefault(); //patched for now, moving away from HueMulator doing work
Expand All @@ -60,8 +65,10 @@ public HueMulator(){

@RequestMapping(value = "/{userId}/lights", method = RequestMethod.GET, produces = "application/json")
public ResponseEntity<Map<String, String>> getUpnpConfiguration(@PathVariable(value = "userId") String userId, HttpServletRequest request) {
log.info("hue lights list requested: " + userId + " from " + request.getRemoteAddr());
Page<DeviceDescriptor> deviceList = repository.findByDeviceType("switch", new PageRequest(0,100));
log.info("hue lights list requested: " + userId + " from " + request.getRemoteAddr() + request.getLocalPort());

int pageNumber = request.getLocalPort()-portBase;
Page<DeviceDescriptor> deviceList = repository.findByDeviceType("switch", new PageRequest(pageNumber, 25));
Map<String, String> deviceResponseMap = new HashMap<>();
for (DeviceDescriptor device : deviceList) {
deviceResponseMap.put(device.getId(), device.getName());
Expand All @@ -71,13 +78,15 @@ public ResponseEntity<Map<String, String>> getUpnpConfiguration(@PathVariable(va

@RequestMapping(value = "/*", method = RequestMethod.POST, produces = "application/json")
public ResponseEntity<String> postAPI(HttpServletRequest request) {
log.info("registered device: " + request.toString());
return new ResponseEntity<String>("[{\"success\":{\"username\":\"lights\"}}]", HttpStatus.OK);
}

@RequestMapping(value = "/{userId}", method = RequestMethod.GET, produces = "application/json")
public ResponseEntity<HueApiResponse> getApi(@PathVariable(value = "userId") String userId, HttpServletRequest request) {
log.info("hue api root requested: " + userId + " from " + request.getRemoteAddr());
Page<DeviceDescriptor> descriptorList = repository.findByDeviceType("switch", new PageRequest(0, 100));
int pageNumber = request.getLocalPort()-portBase;
Page<DeviceDescriptor> descriptorList = repository.findByDeviceType("switch", new PageRequest(pageNumber, 25));
if (descriptorList == null) {
return new ResponseEntity<>(null, null, HttpStatus.NOT_FOUND);
}
Expand Down Expand Up @@ -201,8 +210,9 @@ protected boolean doHttpRequest(String url, String httpVerb, String contentType,
try {
HttpResponse response = httpClient.execute(request);
EntityUtils.consume(response.getEntity()); //close out inputstream ignore content
log.info("GET on URL responded: " + response.getStatusLine().getStatusCode());
if(response.getStatusLine().getStatusCode() == 200){
int httpResponseCode = response.getStatusLine().getStatusCode();
log.info("GET on URL responded: " + httpResponseCode);
if(httpResponseCode >= 200 && httpResponseCode < 300){ //had complaints that some apps do not respond back with pure 200
return true;
}
} catch (IOException e) {
Expand Down
18 changes: 11 additions & 7 deletions src/main/java/com/armzilla/ha/upnp/UpnpListener.java
Expand Up @@ -26,12 +26,14 @@ public class UpnpListener {
@Value("${upnp.response.port}")
private int upnpResponsePort;

@Value("${server.port}")
private int httpServerPort;

@Value("${upnp.config.address}")
private String responseAddress;

@Value("${emulator.portbase}")
private int portBase;
@Value("${emulator.portcount}")
private int portCount;

@Value("${upnp.disable}")
private boolean disable;

Expand Down Expand Up @@ -79,7 +81,9 @@ public void startListening(){
String packetString = new String(packet.getData());
if(isSSDPDiscovery(packetString)){
log.debug("Got SSDP Discovery packet from " + packet.getAddress().getHostAddress() + ":" + packet.getPort());
sendUpnpResponse(responseSocket, packet.getAddress(), packet.getPort());
for(int i = 0; i < portCount; i ++) {
sendUpnpResponse(responseSocket, packet.getAddress(), packet.getPort(), portBase+i, i);
}
}
}

Expand Down Expand Up @@ -108,13 +112,13 @@ protected boolean isSSDPDiscovery(String body){
String discoveryTemplate = "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" +
"LOCATION: http://%s:%s/upnp/%s/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";
protected void sendUpnpResponse(DatagramSocket socket, InetAddress requester, int sourcePort) throws IOException {
String discoveryResponse = String.format(discoveryTemplate, responseAddress, httpServerPort, getRandomUUIDString());
protected void sendUpnpResponse(DatagramSocket socket, InetAddress requester, int sourcePort, int gatewayPort, int emulatorId) throws IOException {
String discoveryResponse = String.format(discoveryTemplate, responseAddress, gatewayPort, "amazon-ha-bridge" + emulatorId, "D1710C33-328D-4152-A5FA-5382541A92FF");
DatagramPacket response = new DatagramPacket(discoveryResponse.getBytes(), discoveryResponse.length(), requester, sourcePort);
socket.send(response);
}
Expand Down
10 changes: 6 additions & 4 deletions src/main/java/com/armzilla/ha/upnp/UpnpSettingsResource.java
@@ -1,6 +1,7 @@
package com.armzilla.ha.upnp;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
Expand All @@ -16,8 +17,9 @@
@Controller
@RequestMapping("/upnp")
public class UpnpSettingsResource {

private Logger log = Logger.getLogger(UpnpSettingsResource.class);
@Value("${emulator.portcount}")
private int portCount;

private String hueTemplate = "<?xml version=\"1.0\"?>\n" +
"<root xmlns=\"urn:schemas-upnp-org:device-1-0\">\n" +
Expand All @@ -35,8 +37,8 @@ public class UpnpSettingsResource {
"<modelName>Philips hue bridge 2012</modelName>\n" +
"<modelNumber>929000226503</modelNumber>\n" +
"<modelURL>http://www.armzilla.com/amazon-echo-ha-bridge</modelURL>\n" +
"<serialNumber>01189998819991197253</serialNumber>\n" +
"<UDN>uuid:88f6698f-2c83-4393-bd03-cd54a9f8595</UDN>\n" +
"<serialNumber>%s</serialNumber>\n" +
"<UDN>uuid:%s</UDN>\n" +
"<serviceList>\n" +
"<service>\n" +
"<serviceType>(null)</serviceType>\n" +
Expand Down Expand Up @@ -72,7 +74,7 @@ public ResponseEntity<String> getUpnpConfiguration(@PathVariable(value="deviceId
log.info("upnp device settings requested: " + deviceId + " from " + request.getRemoteAddr());
String hostName = request.getLocalAddr();
String portNumber = Integer.toString(request.getLocalPort());
String filledTemplate = String.format(hueTemplate, hostName, portNumber, hostName);
String filledTemplate = String.format(hueTemplate, hostName, request.getLocalPort(), hostName, deviceId, deviceId);

return new ResponseEntity<>(filledTemplate, null, HttpStatus.OK);
}
Expand Down
5 changes: 3 additions & 2 deletions src/main/resources/application.properties
@@ -1,4 +1,5 @@
upnp.response.port=50000
server.port=8080
upnp.config.address=192.168.1.1
upnp.config.address=
emulator.portbase=8080
emulator.portcount=3
upnp.disable=false
2 changes: 2 additions & 0 deletions src/test/java/demo/DemoApplicationTests.java
Expand Up @@ -3,12 +3,14 @@
import com.armzilla.ha.SpringbootEntry;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SpringbootEntry.class)
@TestPropertySource(locations="classpath:test.properties")
@WebAppConfiguration
public class DemoApplicationTests {

Expand Down
5 changes: 5 additions & 0 deletions src/test/resources/test.properties
@@ -0,0 +1,5 @@
upnp.response.port=50000
upnp.config.address=192.168.1.1
emulator.portbase=8080
emulator.portcount=3
upnp.disable=false

0 comments on commit 0ab7872

Please sign in to comment.