mirror of
https://github.com/bwssytems/ha-bridge.git
synced 2025-12-19 16:41:53 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c1d6e40b8 | ||
|
|
c5fbd5d1f0 |
12
README.md
12
README.md
@@ -9,13 +9,13 @@ Otherwise go to http://www.bwssystems.com/apps.html to download the latest jar f
|
||||
## Run
|
||||
Then locate the jar and start the server with:
|
||||
```
|
||||
java -jar -Dvera.address=192.168.X.Y ha-bridge-0.X.Y.jar
|
||||
java -jar -Dvera.address=X.Y.Z.A ha-bridge-0.X.Y.jar
|
||||
```
|
||||
## Available Arguments
|
||||
### -Dvera.address=`<ip address>`
|
||||
The argument for the vera address should be given as it the system does not have a way to find the address. Supply -Dvera.address=X.Y.Z.A on the command line to provide it.
|
||||
The argument for the vera address should be given as it the system does not have a way to find the address. Supply -Dvera.address=X.Y.Z.A on the command line to provide it. If a vera is not used, do not set it.
|
||||
### -Dupnp.config.address=`<ip address>`
|
||||
The server defaults to the first available address on the host. Replace the -Dupnp.config.address=`<ip address>` value with the server ipv4 address you would like to use.
|
||||
The server defaults to the first available address on the host. Replace the -Dupnp.config.address=`<ip address>` value with the server ipv4 address you would like to use as the address that any upnp device will call after discovery.
|
||||
### -Dserver.port=`<port>`
|
||||
The server defaults to running on port 8080. If you're already running a server (like openHAB) on 8080, -Dserver.port=`<port>` on the command line.
|
||||
### -Dupnp.device.db=`<filepath>`
|
||||
@@ -23,11 +23,11 @@ The default location for the db to contain the devices as they are added is "dat
|
||||
### -Dupnp.response.port=`<port>`
|
||||
The upnp response port that will be used. The default is 50000.
|
||||
### -Dupnp.strict=`<true|false>`
|
||||
Upnp has been very closed on this platform to try and respond as a hue and there is now a setting to control if it is more open or strict, Add -Dupnp.strict=`<true|false>` to your command line to have the emulator respond to what it thinks is an echo to a hue or any other device. The default is upnp.strict=false.
|
||||
Upnp has been very closed on this platform to try and respond as a hue and there is now a setting to control if it is more open or strict, Add -Dupnp.strict=`<true|false>` to your command line to have the emulator respond to what it thinks is an echo to a hue or any other device. The default is upnp.strict=true.
|
||||
### -Dtrace.upnp=`<true|false>`
|
||||
Turn on tracing for upnp discovery messages. The default is false.
|
||||
### -Dvtwo.compatibility=`<true|false>`
|
||||
Turns on compatibility for upnp detection and response as it was in the original version of amazon-echo-ha-bridge. The default is true.
|
||||
Turns on compatibility for upnp detection and response as it was in the original version of amazon-echo-ha-bridge. The default is false.
|
||||
## Web Config
|
||||
Configure by going to the url for the host you are running on or localhost with port you have assigned:
|
||||
```
|
||||
@@ -45,7 +45,7 @@ POST http://host:8080/api/devices
|
||||
}
|
||||
```
|
||||
## Dimming and value passing control
|
||||
Dimming is also supported by using the expressions ${intensity.percent} for 0-100 or ${intensity.byte} for 0-255 or $intensity{match(<your expression using "X" as the value to operate on>)} i.e. "$intensity.math(X/4)}".
|
||||
Dimming is also supported by using the expressions ${intensity.percent} for 0-100 or ${intensity.byte} for 0-255 or custom values using ${intensity.math(<your expression using "X" as the value to operate on>)} i.e. "{$intensity.math(X/4)}".
|
||||
e.g.
|
||||
```
|
||||
{
|
||||
|
||||
7
pom.xml
7
pom.xml
@@ -5,7 +5,7 @@
|
||||
|
||||
<groupId>com.bwssystems.HABridge</groupId>
|
||||
<artifactId>ha-bridge</artifactId>
|
||||
<version>0.4.8</version>
|
||||
<version>0.4.9</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>HA Bridge</name>
|
||||
@@ -53,6 +53,11 @@
|
||||
<artifactId>json-io</artifactId>
|
||||
<version>4.1.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.java.dev.eval</groupId>
|
||||
<artifactId>eval</artifactId>
|
||||
<version>0.5</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -61,4 +61,9 @@ public class BridgeSettings {
|
||||
this.vtwocompatibility = vtwocompatibility;
|
||||
}
|
||||
|
||||
public Boolean isValidVera() {
|
||||
if(this.veraaddress.contains(Configuration.DEFAULT_VERA_ADDRESS))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
8
src/main/java/com/bwssystems/HABridge/Configuration.java
Normal file
8
src/main/java/com/bwssystems/HABridge/Configuration.java
Normal file
@@ -0,0 +1,8 @@
|
||||
package com.bwssystems.HABridge;
|
||||
|
||||
public class Configuration {
|
||||
public final static String DEVICE_DB_DIRECTORY = "data/device.db";
|
||||
public final static String UPNP_RESPONSE_PORT = "50000";
|
||||
public final static String DEFAULT_VERA_ADDRESS = "1.1.1.1";
|
||||
public final static String DFAULT_WEB_PORT = "8080";
|
||||
}
|
||||
@@ -51,17 +51,17 @@ public class HABridge {
|
||||
|
||||
bridgeSettings = new BridgeSettings();
|
||||
bridgeSettings.setUpnpConfigAddress(System.getProperty("upnp.config.address", addressString));
|
||||
bridgeSettings.setUpnpDeviceDb(System.getProperty("upnp.device.db", "data/device.db"));
|
||||
bridgeSettings.setUpnpResponsePort(System.getProperty("upnp.response.port", "50000"));
|
||||
bridgeSettings.setVeraAddress(System.getProperty("vera.address", "192.168.1.100"));
|
||||
bridgeSettings.setUpnpStrict(Boolean.parseBoolean(System.getProperty("upnp.strict", "false")));
|
||||
bridgeSettings.setUpnpDeviceDb(System.getProperty("upnp.device.db", Configuration.DEVICE_DB_DIRECTORY));
|
||||
bridgeSettings.setUpnpResponsePort(System.getProperty("upnp.response.port", Configuration.UPNP_RESPONSE_PORT));
|
||||
bridgeSettings.setVeraAddress(System.getProperty("vera.address", Configuration.DEFAULT_VERA_ADDRESS));
|
||||
bridgeSettings.setUpnpStrict(Boolean.parseBoolean(System.getProperty("upnp.strict", "true")));
|
||||
bridgeSettings.setTraceupnp(Boolean.parseBoolean(System.getProperty("trace.upnp", "false")));
|
||||
bridgeSettings.setVtwocompatibility(Boolean.parseBoolean(System.getProperty("vtwo.compatibility", "true")));
|
||||
bridgeSettings.setVtwocompatibility(Boolean.parseBoolean(System.getProperty("vtwo.compatibility", "false")));
|
||||
|
||||
// sparkjava config directive to set ip address for the web server to listen on
|
||||
// ipAddress("0.0.0.0"); // not used
|
||||
// sparkjava config directive to set port for the web server to listen on
|
||||
bridgeSettings.setServerPort(System.getProperty("server.port", "8080"));
|
||||
bridgeSettings.setServerPort(System.getProperty("server.port", Configuration.DFAULT_WEB_PORT));
|
||||
port(Integer.valueOf(bridgeSettings.getServerPort()));
|
||||
// sparkjava config directive to set html static file location for Jetty
|
||||
staticFileLocation("/public");
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.bwssystems.HABridge.dao;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
@@ -108,9 +107,13 @@ public class DeviceRepository {
|
||||
}
|
||||
|
||||
try {
|
||||
Path target = FileSystems.getDefault().getPath("data", "device.db.old");
|
||||
Path target = null;
|
||||
if(Files.exists(filePath)) {
|
||||
target = FileSystems.getDefault().getPath(filePath.getParent().toString(), "device.db.old");
|
||||
Files.move(filePath, target);
|
||||
}
|
||||
Files.write(filePath, content.getBytes(), StandardOpenOption.CREATE);
|
||||
if(target != null)
|
||||
Files.delete(target);
|
||||
} catch (IOException e) {
|
||||
log.error("Error writing the file: " + filePath + " message: " + e.getMessage(), e);
|
||||
@@ -121,7 +124,7 @@ public class DeviceRepository {
|
||||
|
||||
String content = null;
|
||||
if(Files.notExists(filePath) || !Files.isReadable(filePath)){
|
||||
log.error("Error reading the file: " + filePath + " - Does not exist or is not readable. ");
|
||||
log.warn("Error reading the file: " + filePath + " - Does not exist or is not readable. continuing...");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ public class DeviceResource {
|
||||
public DeviceResource(BridgeSettings theSettings) {
|
||||
super();
|
||||
deviceRepository = new DeviceRepository(theSettings.getUpnpDeviceDb());
|
||||
veraInfo = new VeraInfo(theSettings.getVeraAddress());
|
||||
veraInfo = new VeraInfo(theSettings.getVeraAddress(), theSettings.isValidVera());
|
||||
setupEndpoints();
|
||||
}
|
||||
|
||||
|
||||
@@ -9,9 +9,9 @@ import com.bwssystems.HABridge.dao.*;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.gson.Gson;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
import javax.script.ScriptEngine;
|
||||
|
||||
import net.java.dev.eval.Expression;
|
||||
|
||||
import static spark.Spark.get;
|
||||
import static spark.Spark.post;
|
||||
import static spark.Spark.put;
|
||||
@@ -32,6 +32,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -47,7 +48,6 @@ public class HueMulator {
|
||||
private static final String INTENSITY_MATH = "${intensity.math(";
|
||||
private static final String INTENSITY_MATH_VALUE = "X";
|
||||
private static final String INTENSITY_MATH_CLOSE = ")}";
|
||||
private static final String ENGINE_JAVASCRIPT = "JavaScript";
|
||||
private static final String HUE_CONTEXT = "/api";
|
||||
|
||||
private DeviceRepository repository;
|
||||
@@ -232,9 +232,10 @@ public class HueMulator {
|
||||
/* light weight templating here, was going to use free marker but it was a bit too
|
||||
* heavy for what we were trying to do.
|
||||
*
|
||||
* currently provides only two variables:
|
||||
* currently provides:
|
||||
* intensity.byte : 0-255 brightness. this is raw from the echo
|
||||
* intensity.percent : 0-100, adjusted for the vera
|
||||
* intensity.math(X*1) : where X is the value from the interface call and can use net.java.dev.eval math
|
||||
*/
|
||||
protected String replaceIntensityValue(String request, int intensity){
|
||||
if(request == null){
|
||||
@@ -248,16 +249,18 @@ public class HueMulator {
|
||||
String intensityPercent = String.valueOf(percentBrightness);
|
||||
request = request.replace(INTENSITY_PERCENT, intensityPercent);
|
||||
} else if(request.contains(INTENSITY_MATH)){
|
||||
Map<String, BigDecimal> variables = new HashMap<String, BigDecimal>();
|
||||
String mathDescriptor = request.substring(request.indexOf(INTENSITY_MATH) + INTENSITY_MATH.length(),request.indexOf(INTENSITY_MATH_CLOSE));
|
||||
String updatedMath = mathDescriptor.replace(INTENSITY_MATH_VALUE, String.valueOf(intensity));
|
||||
ScriptEngineManager mgr = new ScriptEngineManager();
|
||||
ScriptEngine engine = mgr.getEngineByName(ENGINE_JAVASCRIPT);
|
||||
variables.put(INTENSITY_MATH_VALUE, new BigDecimal(intensity));
|
||||
|
||||
try {
|
||||
log.debug("Math eval is: " + updatedMath);
|
||||
Integer endResult = (Integer) engine.eval(updatedMath);
|
||||
log.debug("Math eval is: " + mathDescriptor + ", Where " + INTENSITY_MATH_VALUE + " is: " + String.valueOf(intensity));
|
||||
Expression exp = new Expression(mathDescriptor);
|
||||
BigDecimal result = exp.eval(variables);
|
||||
Integer endResult = Math.round(result.floatValue());
|
||||
request = request.replace(INTENSITY_MATH + mathDescriptor + INTENSITY_MATH_CLOSE, endResult.toString());
|
||||
} catch (ScriptException e) {
|
||||
log.error("Could not execute Math: " + updatedMath, e);
|
||||
} catch (Exception e) {
|
||||
log.error("Could not execute Math: " + mathDescriptor, e);
|
||||
} }
|
||||
return request;
|
||||
}
|
||||
|
||||
@@ -26,14 +26,19 @@ public class VeraInfo {
|
||||
private HttpClient httpClient;
|
||||
private static final String SDATA_REQUEST = ":3480/data_request?id=sdata&output_format=json";
|
||||
private String veraAddressString;
|
||||
private Boolean validVera;
|
||||
|
||||
public VeraInfo(String addressString) {
|
||||
public VeraInfo(String addressString, Boolean isValidVera) {
|
||||
super();
|
||||
httpClient = HttpClients.createMinimal();
|
||||
veraAddressString = addressString;
|
||||
validVera = isValidVera;
|
||||
}
|
||||
|
||||
public Sdata getSdata() {
|
||||
if(!validVera)
|
||||
return new Sdata();
|
||||
|
||||
String theUrl = "http://" + veraAddressString + SDATA_REQUEST;
|
||||
String theData;
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
|
||||
<li><a href="http://www.bwssystems.com" target="_blank">Developed by BWS Systems</a></li>
|
||||
<li><a href="http://www.amazon.com/echo" target="_blank">Amazon Echo</a></li>
|
||||
<li><a href="">HA Bridge Version 0.4.8</a></li>
|
||||
<li><a href="">HA Bridge Version 0.4.9</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -26,6 +26,7 @@ app.config(function ($routeProvider) {
|
||||
|
||||
app.run( function (bridgeService) {
|
||||
bridgeService.loadBridgeSettings();
|
||||
bridgeService.updateShowVera();
|
||||
});
|
||||
|
||||
app.factory('BridgeSettings', function() {
|
||||
@@ -75,7 +76,7 @@ app.factory('BridgeSettings', function() {
|
||||
app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
||||
var self = this;
|
||||
self.BridgeSettings = BridgeSettings;
|
||||
this.state = {base: window.location.origin + "/api/devices", upnpbase: window.location.origin + "/upnp/settings", devices: [], device: [], error: ""};
|
||||
this.state = {base: window.location.origin + "/api/devices", upnpbase: window.location.origin + "/upnp/settings", devices: [], device: [], error: "", showVera: false};
|
||||
|
||||
this.viewDevices = function () {
|
||||
this.state.error = "";
|
||||
@@ -107,6 +108,10 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
||||
self.BridgeSettings.settraceupnp(response.data.traceupnp);
|
||||
self.BridgeSettings.setupnpstrict(response.data.upnpstrict);
|
||||
self.BridgeSettings.setvtwocompatibility(response.data.vtwocompatibility);
|
||||
if(self.BridgeSettings.veraaddress == "1.1.1.1" || self.BridgeSettings.veraaddress == "")
|
||||
self.state.showVera = false;
|
||||
else
|
||||
self.state.showVera = true;
|
||||
},
|
||||
function (error) {
|
||||
if (error.data) {
|
||||
@@ -119,7 +124,18 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
||||
);
|
||||
};
|
||||
|
||||
this.updateShowVera = function () {
|
||||
if(self.BridgeSettings.veraaddress == "1.1.1.1" || self.BridgeSettings.veraaddress == "")
|
||||
this.state.showVera = false;
|
||||
else
|
||||
this.state.showVera = true;
|
||||
return;
|
||||
}
|
||||
|
||||
this.viewVeraDevices = function () {
|
||||
this.state.error = "";
|
||||
if(BridgeSettings.veraaddress == "1.1.1.1" || BridgeSettings.veraaddress == "")
|
||||
return;
|
||||
this.state.error = "";
|
||||
return $http.get(this.state.base + "/vera/devices").then(
|
||||
function (response) {
|
||||
@@ -137,6 +153,8 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
||||
|
||||
this.viewVeraScenes = function () {
|
||||
this.state.error = "";
|
||||
if(BridgeSettings.veraaddress == "1.1.1.1" || BridgeSettings.veraaddress == "")
|
||||
return;
|
||||
return $http.get(this.state.base + "/vera/scenes").then(
|
||||
function (response) {
|
||||
self.state.verascenes = response.data;
|
||||
@@ -227,6 +245,7 @@ app.controller('ViewingController', function ($scope, $location, $http, $window,
|
||||
$scope.BridgeSettings = bridgeService.BridgeSettings;
|
||||
bridgeService.viewDevices();
|
||||
$scope.bridge = bridgeService.state;
|
||||
bridgeService.updateShowVera();
|
||||
$scope.predicate = '';
|
||||
$scope.reverse = true;
|
||||
$scope.order = function(predicate) {
|
||||
@@ -301,6 +320,7 @@ app.controller('AddingController', function ($scope, $location, $http, bridgeSer
|
||||
bridgeService.viewVeraDevices();
|
||||
bridgeService.viewVeraScenes();
|
||||
$scope.bridge = bridgeService.state;
|
||||
bridgeService.updateShowVera();
|
||||
$scope.device = bridgeService.state.device;
|
||||
$scope.predicate = '';
|
||||
$scope.reverse = true;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<ul class="nav nav-pills" role="tablist">
|
||||
<li role="presentation" class="active"><a href="#">Configuration</a></li>
|
||||
<li role="presentation"><a href="#/veradevices">Vera Devices</a></li>
|
||||
<li role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a href="#/veradevices">Vera Devices</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
|
||||
<li role="presentation"><a href="#/editor">Manual Add</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<ul class="nav nav-pills" role="tablist">
|
||||
<li role="presentation"><a href="#">Configuration</a></li>
|
||||
<li role="presentation"><a href="#/veradevices">Vera Devices</a></li>
|
||||
<li role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a href="#/veradevices">Vera Devices</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
|
||||
<li role="presentation"><a href="#/editor">Manual Add</a></li>
|
||||
<li role="presentation" class="active"><a href="#/editdevice">Edit Device</a></li>
|
||||
</ul>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<ul class="nav nav-pills" role="tablist">
|
||||
<li role="presentation"><a href="#">Configuration</a></li>
|
||||
<li role="presentation"><a href="#/veradevices">Vera Devices</a></li>
|
||||
<li role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a href="#/veradevices">Vera Devices</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
|
||||
<li role="presentation" class="active"><a href="#/editor">Manual Add</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user