From af79b8c4754fb1ed1999f63ebac3c1a57b7dc5ac Mon Sep 17 00:00:00 2001 From: Duane May Date: Wed, 24 Jun 2015 21:18:04 -0400 Subject: [PATCH 1/5] get the base url for devices call from the browser so that it works when not on localhost --- src/main/resources/static/configurator.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 src/main/resources/static/configurator.html diff --git a/src/main/resources/static/configurator.html b/src/main/resources/static/configurator.html old mode 100644 new mode 100755 index 7c7a8d1..eb54a4e --- a/src/main/resources/static/configurator.html +++ b/src/main/resources/static/configurator.html @@ -15,7 +15,7 @@ .service('bridgeService', ["$http", function($http) { var self = this; - this.state = {base: "http://localhost:8080/api/devices", devices: [], error: ""}; + this.state = {base: window.location.origin + "/api/devices", devices: [], error: ""}; this.viewDevices = function() { this.state.error = ""; From 6a476e5d0665ca4885651b02bcbd9c371a45d88c Mon Sep 17 00:00:00 2001 From: Duane May Date: Wed, 24 Jun 2015 23:27:19 -0400 Subject: [PATCH 2/5] improved styling of the confuration page, added the ability to load devices after changing bridge URL --- src/main/resources/static/configurator.html | 416 ++++++++++++-------- 1 file changed, 258 insertions(+), 158 deletions(-) diff --git a/src/main/resources/static/configurator.html b/src/main/resources/static/configurator.html index eb54a4e..7c5acd2 100755 --- a/src/main/resources/static/configurator.html +++ b/src/main/resources/static/configurator.html @@ -1,166 +1,266 @@ - - + + - - - - + + + + Amazon Echo Bridge Configuration + + + + + + + + -
- -

Bridge settings

- - -

Current devices

-
- - - - - - - - - - -
IDNAMETYPE
{{device.id}}{{device.name}}{{device.deviceType}}
-
+ -
-

Add a new device

- You can generate on/off URLs by filling in the Vera server URL and device ID, or you - can fill them out manually. - -
-
- -
- -
- -
- -
-
+
+
-
-

ERROR

-
-{{bridge.error}} -
-
+
+

Bridge settings

+
+
+ + +
+ +
+ + +
+
+
+ +
+ +
+ +
+

Current devices

+ + + + + + + + + + + + + + + +
IDNameTypeActions
{{device.id}}{{device.name}}{{device.deviceType}} + + + +
+
+
+ +
+
+

Add a new device

+
+

You can generate on/off URLs by filling in the Vera server URL and device ID, or + you can fill them out manually.

+ +
+
+ + +
+ +
+
+
+ + +
+ +
+ + + +
+ +
+ +
+
+ + +
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
+
+
+ +
- + \ No newline at end of file From 5f27f3cdef090820bca1e626041df22273450bbe Mon Sep 17 00:00:00 2001 From: Duane May Date: Wed, 24 Jun 2015 23:39:28 -0400 Subject: [PATCH 3/5] added more explanation on how to use and configure the bridge to the README --- README.md | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) mode change 100644 => 100755 README.md diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 00a8163..5b3dcf2 --- a/README.md +++ b/README.md @@ -5,7 +5,27 @@ emulates philips hue api to other home automation gateways. The Amazon echo now supports wemo and philip hue... great news if you own any of those devices! My house is pretty heavily invested in the z-wave using the Vera as the gateway and thought it would be nice bridge the Amazon Echo to it. -Register a device, bind to some sort of on/off (vera style) url + +To run using maven +``` +mvn spring-boot:run +``` + +somewhat hacked together for now, please excuse the hard coded values + +or build using maven, grab the jar, run like this: +``` +mvn install +java -jar target/amazon-echo-bridge-0.1.0.jar --upnp.config.address=192.168.1.240 +``` +replace the --upnp.config.address value with the server ipv4 address. + +Then configure by going to the /configurator.html url +``` +http://192.168.1.240:8080/configurator.html +``` + +or Register a device, via REST by binding some sort of on/off (vera style) url ``` POST http://host:8080/api/devices { @@ -16,15 +36,8 @@ POST http://host:8080/api/devices } ``` -To run using maven -``` -mvn spring-boot:run -``` +After this Tell Alexa: "Alexa, discover my devices" -somewhat hacked together for now, please excuse the hard coded values +Then you can say "Alexa, Turn on the office light" or whatever name you have given your configured devices. -grab the jar, run like this: -``` -java -jar amazon-echo-bridge-0.1.0.jar --upnp.config.address=192.168.1.240 -``` -replace the --upnp.config.address value with the server ipv4 address. +To view or remove devices that Alexa knows about, you can use the mobile app Menu / Settings / Connected Home From ca87feb6e7d9cf44d3de52091da3a7b2c66f5273 Mon Sep 17 00:00:00 2001 From: Duane May Date: Thu, 25 Jun 2015 22:42:20 -0400 Subject: [PATCH 4/5] split out the port from the url, auto insert the http: if not there, took out the default value for the vera url --- src/main/resources/static/configurator.html | 121 ++++++++++++-------- 1 file changed, 73 insertions(+), 48 deletions(-) diff --git a/src/main/resources/static/configurator.html b/src/main/resources/static/configurator.html index 7c5acd2..39a0b34 100755 --- a/src/main/resources/static/configurator.html +++ b/src/main/resources/static/configurator.html @@ -97,14 +97,17 @@ .controller('AddingController', ["$scope", "bridgeService", function ($scope, bridgeService) { $scope.bridge = bridgeService.state; - $scope.device = {name: "", type: "switch", onUrl: "", offUrl: ""}; - $scope.vera = {base: "http://192.168.1.144:3480", id: 1}; + $scope.device = {id: "", name: "", type: "switch", onUrl: "", offUrl: ""}; + $scope.vera = {base: "", port: "3480", id: ""}; $scope.buildUrls = function () { - $scope.device.onUrl = $scope.vera.base + if ($scope.vera.base.indexOf("http") < 0) { + $scope.vera.base = "http://" + $scope.vera.base; + } + $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.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; }; @@ -116,6 +119,7 @@ $scope.addDevice = function () { bridgeService.addDevice($scope.device.name, $scope.device.type, $scope.device.onUrl, $scope.device.offUrl).then( function () { + $scope.device.id = ""; $scope.device.name = ""; $scope.device.onUrl = ""; $scope.device.offUrl = ""; @@ -150,10 +154,11 @@
- +
- +
- - -
- + + +
  • +
    +
    + -
    - +
    + +
    +
    - -
    -
    - +
    + -
    - +
    + +
    +
    - -
    - - -
    +
    + + +
    + +
    + +
    + +
  • +
    + From 31453c4258622978e929dd7d5d6f85b083e9db4d Mon Sep 17 00:00:00 2001 From: Duane May Date: Thu, 25 Jun 2015 23:56:38 -0400 Subject: [PATCH 5/5] added the capability to edit/update devices with PUT and via configurator --- .../ha/devicemanagmeent/DeviceResource.java | 17 ++ .../ha/filters/SpringBootCorsFilter.java | 4 +- src/main/resources/static/app.js | 145 ++++++++++++++++++ src/main/resources/static/configurator.html | 128 +--------------- 4 files changed, 172 insertions(+), 122 deletions(-) mode change 100644 => 100755 src/main/java/com/armzilla/ha/devicemanagmeent/DeviceResource.java mode change 100644 => 100755 src/main/java/com/armzilla/ha/filters/SpringBootCorsFilter.java create mode 100755 src/main/resources/static/app.js diff --git a/src/main/java/com/armzilla/ha/devicemanagmeent/DeviceResource.java b/src/main/java/com/armzilla/ha/devicemanagmeent/DeviceResource.java old mode 100644 new mode 100755 index 57673a3..1f6dc8e --- a/src/main/java/com/armzilla/ha/devicemanagmeent/DeviceResource.java +++ b/src/main/java/com/armzilla/ha/devicemanagmeent/DeviceResource.java @@ -40,6 +40,23 @@ public ResponseEntity createDevice(@RequestBody Device device) return new ResponseEntity<>(deviceEntry, null, HttpStatus.CREATED); } + @RequestMapping(value = "/{lightId}", method = RequestMethod.PUT, produces = "application/json", headers = "Accept=application/json") + public ResponseEntity updateDevice(@PathVariable("lightId") String id, @RequestBody Device device) { + DeviceDescriptor deviceEntry = deviceRepository.findOne(id); + if(deviceEntry == null){ + return new ResponseEntity<>(null, null, HttpStatus.NOT_FOUND); + } + + deviceEntry.setName(device.getName()); + deviceEntry.setDeviceType(device.getDeviceType()); + deviceEntry.setOnUrl(device.getOnUrl()); + deviceEntry.setOffUrl(device.getOffUrl()); + + deviceRepository.save(deviceEntry); + + return new ResponseEntity<>(deviceEntry, null, HttpStatus.OK); + } + @RequestMapping(method = RequestMethod.GET, produces = "application/json") public ResponseEntity> findAllDevices() { List deviceList = deviceRepository.findAll(); diff --git a/src/main/java/com/armzilla/ha/filters/SpringBootCorsFilter.java b/src/main/java/com/armzilla/ha/filters/SpringBootCorsFilter.java old mode 100644 new mode 100755 index 0d0fa40..3cd0223 --- a/src/main/java/com/armzilla/ha/filters/SpringBootCorsFilter.java +++ b/src/main/java/com/armzilla/ha/filters/SpringBootCorsFilter.java @@ -22,9 +22,9 @@ public class SpringBootCorsFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) res; response.setHeader("Access-Control-Allow-Origin", "*"); - response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); + response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT"); response.setHeader("Access-Control-Max-Age", "3600"); - response.setHeader("Access-Control-Allow-Headers", "x-requested-with"); + response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); chain.doFilter(req, res); } diff --git a/src/main/resources/static/app.js b/src/main/resources/static/app.js new file mode 100755 index 0000000..572b287 --- /dev/null +++ b/src/main/resources/static/app.js @@ -0,0 +1,145 @@ +angular.module('configurator', []) + .service('bridgeService', ["$http", function ($http) { + var self = this; + this.state = {base: window.location.origin + "/api/devices", devices: [], error: ""}; + + this.viewDevices = function () { + this.state.error = ""; + return $http.get(this.state.base).then( + function (response) { + self.state.devices = response.data[0].content; + }, + function (error) { + if (error.data) { + self.state.error = error.data.message; + } else { + self.state.error = "If you're not seeing any devices, you may be running into problems with CORS. " + + "You can work around this by running a fresh launch of Chrome with the --disable-web-security flag."; + } + console.log(error); + } + ); + }; + + this.addDevice = function (id, name, type, onUrl, offUrl) { + this.state.error = ""; + if (id) { + var putUrl = this.state.base + "/" + id; + return $http.put(putUrl, { + id: id, + name: name, + deviceType: type, + onUrl: onUrl, + offUrl: offUrl + }).then( + function (response) { + self.viewDevices(); + }, + function (error) { + if (error.data) { + self.state.error = error.data.message; + } + console.log(error); + } + ); + } else { + return $http.post(this.state.base, { + name: name, + deviceType: type, + onUrl: onUrl, + offUrl: offUrl + }).then( + function (response) { + self.viewDevices(); + }, + function (error) { + if (error.data) { + self.state.error = error.data.message; + } + console.log(error); + } + ); + } + }; + + this.deleteDevice = function (id) { + this.state.error = ""; + return $http.delete(this.state.base + "/" + id).then( + function (response) { + self.viewDevices(); + }, + function (error) { + if (error.data) { + self.state.error = error.data.message; + } + console.log(error); + } + ); + }; + + this.editDevice = function (id, name, type, onUrl, offUrl) { + this.device.id = id; + this.device.name = name; + this.device.onUrl = onUrl; + this.device.offUrl = offUrl; + }; + }]) + + .controller('ViewingController', ["$scope", "bridgeService", function ($scope, bridgeService) { + bridgeService.viewDevices(); + $scope.bridge = bridgeService.state; + $scope.deleteDevice = function (device) { + bridgeService.deleteDevice(device.id); + }; + $scope.testUrl = function (url) { + window.open(url, "_blank"); + }; + $scope.setBridgeUrl = function (url) { + bridgeService.state.base = url; + bridgeService.viewDevices(); + }; + $scope.editDevice = function (device) { + bridgeService.editDevice(device.id, device.name, device.type, device.onUrl, device.offUrl); + }; + }]) + + .controller('AddingController', ["$scope", "bridgeService", function ($scope, bridgeService) { + + $scope.bridge = bridgeService.state; + $scope.device = {id: "", name: "", type: "switch", onUrl: "", offUrl: ""}; + $scope.vera = {base: "", port: "3480", id: ""}; + bridgeService.device = $scope.device; + + $scope.buildUrls = function () { + if ($scope.vera.base.indexOf("http") < 0) { + $scope.vera.base = "http://" + $scope.vera.base; + } + $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; + }; + + $scope.testUrl = function (url) { + window.open(url, "_blank"); + }; + + $scope.addDevice = function () { + bridgeService.addDevice($scope.device.id, $scope.device.name, $scope.device.type, $scope.device.onUrl, $scope.device.offUrl).then( + function () { + $scope.device.id = ""; + $scope.device.name = ""; + $scope.device.onUrl = ""; + $scope.device.offUrl = ""; + }, + function (error) { + } + ); + } + }]) + + .controller('ErrorsController', ["$scope", "bridgeService", function ($scope, bridgeService) { + $scope.bridge = bridgeService.state; + }]); \ No newline at end of file diff --git a/src/main/resources/static/configurator.html b/src/main/resources/static/configurator.html index 39a0b34..e1542ef 100755 --- a/src/main/resources/static/configurator.html +++ b/src/main/resources/static/configurator.html @@ -19,121 +19,7 @@ - + @@ -200,6 +86,7 @@

    ERROR

    + @@ -238,10 +125,9 @@

    ERROR

    - @@ -255,7 +141,9 @@

    ERROR

    - +