From 561d3cfed54f757ef3ee765dcf16a9620dde3397 Mon Sep 17 00:00:00 2001 From: Admin Date: Wed, 5 Aug 2015 16:21:20 -0500 Subject: [PATCH] Updated persistence --- README.md | 14 +++-- .../bwssytems/HABridge/AmazonEchoBridge.java | 33 +++++++--- .../HABridge/dao/DeviceRepository.java | 63 +++++++++---------- .../devicemanagmeent/DeviceResource.java | 4 +- .../bwssytems/HABridge/upnp/UpnpListener.java | 6 +- .../HABridge/upnp/UpnpSettingsResource.java | 15 +++-- src/main/resources/public/index.html | 29 ++++++--- src/main/resources/public/scripts/app.js | 21 ++++++- 8 files changed, 120 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index d116a7e..f9ab53d 100644 --- a/README.md +++ b/README.md @@ -9,19 +9,23 @@ mvn install ``` Then locate the jar and start the server with: ``` -java -jar -Dupnp.config.address=192.168.1.Z amazon-echo-bridge-compact-0.X.Y.jar +java -jar amazon-echo-bridge-compact-0.X.Y.jar ``` -replace the -Dupnp.config.address value with the server ipv4 address. +The server defaults to the first available address on the host. Replace the -Dupnp.config.address= value with the server ipv4 address you would like to use. -The server defaults to running on port 8080. If you're already running a server (like openHAB) on 8080, -Dserver.port=XXXX on the command line. +The server defaults to running on port 8080. If you're already running a server (like openHAB) on 8080, -Dserver.port= on the command line. -Then configure by going to the url: +The default location for the db to contain the devices as they are added is "data/devices.db". If you would like a different filename or directory, specify -Dupnp.devices.db=/ or if it is the same directory. + +The default upnp response port will be 50000 otherwise it can be set with -Dupnp.response.port=. + +Then configure by going to the url for the host you are running on or localhost: ``` http://192.168.1.240:8080 ``` or Register a device, via REST by binding some sort of on/off (vera style) url ``` -POST http://host:8080/api/devices/ +POST http://host:8080/api/devices { "name" : "bedroom light", "deviceType" : "switch", diff --git a/src/main/java/com/bwssytems/HABridge/AmazonEchoBridge.java b/src/main/java/com/bwssytems/HABridge/AmazonEchoBridge.java index 66e11d3..07f0b14 100644 --- a/src/main/java/com/bwssytems/HABridge/AmazonEchoBridge.java +++ b/src/main/java/com/bwssytems/HABridge/AmazonEchoBridge.java @@ -2,6 +2,9 @@ package com.bwssytems.HABridge; import static spark.Spark.*; +import java.net.InetAddress; +import java.net.UnknownHostException; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -25,8 +28,6 @@ public class AmazonEchoBridge { * * There is a custom upnp listener that is started to handle discovery. * - * This application does not store the lights configuration persistently. - * * */ public static void main(String[] args) { @@ -35,25 +36,41 @@ public class AmazonEchoBridge { HueMulator theHueMulator; UpnpSettingsResource theSettingResponder; UpnpListener theUpnpListener; + InetAddress address; + String addressString; + String upnpAddressString; + String serverPort; + //get ip address for upnp requests + try { + address = InetAddress.getLocalHost(); + addressString = address.getHostAddress(); + } catch (UnknownHostException e) { + log.error("Cannot get ip address of this host, Exiting with message: " + e.getMessage(), e); + return; + } + + upnpAddressString = System.getProperty("upnp.config.address", addressString); // sparkjava config directive to set ip address for the web server to listen on - ipAddress(System.getProperty("upnp.config.address", "0.0.0.0")); + // ipAddress("0.0.0.0"); // not used // sparkjava config directive to set port for the web server to listen on - port(Integer.valueOf(System.getProperty("server.port", "8080"))); + serverPort = System.getProperty("server.port", "8080"); + port(Integer.valueOf(serverPort)); // sparkjava config directive to set html static file location for Jetty staticFileLocation("/public"); - log.debug("Starting setup...."); + log.info("Starting setup...."); // setup the class to handle the resource setup rest api theResources = new DeviceResource(); // setup the class to handle the hue emulator rest api theHueMulator = new HueMulator(theResources.getDeviceRepository()); // setup the class to handle the upnp response rest api - theSettingResponder = new UpnpSettingsResource(); + theSettingResponder = new UpnpSettingsResource(upnpAddressString); // wait for the sparkjava initialization of the rest api classes to be complete awaitInitialization(); + // start the upnp ssdp discovery listener - theUpnpListener = new UpnpListener(); - log.debug("Done setup, application to run...."); + theUpnpListener = new UpnpListener(upnpAddressString, serverPort); + log.info("Done setup, application to run...."); theUpnpListener.startListening(); } } diff --git a/src/main/java/com/bwssytems/HABridge/dao/DeviceRepository.java b/src/main/java/com/bwssytems/HABridge/dao/DeviceRepository.java index ea9bbec..92ed0c4 100644 --- a/src/main/java/com/bwssytems/HABridge/dao/DeviceRepository.java +++ b/src/main/java/com/bwssytems/HABridge/dao/DeviceRepository.java @@ -1,10 +1,12 @@ package com.bwssytems.HABridge.dao; -import java.io.BufferedReader; -import java.io.FileReader; -import java.io.FileWriter; + import java.io.IOException; import java.io.StringReader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -14,7 +16,6 @@ import org.slf4j.LoggerFactory; import com.bwssytems.HABridge.JsonTransformer; import com.bwssytems.HABridge.dao.DeviceDescriptor; -import com.google.gson.Gson; import com.google.gson.stream.JsonReader; import java.util.List; @@ -25,12 +26,13 @@ import java.util.ListIterator; */ public class DeviceRepository { Map devices; + Path repositoryPath; final Random random = new Random(); - final String repositoryPath = "device.db"; final Logger log = LoggerFactory.getLogger(DeviceRepository.class); public DeviceRepository() { super(); + repositoryPath = Paths.get(System.getProperty("upnp.device.db", "data/device.db")); String jsonContent = repositoryReader(repositoryPath); devices = new HashMap(); if(jsonContent != null) @@ -85,45 +87,42 @@ public class DeviceRepository { } - private void repositoryWriter(String content, String filePath) { - FileWriter writer = null; + private void repositoryWriter(String content, Path filePath) { + if(Files.exists(filePath) && !Files.isWritable(filePath)){ + log.error("Error file is not writable: " + filePath); + return; + } + + if(Files.notExists(filePath.getParent())) { + try { + Files.createDirectories(filePath.getParent()); + } catch (IOException e) { + log.error("Error creating the directory: " + filePath + " message: " + e.getMessage(), e); + } + } try { - writer = new FileWriter(filePath, false); - writer.write(content); + Files.write(filePath, content.getBytes(), StandardOpenOption.CREATE); } catch (IOException e) { log.error("Error writing the file: " + filePath + " message: " + e.getMessage(), e); - } finally { - if (writer != null) { - try { - writer.close(); - } catch (IOException e) { - log.error("Error closing the file (w): " + filePath + " message: " + e.getMessage(), e); - } - } } } - private String repositoryReader(String filePath) { - FileReader reader = null; - BufferedReader br = null; + private String repositoryReader(Path filePath) { + String content = null; + if(Files.notExists(filePath) || !Files.isReadable(filePath)){ + log.error("Error reading the file: " + filePath + " - Does not exist or is not readable. "); + return null; + } + + try { - reader = new FileReader(filePath); - br = new BufferedReader(reader); - content = br.readLine(); + content = new String(Files.readAllBytes(filePath)); } catch (IOException e) { log.error("Error reading the file: " + filePath + " message: " + e.getMessage(), e); - } finally { - if (reader != null) { - try { - br.close(); - reader.close(); - } catch (IOException e) { - log.error("Error closing the file (r): " + filePath + " message: " + e.getMessage(), e); - } - } } + return content; } diff --git a/src/main/java/com/bwssytems/HABridge/devicemanagmeent/DeviceResource.java b/src/main/java/com/bwssytems/HABridge/devicemanagmeent/DeviceResource.java index ce4a9ef..57cf770 100644 --- a/src/main/java/com/bwssytems/HABridge/devicemanagmeent/DeviceResource.java +++ b/src/main/java/com/bwssytems/HABridge/devicemanagmeent/DeviceResource.java @@ -38,7 +38,7 @@ public class DeviceResource { private void setupEndpoints() { log.debug("Setting up endpoints"); - post(API_CONTEXT + "/", "application/json", (request, response) -> { + post(API_CONTEXT, "application/json", (request, response) -> { log.debug("Create a Device - request body: " + request.body()); DeviceDescriptor device = new Gson().fromJson(request.body(), DeviceDescriptor.class); DeviceDescriptor deviceEntry = new DeviceDescriptor(); @@ -75,7 +75,7 @@ public class DeviceResource { return deviceEntry; }, new JsonTransformer()); - get (API_CONTEXT + "/", "application/json", (request, response) -> { + get (API_CONTEXT, "application/json", (request, response) -> { List deviceList = deviceRepository.findAll(); log.debug("Get all devices"); JsonTransformer aRenderer = new JsonTransformer(); diff --git a/src/main/java/com/bwssytems/HABridge/upnp/UpnpListener.java b/src/main/java/com/bwssytems/HABridge/upnp/UpnpListener.java index 5b215d1..deb94c1 100644 --- a/src/main/java/com/bwssytems/HABridge/upnp/UpnpListener.java +++ b/src/main/java/com/bwssytems/HABridge/upnp/UpnpListener.java @@ -21,11 +21,11 @@ public class UpnpListener { private String responseAddress; - public UpnpListener() { + public UpnpListener(String upnpAddress, String upnpServerPort) { super(); upnpResponsePort = Integer.valueOf(System.getProperty("upnp.response.port", "50000")); - httpServerPort = Integer.valueOf(System.getProperty("server.port", "8080")); - responseAddress = System.getProperty("upnp.config.address", "192.168.14.136"); + httpServerPort = Integer.valueOf(upnpServerPort); + responseAddress = upnpAddress; } public void startListening(){ diff --git a/src/main/java/com/bwssytems/HABridge/upnp/UpnpSettingsResource.java b/src/main/java/com/bwssytems/HABridge/upnp/UpnpSettingsResource.java index 3b7b45d..2842290 100644 --- a/src/main/java/com/bwssytems/HABridge/upnp/UpnpSettingsResource.java +++ b/src/main/java/com/bwssytems/HABridge/upnp/UpnpSettingsResource.java @@ -35,16 +35,15 @@ public class UpnpSettingsResource { + "24\n" + "hue_logo_3.png\n" + "\n" + "\n" + "\n" + "\n"; - public UpnpSettingsResource() { + public UpnpSettingsResource(String upnpAddress) { super(); - setupListener(); + setupListener(upnpAddress); } - private void setupListener () { + private void setupListener (String hostName) { // http://ip_address:port/upnp/:id/setup.xml which returns the xml configuration for the location of the hue emulator get(UPNP_CONTEXT + "/:id/setup.xml", "application/xml", (request, response) -> { log.info("upnp device settings requested: " + request.params(":id") + " from " + request.ip()); - String hostName = System.getProperty("upnp.config.address", "192.168.1.1"); String portNumber = Integer.toString(request.port()); String filledTemplate = String.format(hueTemplate, hostName, portNumber, hostName); log.debug("upnp device settings response: " + filledTemplate); @@ -52,5 +51,13 @@ public class UpnpSettingsResource { return filledTemplate; } ); + + get(UPNP_CONTEXT + "/configaddress", "application/xml", (request, response) -> { + log.info("upnp config address requested: from " + request.ip()); + + response.status(201); + + return hostName; + } ); } } diff --git a/src/main/resources/public/index.html b/src/main/resources/public/index.html index eca186d..2005c61 100644 --- a/src/main/resources/public/index.html +++ b/src/main/resources/public/index.html @@ -40,17 +40,26 @@
- - -
- +
+ + +
+ +
+ + +
+
+ +
+ +
- -
diff --git a/src/main/resources/public/scripts/app.js b/src/main/resources/public/scripts/app.js index 0ba11a9..d0fe47b 100644 --- a/src/main/resources/public/scripts/app.js +++ b/src/main/resources/public/scripts/app.js @@ -1,7 +1,7 @@ angular.module('amazonechobridge', []) .service('bridgeService', ["$http", function ($http) { var self = this; - this.state = {base: window.location.origin + "/api/devices/", devices: [], error: ""}; + this.state = {base: window.location.origin + "/api/devices", upnpbase: window.location.origin + "/upnp/configaddress", devices: [], error: ""}; this.viewDevices = function () { this.state.error = ""; @@ -21,6 +21,24 @@ angular.module('amazonechobridge', []) ); }; + this.viewConfigAddress = function () { + this.state.error = ""; + return $http.get(this.state.upnpbase).then( + function (response) { + self.state.upnpconfigaddress = response.data; + }, + function (error) { + if (error.data) { + self.state.error = error.data.message; + } else { + self.state.error = "If you're not seeing any address, 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) { @@ -87,6 +105,7 @@ angular.module('amazonechobridge', []) .controller('ViewingController', ["$scope", "bridgeService", function ($scope, bridgeService) { bridgeService.viewDevices(); + bridgeService.viewConfigAddress(); $scope.bridge = bridgeService.state; $scope.deleteDevice = function (device) { bridgeService.deleteDevice(device.id);