diff --git a/.gitignore b/.gitignore index 77b7014..92a0f85 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ buildNumber.properties *.iml data .idea +config/ \ No newline at end of file diff --git a/README.md b/README.md index 884f24c..ee53aca 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,24 @@ You can now control devices with your Amazon Echo by saying "Alexa, Turn on the To view or remove devices that Alexa knows about, you can use the mobile app Menu / Settings / Connected Home, This is needed if you remove a device from the Amazon Echo Bridge. +## Running as a service + +If you are running this on Linux with `systemd`, do the following: +1. Modify `echo-ha-bridge.service` by changing the name of the jar file to execute and location of the working directory +2. Copy `echo-ha-bridge.service` to `/lib/systemd/system/` +3. Run `sudo systemctl enable echo-ha-bridge.service` +4. Navigate to the location of `amazon-ha-bridge-*.jar` and create a file called `application.properties` with the following content: +``` +upnp.response.port=50000 +upnp.config.address=ip address of your machine +emulator.portbase=should be same as server.port +emulator.portcount=3 +upnp.disable=false +server.port=port number you want the server to be listening on +logging.file=full path to the file where logs will be written to +``` + + ## Build In case you would like to internally configure your own build of the Amazon Echo Bridge, a few requisites are required. diff --git a/echo-ha-bridge.service b/echo-ha-bridge.service new file mode 100644 index 0000000..f367467 --- /dev/null +++ b/echo-ha-bridge.service @@ -0,0 +1,13 @@ +[Unit] +Description=Amazon Echo HA Bridge +After=syslog.target + +[Service] +Type=simple +PIDFile=/var/run/echo-ha-bridge/echo-ha-bridge.pid +WorkingDirectory=/opt/echo-ha-bridge/ +ExecStart=/usr/bin/java -jar amazon-echo-bridge.jar & > /dev/null +SuccessExitStatus=143 + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/pom.xml b/pom.xml index 52dab98..5c9e6c4 100755 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.armzilla.ha amazon-echo-bridge - 0.4.0 + 0.4.1 jar Amazon Echo Bridge diff --git a/src/main/java/com/armzilla/ha/SpringbootEntry.java b/src/main/java/com/armzilla/ha/SpringbootEntry.java index 93009c1..a27b9f5 100644 --- a/src/main/java/com/armzilla/ha/SpringbootEntry.java +++ b/src/main/java/com/armzilla/ha/SpringbootEntry.java @@ -1,17 +1,10 @@ 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 diff --git a/src/main/java/com/armzilla/ha/TomcatConnectorBean.java b/src/main/java/com/armzilla/ha/TomcatConnectorBean.java index e802566..d4ef35f 100644 --- a/src/main/java/com/armzilla/ha/TomcatConnectorBean.java +++ b/src/main/java/com/armzilla/ha/TomcatConnectorBean.java @@ -1,17 +1,12 @@ 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. */ @@ -37,7 +32,6 @@ public EmbeddedServletContainerFactory servletContainer() { 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; diff --git a/src/main/java/com/armzilla/ha/dao/DeviceRepository.java b/src/main/java/com/armzilla/ha/dao/DeviceRepository.java index 3b0a80d..ba2b0ca 100644 --- a/src/main/java/com/armzilla/ha/dao/DeviceRepository.java +++ b/src/main/java/com/armzilla/ha/dao/DeviceRepository.java @@ -1,7 +1,6 @@ package com.armzilla.ha.dao; import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; diff --git a/src/main/java/com/armzilla/ha/hue/HueMulator.java b/src/main/java/com/armzilla/ha/hue/HueMulator.java index 5934c4c..a688d69 100644 --- a/src/main/java/com/armzilla/ha/hue/HueMulator.java +++ b/src/main/java/com/armzilla/ha/hue/HueMulator.java @@ -62,13 +62,20 @@ public HueMulator(){ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); } + private Page getDevices(HttpServletRequest request) { + int pageNumber = request.getLocalPort()-portBase; + Page result = repository.findByDeviceType("switch", new PageRequest(pageNumber, 25)); + log.info("Found " + result.getNumberOfElements() + " devices on port " + request.getLocalPort()); + + return result; + } + @RequestMapping(value = "/{userId}/lights", method = RequestMethod.GET, produces = "application/json") public ResponseEntity> getUpnpConfiguration(@PathVariable(value = "userId") String userId, HttpServletRequest request) { - log.info("hue lights list requested: " + userId + " from " + request.getRemoteAddr() + request.getLocalPort()); + log.info("hue lights list requested: " + userId + " from " + request.getRemoteAddr() + ":" + request.getLocalPort()); - int pageNumber = request.getLocalPort()-portBase; - Page deviceList = repository.findByDeviceType("switch", new PageRequest(pageNumber, 25)); + Page deviceList = this.getDevices(request); Map deviceResponseMap = new HashMap<>(); for (DeviceDescriptor device : deviceList) { deviceResponseMap.put(device.getId(), device.getName()); @@ -85,8 +92,7 @@ public ResponseEntity postAPI(HttpServletRequest request) { @RequestMapping(value = "/{userId}", method = RequestMethod.GET, produces = "application/json") public ResponseEntity getApi(@PathVariable(value = "userId") String userId, HttpServletRequest request) { log.info("hue api root requested: " + userId + " from " + request.getRemoteAddr()); - int pageNumber = request.getLocalPort()-portBase; - Page descriptorList = repository.findByDeviceType("switch", new PageRequest(pageNumber, 25)); + Page descriptorList = this.getDevices(request); if (descriptorList == null) { return new ResponseEntity<>(null, null, HttpStatus.NOT_FOUND); } diff --git a/src/main/resources/static/app.js b/src/main/resources/static/app.js index 572b287..0925dca 100755 --- a/src/main/resources/static/app.js +++ b/src/main/resources/static/app.js @@ -107,20 +107,61 @@ angular.module('configurator', []) $scope.bridge = bridgeService.state; $scope.device = {id: "", name: "", type: "switch", onUrl: "", offUrl: ""}; - $scope.vera = {base: "", port: "3480", id: ""}; + $scope.hubs = { + vera: { + base: "" + , port: "3480" + , id: "" + , onUrl: "/data_request?id=action&output_format=json&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=1&DeviceNum={deviceId}" + , offUrl: "/data_request?id=action&output_format=json&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=0&DeviceNum={deviceId}" + , user: "" + , pass: "" + } + , openhab: { + base: "" + , port: "8080" + , id: "" + , onUrl: "/CMD?{deviceId}=ON" + , offUrl: "/CMD?{deviceId}=OFF" + , user: "" + , pass: "" + } + } + // set default system to Vera + $scope.selectedHub = "vera"; + $scope.system = $scope.hubs.vera; bridgeService.device = $scope.device; + $scope.selectHub = function (hubName) { + console.log('Selecting hub', $scope.selectedHub) + if (hubName === "openhab") { + $scope.system = $scope.hubs.openhab; + } + else { + $scope.system = $scope.hubs.vera; + } + } + $scope.buildUrls = function () { - if ($scope.vera.base.indexOf("http") < 0) { - $scope.vera.base = "http://" + $scope.vera.base; + var base = "" + if ($scope.system.base.indexOf("http") < 0) { + base = "http://"; } - $scope.device.onUrl = $scope.vera.base + ":" + $scope.vera.port - + "/data_request?id=action&output_format=json&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=1&DeviceNum=" - + $scope.vera.id; - $scope.device.offUrl = $scope.vera.base + ":" + $scope.vera.port - + "/data_request?id=action&output_format=json&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=0&DeviceNum=" - + $scope.vera.id; - }; + base += $scope.system.base; + + var user = $scope.system.user.trim(); + var pass = $scope.system.pass.trim(); + var creds = ""; + if (user.length > 0 && pass.length > 0) { + creds = encodeURIComponent(user) + ":" + encodeURIComponent(pass) + "@"; + } + + var index = base.indexOf("//") + 2; + base = base.slice(0, index) + creds + base.slice(index); + + $scope.device.onUrl = base + ":" + $scope.system.port + $scope.system.onUrl.replace("{deviceId}", $scope.system.id); + $scope.device.offUrl = base + ":" + $scope.system.port + $scope.system.offUrl.replace("{deviceId}", $scope.system.id); + }; $scope.testUrl = function (url) { window.open(url, "_blank"); diff --git a/src/main/resources/static/configurator.html b/src/main/resources/static/configurator.html index 8dabf1d..c02b67f 100755 --- a/src/main/resources/static/configurator.html +++ b/src/main/resources/static/configurator.html @@ -95,38 +95,63 @@

ERROR

+
+

Select Hub Type

+
    +
  • + + + +
  • + +
+

Add a new device

  • -

    You can generate on/off URLs by filling in a Vera server URL, port, and +

    You can generate on/off URLs by filling in a hub server URL, port, and device ID; or you can fill them out manually in the lower section.

    - +
    - +
    - +
    - +
    - - + +
    + +
    + +
    + +
    +
    +
    +
    -