Finished slider for testint items with percentage items. Many refactors

and fixes.

Fixes #43
Fixes #46
Fixes #47
Fixes #48
This commit is contained in:
Admin
2016-02-19 16:34:04 -06:00
parent 922bb54143
commit 77d3084b01
15 changed files with 193 additions and 149 deletions

View File

@@ -9,35 +9,12 @@ Otherwise, downloads are available at https://github.com/bwssytems/ha-bridge/rel
## Run
Then locate the jar and start the server with:
```
java -jar -Dupnp.config.address=A.B.C.D -Dvera.address=E.F.G.H -Dharmony.address=W.X.Y.Z -Dharmony.user=myself -Dharmony.pwd=passwd ha-bridge-W.X.Y.jar
java -jar ha-bridge-W.X.Y.jar
```
## Available Arguments
### -Dupnp.config.address=`<ip address>`
The server defaults to the first available address on the host if this is not given. This default may NOT be the correct IP that is your public IP for your host on the network. It is best to set this parameter to not have discovery issues. 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.
### -Dvera.address=`<ip address>` | `<{devices:[{name:avera,ip:x.y.w.z},{name:anothervera,ip:a.b.c.d}]}>`
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. To provide multiple veras, use the json style notation outlined above to provide the list. The json notation may need to be surrounded by quotation marks when starting from a shell script. Most service scripts will not need the quotation marks. This argument is backwards compatible.
### -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>`
The default location for the db to contain the devices as they are added is the relative path from where the bridge is started in "data/device.db". If you would like a different filename or directory, specify -Dupnp.devices.db=`<directory>/<filename>` explicitly.
### -Dupnp.response.port=`<port>`
The upnp response port that will be used. The default is 50000.
### -Dharmony.address=`<ip address>` | `<{devices:[{name:ahub,ip:x.y.w.z},{name:anotherhub,ip:a.b.c.d}]}>`
The argument for the Harmony Hub address should be given as the system does not have a way to find the address. Supply -Dharmony.address=X.Y.Z.A on the command line to provide it. If a Harmony Hub is not used, do not set it. To provide multiple harmony hubs, use the json style notation outlined above to provide the list. The json notation may need to be surrounded by quotation marks when starting from a shell script. Most service scripts will not need the quotation marks. This argument is backwards compatible.
### -Dharmony.user=`<username>`
The user name of the MyHarmony.com account for the Harmony Hub. This needs to be given if you are using the Harmony Hub features, provide -Dharmony.user=`<username>` on the command line.
### -Dharmony.pwd=`<password>`
The password for the user name of the MyHarmony.com account for the Harmony Hub. This needs to be given if you are using the Harmony Hub Features, provide -Dharmony.pwd=`<password>` on the command line.
### -Dbutton.sleep=`<time in milliseconds>`
The default button press sleep time interval is 100 milliseconds. If you need more time add this parameter. For example 1000 ms is 1 second and you could set -Dbutton.sleep=1000 for the longer interval if you are having issues on your devices not handling button presses fast enough.
### -Dnest.user=`<username>`
The user name of the home.nest.com account for the Nest user. This needs to be given if you are using the Nest features, provide -Dnest.user=`<username>` on the command line. There is no need to give any ip address or host information as this contacts your cloud account.
### -Dnest.pwd=`<password>`
The password for the user name of the home.nest.com account for the Nestr user. This needs to be given if you are using the Nest features, provide -Dnest.pwd=`<password>` on the command line.
### -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=true.
### -Dtrace.upnp=`<true|false>`
Turn on tracing for upnp discovery messages. The default is false.
Arguments are now depecated. The ha-bridge will use the old -D arguments and populate the config screen which can now be saved to a file and will not be needed. There is only one optional argument that overides and that is the location of the config file. The default is the relative path "data/habridge.config".
### -Dconfig.file=`<filepath>`
The default location for the config fileto contain the settings for the bridge is the relative path from where the bridge is started in "data/habridge.config". If you would like a different filename or directory, specify -Dconfig.file=`<directory>/<filename>` explicitly.
## HA Bridge Device Configuration
You must configure devices before you will have any thing for the Echo to receive. The easy way to get devices configures is with the web interface by going to the url for the host you are running on or localhost with port you have assigned: and use the helpers for the Vera or Harmony Hub to create devices that the Echo will find.

View File

@@ -5,7 +5,7 @@
<groupId>com.bwssystems.HABridge</groupId>
<artifactId>ha-bridge</artifactId>
<version>1.3.8h</version>
<version>1.4.0</version>
<packaging>jar</packaging>
<name>HA Bridge</name>

View File

@@ -87,7 +87,7 @@ public abstract class BackupHandler {
} catch (IOException x) {
// IOException can never be thrown by the iteration.
// In this snippet, it can // only be thrown by newDirectoryStream.
log.error("Issue getting directory listing for backups - " + x.getMessage());
log.warn("Issue getting directory listing for backups in directory: " + x.getMessage());
}
return theFilenames;
}

View File

@@ -54,10 +54,10 @@ public class BridgeSettings extends BackupHandler {
{
log.info("reading from system properties");
theBridgeSettings.setConfigfile(Configuration.CONFIG_FILE);
theBridgeSettings.setServerPort(System.getProperty("server.port"));
theBridgeSettings.setServerPort(System.getProperty("server.port", Configuration.DEFAULT_WEB_PORT));
theBridgeSettings.setUpnpConfigAddress(System.getProperty("upnp.config.address"));
theBridgeSettings.setUpnpDeviceDb(System.getProperty("upnp.device.db"));
theBridgeSettings.setUpnpResponsePort(System.getProperty("upnp.response.port"));
theBridgeSettings.setUpnpResponsePort(System.getProperty("upnp.response.port", Configuration.UPNP_RESPONSE_PORT));
theVeraAddress = System.getProperty("vera.address");
IpList theVeraList = null;
@@ -94,8 +94,7 @@ public class BridgeSettings extends BackupHandler {
theBridgeSettings.setHarmonyPwd(System.getProperty("harmony.pwd"));
theBridgeSettings.setUpnpStrict(Boolean.parseBoolean(System.getProperty("upnp.strict", "true")));
theBridgeSettings.setTraceupnp(Boolean.parseBoolean(System.getProperty("trace.upnp", "false")));
theBridgeSettings.setDevMode(Boolean.parseBoolean(System.getProperty("dev.mode", "false")));
theBridgeSettings.setButtonsleep(Integer.parseInt(System.getProperty("button.sleep", Configuration.DFAULT_BUTTON_SLEEP)));
theBridgeSettings.setButtonsleep(Integer.parseInt(System.getProperty("button.sleep", Configuration.DEFAULT_BUTTON_SLEEP)));
theBridgeSettings.setNestuser(System.getProperty("nest.user"));
theBridgeSettings.setNestpwd(System.getProperty("nest.pwd"));
}
@@ -135,13 +134,13 @@ public class BridgeSettings extends BackupHandler {
theBridgeSettings.setUpnpResponsePort(Configuration.UPNP_RESPONSE_PORT);
if(theBridgeSettings.getServerPort() == null)
theBridgeSettings.setServerPort(Configuration.DFAULT_WEB_PORT);
theBridgeSettings.setServerPort(Configuration.DEFAULT_WEB_PORT);
if(theBridgeSettings.getUpnpDeviceDb() == null)
theBridgeSettings.setUpnpDeviceDb(Configuration.DEVICE_DB_DIRECTORY);
if(theBridgeSettings.getButtonsleep() <= 0)
theBridgeSettings.setButtonsleep(Integer.parseInt(Configuration.DFAULT_BUTTON_SLEEP));
theBridgeSettings.setButtonsleep(Integer.parseInt(Configuration.DEFAULT_BUTTON_SLEEP));
theBridgeSettings.setVeraconfigured(theBridgeSettings.isValidVera());
theBridgeSettings.setHarmonyconfigured(theBridgeSettings.isValidHarmony());
@@ -172,7 +171,6 @@ public class BridgeSettings extends BackupHandler {
theBridgeSettings.setHarmonyPwd(aBridgeSettings.getHarmonyPwd());
theBridgeSettings.setUpnpStrict(aBridgeSettings.isUpnpStrict());
theBridgeSettings.setTraceupnp(aBridgeSettings.isTraceupnp());
theBridgeSettings.setDevMode(aBridgeSettings.isDevMode());
theBridgeSettings.setNestuser(aBridgeSettings.getNestuser());
theBridgeSettings.setNestpwd(aBridgeSettings.getNestpwd());
theBridgeSettings.setVeraconfigured(aBridgeSettings.isValidVera());

View File

@@ -14,7 +14,6 @@ public class BridgeSettingsDescriptor {
private Integer buttonsleep;
private boolean upnpstrict;
private boolean traceupnp;
private boolean devmode;
private String nestuser;
private String nestpwd;
private boolean veraconfigured;
@@ -25,7 +24,6 @@ public class BridgeSettingsDescriptor {
public BridgeSettingsDescriptor() {
super();
this.upnpstrict = true;
this.devmode = false;
this.traceupnp = false;
this.nestconfigured = false;
this.veraconfigured = false;
@@ -97,12 +95,6 @@ public class BridgeSettingsDescriptor {
public void setTraceupnp(boolean traceupnp) {
this.traceupnp = traceupnp;
}
public boolean isDevMode() {
return devmode;
}
public void setDevMode(boolean devmode) {
this.devmode = devmode;
}
public String getNestuser() {
return nestuser;
}

View File

@@ -3,12 +3,11 @@ 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 UPNP_RESPONSE_DEVICES = "30";
public final static String DEFAULT_ADDRESS = "1.1.1.1";
public final static String LOOP_BACK_ADDRESS = "127.0.0.1";
public final static String LOOP_BACK_INTERFACE = "lo";
public final static String DFAULT_WEB_PORT = "8080";
public final static String DFAULT_BUTTON_SLEEP = "100";
public final static String DEFAULT_WEB_PORT = "8080";
public final static String DEFAULT_BUTTON_SLEEP = "100";
public static final int UPNP_DISCOVERY_PORT = 1900;
public static final String UPNP_MULTICAST_ADDRESS = "239.255.255.250";
public static final String CONFIG_FILE = "data/habridge.config";

View File

@@ -78,7 +78,7 @@ public class DeviceResource {
return "";
});
post(API_CONTEXT, "application/json", (request, response) -> {
log.info("Create a Device(s) - request body: " + request.body());
log.debug("Create a Device(s) - request body: " + request.body());
DeviceDescriptor devices[];
if(request.body().substring(0,1).equalsIgnoreCase("[") == true) {
devices = new Gson().fromJson(request.body(), DeviceDescriptor[].class);

View File

@@ -245,7 +245,7 @@ public class HueMulator {
DeviceDescriptor device = repository.findOne(lightId);
if (device == null) {
response.status(HttpStatus.SC_NOT_FOUND);
return "[{\"error\":{\"type\": 3, \"address\": \"/lights/" + lightId + ",\"description\": \"Object not found\"}}]";
return "[{\"error\":{\"type\": 3, \"address\": \"/lights/" + lightId + "\",\"description\": \"Object not found\"}}]";
} else {
log.debug("found device named: " + device.getName());
}
@@ -285,14 +285,14 @@ public class HueMulator {
state = mapper.readValue(request.body(), DeviceState.class);
} catch (IOException e) {
log.warn("Object mapper barfed on input of body.", e);
responseString = "[{\"error\":{\"type\": 2, \"address\": \"/lights/" + lightId + ",\"description\": \"Object mapper barfed on input of body.\"}}]";
responseString = "[{\"error\":{\"type\": 2, \"address\": \"/lights/" + lightId + "\",\"description\": \"Object mapper barfed on input of body.\"}}]";
return responseString;
}
DeviceDescriptor device = repository.findOne(lightId);
if (device == null) {
log.warn("Could not find device: " + lightId + " for hue state change request: " + userId + " from " + request.ip() + " body: " + request.body());
responseString = "[{\"error\":{\"type\": 3, \"address\": \"/lights/" + lightId + ",\"description\": \"Could not find device\", \"resource\": \"/lights/" + lightId + "\"}}]";
responseString = "[{\"error\":{\"type\": 3, \"address\": \"/lights/" + lightId + "\",\"description\": \"Could not find device\", \"resource\": \"/lights/" + lightId + "\"}}]";
return responseString;
}
@@ -322,60 +322,77 @@ public class HueMulator {
if(device.getDeviceType().toLowerCase().contains("activity") || (device.getMapType() != null && device.getMapType().equalsIgnoreCase("harmonyActivity")))
{
log.debug("executing HUE api request to change activity to Harmony: " + url);
RunActivity anActivity = new Gson().fromJson(url, RunActivity.class);
HarmonyHandler myHarmony = myHarmonyHome.getHarmonyHandler(device.getTargetDevice());
if(myHarmony == null)
if(myHarmonyHome != null)
{
log.warn("Should not get here, no harmony hub available");
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + ",\"description\": \"Should not get here, no harmony hub available\", \"parameter\": \"/lights/" + lightId + "state\"}}]";
RunActivity anActivity = new Gson().fromJson(url, RunActivity.class);
HarmonyHandler myHarmony = myHarmonyHome.getHarmonyHandler(device.getTargetDevice());
if(myHarmony == null)
{
log.warn("Should not get here, no harmony hub available");
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + "\",\"description\": \"Should not get here, no harmony hub available\", \"parameter\": \"/lights/" + lightId + "state\"}}]";
}
else
myHarmony.startActivity(anActivity);
}
else {
log.warn("Should not get here, no harmony configured");
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + "\",\"description\": \"Should not get here, no harmony configured\", \"parameter\": \"/lights/" + lightId + "state\"}}]";
}
else
myHarmony.startActivity(anActivity);
}
else if(device.getDeviceType().toLowerCase().contains("button") || (device.getMapType() != null && device.getMapType().equalsIgnoreCase("harmonyButton")))
{
log.debug("executing HUE api request to button press(es) to Harmony: " + url);
if(url.substring(0, 1).equalsIgnoreCase("{")) {
url = "[" + url +"]";
}
ButtonPress[] deviceButtons = new Gson().fromJson(url, ButtonPress[].class);
HarmonyHandler myHarmony = myHarmonyHome.getHarmonyHandler(device.getTargetDevice());
if(myHarmony == null)
if(myHarmonyHome != null)
{
log.warn("Should not get here, no harmony hub available");
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + ",\"description\": \"Should not get here, no harmony hub available\", \"parameter\": \"/lights/" + lightId + "state\"}}]";
if(url.substring(0, 1).equalsIgnoreCase("{")) {
url = "[" + url +"]";
}
ButtonPress[] deviceButtons = new Gson().fromJson(url, ButtonPress[].class);
HarmonyHandler myHarmony = myHarmonyHome.getHarmonyHandler(device.getTargetDevice());
if(myHarmony == null)
{
log.warn("Should not get here, no harmony hub available");
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + "\",\"description\": \"Should not get here, no harmony hub available\", \"parameter\": \"/lights/" + lightId + "state\"}}]";
}
else {
for(int i = 0; i < deviceButtons.length; i++) {
if( i > 0)
Thread.sleep(bridgeSettings.getButtonsleep());
log.debug("pressing button: " + deviceButtons[i].getDevice() + " - " + deviceButtons[i].getButton() + " - iteration: " + String.valueOf(i));
myHarmony.pressButton(deviceButtons[i]);
}
}
}
else {
for(int i = 0; i < deviceButtons.length; i++) {
if( i > 0)
Thread.sleep(bridgeSettings.getButtonsleep());
log.debug("pressing button: " + deviceButtons[i].getDevice() + " - " + deviceButtons[i].getButton() + " - iteration: " + String.valueOf(i));
myHarmony.pressButton(deviceButtons[i]);
}
log.warn("Should not get here, no harmony configured");
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + "\",\"description\": \"Should not get here, no harmony configured\", \"parameter\": \"/lights/" + lightId + "state\"}}]";
}
}
else if(device.getDeviceType().toLowerCase().contains("home") || (device.getMapType() != null && device.getMapType().equalsIgnoreCase("nestHomeAway")))
{
log.debug("executing HUE api request to set away for nest home: " + url);
NestInstruction homeAway = new Gson().fromJson(url, NestInstruction.class);
if(theNest == null)
{
log.warn("Should not get here, no Nest available");
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + ",\"description\": \"Should not get here, no Nest available\", \"parameter\": \"/lights/" + lightId + "state\"}}]";
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + "\",\"description\": \"Should not get here, no Nest available\", \"parameter\": \"/lights/" + lightId + "state\"}}]";
}
else
else {
NestInstruction homeAway = new Gson().fromJson(url, NestInstruction.class);
theNest.getHome(homeAway.getName()).setAway(homeAway.getAway());
}
}
else if(device.getDeviceType().toLowerCase().contains("thermo") || (device.getMapType() != null && device.getMapType().equalsIgnoreCase("nestThermoSet")))
{
log.debug("executing HUE api request to set thermostat for nest: " + url);
NestInstruction thermoSetting = new Gson().fromJson(url, NestInstruction.class);
if(theNest == null)
{
log.warn("Should not get here, no Nest available");
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + ",\"description\": \"Should not get here, no Nest available\", \"parameter\": \"/lights/" + lightId + "state\"}}]";
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + "\",\"description\": \"Should not get here, no Nest available\", \"parameter\": \"/lights/" + lightId + "state\"}}]";
}
else {
NestInstruction thermoSetting = new Gson().fromJson(url, NestInstruction.class);
if(thermoSetting.getControl().equalsIgnoreCase("temp")) {
if(request.body().contains("bri")) {
thermoSetting.setTemp(String.valueOf((Double.parseDouble(replaceIntensityValue(thermoSetting.getTemp(), state.getBri())) - 32.0)/1.8));
@@ -393,7 +410,7 @@ public class HueMulator {
}
else {
log.warn("no valid Nest control info: " + thermoSetting.getControl());
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + ",\"description\": \"no valid Nest control info\", \"parameter\": \"/lights/" + lightId + "state\"}}]";
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + "\",\"description\": \"no valid Nest control info\", \"parameter\": \"/lights/" + lightId + "state\"}}]";
}
}
}
@@ -417,7 +434,7 @@ public class HueMulator {
responseSocket.close();
} catch (IOException e) {
log.warn("Could not send UDP Datagram packet for request.", e);
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + ",\"description\": \"Error on calling out to device\", \"parameter\": \"/lights/" + lightId + "state\"}}]";
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + "\",\"description\": \"Error on calling out to device\", \"parameter\": \"/lights/" + lightId + "state\"}}]";
}
}
else
@@ -433,7 +450,7 @@ public class HueMulator {
// make call
if (!doHttpRequest(url, device.getHttpVerb(), device.getContentType(), body)) {
log.warn("Error on calling url to change device state: " + url);
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + ",\"description\": \"Error on calling url to change device state\", \"parameter\": \"/lights/" + lightId + "state\"}}]";
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + "\",\"description\": \"Error on calling url to change device state\", \"parameter\": \"/lights/" + lightId + "state\"}}]";
}
}

View File

@@ -20,13 +20,15 @@ import net.whistlingfish.harmony.config.Device;
public class HarmonyHome {
private static final Logger log = LoggerFactory.getLogger(HarmonyHome.class);
private Map<String, HarmonyServer> hubs;
private Boolean isDevMode;
public HarmonyHome(BridgeSettingsDescriptor bridgeSettings) {
super();
isDevMode = Boolean.parseBoolean(System.getProperty("dev.mode", "false"));
hubs = new HashMap<String, HarmonyServer>();
if(!bridgeSettings.isValidHarmony() && !bridgeSettings.isDevMode())
if(!bridgeSettings.isValidHarmony() && !isDevMode)
return;
if(bridgeSettings.isDevMode()) {
if(isDevMode) {
NamedIP devModeIp = new NamedIP();
devModeIp.setIp("10.10.10.10");
devModeIp.setName("devMode");
@@ -40,7 +42,7 @@ public class HarmonyHome {
while(theList.hasNext()) {
NamedIP aHub = theList.next();
try {
hubs.put(aHub.getName(), HarmonyServer.setup(bridgeSettings, aHub));
hubs.put(aHub.getName(), HarmonyServer.setup(bridgeSettings, isDevMode, aHub));
} catch (Exception e) {
log.error("Cannot get harmony client (" + aHub.getName() + ") setup, Exiting with message: " + e.getMessage(), e);
return;
@@ -49,6 +51,8 @@ public class HarmonyHome {
}
public void shutdownHarmonyHubs() {
if(isDevMode)
return;
Iterator<String> keys = hubs.keySet().iterator();
while(keys.hasNext()) {
String key = keys.next();

View File

@@ -26,7 +26,7 @@ public class HarmonyServer {
private DevModeResponse devResponse;
private OAReplyProvider dummyProvider;
private NamedIP myNameAndIP;
private Boolean isDevMode;
private Logger log = LoggerFactory.getLogger(HarmonyServer.class);
public HarmonyServer(NamedIP theHarmonyAddress) {
@@ -34,33 +34,35 @@ public class HarmonyServer {
myHarmony = null;
dummyProvider = null;
myNameAndIP = theHarmonyAddress;
isDevMode = false;
}
public static HarmonyServer setup(BridgeSettingsDescriptor bridgeSettings, NamedIP theHarmonyAddress) throws Exception {
if(!bridgeSettings.isValidHarmony() && !bridgeSettings.isDevMode()) {
public static HarmonyServer setup(BridgeSettingsDescriptor bridgeSettings, Boolean harmonyDevMode, NamedIP theHarmonyAddress) throws Exception {
if(!bridgeSettings.isValidHarmony() && harmonyDevMode) {
return new HarmonyServer(theHarmonyAddress);
}
Injector injector = null;
if(!bridgeSettings.isDevMode())
if(!harmonyDevMode)
injector = Guice.createInjector(new HarmonyClientModule());
HarmonyServer mainObject = new HarmonyServer(theHarmonyAddress);
if(!bridgeSettings.isDevMode())
if(!harmonyDevMode)
injector.injectMembers(mainObject);
mainObject.execute(bridgeSettings);
mainObject.execute(bridgeSettings, harmonyDevMode);
return mainObject;
}
private void execute(BridgeSettingsDescriptor mySettings) throws Exception {
private void execute(BridgeSettingsDescriptor mySettings, Boolean harmonyDevMode) throws Exception {
Boolean noopCalls = Boolean.parseBoolean(System.getProperty("noop.calls", "false"));
String modeString = "";
isDevMode = harmonyDevMode;
String modeString = "";
if(dummyProvider != null)
log.debug("something is very wrong as dummyProvider is not null...");
if(mySettings.isDevMode())
if(isDevMode)
modeString = " (development mode)";
else if(noopCalls)
modeString = " (no op calls to harmony)";
log.info("setup initiated " + modeString + "....");
if(mySettings.isDevMode())
if(isDevMode)
{
harmonyClient = null;
devResponse = new DevModeResponse();

File diff suppressed because one or more lines are too long

View File

@@ -7,6 +7,7 @@
<title>HA Bridge</title>
<link href="css/main.css" rel="stylesheet">
<link href="css/bootstrap.min.css" rel="stylesheet">
<link href="css/bootstrap-theme.min.css" rel="stylesheet">
<link href="css/ngToast.min.css" rel="stylesheet">
<link href="css/rzslider.min.css" rel="stylesheet">
<link href="css/ngDialog.min.css" rel="stylesheet">
@@ -23,10 +24,11 @@
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container" ng-controller="VersionController">
<div class="navbar-header">
<button type="button" class="navbar-toggle">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">HA Bridge</a>
</div>
@@ -36,10 +38,8 @@
<li><a href="http://echo.amazon.com/#cards" target="_blank">My Echo</a></li>
<li><a href="https://github.com/bwssytems/ha-bridge/blob/master/README.md" target="_blank">Help</a></li>
<li class="dropdown">
<a id="dropdownMenu1" href="" class="dropdown-toggle"
data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false">About <span class="caret"></span></a>
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
<a id="dLabel" href="" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">About <span class="caret"></span></a>
<ul class="dropdown-menu" aria-labelledby="dLabel">
<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 {{bridge.habridgeversion}}</a></li>

View File

@@ -41,10 +41,10 @@ app.run( function (bridgeService) {
app.service('bridgeService', function ($http, $window, ngToast) {
var self = this;
this.state = {base: window.location.origin + "/api/devices", bridgelocation: window.location.origin, systemsbase: window.location.origin + "/system", huebase: window.location.origin + "/api", configs: [], backups: [], devices: [], device: [], settings: [], myToastMsg: [], olddevicename: "", showVera: false, showHarmony: false, showNest: false, habridgeversion: ""};
this.state = {base: window.location.origin + "/api/devices", bridgelocation: window.location.origin, systemsbase: window.location.origin + "/system", huebase: window.location.origin + "/api", configs: [], backups: [], devices: [], device: [], type: "", settings: [], myToastMsg: [], olddevicename: "", isInControl: false, showVera: false, showHarmony: false, showNest: false, habridgeversion: ""};
this.displayWarn = function(errorTitle, error) {
if(error == null) {
if(error == null || typeof(error) != 'undefined') {
error = {status: 200, statusText: "OK", data: []};
error.data = {message: "success"};
}
@@ -56,7 +56,7 @@ app.service('bridgeService', function ($http, $window, ngToast) {
};
this.displayError = function(errorTitle, error) {
if(error == null) {
if(error == null || typeof(error) != 'undefined') {
error = {status: 200, statusText: "OK", data: []};
error.data = {message: "success"};
}
@@ -67,6 +67,14 @@ app.service('bridgeService', function ($http, $window, ngToast) {
content: errorTitle + error.data.message + " with status: " + error.statusText + " - " + error.status});
};
this.displayErrorMessage = function(errorTitle, errorMessage) {
ngToast.create({
className: "danger",
dismissButton: true,
dismissOnTimeout: false,
content: errorTitle + errorMessage});
};
this.displaySuccess = function(theTitle) {
ngToast.create({
className: "success",
@@ -339,6 +347,8 @@ app.service('bridgeService', function ($http, $window, ngToast) {
ngToast.dismiss(self.state.myToastMsg);
self.viewConfigs();
self.state.myToastMsg = null;
self.state.isInControl = false;
window.location.reload();
},
function (error) {
setTimeout(function(){
@@ -350,6 +360,7 @@ app.service('bridgeService', function ($http, $window, ngToast) {
};
this.stop = function() {
self.state.isInControl = true;
return $http.put(this.state.systemsbase + "/control/stop").then(
function (response) {
self.displayError("HABridge is now stopped. Restart must occur from the server.", null);
@@ -361,6 +372,7 @@ app.service('bridgeService', function ($http, $window, ngToast) {
};
this.reinit = function() {
self.state.isInControl = true;
return $http.put(this.state.systemsbase + "/control/reinit").then(
function (response) {
self.state.myToastMsg = ngToast.create({
@@ -453,40 +465,38 @@ app.service('bridgeService', function ($http, $window, ngToast) {
self.state.olddevicename = device.name;
};
this.testUrl = function (device, type) {
this.testUrl = function (device, type, value) {
var msgDescription = "unknown";
var testUrl = this.state.huebase + "/test/lights/" + device.id + "/state";
var testBody = "{\"on\":";
if(type == "on") {
$http.put(this.state.huebase + "/test/lights/" + device.id + "/state", "{\"on\":true}").then(
function (response) {
if(typeof(response.data[0].success) != 'undefined')
msgDescription = "success " + angular.toJson(response.data[0].success);
if(typeof(response.data[0].error) != 'undefined')
msgDescription = "error " + angular.toJson(response.data[0].error);
self.displaySuccess("Request Exceuted: " + msgDescription);
},
function (error) {
self.displayWarn("Request Error, Pleae look in your habridge log: ", error);
}
);
return;
testBody = testBody + "true";
}
else {
$http.put(this.state.huebase + "/test/lights/" + device.id + "/state", "{\"on\":false}").then(
function (response) {
if(typeof(response.data[0].success) != 'undefined')
msgDescription = "success " + angular.toJson(response.data[0].success);
if(typeof(response.data[0].error) != 'undefined')
msgDescription = "error " + angular.toJson(response.data[0].error);
self.displaySuccess("Request Exceuted: " + msgDescription);
},
function (error) {
self.displayWarn("Request Error, Pleae look in your habridge log: ", error);
}
);
return;
testBody = testBody + "false";
}
if(value) {
testBody = testBody + ",\"bri\":" + value;
}
testBody = testBody + "}";
$http.put(testUrl, testBody).then(
function (response) {
if(typeof(response.data[0].success) != 'undefined') {
msgDescription = "success " + angular.toJson(response.data[0].success);
}
if(typeof(response.data[0].error) != 'undefined') {
msgDescription = "error " + angular.toJson(response.data[0].error);
self.displayErrorMessage("Request Error, Pleae look in your habridge log: ", msgDescription);
return;
}
self.displaySuccess("Request Exceuted: " + msgDescription);
},
function (error) {
self.displayWarn("Request Error, Pleae look in your habridge log: ", error);
}
);
return;
};
});
@@ -494,13 +504,14 @@ app.controller('SystemController', function ($scope, $location, $http, $window,
bridgeService.viewConfigs();
$scope.bridge = bridgeService.state;
$scope.optionalbackupname = "";
$scope.isInControl = false;
$scope.visible = false;
$scope.imgUrl = "glyphicon glyphicon-plus";
$scope.visibleBk = false;
$scope.imgBkUrl = "glyphicon glyphicon-plus";
$scope.addVeratoSettings = function (newveraname, newveraip) {
if($scope.bridge.settings.veraddress == null) {
$scope.bridge.settings.veraddress = { devices: [] };
if($scope.bridge.settings.veraaddress == null) {
$scope.bridge.settings.veraaddress = { devices: [] };
}
var newVera = {name: newveraname, ip: newveraip }
$scope.bridge.settings.veraaddress.devices.push(newVera);
@@ -531,9 +542,11 @@ app.controller('SystemController', function ($scope, $location, $http, $window,
}
};
$scope.bridgeReinit = function () {
$scope.isInControl = false;
bridgeService.reinit();
};
$scope.bridgeStop = function () {
$scope.isInControl = false;
bridgeService.stop();
};
$scope.saveSettings = function() {
@@ -588,15 +601,23 @@ app.controller('ViewingController', function ($scope, $location, $http, $window,
$scope.predicate = predicate;
};
$scope.testUrl = function (device, type) {
if(type == "on") {
var dialogNeeded = false;
if((type == "on" && (bridgeService.aContainsB(device.onUrl, "${intensity..byte}") ||
bridgeService.aContainsB(device.onUrl, "${intensity.percent}") ||
bridgeService.aContainsB(device.onUrl, "${intensity.math("))) ||
(type == "off" && (bridgeService.aContainsB(device.offUrl, "${intensity..byte}") ||
bridgeService.aContainsB(device.offUrl, "${intensity.percent}") ||
bridgeService.aContainsB(device.offUrl, "${intensity.math(")))) {
$scope.bridge.device = device;
$scope.bridge.type = type;
ngDialog.open({
template: 'valueDialog',
controller: 'ValueDialogCtrl',
className: 'ngdialog-theme-default'
});
}
ngDialog.open({
template: 'valueDialog',
controller: 'ValueDialogCtrl',
className: 'ngdialog-theme-default'
});
// bridgeService.testUrl(device, type);
else
bridgeService.testUrl(device, type);
};
$scope.deleteDevice = function (device) {
bridgeService.deleteDevice(device.id);
@@ -630,7 +651,7 @@ app.controller('ViewingController', function ($scope, $location, $http, $window,
};
});
app.controller('ValueDialogCtrl', function ($scope, ngDialog) {
app.controller('ValueDialogCtrl', function ($scope, bridgeService, ngDialog) {
$scope.slider = {
value: 100,
options: {
@@ -639,8 +660,28 @@ app.controller('ValueDialogCtrl', function ($scope, ngDialog) {
showSelectionBar: true
}
};
$scope.bridge = bridgeService.state;
$scope.valueType = "percentage";
$scope.changeScale = function () {
if($scope.valueType == "raw") {
$scope.slider.options.ceil = 255;
$scope.slider.value = 255;
}
else {
$scope.slider.options.ceil = 100;
$scope.slider.value = 100;
}
};
$scope.setValue = function () {
ngDialog.close('ngdialog1');
var theValue = 0;
if($scope.valueType == "percentage")
theValue = Math.round(($scope.slider.value * .01) * 255);
else
theValue = $scope.slider.value;
bridgeService.testUrl($scope.bridge.device, $scope.bridge.type, theValue);
$scope.bridge.device = null;
$scope.bridge.type = "";
};
});

View File

@@ -93,6 +93,10 @@
<script type="text/ng-template" id="valueDialog">
<div class="ngdialog-message">
<h2>Select value</h2>
<p>
<input type="radio" ng-model="valueType" value="percentage" ng-change="changeScale()"> Percentage
<input type="radio" ng-model="valueType" value="raw" ng-change="changeScale()"> Raw
</p>
<p>
<rzslider rz-slider-model="slider.value" rz-slider-options="slider.options"></rzslider>
</p>

View File

@@ -30,13 +30,21 @@
ng-click="goBridgeUrl(bridge.base)">Go</button>
</div>
</form>
<form name="form">
<p>
<button class="btn btn-success" type="submit"
<button ng-disabled="form.$pristine || bridge.isInControl" class="btn btn-success" type="submit"
ng-click="saveSettings()">Save</button>
<button class="btn btn-warning" type="submit"
<button ng-disabled="bridge.isInControl" class="btn btn-warning" type="submit"
ng-click="bridgeReinit()">Bridge Reinitialize</button>
<button class="btn btn-danger" type="submit"
<button ng-disabled="bridge.isInControl" class="btn btn-danger" type="submit"
ng-click="bridgeStop()">Bridge Stop</button>
<button class="btn btn-primary" type="submit"
onclick="myRefresh()">Refresh</button>
<script>
function myRefresh() {
location.reload();
}
</script>
</p>
<table class="table table-bordered table-striped table-hover">
<thead>
@@ -159,12 +167,8 @@
<td><input type="checkbox" ng-model="bridge.settings.traceupnp"
ng-true-value=true ng-false-value=false> {{bridge.settings.traceupnp}}</td>
</tr>
<tr>
<td>Harmony Development Mode</td>
<td><input type="checkbox" ng-model="bridge.settings.devmode"
ng-true-value=true ng-false-value=false> {{bridge.settings.devmode}}</td>
</tr>
</table>
</form>
</div>
</div>
<div class="panel panel-default backup">