mirror of
https://github.com/bwssytems/ha-bridge.git
synced 2025-12-19 00:20:26 +00:00
Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2565183ee9 | ||
|
|
a6bb1ae3aa | ||
|
|
4bc91be88b | ||
|
|
315fd31270 | ||
|
|
09787fe08d | ||
|
|
37d346f558 | ||
|
|
ac59398aa0 | ||
|
|
87073435fc | ||
|
|
8687f3482a | ||
|
|
32a5f26ddd | ||
|
|
c28f07d628 | ||
|
|
d3cc961dfb | ||
|
|
1b3d826f28 | ||
|
|
c8f4d89a45 | ||
|
|
2b335d6b9b | ||
|
|
b27bb5eef8 | ||
|
|
3c54ccd56d | ||
|
|
cf772334c4 | ||
|
|
5a843f7569 | ||
|
|
2a52783bb1 | ||
|
|
195f1854ec | ||
|
|
2e5596a6e4 | ||
|
|
9fc13c6c45 | ||
|
|
4b4d4e36c7 | ||
|
|
1e7bdc560b | ||
|
|
aff0f8d64c | ||
|
|
7a812d6e6b | ||
|
|
26f2105801 | ||
|
|
feef345a3b |
18
pom.xml
18
pom.xml
@@ -5,11 +5,11 @@
|
|||||||
|
|
||||||
<groupId>com.bwssystems.HABridge</groupId>
|
<groupId>com.bwssystems.HABridge</groupId>
|
||||||
<artifactId>ha-bridge</artifactId>
|
<artifactId>ha-bridge</artifactId>
|
||||||
<version>1.1.0</version>
|
<version>1.3.5</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>HA Bridge</name>
|
<name>HA Bridge</name>
|
||||||
<description>Emulates a Philips Hue bridge to allow the Amazon Echo to hook up to other HA systems, i.e. Vera or Harmony Hub, using lightweight frameworks</description>
|
<description>Emulates a Philips Hue bridge to allow the Amazon Echo to hook up to other HA systems, i.e. Vera or Harmony Hub or Nest, using lightweight frameworks</description>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
@@ -30,16 +30,26 @@
|
|||||||
<artifactId>harmony-java-client</artifactId>
|
<artifactId>harmony-java-client</artifactId>
|
||||||
<version>1.0.8</version>
|
<version>1.0.8</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.bwssytems</groupId>
|
||||||
|
<artifactId>nest-controller</artifactId>
|
||||||
|
<version>1.0.3</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.sparkjava</groupId>
|
<groupId>com.sparkjava</groupId>
|
||||||
<artifactId>spark-core</artifactId>
|
<artifactId>spark-core</artifactId>
|
||||||
<version>2.2</version>
|
<version>2.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.httpcomponents</groupId>
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
<artifactId>httpclient</artifactId>
|
<artifactId>httpclient</artifactId>
|
||||||
<version>4.3.6</version>
|
<version>4.5.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
|
<artifactId>httpcore</artifactId>
|
||||||
|
<version>4.4.4</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>slf4j-simple</artifactId>
|
<artifactId>slf4j-simple</artifactId>
|
||||||
|
|||||||
@@ -1,17 +1,23 @@
|
|||||||
package com.bwssystems.HABridge;
|
package com.bwssystems.HABridge;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class BridgeSettings {
|
public class BridgeSettings {
|
||||||
private String upnpconfigaddress;
|
private String upnpconfigaddress;
|
||||||
private String serverport;
|
private String serverport;
|
||||||
private String upnpresponseport;
|
private String upnpresponseport;
|
||||||
private String upnpdevicedb;
|
private String upnpdevicedb;
|
||||||
private String veraaddress;
|
private IpList veraaddress;
|
||||||
private String harmonyaddress;
|
private IpList harmonyaddress;
|
||||||
private String harmonyuser;
|
private String harmonyuser;
|
||||||
private String harmonypwd;
|
private String harmonypwd;
|
||||||
|
private Integer upnpresponsedevices;
|
||||||
private boolean upnpstrict;
|
private boolean upnpstrict;
|
||||||
private boolean traceupnp;
|
private boolean traceupnp;
|
||||||
private boolean devmode;
|
private boolean devmode;
|
||||||
|
private String nestuser;
|
||||||
|
private String nestpwd;
|
||||||
|
private boolean nestconfigured;
|
||||||
|
|
||||||
public String getUpnpConfigAddress() {
|
public String getUpnpConfigAddress() {
|
||||||
return upnpconfigaddress;
|
return upnpconfigaddress;
|
||||||
@@ -37,16 +43,16 @@ public class BridgeSettings {
|
|||||||
public void setUpnpDeviceDb(String upnpDeviceDb) {
|
public void setUpnpDeviceDb(String upnpDeviceDb) {
|
||||||
this.upnpdevicedb = upnpDeviceDb;
|
this.upnpdevicedb = upnpDeviceDb;
|
||||||
}
|
}
|
||||||
public String getVeraAddress() {
|
public IpList getVeraAddress() {
|
||||||
return veraaddress;
|
return veraaddress;
|
||||||
}
|
}
|
||||||
public void setVeraAddress(String veraAddress) {
|
public void setVeraAddress(IpList veraAddress) {
|
||||||
this.veraaddress = veraAddress;
|
this.veraaddress = veraAddress;
|
||||||
}
|
}
|
||||||
public String getHarmonyAddress() {
|
public IpList getHarmonyAddress() {
|
||||||
return harmonyaddress;
|
return harmonyaddress;
|
||||||
}
|
}
|
||||||
public void setHarmonyAddress(String harmonyaddress) {
|
public void setHarmonyAddress(IpList harmonyaddress) {
|
||||||
this.harmonyaddress = harmonyaddress;
|
this.harmonyaddress = harmonyaddress;
|
||||||
}
|
}
|
||||||
public String getHarmonyUser() {
|
public String getHarmonyUser() {
|
||||||
@@ -61,6 +67,12 @@ public class BridgeSettings {
|
|||||||
public void setHarmonyPwd(String harmonypwd) {
|
public void setHarmonyPwd(String harmonypwd) {
|
||||||
this.harmonypwd = harmonypwd;
|
this.harmonypwd = harmonypwd;
|
||||||
}
|
}
|
||||||
|
public Integer getUpnpResponseDevices() {
|
||||||
|
return upnpresponsedevices;
|
||||||
|
}
|
||||||
|
public void setUpnpResponseDevices(Integer upnpresponsedevices) {
|
||||||
|
this.upnpresponsedevices = upnpresponsedevices;
|
||||||
|
}
|
||||||
public boolean isUpnpStrict() {
|
public boolean isUpnpStrict() {
|
||||||
return upnpstrict;
|
return upnpstrict;
|
||||||
}
|
}
|
||||||
@@ -79,13 +91,33 @@ public class BridgeSettings {
|
|||||||
public void setDevMode(boolean devmode) {
|
public void setDevMode(boolean devmode) {
|
||||||
this.devmode = devmode;
|
this.devmode = devmode;
|
||||||
}
|
}
|
||||||
|
public String getNestuser() {
|
||||||
|
return nestuser;
|
||||||
|
}
|
||||||
|
public void setNestuser(String nestuser) {
|
||||||
|
this.nestuser = nestuser;
|
||||||
|
}
|
||||||
|
public String getNestpwd() {
|
||||||
|
return nestpwd;
|
||||||
|
}
|
||||||
|
public void setNestpwd(String nestpwd) {
|
||||||
|
this.nestpwd = nestpwd;
|
||||||
|
}
|
||||||
|
public boolean isNestConfigured() {
|
||||||
|
return nestconfigured;
|
||||||
|
}
|
||||||
|
public void setNestConfigured(boolean isNestConfigured) {
|
||||||
|
this.nestconfigured = isNestConfigured;
|
||||||
|
}
|
||||||
public Boolean isValidVera() {
|
public Boolean isValidVera() {
|
||||||
if(this.veraaddress.contains(Configuration.DEFAULT_VERA_ADDRESS))
|
List<NamedIP> devicesList = this.veraaddress.getDevices();
|
||||||
|
if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
public Boolean isValidHarmony() {
|
public Boolean isValidHarmony() {
|
||||||
if(this.harmonyaddress.contains(Configuration.DEFAULT_HARMONY_ADDRESS))
|
List<NamedIP> devicesList = this.harmonyaddress.getDevices();
|
||||||
|
if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS))
|
||||||
return false;
|
return false;
|
||||||
if(this.harmonypwd == null || this.harmonypwd == "")
|
if(this.harmonypwd == null || this.harmonypwd == "")
|
||||||
return false;
|
return false;
|
||||||
@@ -93,4 +125,11 @@ public class BridgeSettings {
|
|||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
public Boolean isValidNest() {
|
||||||
|
if(this.nestpwd == null || this.nestpwd == "")
|
||||||
|
return false;
|
||||||
|
if(this.nestuser == null || this.nestuser == "")
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,12 @@ package com.bwssystems.HABridge;
|
|||||||
public class Configuration {
|
public class Configuration {
|
||||||
public final static String DEVICE_DB_DIRECTORY = "data/device.db";
|
public final static String DEVICE_DB_DIRECTORY = "data/device.db";
|
||||||
public final static String UPNP_RESPONSE_PORT = "50000";
|
public final static String UPNP_RESPONSE_PORT = "50000";
|
||||||
public final static String DEFAULT_VERA_ADDRESS = "1.1.1.1";
|
public final static String UPNP_RESPONSE_DEVICES = "30";
|
||||||
public final static String DEFAULT_HARMONY_ADDRESS = "1.1.1.1";
|
public final static String DEFAULT_ADDRESS = "1.1.1.1";
|
||||||
public final static String DEFAULT_HARMONY_USER = "";
|
public final static String LOOP_BACK_ADDRESS = "127.0.0.1";
|
||||||
public final static String DEFAULT_HARMONY_PWD = "";
|
public final static String LOOP_BACK_INTERFACE = "lo";
|
||||||
|
public final static String DEFAULT_HARMONY_ADDRESS_LIST = "{devices:[{name:default,ip:1.1.1.1}]}";
|
||||||
|
public final static String DEFAULT_USER = "";
|
||||||
|
public final static String DEFAULT_PWD = "";
|
||||||
public final static String DFAULT_WEB_PORT = "8080";
|
public final static String DFAULT_WEB_PORT = "8080";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,11 @@ package com.bwssystems.HABridge;
|
|||||||
import static spark.Spark.*;
|
import static spark.Spark.*;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.NetworkInterface;
|
||||||
|
import java.net.SocketException;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
|
||||||
|
import org.apache.http.conn.util.InetAddressUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@@ -12,7 +15,9 @@ import com.bwssystems.HABridge.devicemanagmeent.*;
|
|||||||
import com.bwssystems.HABridge.hue.HueMulator;
|
import com.bwssystems.HABridge.hue.HueMulator;
|
||||||
import com.bwssystems.HABridge.upnp.UpnpListener;
|
import com.bwssystems.HABridge.upnp.UpnpListener;
|
||||||
import com.bwssystems.HABridge.upnp.UpnpSettingsResource;
|
import com.bwssystems.HABridge.upnp.UpnpSettingsResource;
|
||||||
import com.bwssystems.harmony.HarmonyServer;
|
import com.bwssystems.NestBridge.NestHome;
|
||||||
|
import com.bwssystems.harmony.HarmonyHome;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
public class HABridge {
|
public class HABridge {
|
||||||
|
|
||||||
@@ -34,40 +39,91 @@ public class HABridge {
|
|||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
Logger log = LoggerFactory.getLogger(HABridge.class);
|
Logger log = LoggerFactory.getLogger(HABridge.class);
|
||||||
DeviceResource theResources;
|
DeviceResource theResources;
|
||||||
HarmonyServer myHarmonyServer;
|
HarmonyHome harmonyHome;
|
||||||
|
NestHome nestHome;
|
||||||
HueMulator theHueMulator;
|
HueMulator theHueMulator;
|
||||||
UpnpSettingsResource theSettingResponder;
|
UpnpSettingsResource theSettingResponder;
|
||||||
UpnpListener theUpnpListener;
|
UpnpListener theUpnpListener;
|
||||||
InetAddress address;
|
InetAddress address = null;
|
||||||
String addressString;
|
String addressString = null;
|
||||||
BridgeSettings bridgeSettings;
|
BridgeSettings bridgeSettings;
|
||||||
Version theVersion;
|
Version theVersion;
|
||||||
|
|
||||||
theVersion = new Version();
|
theVersion = new Version();
|
||||||
|
|
||||||
log.info("HA Bridge (v" + theVersion.getVersion() + ") starting setup....");
|
log.info("HA Bridge (v" + theVersion.getVersion() + ") starting setup....");
|
||||||
//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;
|
|
||||||
}
|
|
||||||
|
|
||||||
bridgeSettings = new BridgeSettings();
|
bridgeSettings = new BridgeSettings();
|
||||||
bridgeSettings.setServerPort(System.getProperty("server.port", Configuration.DFAULT_WEB_PORT));
|
bridgeSettings.setServerPort(System.getProperty("server.port", Configuration.DFAULT_WEB_PORT));
|
||||||
bridgeSettings.setUpnpConfigAddress(System.getProperty("upnp.config.address", addressString));
|
bridgeSettings.setUpnpConfigAddress(System.getProperty("upnp.config.address", Configuration.DEFAULT_ADDRESS));
|
||||||
|
if(bridgeSettings.getUpnpConfigAddress().equalsIgnoreCase(Configuration.DEFAULT_ADDRESS)) {
|
||||||
|
try {
|
||||||
|
log.info("Getting an IP address for this host....");
|
||||||
|
Enumeration<NetworkInterface> ifs = NetworkInterface.getNetworkInterfaces();
|
||||||
|
|
||||||
|
while (ifs.hasMoreElements() && addressString == null) {
|
||||||
|
NetworkInterface xface = ifs.nextElement();
|
||||||
|
Enumeration<InetAddress> addrs = xface.getInetAddresses();
|
||||||
|
String name = xface.getName();
|
||||||
|
int IPsPerNic = 0;
|
||||||
|
|
||||||
|
while (addrs.hasMoreElements() && IPsPerNic == 0) {
|
||||||
|
address = addrs.nextElement();
|
||||||
|
if (InetAddressUtils.isIPv4Address(address.getHostAddress())) {
|
||||||
|
log.debug(name + " ... has IPV4 addr " + address);
|
||||||
|
if(!name.equalsIgnoreCase(Configuration.LOOP_BACK_INTERFACE)|| !address.getHostAddress().equalsIgnoreCase(Configuration.LOOP_BACK_ADDRESS)) {
|
||||||
|
IPsPerNic++;
|
||||||
|
addressString = address.getHostAddress();
|
||||||
|
log.info("Adding " + addressString + " from interface " + name + " as our default upnp config address.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SocketException e) {
|
||||||
|
log.error("Cannot get ip address of this host, Exiting with message: " + e.getMessage(), e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bridgeSettings.setUpnpConfigAddress(addressString);
|
||||||
|
}
|
||||||
|
|
||||||
bridgeSettings.setUpnpDeviceDb(System.getProperty("upnp.device.db", Configuration.DEVICE_DB_DIRECTORY));
|
bridgeSettings.setUpnpDeviceDb(System.getProperty("upnp.device.db", Configuration.DEVICE_DB_DIRECTORY));
|
||||||
bridgeSettings.setUpnpResponsePort(System.getProperty("upnp.response.port", Configuration.UPNP_RESPONSE_PORT));
|
bridgeSettings.setUpnpResponsePort(System.getProperty("upnp.response.port", Configuration.UPNP_RESPONSE_PORT));
|
||||||
bridgeSettings.setVeraAddress(System.getProperty("vera.address", Configuration.DEFAULT_VERA_ADDRESS));
|
IpList theVeraList;
|
||||||
bridgeSettings.setHarmonyAddress(System.getProperty("harmony.address", Configuration.DEFAULT_HARMONY_ADDRESS));
|
|
||||||
bridgeSettings.setHarmonyUser(System.getProperty("harmony.user", Configuration.DEFAULT_HARMONY_USER));
|
try {
|
||||||
bridgeSettings.setHarmonyPwd(System.getProperty("harmony.pwd", Configuration.DEFAULT_HARMONY_PWD));
|
theVeraList = new Gson().fromJson(System.getProperty("vera.address", Configuration.DEFAULT_HARMONY_ADDRESS_LIST), IpList.class);
|
||||||
|
} catch (Exception e) {
|
||||||
|
try {
|
||||||
|
theVeraList = new Gson().fromJson("{devices:[{name:default,ip:" + System.getProperty("vera.address", Configuration.DEFAULT_ADDRESS) + "}]}", IpList.class);
|
||||||
|
} catch (Exception et) {
|
||||||
|
log.error("Cannot parse vera.address, Exiting with message: " + e.getMessage(), e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bridgeSettings.setVeraAddress(theVeraList);
|
||||||
|
IpList theHarmonyList;
|
||||||
|
|
||||||
|
try {
|
||||||
|
theHarmonyList = new Gson().fromJson(System.getProperty("harmony.address", Configuration.DEFAULT_HARMONY_ADDRESS_LIST), IpList.class);
|
||||||
|
} catch (Exception e) {
|
||||||
|
try {
|
||||||
|
theHarmonyList = new Gson().fromJson("{devices:[{name:default,ip:" + System.getProperty("harmony.address", Configuration.DEFAULT_ADDRESS) + "}]}", IpList.class);
|
||||||
|
} catch (Exception et) {
|
||||||
|
log.error("Cannot parse harmony.address, Exiting with message: " + e.getMessage(), e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bridgeSettings.setHarmonyAddress(theHarmonyList);
|
||||||
|
bridgeSettings.setHarmonyUser(System.getProperty("harmony.user", Configuration.DEFAULT_USER));
|
||||||
|
bridgeSettings.setHarmonyPwd(System.getProperty("harmony.pwd", Configuration.DEFAULT_PWD));
|
||||||
bridgeSettings.setUpnpStrict(Boolean.parseBoolean(System.getProperty("upnp.strict", "true")));
|
bridgeSettings.setUpnpStrict(Boolean.parseBoolean(System.getProperty("upnp.strict", "true")));
|
||||||
bridgeSettings.setTraceupnp(Boolean.parseBoolean(System.getProperty("trace.upnp", "false")));
|
bridgeSettings.setTraceupnp(Boolean.parseBoolean(System.getProperty("trace.upnp", "false")));
|
||||||
bridgeSettings.setDevMode(Boolean.parseBoolean(System.getProperty("dev.mode", "false")));
|
bridgeSettings.setDevMode(Boolean.parseBoolean(System.getProperty("dev.mode", "false")));
|
||||||
|
bridgeSettings.setUpnpResponseDevices(Integer.parseInt(System.getProperty("upnp.response.devices", Configuration.UPNP_RESPONSE_DEVICES)));
|
||||||
|
bridgeSettings.setNestuser(System.getProperty("nest.user", Configuration.DEFAULT_USER));
|
||||||
|
bridgeSettings.setNestpwd(System.getProperty("nest.pwd", Configuration.DEFAULT_PWD));
|
||||||
|
|
||||||
// sparkjava config directive to set ip address for the web server to listen on
|
// sparkjava config directive to set ip address for the web server to listen on
|
||||||
// ipAddress("0.0.0.0"); // not used
|
// ipAddress("0.0.0.0"); // not used
|
||||||
// sparkjava config directive to set port for the web server to listen on
|
// sparkjava config directive to set port for the web server to listen on
|
||||||
@@ -75,16 +131,13 @@ public class HABridge {
|
|||||||
// sparkjava config directive to set html static file location for Jetty
|
// sparkjava config directive to set html static file location for Jetty
|
||||||
staticFileLocation("/public");
|
staticFileLocation("/public");
|
||||||
//setup the harmony connection if available
|
//setup the harmony connection if available
|
||||||
try {
|
harmonyHome = new HarmonyHome(bridgeSettings);
|
||||||
myHarmonyServer = HarmonyServer.setup(bridgeSettings);
|
//setup the nest connection if available
|
||||||
} catch (Exception e) {
|
nestHome = new NestHome(bridgeSettings);
|
||||||
log.error("Cannot get harmony client setup, Exiting with message: " + e.getMessage(), e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// setup the class to handle the resource setup rest api
|
// setup the class to handle the resource setup rest api
|
||||||
theResources = new DeviceResource(bridgeSettings, theVersion, myHarmonyServer.getMyHarmony());
|
theResources = new DeviceResource(bridgeSettings, theVersion, harmonyHome, nestHome);
|
||||||
// setup the class to handle the hue emulator rest api
|
// setup the class to handle the hue emulator rest api
|
||||||
theHueMulator = new HueMulator(theResources.getDeviceRepository(), myHarmonyServer.getMyHarmony());
|
theHueMulator = new HueMulator(bridgeSettings, theResources.getDeviceRepository(), harmonyHome, nestHome);
|
||||||
theHueMulator.setupServer();
|
theHueMulator.setupServer();
|
||||||
// setup the class to handle the upnp response rest api
|
// setup the class to handle the upnp response rest api
|
||||||
theSettingResponder = new UpnpSettingsResource(bridgeSettings);
|
theSettingResponder = new UpnpSettingsResource(bridgeSettings);
|
||||||
|
|||||||
16
src/main/java/com/bwssystems/HABridge/IpList.java
Normal file
16
src/main/java/com/bwssystems/HABridge/IpList.java
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package com.bwssystems.HABridge;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class IpList {
|
||||||
|
private List<NamedIP> devices;
|
||||||
|
|
||||||
|
public List<NamedIP> getDevices() {
|
||||||
|
return devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDevices(List<NamedIP> devices) {
|
||||||
|
this.devices = devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
25
src/main/java/com/bwssystems/HABridge/NamedIP.java
Normal file
25
src/main/java/com/bwssystems/HABridge/NamedIP.java
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package com.bwssystems.HABridge;
|
||||||
|
|
||||||
|
public class NamedIP {
|
||||||
|
private String name;
|
||||||
|
private String ip;
|
||||||
|
private String port;
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
public String getIp() {
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
public void setIp(String ip) {
|
||||||
|
this.ip = ip;
|
||||||
|
}
|
||||||
|
public String getPort() {
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
public void setPort(String port) {
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,11 +12,17 @@ public class HueApiResponse {
|
|||||||
private Map<String, DeviceResponse> lights;
|
private Map<String, DeviceResponse> lights;
|
||||||
private Map<String, String> scenes;
|
private Map<String, String> scenes;
|
||||||
private Map<String, String> groups;
|
private Map<String, String> groups;
|
||||||
|
private Map<String, String> schedules;
|
||||||
|
private Map<String, String> sensors;
|
||||||
|
private Map<String, String> rules;
|
||||||
private HueConfig config;
|
private HueConfig config;
|
||||||
|
|
||||||
public HueApiResponse(String name, String ipaddress, String devicetype, String userid) {
|
public HueApiResponse(String name, String ipaddress, String devicetype, String userid) {
|
||||||
super();
|
super();
|
||||||
this.setConfig(HueConfig.createConfig(name, ipaddress, devicetype, userid));
|
this.setConfig(HueConfig.createConfig(name, ipaddress, devicetype, userid));
|
||||||
|
this.setRules(new HashMap<>());
|
||||||
|
this.setSensors(new HashMap<>());
|
||||||
|
this.setSchedules(new HashMap<>());
|
||||||
this.setGroups(new HashMap<>());
|
this.setGroups(new HashMap<>());
|
||||||
this.setScenes(new HashMap<>());
|
this.setScenes(new HashMap<>());
|
||||||
}
|
}
|
||||||
@@ -45,6 +51,30 @@ public class HueApiResponse {
|
|||||||
this.groups = groups;
|
this.groups = groups;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getSchedules() {
|
||||||
|
return schedules;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSchedules(Map<String, String> schedules) {
|
||||||
|
this.schedules = schedules;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getSensors() {
|
||||||
|
return sensors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSensors(Map<String, String> sensors) {
|
||||||
|
this.sensors = sensors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getRules() {
|
||||||
|
return rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRules(Map<String, String> rules) {
|
||||||
|
this.rules = rules;
|
||||||
|
}
|
||||||
|
|
||||||
public HueConfig getConfig() {
|
public HueConfig getConfig() {
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,6 +84,10 @@ public class HueConfig
|
|||||||
|
|
||||||
sb.append("00:00:88:00:bb:ee");
|
sb.append("00:00:88:00:bb:ee");
|
||||||
|
|
||||||
|
} catch (Exception e){
|
||||||
|
|
||||||
|
sb.append("00:00:88:00:bb:ee");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.bwssystems.HABridge.dao;
|
||||||
|
|
||||||
|
public class BackupFilename {
|
||||||
|
private String filename;
|
||||||
|
|
||||||
|
public String getFilename() {
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFilename(String filename) {
|
||||||
|
this.filename = filename;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ public class DeviceDescriptor{
|
|||||||
private String mapId;
|
private String mapId;
|
||||||
private String mapType;
|
private String mapType;
|
||||||
private String deviceType;
|
private String deviceType;
|
||||||
|
private String targetDevice;
|
||||||
private String offUrl;
|
private String offUrl;
|
||||||
private String onUrl;
|
private String onUrl;
|
||||||
private String httpVerb;
|
private String httpVerb;
|
||||||
@@ -47,7 +48,15 @@ public class DeviceDescriptor{
|
|||||||
this.deviceType = deviceType;
|
this.deviceType = deviceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getOffUrl() {
|
public String getTargetDevice() {
|
||||||
|
return targetDevice;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTargetDevice(String targetDevice) {
|
||||||
|
this.targetDevice = targetDevice;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOffUrl() {
|
||||||
return offUrl;
|
return offUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,12 +3,17 @@ package com.bwssystems.HABridge.dao;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
|
import java.nio.file.DirectoryStream;
|
||||||
import java.nio.file.FileSystems;
|
import java.nio.file.FileSystems;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.StandardCopyOption;
|
||||||
import java.nio.file.StandardOpenOption;
|
import java.nio.file.StandardOpenOption;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
@@ -33,8 +38,16 @@ public class DeviceRepository {
|
|||||||
|
|
||||||
public DeviceRepository(String deviceDb) {
|
public DeviceRepository(String deviceDb) {
|
||||||
super();
|
super();
|
||||||
repositoryPath = Paths.get(deviceDb);
|
_loadRepository(deviceDb);
|
||||||
String jsonContent = repositoryReader(repositoryPath);
|
}
|
||||||
|
|
||||||
|
private void _loadRepository(String aFilePath){
|
||||||
|
repositoryPath = Paths.get(aFilePath);
|
||||||
|
_loadRepository(repositoryPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void _loadRepository(Path aPath){
|
||||||
|
String jsonContent = repositoryReader(aPath);
|
||||||
devices = new HashMap<String, DeviceDescriptor>();
|
devices = new HashMap<String, DeviceDescriptor>();
|
||||||
|
|
||||||
if(jsonContent != null)
|
if(jsonContent != null)
|
||||||
@@ -47,7 +60,8 @@ public class DeviceRepository {
|
|||||||
put(theDevice.getId(), theDevice);
|
put(theDevice.getId(), theDevice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
}
|
||||||
|
|
||||||
public List<DeviceDescriptor> findAll() {
|
public List<DeviceDescriptor> findAll() {
|
||||||
List<DeviceDescriptor> list = new ArrayList<DeviceDescriptor>(devices.values());
|
List<DeviceDescriptor> list = new ArrayList<DeviceDescriptor>(devices.values());
|
||||||
@@ -79,6 +93,66 @@ public class DeviceRepository {
|
|||||||
log.debug("Save device: " + aDescriptor.getName());
|
log.debug("Save device: " + aDescriptor.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String backup(String aFilename) {
|
||||||
|
if(aFilename == null || aFilename.equalsIgnoreCase("")) {
|
||||||
|
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
|
||||||
|
aFilename = "devicedb-" + dateFormat.format(Calendar.getInstance().getTime()) + ".bk";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
aFilename = aFilename + ".bk";
|
||||||
|
try {
|
||||||
|
Files.copy(repositoryPath, FileSystems.getDefault().getPath(repositoryPath.getParent().toString(), aFilename), StandardCopyOption.COPY_ATTRIBUTES);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Could not backup to file: " + aFilename + " message: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
log.debug("Backup repository: " + aFilename);
|
||||||
|
return aFilename;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String deleteBackup(String aFilename) {
|
||||||
|
log.debug("Delete backup repository: " + aFilename);
|
||||||
|
try {
|
||||||
|
Files.delete(FileSystems.getDefault().getPath(repositoryPath.getParent().toString(), aFilename));
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Could not delete file: " + aFilename + " message: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
return aFilename;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String restoreBackup(String aFilename) {
|
||||||
|
log.debug("Restore backup repository: " + aFilename);
|
||||||
|
try {
|
||||||
|
Path target = null;
|
||||||
|
if(Files.exists(repositoryPath)) {
|
||||||
|
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
|
||||||
|
target = FileSystems.getDefault().getPath(repositoryPath.getParent().toString(), "devicedb-" + dateFormat.format(Calendar.getInstance().getTime()) + ".bk");
|
||||||
|
Files.move(repositoryPath, target);
|
||||||
|
}
|
||||||
|
Files.copy(FileSystems.getDefault().getPath(repositoryPath.getParent().toString(), aFilename), repositoryPath, StandardCopyOption.COPY_ATTRIBUTES);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Error restoring the file: " + aFilename + " message: " + e.getMessage(), e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
_loadRepository(repositoryPath);
|
||||||
|
return aFilename;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getBackups() {
|
||||||
|
List<String> theFilenames = new ArrayList<String>();
|
||||||
|
Path dir = repositoryPath.getParent();
|
||||||
|
try (DirectoryStream<Path> stream =
|
||||||
|
Files.newDirectoryStream(dir, "*.{bk}")) {
|
||||||
|
for (Path entry: stream) {
|
||||||
|
theFilenames.add(entry.getFileName().toString());
|
||||||
|
}
|
||||||
|
} 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 direcotyr listing for backups - " + x.getMessage());
|
||||||
|
}
|
||||||
|
return theFilenames;
|
||||||
|
}
|
||||||
|
|
||||||
public String delete(DeviceDescriptor aDescriptor) {
|
public String delete(DeviceDescriptor aDescriptor) {
|
||||||
if (aDescriptor != null) {
|
if (aDescriptor != null) {
|
||||||
devices.remove(aDescriptor.getId());
|
devices.remove(aDescriptor.getId());
|
||||||
@@ -187,6 +261,9 @@ public class DeviceRepository {
|
|||||||
} else if (name.equals("deviceType")) {
|
} else if (name.equals("deviceType")) {
|
||||||
deviceEntry.setDeviceType(reader.nextString());
|
deviceEntry.setDeviceType(reader.nextString());
|
||||||
log.debug("Read a Device - device json type:" + deviceEntry.getDeviceType());
|
log.debug("Read a Device - device json type:" + deviceEntry.getDeviceType());
|
||||||
|
} else if (name.equals("targetDevice")) {
|
||||||
|
deviceEntry.setTargetDevice(reader.nextString());
|
||||||
|
log.debug("Read a Device - device json type:" + deviceEntry.getTargetDevice());
|
||||||
} else if (name.equals("offUrl")) {
|
} else if (name.equals("offUrl")) {
|
||||||
deviceEntry.setOffUrl(reader.nextString());
|
deviceEntry.setOffUrl(reader.nextString());
|
||||||
log.debug("Read a Device - device json off URL:" + deviceEntry.getOffUrl());
|
log.debug("Read a Device - device json off URL:" + deviceEntry.getOffUrl());
|
||||||
|
|||||||
@@ -18,10 +18,13 @@ import org.slf4j.LoggerFactory;
|
|||||||
import com.bwssystems.HABridge.BridgeSettings;
|
import com.bwssystems.HABridge.BridgeSettings;
|
||||||
import com.bwssystems.HABridge.JsonTransformer;
|
import com.bwssystems.HABridge.JsonTransformer;
|
||||||
import com.bwssystems.HABridge.Version;
|
import com.bwssystems.HABridge.Version;
|
||||||
|
import com.bwssystems.HABridge.dao.BackupFilename;
|
||||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||||
import com.bwssystems.HABridge.dao.DeviceRepository;
|
import com.bwssystems.HABridge.dao.DeviceRepository;
|
||||||
import com.bwssystems.harmony.HarmonyHandler;
|
import com.bwssystems.NestBridge.NestHome;
|
||||||
|
import com.bwssystems.harmony.HarmonyHome;
|
||||||
import com.bwssystems.luupRequests.Sdata;
|
import com.bwssystems.luupRequests.Sdata;
|
||||||
|
import com.bwssystems.vera.VeraHome;
|
||||||
import com.bwssystems.vera.VeraInfo;
|
import com.bwssystems.vera.VeraInfo;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
@@ -33,16 +36,30 @@ public class DeviceResource {
|
|||||||
private static final Logger log = LoggerFactory.getLogger(DeviceResource.class);
|
private static final Logger log = LoggerFactory.getLogger(DeviceResource.class);
|
||||||
|
|
||||||
private DeviceRepository deviceRepository;
|
private DeviceRepository deviceRepository;
|
||||||
private VeraInfo veraInfo;
|
private VeraHome veraHome;
|
||||||
private Version version;
|
private Version version;
|
||||||
private HarmonyHandler myHarmonyHandler;
|
private HarmonyHome myHarmonyHome;
|
||||||
|
private NestHome nestHome;
|
||||||
private static final Set<String> supportedVerbs = new HashSet<>(Arrays.asList("get", "put", "post"));
|
private static final Set<String> supportedVerbs = new HashSet<>(Arrays.asList("get", "put", "post"));
|
||||||
|
|
||||||
public DeviceResource(BridgeSettings theSettings, Version theVersion, HarmonyHandler myHarmony) {
|
public DeviceResource(BridgeSettings theSettings, Version theVersion, HarmonyHome theHarmonyHome, NestHome aNestHome) {
|
||||||
super();
|
|
||||||
this.deviceRepository = new DeviceRepository(theSettings.getUpnpDeviceDb());
|
this.deviceRepository = new DeviceRepository(theSettings.getUpnpDeviceDb());
|
||||||
this.veraInfo = new VeraInfo(theSettings.getVeraAddress(), theSettings.isValidVera());
|
|
||||||
this.myHarmonyHandler = myHarmony;
|
if(theSettings.isValidVera())
|
||||||
|
this.veraHome = new VeraHome(theSettings);
|
||||||
|
else
|
||||||
|
this.veraHome = null;
|
||||||
|
|
||||||
|
if(theSettings.isValidHarmony())
|
||||||
|
this.myHarmonyHome = theHarmonyHome;
|
||||||
|
else
|
||||||
|
this.myHarmonyHome = null;
|
||||||
|
|
||||||
|
if(theSettings.isValidNest())
|
||||||
|
this.nestHome = aNestHome;
|
||||||
|
else
|
||||||
|
this.nestHome = null;
|
||||||
|
|
||||||
this.version = theVersion;
|
this.version = theVersion;
|
||||||
setupEndpoints();
|
setupEndpoints();
|
||||||
}
|
}
|
||||||
@@ -109,6 +126,7 @@ public class DeviceResource {
|
|||||||
deviceEntry.setDeviceType(device.getDeviceType());
|
deviceEntry.setDeviceType(device.getDeviceType());
|
||||||
deviceEntry.setMapId(device.getMapId());
|
deviceEntry.setMapId(device.getMapId());
|
||||||
deviceEntry.setMapType(device.getMapType());
|
deviceEntry.setMapType(device.getMapType());
|
||||||
|
deviceEntry.setTargetDevice(device.getTargetDevice());
|
||||||
deviceEntry.setOnUrl(device.getOnUrl());
|
deviceEntry.setOnUrl(device.getOnUrl());
|
||||||
deviceEntry.setOffUrl(device.getOffUrl());
|
deviceEntry.setOffUrl(device.getOffUrl());
|
||||||
deviceEntry.setHttpVerb(device.getHttpVerb());
|
deviceEntry.setHttpVerb(device.getHttpVerb());
|
||||||
@@ -164,56 +182,124 @@ public class DeviceResource {
|
|||||||
|
|
||||||
get (API_CONTEXT + "/vera/devices", "application/json", (request, response) -> {
|
get (API_CONTEXT + "/vera/devices", "application/json", (request, response) -> {
|
||||||
log.debug("Get vera devices");
|
log.debug("Get vera devices");
|
||||||
Sdata sData = veraInfo.getSdata();
|
if(veraHome == null){
|
||||||
if(sData == null){
|
|
||||||
response.status(HttpStatus.SC_NOT_FOUND);
|
response.status(HttpStatus.SC_NOT_FOUND);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
response.status(HttpStatus.SC_OK);
|
response.status(HttpStatus.SC_OK);
|
||||||
return sData.getDevices();
|
return veraHome.getDevices();
|
||||||
}, new JsonTransformer());
|
}, new JsonTransformer());
|
||||||
|
|
||||||
get (API_CONTEXT + "/vera/scenes", "application/json", (request, response) -> {
|
get (API_CONTEXT + "/vera/scenes", "application/json", (request, response) -> {
|
||||||
log.debug("Get vera scenes");
|
log.debug("Get vera scenes");
|
||||||
Sdata sData = veraInfo.getSdata();
|
if(veraHome == null){
|
||||||
if(sData == null){
|
|
||||||
response.status(HttpStatus.SC_NOT_FOUND);
|
response.status(HttpStatus.SC_NOT_FOUND);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
response.status(HttpStatus.SC_OK);
|
response.status(HttpStatus.SC_OK);
|
||||||
return sData.getScenes();
|
return veraHome.getScenes();
|
||||||
}, new JsonTransformer());
|
}, new JsonTransformer());
|
||||||
|
|
||||||
get (API_CONTEXT + "/harmony/activities", "application/json", (request, response) -> {
|
get (API_CONTEXT + "/harmony/activities", "application/json", (request, response) -> {
|
||||||
log.debug("Get harmony activities");
|
log.debug("Get harmony activities");
|
||||||
if(myHarmonyHandler == null) {
|
if(myHarmonyHome == null) {
|
||||||
response.status(HttpStatus.SC_NOT_FOUND);
|
response.status(HttpStatus.SC_NOT_FOUND);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
response.status(HttpStatus.SC_OK);
|
response.status(HttpStatus.SC_OK);
|
||||||
return myHarmonyHandler.getActivities();
|
return myHarmonyHome.getActivities();
|
||||||
}, new JsonTransformer());
|
}, new JsonTransformer());
|
||||||
|
|
||||||
get (API_CONTEXT + "/harmony/show", "application/json", (request, response) -> {
|
get (API_CONTEXT + "/harmony/show", "application/json", (request, response) -> {
|
||||||
log.debug("Get harmony current activity");
|
log.debug("Get harmony current activity");
|
||||||
if(myHarmonyHandler == null) {
|
if(myHarmonyHome == null) {
|
||||||
response.status(HttpStatus.SC_NOT_FOUND);
|
response.status(HttpStatus.SC_NOT_FOUND);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
response.status(HttpStatus.SC_OK);
|
response.status(HttpStatus.SC_OK);
|
||||||
return myHarmonyHandler.getCurrentActivity();
|
return myHarmonyHome.getCurrentActivities();
|
||||||
}, new JsonTransformer());
|
}, new JsonTransformer());
|
||||||
|
|
||||||
get (API_CONTEXT + "/harmony/devices", "application/json", (request, response) -> {
|
get (API_CONTEXT + "/harmony/devices", "application/json", (request, response) -> {
|
||||||
log.debug("Get harmony devices");
|
log.debug("Get harmony devices");
|
||||||
if(myHarmonyHandler == null) {
|
if(myHarmonyHome == null) {
|
||||||
response.status(HttpStatus.SC_NOT_FOUND);
|
response.status(HttpStatus.SC_NOT_FOUND);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
response.status(HttpStatus.SC_OK);
|
response.status(HttpStatus.SC_OK);
|
||||||
return myHarmonyHandler.getDevices();
|
return myHarmonyHome.getDevices();
|
||||||
}, new JsonTransformer());
|
}, new JsonTransformer());
|
||||||
|
|
||||||
|
get (API_CONTEXT + "/nest/items", "application/json", (request, response) -> {
|
||||||
|
log.debug("Get nest items");
|
||||||
|
if(nestHome == null) {
|
||||||
|
response.status(HttpStatus.SC_NOT_FOUND);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
response.status(HttpStatus.SC_OK);
|
||||||
|
return nestHome.getItems();
|
||||||
|
}, new JsonTransformer());
|
||||||
|
|
||||||
|
get (API_CONTEXT + "/backup/available", "application/json", (request, response) -> {
|
||||||
|
log.debug("Get backup filenames");
|
||||||
|
response.status(HttpStatus.SC_OK);
|
||||||
|
return deviceRepository.getBackups();
|
||||||
|
}, new JsonTransformer());
|
||||||
|
|
||||||
|
// http://ip_address:port/api/devices/backup/create CORS request
|
||||||
|
options(API_CONTEXT + "/backup/create", "application/json", (request, response) -> {
|
||||||
|
response.status(HttpStatus.SC_OK);
|
||||||
|
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
||||||
|
response.header("Access-Control-Allow-Methods", "PUT");
|
||||||
|
response.header("Access-Control-Allow-Headers", request.headers("Access-Control-Request-Headers"));
|
||||||
|
response.header("Content-Type", "text/html; charset=utf-8");
|
||||||
|
return "";
|
||||||
|
});
|
||||||
|
put (API_CONTEXT + "/backup/create", "application/json", (request, response) -> {
|
||||||
|
log.debug("Create backup: " + request.body());
|
||||||
|
BackupFilename aFilename = new Gson().fromJson(request.body(), BackupFilename.class);
|
||||||
|
BackupFilename returnFilename = new BackupFilename();
|
||||||
|
returnFilename.setFilename(deviceRepository.backup(aFilename.getFilename()));
|
||||||
|
return returnFilename;
|
||||||
|
}, new JsonTransformer());
|
||||||
|
|
||||||
|
// http://ip_address:port/api/devices/backup/delete CORS request
|
||||||
|
options(API_CONTEXT + "/backup/delete", "application/json", (request, response) -> {
|
||||||
|
response.status(HttpStatus.SC_OK);
|
||||||
|
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
||||||
|
response.header("Access-Control-Allow-Methods", "POST");
|
||||||
|
response.header("Access-Control-Allow-Headers", request.headers("Access-Control-Request-Headers"));
|
||||||
|
response.header("Content-Type", "text/html; charset=utf-8");
|
||||||
|
return "";
|
||||||
|
});
|
||||||
|
post (API_CONTEXT + "/backup/delete", "application/json", (request, response) -> {
|
||||||
|
log.debug("Delete backup: " + request.body());
|
||||||
|
BackupFilename aFilename = new Gson().fromJson(request.body(), BackupFilename.class);
|
||||||
|
if(aFilename != null)
|
||||||
|
deviceRepository.deleteBackup(aFilename.getFilename());
|
||||||
|
else
|
||||||
|
log.warn("No filename given for delete backup.");
|
||||||
|
return null;
|
||||||
|
}, new JsonTransformer());
|
||||||
|
|
||||||
|
// http://ip_address:port/api/devices/backup/restore CORS request
|
||||||
|
options(API_CONTEXT + "/backup/restore", "application/json", (request, response) -> {
|
||||||
|
response.status(HttpStatus.SC_OK);
|
||||||
|
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
||||||
|
response.header("Access-Control-Allow-Methods", "POST");
|
||||||
|
response.header("Access-Control-Allow-Headers", request.headers("Access-Control-Request-Headers"));
|
||||||
|
response.header("Content-Type", "text/html; charset=utf-8");
|
||||||
|
return "";
|
||||||
|
});
|
||||||
|
post (API_CONTEXT + "/backup/restore", "application/json", (request, response) -> {
|
||||||
|
log.debug("Restore backup: " + request.body());
|
||||||
|
BackupFilename aFilename = new Gson().fromJson(request.body(), BackupFilename.class);
|
||||||
|
if(aFilename != null)
|
||||||
|
deviceRepository.restoreBackup(aFilename.getFilename());
|
||||||
|
else
|
||||||
|
log.warn("No filename given for restore backup.");
|
||||||
|
return null;
|
||||||
|
}, new JsonTransformer());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,19 @@
|
|||||||
package com.bwssystems.HABridge.hue;
|
package com.bwssystems.HABridge.hue;
|
||||||
|
|
||||||
|
import com.bwssystems.HABridge.BridgeSettings;
|
||||||
import com.bwssystems.HABridge.JsonTransformer;
|
import com.bwssystems.HABridge.JsonTransformer;
|
||||||
import com.bwssystems.HABridge.api.UserCreateRequest;
|
import com.bwssystems.HABridge.api.UserCreateRequest;
|
||||||
import com.bwssystems.HABridge.api.hue.DeviceResponse;
|
import com.bwssystems.HABridge.api.hue.DeviceResponse;
|
||||||
import com.bwssystems.HABridge.api.hue.DeviceState;
|
import com.bwssystems.HABridge.api.hue.DeviceState;
|
||||||
import com.bwssystems.HABridge.api.hue.HueApiResponse;
|
import com.bwssystems.HABridge.api.hue.HueApiResponse;
|
||||||
import com.bwssystems.HABridge.dao.*;
|
import com.bwssystems.HABridge.dao.*;
|
||||||
|
import com.bwssystems.NestBridge.NestInstruction;
|
||||||
|
import com.bwssystems.NestBridge.NestHome;
|
||||||
import com.bwssystems.harmony.ButtonPress;
|
import com.bwssystems.harmony.ButtonPress;
|
||||||
import com.bwssystems.harmony.HarmonyHandler;
|
import com.bwssystems.harmony.HarmonyHandler;
|
||||||
|
import com.bwssystems.harmony.HarmonyHome;
|
||||||
import com.bwssystems.harmony.RunActivity;
|
import com.bwssystems.harmony.RunActivity;
|
||||||
|
import com.bwssystems.nest.controller.Nest;
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
@@ -37,10 +42,15 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.net.DatagramPacket;
|
||||||
|
import java.net.DatagramSocket;
|
||||||
|
import java.net.InetAddress;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.xml.bind.DatatypeConverter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Based on Armzilla's HueMulator - a Philips Hue emulator using sparkjava rest server
|
* Based on Armzilla's HueMulator - a Philips Hue emulator using sparkjava rest server
|
||||||
*/
|
*/
|
||||||
@@ -55,17 +65,28 @@ public class HueMulator {
|
|||||||
private static final String HUE_CONTEXT = "/api";
|
private static final String HUE_CONTEXT = "/api";
|
||||||
|
|
||||||
private DeviceRepository repository;
|
private DeviceRepository repository;
|
||||||
private HarmonyHandler myHarmony;
|
private HarmonyHome myHarmonyHome;
|
||||||
|
private Nest theNest;
|
||||||
private HttpClient httpClient;
|
private HttpClient httpClient;
|
||||||
private ObjectMapper mapper;
|
private ObjectMapper mapper;
|
||||||
|
private BridgeSettings bridgeSettings;
|
||||||
|
private byte[] sendData;
|
||||||
|
|
||||||
|
|
||||||
public HueMulator(DeviceRepository aDeviceRepository, HarmonyHandler theHandler){
|
public HueMulator(BridgeSettings theBridgeSettings, DeviceRepository aDeviceRepository, HarmonyHome theHarmonyHome, NestHome aNestHome){
|
||||||
httpClient = HttpClients.createDefault();
|
httpClient = HttpClients.createDefault();
|
||||||
mapper = new ObjectMapper(); //armzilla: work around Echo incorrect content type and breaking mapping. Map manually
|
mapper = new ObjectMapper(); //armzilla: work around Echo incorrect content type and breaking mapping. Map manually
|
||||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||||
repository = aDeviceRepository;
|
repository = aDeviceRepository;
|
||||||
myHarmony = theHandler;
|
if(theBridgeSettings.isValidHarmony())
|
||||||
|
this.myHarmonyHome = theHarmonyHome;
|
||||||
|
else
|
||||||
|
this.myHarmonyHome = null;
|
||||||
|
if(theBridgeSettings.isValidNest())
|
||||||
|
this.theNest = aNestHome.getTheNest();
|
||||||
|
else
|
||||||
|
this.theNest = null;
|
||||||
|
bridgeSettings = theBridgeSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function sets up the sparkjava rest calls for the hue api
|
// This function sets up the sparkjava rest calls for the hue api
|
||||||
@@ -74,6 +95,8 @@ public class HueMulator {
|
|||||||
// http://ip_address:port/api/{userId}/lights returns json objects of all lights configured
|
// http://ip_address:port/api/{userId}/lights returns json objects of all lights configured
|
||||||
get(HUE_CONTEXT + "/:userid/lights", "application/json", (request, response) -> {
|
get(HUE_CONTEXT + "/:userid/lights", "application/json", (request, response) -> {
|
||||||
String userId = request.params(":userid");
|
String userId = request.params(":userid");
|
||||||
|
if(bridgeSettings.isTraceupnp())
|
||||||
|
log.info("Traceupnp: hue lights list requested: " + userId + " from " + request.ip());
|
||||||
log.debug("hue lights list requested: " + userId + " from " + request.ip());
|
log.debug("hue lights list requested: " + userId + " from " + request.ip());
|
||||||
List<DeviceDescriptor> deviceList = repository.findAll();
|
List<DeviceDescriptor> deviceList = repository.findAll();
|
||||||
Map<String, DeviceResponse> deviceResponseMap = new HashMap<>();
|
Map<String, DeviceResponse> deviceResponseMap = new HashMap<>();
|
||||||
@@ -101,6 +124,8 @@ public class HueMulator {
|
|||||||
String newUser = null;
|
String newUser = null;
|
||||||
String aDeviceType = null;
|
String aDeviceType = null;
|
||||||
|
|
||||||
|
if(bridgeSettings.isTraceupnp())
|
||||||
|
log.info("Traceupnp: hue api/ user create requested: " + request.body() + " from " + request.ip());
|
||||||
log.debug("hue api user create requested: " + request.body() + " from " + request.ip());
|
log.debug("hue api user create requested: " + request.body() + " from " + request.ip());
|
||||||
|
|
||||||
if(request.body() != null && !request.body().isEmpty()) {
|
if(request.body() != null && !request.body().isEmpty()) {
|
||||||
@@ -113,6 +138,8 @@ public class HueMulator {
|
|||||||
|
|
||||||
if(aDeviceType == null)
|
if(aDeviceType == null)
|
||||||
aDeviceType = "<not given>";
|
aDeviceType = "<not given>";
|
||||||
|
if(bridgeSettings.isTraceupnp())
|
||||||
|
log.info("Traceupnp: hue api user create requested for device type: " + aDeviceType + " and username: " + newUser);
|
||||||
log.debug("hue api user create requested for device type: " + aDeviceType + " and username: " + newUser);
|
log.debug("hue api user create requested for device type: " + aDeviceType + " and username: " + newUser);
|
||||||
|
|
||||||
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
||||||
@@ -136,7 +163,8 @@ public class HueMulator {
|
|||||||
String newUser = null;
|
String newUser = null;
|
||||||
String aDeviceType = null;
|
String aDeviceType = null;
|
||||||
|
|
||||||
log.info("HH trace: hue api user create requested: " + request.body() + " from " + request.ip());
|
if(bridgeSettings.isTraceupnp())
|
||||||
|
log.info("Traceupnp: hue api/* user create requested: " + request.body() + " from " + request.ip());
|
||||||
|
|
||||||
if(request.body() != null && !request.body().isEmpty()) {
|
if(request.body() != null && !request.body().isEmpty()) {
|
||||||
aNewUser = new Gson().fromJson(request.body(), UserCreateRequest.class);
|
aNewUser = new Gson().fromJson(request.body(), UserCreateRequest.class);
|
||||||
@@ -158,22 +186,26 @@ public class HueMulator {
|
|||||||
|
|
||||||
// http://ip_address:port/api/config returns json objects for the config when no user is given
|
// http://ip_address:port/api/config returns json objects for the config when no user is given
|
||||||
get(HUE_CONTEXT + "/config", "application/json", (request, response) -> {
|
get(HUE_CONTEXT + "/config", "application/json", (request, response) -> {
|
||||||
String userId = request.params(":userid");
|
if(bridgeSettings.isTraceupnp())
|
||||||
log.debug("hue api config requested: " + userId + " from " + request.ip());
|
log.info("Traceupnp: hue api/config config requested: <no_user> from " + request.ip());
|
||||||
HueApiResponse apiResponse = new HueApiResponse("Philips hue", request.ip(), "My App", userId);
|
log.debug("hue api config requested: <no_user> from " + request.ip());
|
||||||
|
HueApiResponse apiResponse = new HueApiResponse("Philips hue", bridgeSettings.getUpnpConfigAddress(), "My App", "none");
|
||||||
|
|
||||||
response.type("application/json; charset=utf-8");
|
response.type("application/json; charset=utf-8");
|
||||||
response.status(HttpStatus.SC_OK);
|
response.status(HttpStatus.SC_OK);
|
||||||
String responseString = null;
|
// String responseString = null;
|
||||||
responseString = "[{\"swversion\":\"" + apiResponse.getConfig().getSwversion() + "\",\"apiversion\":\"" + apiResponse.getConfig().getApiversion() + "\",\"name\":\"" + apiResponse.getConfig().getName() + "\",\"mac\":\"" + apiResponse.getConfig().getMac() + "\"}]";
|
// responseString = "[{\"swversion\":\"" + apiResponse.getConfig().getSwversion() + "\",\"apiversion\":\"" + apiResponse.getConfig().getApiversion() + "\",\"name\":\"" + apiResponse.getConfig().getName() + "\",\"mac\":\"" + apiResponse.getConfig().getMac() + "\"}]";
|
||||||
return responseString;
|
// return responseString;
|
||||||
});
|
return apiResponse.getConfig();
|
||||||
|
}, new JsonTransformer());
|
||||||
|
|
||||||
// http://ip_address:port/api/{userId}/config returns json objects for the config
|
// http://ip_address:port/api/{userId}/config returns json objects for the config
|
||||||
get(HUE_CONTEXT + "/:userid/config", "application/json", (request, response) -> {
|
get(HUE_CONTEXT + "/:userid/config", "application/json", (request, response) -> {
|
||||||
String userId = request.params(":userid");
|
String userId = request.params(":userid");
|
||||||
|
if(bridgeSettings.isTraceupnp())
|
||||||
|
log.info("Traceupnp: hue api/:userid/config config requested: " + userId + " from " + request.ip());
|
||||||
log.debug("hue api config requested: " + userId + " from " + request.ip());
|
log.debug("hue api config requested: " + userId + " from " + request.ip());
|
||||||
HueApiResponse apiResponse = new HueApiResponse("Philips hue", request.ip(), "My App", userId);
|
HueApiResponse apiResponse = new HueApiResponse("Philips hue", bridgeSettings.getUpnpConfigAddress(), "My App", userId);
|
||||||
|
|
||||||
response.type("application/json; charset=utf-8");
|
response.type("application/json; charset=utf-8");
|
||||||
response.status(HttpStatus.SC_OK);
|
response.status(HttpStatus.SC_OK);
|
||||||
@@ -197,7 +229,7 @@ public class HueMulator {
|
|||||||
deviceList.put(descriptor.getId(), deviceResponse);
|
deviceList.put(descriptor.getId(), deviceResponse);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
HueApiResponse apiResponse = new HueApiResponse("Philips hue", request.ip(), "My App", userId);
|
HueApiResponse apiResponse = new HueApiResponse("Philips hue", bridgeSettings.getUpnpConfigAddress(), "My App", userId);
|
||||||
apiResponse.setLights(deviceList);
|
apiResponse.setLights(deviceList);
|
||||||
|
|
||||||
response.type("application/json; charset=utf-8");
|
response.type("application/json; charset=utf-8");
|
||||||
@@ -241,26 +273,29 @@ public class HueMulator {
|
|||||||
*/
|
*/
|
||||||
String userId = request.params(":userid");
|
String userId = request.params(":userid");
|
||||||
String lightId = request.params(":id");
|
String lightId = request.params(":id");
|
||||||
log.debug("hue state change requested: " + userId + " from " + request.ip() + " body: " + request.body());
|
String responseString = null;
|
||||||
|
String url = null;
|
||||||
DeviceState state = null;
|
DeviceState state = null;
|
||||||
|
log.debug("hue state change requested: " + userId + " from " + request.ip() + " body: " + request.body());
|
||||||
|
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
||||||
|
response.type("application/json; charset=utf-8");
|
||||||
|
response.status(HttpStatus.SC_OK);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
state = mapper.readValue(request.body(), DeviceState.class);
|
state = mapper.readValue(request.body(), DeviceState.class);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("Object mapper barfed on input of body.", e);
|
log.warn("Object mapper barfed on input of body.", e);
|
||||||
response.status(HttpStatus.SC_BAD_REQUEST);
|
responseString = "[{\"error\":{\"type\": 2, \"address\": \"/lights/" + lightId + ",\"description\": \"Object mapper barfed on input of body.\"}}]";
|
||||||
return null;
|
return responseString;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceDescriptor device = repository.findOne(lightId);
|
DeviceDescriptor device = repository.findOne(lightId);
|
||||||
if (device == null) {
|
if (device == null) {
|
||||||
response.status(HttpStatus.SC_NOT_FOUND);
|
log.warn("Could not find device: " + lightId + " for hue state change request: " + userId + " from " + request.ip() + " body: " + request.body());
|
||||||
log.error("Could not find devcie: " + 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 + "\"}}]";
|
||||||
return null;
|
return responseString;
|
||||||
}
|
}
|
||||||
|
|
||||||
String responseString =null;
|
|
||||||
String url = null;
|
|
||||||
if (state.isOn()) {
|
if (state.isOn()) {
|
||||||
responseString = "[{\"success\":{\"/lights/" + lightId + "/state/on\":true}}";
|
responseString = "[{\"success\":{\"/lights/" + lightId + "/state/on\":true}}";
|
||||||
url = device.getOnUrl();
|
url = device.getOnUrl();
|
||||||
@@ -283,23 +318,111 @@ public class HueMulator {
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
responseString = responseString + "]";
|
responseString = responseString + "]";
|
||||||
|
|
||||||
|
if(device.getDeviceType().toLowerCase().contains("activity") || (device.getMapType() != null && device.getMapType().equalsIgnoreCase("harmonyActivity")))
|
||||||
if(device.getDeviceType().toLowerCase().contains("activity"))
|
|
||||||
{
|
{
|
||||||
log.debug("executing activity to Harmony: " + url);
|
log.debug("executing HUE api request to change activity to Harmony: " + url);
|
||||||
RunActivity anActivity = new Gson().fromJson(url, RunActivity.class);
|
RunActivity anActivity = new Gson().fromJson(url, RunActivity.class);
|
||||||
myHarmony.startActivity(anActivity);
|
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 if(device.getDeviceType().toLowerCase().contains("button"))
|
else if(device.getDeviceType().toLowerCase().contains("button") || (device.getMapType() != null && device.getMapType().equalsIgnoreCase("harmonyButton")))
|
||||||
{
|
{
|
||||||
log.debug("executing button press to Harmony: " + url);
|
log.debug("executing HUE api request to button press(es) to Harmony: " + url);
|
||||||
ButtonPress aDeviceButton = new Gson().fromJson(url, ButtonPress.class);
|
if(url.substring(0, 1).equalsIgnoreCase("{")) {
|
||||||
myHarmony.pressButton(aDeviceButton);
|
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(100);
|
||||||
|
log.debug("pressing button: " + deviceButtons[i].getDevice() + " - " + deviceButtons[i].getButton() + " - iteration: " + String.valueOf(i));
|
||||||
|
myHarmony.pressButton(deviceButtons[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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\"}}]";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
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\"}}]";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(thermoSetting.getControl().equalsIgnoreCase("temp")) {
|
||||||
|
if(request.body().contains("bri")) {
|
||||||
|
thermoSetting.setTemp(String.valueOf(Math.round((Integer.parseInt(replaceIntensityValue(thermoSetting.getTemp(), state.getBri())) - 32)/1.8)));
|
||||||
|
log.debug("Setting thermostat: " + thermoSetting.getName() + " to " + thermoSetting.getTemp() + "C");
|
||||||
|
theNest.getThermostat(thermoSetting.getName()).setTargetTemperature(Float.parseFloat(thermoSetting.getTemp()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (thermoSetting.getControl().contains("range") ||thermoSetting.getControl().contains("heat") ||thermoSetting.getControl().contains("cool") ||thermoSetting.getControl().contains("off")) {
|
||||||
|
log.debug("Setting thermostat target type: " + thermoSetting.getName() + " to " + thermoSetting.getControl());
|
||||||
|
theNest.getThermostat(thermoSetting.getName()).setTargetType(thermoSetting.getControl());
|
||||||
|
}
|
||||||
|
else if(thermoSetting.getControl().contains("fan")) {
|
||||||
|
log.debug("Setting thermostat fan mode: " + thermoSetting.getName() + " to " + thermoSetting.getControl().substring(4));
|
||||||
|
theNest.getThermostat(thermoSetting.getName()).setFanMode(thermoSetting.getControl().substring(4));
|
||||||
|
}
|
||||||
|
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\"}}]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(url.startsWith("udp://"))
|
||||||
|
{
|
||||||
|
log.debug("executing HUE api request to UDP: " + url);
|
||||||
|
try {
|
||||||
|
String intermediate = url.substring(6);
|
||||||
|
String ipAddr = intermediate.substring(0, intermediate.indexOf(':'));
|
||||||
|
String port = intermediate.substring(intermediate.indexOf(':') + 1, intermediate.indexOf('/'));
|
||||||
|
String theBody = intermediate.substring(intermediate.indexOf('/')+1);
|
||||||
|
DatagramSocket responseSocket = new DatagramSocket(Integer.parseInt(port));
|
||||||
|
if(theBody.startsWith("0x")) {
|
||||||
|
sendData = DatatypeConverter.parseHexBinary(theBody.substring(2));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sendData = theBody.getBytes();
|
||||||
|
InetAddress IPAddress = InetAddress.getByName(ipAddr);
|
||||||
|
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, Integer.parseInt(port));
|
||||||
|
responseSocket.send(sendPacket);
|
||||||
|
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\"}}]";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
log.debug("executing activity to Http " + (device.getHttpVerb() == null?"GET":device.getHttpVerb()) + ": " + url);
|
log.debug("executing HUE api request to Http " + (device.getHttpVerb() == null?"GET":device.getHttpVerb()) + ": " + url);
|
||||||
// quick template
|
// quick template
|
||||||
String body;
|
String body;
|
||||||
url = replaceIntensityValue(url, state.getBri());
|
url = replaceIntensityValue(url, state.getBri());
|
||||||
@@ -309,15 +432,11 @@ public class HueMulator {
|
|||||||
body = replaceIntensityValue(device.getContentBodyOff(), state.getBri());
|
body = replaceIntensityValue(device.getContentBodyOff(), state.getBri());
|
||||||
// make call
|
// make call
|
||||||
if (!doHttpRequest(url, device.getHttpVerb(), device.getContentType(), body)) {
|
if (!doHttpRequest(url, device.getHttpVerb(), device.getContentType(), body)) {
|
||||||
response.status(HttpStatus.SC_SERVICE_UNAVAILABLE);
|
log.warn("Error on calling url to change device state: " + url);
|
||||||
log.error("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\"}}]";
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
|
||||||
response.type("application/json; charset=utf-8");
|
|
||||||
response.status(HttpStatus.SC_OK);
|
|
||||||
return responseString;
|
return responseString;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -353,8 +472,9 @@ public class HueMulator {
|
|||||||
Integer endResult = Math.round(result.floatValue());
|
Integer endResult = Math.round(result.floatValue());
|
||||||
request = request.replace(INTENSITY_MATH + mathDescriptor + INTENSITY_MATH_CLOSE, endResult.toString());
|
request = request.replace(INTENSITY_MATH + mathDescriptor + INTENSITY_MATH_CLOSE, endResult.toString());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("Could not execute Math: " + mathDescriptor, e);
|
log.warn("Could not execute Math: " + mathDescriptor, e);
|
||||||
} }
|
}
|
||||||
|
}
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,7 +506,7 @@ public class HueMulator {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("Error calling out to HA gateway", e);
|
log.warn("Error calling out to HA gateway", e);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,30 +96,34 @@ public class UpnpListener {
|
|||||||
//Only respond to discover request for strict upnp form
|
//Only respond to discover request for strict upnp form
|
||||||
String packetString = new String(packet.getData());
|
String packetString = new String(packet.getData());
|
||||||
if(packetString != null && packetString.startsWith("M-SEARCH * HTTP/1.1") && packetString.contains("\"ssdp:discover\"")){
|
if(packetString != null && packetString.startsWith("M-SEARCH * HTTP/1.1") && packetString.contains("\"ssdp:discover\"")){
|
||||||
if(traceupnp) {
|
log.debug("isSSDPDiscovery Found message to be an M-SEARCH message.");
|
||||||
log.info("Traceupnp: SSDP packet from " + packet.getAddress().getHostAddress() + ":" + packet.getPort() + ", body: " + packetString);
|
log.debug("isSSDPDiscovery Got SSDP packet from " + packet.getAddress().getHostAddress() + ":" + packet.getPort() + ", body: " + packetString);
|
||||||
log.info("Traceupnp: isSSDPDiscovery found message to be an M-SEARCH message.");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
log.debug("Got SSDP packet from " + packet.getAddress().getHostAddress() + ":" + packet.getPort() + ", body: " + packetString);
|
|
||||||
log.debug("Found message to be an M-SEARCH message.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(strict && (packetString.contains("ST: urn:schemas-upnp-org:device:basic:1") || packetString.contains("ST: upnp:rootdevice") || packetString.contains("ST: ssdp:all")))
|
if(strict && (packetString.contains("ST: urn:schemas-upnp-org:device:basic:1") || packetString.contains("ST: upnp:rootdevice") || packetString.contains("ST: ssdp:all")))
|
||||||
{
|
{
|
||||||
if(traceupnp)
|
if(traceupnp) {
|
||||||
|
log.info("Traceupnp: isSSDPDiscovery found message to be an M-SEARCH message.");
|
||||||
log.info("Traceupnp: isSSDPDiscovery found message to be valid under strict rules - strict: " + strict);
|
log.info("Traceupnp: isSSDPDiscovery found message to be valid under strict rules - strict: " + strict);
|
||||||
|
log.info("Traceupnp: SSDP packet from " + packet.getAddress().getHostAddress() + ":" + packet.getPort() + ", body: " + packetString);
|
||||||
|
}
|
||||||
|
log.debug("isSSDPDiscovery found message to be valid under strict rules - strict: " + strict);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (!strict)
|
else if (!strict)
|
||||||
{
|
{
|
||||||
if(traceupnp)
|
if(traceupnp) {
|
||||||
|
log.info("Traceupnp: isSSDPDiscovery found message to be an M-SEARCH message.");
|
||||||
log.info("Traceupnp: isSSDPDiscovery found message to be valid under loose rules - strict: " + strict);
|
log.info("Traceupnp: isSSDPDiscovery found message to be valid under loose rules - strict: " + strict);
|
||||||
|
log.info("Traceupnp: SSDP packet from " + packet.getAddress().getHostAddress() + ":" + packet.getPort() + ", body: " + packetString);
|
||||||
|
}
|
||||||
|
log.debug("isSSDPDiscovery found message to be valid under loose rules - strict: " + strict);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(traceupnp)
|
else {
|
||||||
log.info("Traceupnp: isSSDPDiscovery found message to not be valid - strict: " + strict);
|
// log.debug("isSSDPDiscovery found message to not be valid - strict: " + strict);
|
||||||
|
// log.debug("SSDP packet from " + packet.getAddress().getHostAddress() + ":" + packet.getPort() + ", body: " + packetString);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,9 +40,20 @@ public class UpnpSettingsResource {
|
|||||||
+ "<depth>24</depth>\n" + "<url>hue_logo_3.png</url>\n" + "</icon>\n" + "</iconList>\n" + "</device>\n"
|
+ "<depth>24</depth>\n" + "<url>hue_logo_3.png</url>\n" + "</icon>\n" + "</iconList>\n" + "</device>\n"
|
||||||
+ "</root>\n";
|
+ "</root>\n";
|
||||||
|
|
||||||
public UpnpSettingsResource(BridgeSettings theSettings) {
|
public UpnpSettingsResource(BridgeSettings theBridgeSettings) {
|
||||||
super();
|
super();
|
||||||
this.theSettings = theSettings;
|
this.theSettings = new BridgeSettings();
|
||||||
|
this.theSettings.setDevMode(theBridgeSettings.isDevMode());
|
||||||
|
this.theSettings.setHarmonyAddress(theBridgeSettings.getHarmonyAddress());
|
||||||
|
this.theSettings.setServerPort(theBridgeSettings.getServerPort());
|
||||||
|
this.theSettings.setTraceupnp(theBridgeSettings.isTraceupnp());
|
||||||
|
this.theSettings.setUpnpConfigAddress(theBridgeSettings.getUpnpConfigAddress());
|
||||||
|
this.theSettings.setUpnpDeviceDb(theBridgeSettings.getUpnpDeviceDb());
|
||||||
|
this.theSettings.setUpnpResponseDevices(theBridgeSettings.getUpnpResponseDevices());
|
||||||
|
this.theSettings.setUpnpResponsePort(theBridgeSettings.getUpnpResponsePort());
|
||||||
|
this.theSettings.setUpnpStrict(theBridgeSettings.isUpnpStrict());
|
||||||
|
this.theSettings.setVeraAddress(theBridgeSettings.getVeraAddress());
|
||||||
|
this.theSettings.setNestConfigured(theBridgeSettings.isValidNest());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setupServer() {
|
public void setupServer() {
|
||||||
|
|||||||
101
src/main/java/com/bwssystems/NestBridge/NestHome.java
Normal file
101
src/main/java/com/bwssystems/NestBridge/NestHome.java
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
package com.bwssystems.NestBridge;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ListIterator;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.bwssystems.HABridge.BridgeSettings;
|
||||||
|
import com.bwssystems.nest.controller.Home;
|
||||||
|
import com.bwssystems.nest.controller.Nest;
|
||||||
|
import com.bwssystems.nest.controller.NestSession;
|
||||||
|
import com.bwssystems.nest.controller.Thermostat;
|
||||||
|
import com.bwssystems.nest.protocol.error.LoginException;
|
||||||
|
import com.bwssystems.nest.protocol.status.WhereDetail;
|
||||||
|
import com.bwssystems.nest.protocol.status.WhereItem;
|
||||||
|
|
||||||
|
public class NestHome {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(NestHome.class);
|
||||||
|
private NestSession theSession;
|
||||||
|
private Nest theNest;
|
||||||
|
private ArrayList<NestItem> nestItems;
|
||||||
|
|
||||||
|
public NestHome(BridgeSettings bridgeSettings) {
|
||||||
|
theSession = null;
|
||||||
|
theNest = null;
|
||||||
|
nestItems = null;
|
||||||
|
|
||||||
|
if(!bridgeSettings.isValidNest()) {
|
||||||
|
log.info("not a valid nest");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
theSession = new NestSession(bridgeSettings.getNestuser(), bridgeSettings.getNestpwd());
|
||||||
|
theNest = new Nest(theSession);
|
||||||
|
} catch (LoginException e) {
|
||||||
|
log.error("Caught Login Exception, exiting....");
|
||||||
|
theSession = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<NestItem> getItems() {
|
||||||
|
if(theNest == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if(nestItems == null) {
|
||||||
|
nestItems = new ArrayList<NestItem>();
|
||||||
|
Set<String> homeNames = theNest.getHomeNames();
|
||||||
|
Home aHome = null;
|
||||||
|
NestItem anItem = null;
|
||||||
|
for(String name : homeNames) {
|
||||||
|
aHome = theNest.getHome(name);
|
||||||
|
anItem = new NestItem();
|
||||||
|
anItem.setId(name);
|
||||||
|
anItem.setName(aHome.getDetail().getName());
|
||||||
|
anItem.setType("Home");
|
||||||
|
anItem.setLocation(aHome.getDetail().getLocation());
|
||||||
|
nestItems.add(anItem);
|
||||||
|
}
|
||||||
|
Thermostat thermo = null;
|
||||||
|
Set<String> thermoNames = theNest.getThermostatNames();
|
||||||
|
for(String name : thermoNames) {
|
||||||
|
thermo = theNest.getThermostat(name);
|
||||||
|
anItem = new NestItem();
|
||||||
|
anItem.setId(name);
|
||||||
|
anItem.setType("Thermostat");
|
||||||
|
String where = null;
|
||||||
|
String homeName= null;
|
||||||
|
Boolean found = false;
|
||||||
|
for(String aHomeName : homeNames) {
|
||||||
|
WhereDetail aDetail = theNest.getWhere(aHomeName);
|
||||||
|
ListIterator<WhereItem> anIterator = aDetail.getWheres().listIterator();
|
||||||
|
while(anIterator.hasNext()) {
|
||||||
|
WhereItem aWhereItem = (WhereItem) anIterator.next();
|
||||||
|
if(aWhereItem.getWhereId().equals(thermo.getDeviceDetail().getWhereId())) {
|
||||||
|
where = aWhereItem.getName();
|
||||||
|
homeName = theNest.getHome(aHomeName).getDetail().getName();
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(found)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
anItem.setName(where + "(" + name.substring(name.length() - 4) + ")");
|
||||||
|
anItem.setLocation(where + " - " + homeName);
|
||||||
|
nestItems.add(anItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nestItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Nest getTheNest() {
|
||||||
|
return theNest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
33
src/main/java/com/bwssystems/NestBridge/NestInstruction.java
Normal file
33
src/main/java/com/bwssystems/NestBridge/NestInstruction.java
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package com.bwssystems.NestBridge;
|
||||||
|
|
||||||
|
public class NestInstruction {
|
||||||
|
private String name;
|
||||||
|
private Boolean away;
|
||||||
|
private String control;
|
||||||
|
private String temp;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
public Boolean getAway() {
|
||||||
|
return away;
|
||||||
|
}
|
||||||
|
public void setAway(Boolean away) {
|
||||||
|
this.away = away;
|
||||||
|
}
|
||||||
|
public String getControl() {
|
||||||
|
return control;
|
||||||
|
}
|
||||||
|
public void setControl(String control) {
|
||||||
|
this.control = control;
|
||||||
|
}
|
||||||
|
public String getTemp() {
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
public void setTemp(String temp) {
|
||||||
|
this.temp = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
32
src/main/java/com/bwssystems/NestBridge/NestItem.java
Normal file
32
src/main/java/com/bwssystems/NestBridge/NestItem.java
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package com.bwssystems.NestBridge;
|
||||||
|
|
||||||
|
public class NestItem {
|
||||||
|
private String name;
|
||||||
|
private String id;
|
||||||
|
private String type;
|
||||||
|
private String location;
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
public void setId(String anid) {
|
||||||
|
id = anid;
|
||||||
|
}
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
public String getLocation() {
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
public void setLocation(String location) {
|
||||||
|
this.location = location;
|
||||||
|
}
|
||||||
|
}
|
||||||
21
src/main/java/com/bwssystems/harmony/HarmonyActivity.java
Normal file
21
src/main/java/com/bwssystems/harmony/HarmonyActivity.java
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package com.bwssystems.harmony;
|
||||||
|
|
||||||
|
import net.whistlingfish.harmony.config.Activity;
|
||||||
|
|
||||||
|
public class HarmonyActivity {
|
||||||
|
private String hub;
|
||||||
|
private Activity activity;
|
||||||
|
public String getHub() {
|
||||||
|
return hub;
|
||||||
|
}
|
||||||
|
public void setHub(String hub) {
|
||||||
|
this.hub = hub;
|
||||||
|
}
|
||||||
|
public Activity getActivity() {
|
||||||
|
return activity;
|
||||||
|
}
|
||||||
|
public void setActivity(Activity activity) {
|
||||||
|
this.activity = activity;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
20
src/main/java/com/bwssystems/harmony/HarmonyDevice.java
Normal file
20
src/main/java/com/bwssystems/harmony/HarmonyDevice.java
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package com.bwssystems.harmony;
|
||||||
|
|
||||||
|
import net.whistlingfish.harmony.config.Device;
|
||||||
|
|
||||||
|
public class HarmonyDevice {
|
||||||
|
private Device device;
|
||||||
|
private String hub;
|
||||||
|
public Device getDevice() {
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
public void setDevice(Device device) {
|
||||||
|
this.device = device;
|
||||||
|
}
|
||||||
|
public String getHub() {
|
||||||
|
return hub;
|
||||||
|
}
|
||||||
|
public void setHub(String hub) {
|
||||||
|
this.hub = hub;
|
||||||
|
}
|
||||||
|
}
|
||||||
115
src/main/java/com/bwssystems/harmony/HarmonyHome.java
Normal file
115
src/main/java/com/bwssystems/harmony/HarmonyHome.java
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
package com.bwssystems.harmony;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.bwssystems.HABridge.BridgeSettings;
|
||||||
|
import com.bwssystems.HABridge.IpList;
|
||||||
|
import com.bwssystems.HABridge.NamedIP;
|
||||||
|
|
||||||
|
import net.whistlingfish.harmony.config.Activity;
|
||||||
|
import net.whistlingfish.harmony.config.Device;
|
||||||
|
|
||||||
|
public class HarmonyHome {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(HarmonyHome.class);
|
||||||
|
private Map<String, HarmonyServer> hubs;
|
||||||
|
|
||||||
|
public HarmonyHome(BridgeSettings bridgeSettings) {
|
||||||
|
super();
|
||||||
|
hubs = new HashMap<String, HarmonyServer>();
|
||||||
|
if(!bridgeSettings.isValidHarmony() && !bridgeSettings.isDevMode())
|
||||||
|
return;
|
||||||
|
if(bridgeSettings.isDevMode()) {
|
||||||
|
NamedIP devModeIp = new NamedIP();
|
||||||
|
devModeIp.setIp("10.10.10.10");
|
||||||
|
devModeIp.setName("devMode");
|
||||||
|
List<NamedIP> theList = new ArrayList<NamedIP>();
|
||||||
|
theList.add(devModeIp);
|
||||||
|
IpList thedevList = new IpList();
|
||||||
|
thedevList.setDevices(theList);
|
||||||
|
bridgeSettings.setHarmonyAddress(thedevList);
|
||||||
|
}
|
||||||
|
Iterator<NamedIP> theList = bridgeSettings.getHarmonyAddress().getDevices().iterator();
|
||||||
|
while(theList.hasNext()) {
|
||||||
|
NamedIP aHub = theList.next();
|
||||||
|
try {
|
||||||
|
hubs.put(aHub.getName(), HarmonyServer.setup(bridgeSettings, aHub));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Cannot get harmony client (" + aHub.getName() + ") setup, Exiting with message: " + e.getMessage(), e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public HarmonyHandler getHarmonyHandler(String aName) {
|
||||||
|
HarmonyHandler aHandler = null;
|
||||||
|
if(aName == null || aName.equals("")) {
|
||||||
|
aName = "default";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(hubs.get(aName) == null) {
|
||||||
|
Set<String> keys = hubs.keySet();
|
||||||
|
if(!keys.isEmpty()) {
|
||||||
|
aHandler = hubs.get(keys.toArray()[0]).getMyHarmony();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
aHandler = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
aHandler = hubs.get(aName).getMyHarmony();
|
||||||
|
return aHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<HarmonyActivity> getActivities() {
|
||||||
|
Iterator<String> keys = hubs.keySet().iterator();
|
||||||
|
ArrayList<HarmonyActivity> activityList = new ArrayList<HarmonyActivity>();
|
||||||
|
while(keys.hasNext()) {
|
||||||
|
String key = keys.next();
|
||||||
|
Iterator<Activity> activities = hubs.get(key).getMyHarmony().getActivities().iterator();
|
||||||
|
while(activities.hasNext()) {
|
||||||
|
HarmonyActivity anActivity = new HarmonyActivity();
|
||||||
|
anActivity.setActivity(activities.next());
|
||||||
|
anActivity.setHub(key);
|
||||||
|
activityList.add(anActivity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return activityList;
|
||||||
|
}
|
||||||
|
public List<HarmonyActivity> getCurrentActivities() {
|
||||||
|
Iterator<String> keys = hubs.keySet().iterator();
|
||||||
|
ArrayList<HarmonyActivity> activityList = new ArrayList<HarmonyActivity>();
|
||||||
|
while(keys.hasNext()) {
|
||||||
|
String key = keys.next();
|
||||||
|
Iterator<Activity> activities = hubs.get(key).getMyHarmony().getActivities().iterator();
|
||||||
|
while(activities.hasNext()) {
|
||||||
|
HarmonyActivity anActivity = new HarmonyActivity();
|
||||||
|
anActivity.setActivity(activities.next());
|
||||||
|
anActivity.setHub(key);
|
||||||
|
activityList.add(anActivity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return activityList;
|
||||||
|
}
|
||||||
|
public List<HarmonyDevice> getDevices() {
|
||||||
|
Iterator<String> keys = hubs.keySet().iterator();
|
||||||
|
ArrayList<HarmonyDevice> deviceList = new ArrayList<HarmonyDevice>();
|
||||||
|
while(keys.hasNext()) {
|
||||||
|
String key = keys.next();
|
||||||
|
Iterator<Device> devices = hubs.get(key).getMyHarmony().getDevices().iterator();
|
||||||
|
while(devices.hasNext()) {
|
||||||
|
HarmonyDevice aDevice = new HarmonyDevice();
|
||||||
|
aDevice.setDevice(devices.next());
|
||||||
|
aDevice.setHub(key);
|
||||||
|
deviceList.add(aDevice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return deviceList;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.bwssystems.HABridge.BridgeSettings;
|
import com.bwssystems.HABridge.BridgeSettings;
|
||||||
|
import com.bwssystems.HABridge.NamedIP;
|
||||||
import com.google.inject.Guice;
|
import com.google.inject.Guice;
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
|
|
||||||
@@ -24,23 +25,25 @@ public class HarmonyServer {
|
|||||||
private HarmonyHandler myHarmony;
|
private HarmonyHandler myHarmony;
|
||||||
private DevModeResponse devResponse;
|
private DevModeResponse devResponse;
|
||||||
private OAReplyProvider dummyProvider;
|
private OAReplyProvider dummyProvider;
|
||||||
|
private NamedIP myNameAndIP;
|
||||||
|
|
||||||
private Logger log = LoggerFactory.getLogger(HarmonyServer.class);
|
private Logger log = LoggerFactory.getLogger(HarmonyServer.class);
|
||||||
|
|
||||||
public HarmonyServer() {
|
public HarmonyServer(NamedIP theHarmonyAddress) {
|
||||||
super();
|
super();
|
||||||
myHarmony = null;
|
myHarmony = null;
|
||||||
dummyProvider = null;
|
dummyProvider = null;
|
||||||
|
myNameAndIP = theHarmonyAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static HarmonyServer setup(BridgeSettings bridgeSettings) throws Exception {
|
public static HarmonyServer setup(BridgeSettings bridgeSettings, NamedIP theHarmonyAddress) throws Exception {
|
||||||
if(!bridgeSettings.isValidHarmony()) {
|
if(!bridgeSettings.isValidHarmony() && !bridgeSettings.isDevMode()) {
|
||||||
return new HarmonyServer();
|
return new HarmonyServer(theHarmonyAddress);
|
||||||
}
|
}
|
||||||
Injector injector = null;
|
Injector injector = null;
|
||||||
if(!bridgeSettings.isDevMode())
|
if(!bridgeSettings.isDevMode())
|
||||||
injector = Guice.createInjector(new HarmonyClientModule());
|
injector = Guice.createInjector(new HarmonyClientModule());
|
||||||
HarmonyServer mainObject = new HarmonyServer();
|
HarmonyServer mainObject = new HarmonyServer(theHarmonyAddress);
|
||||||
if(!bridgeSettings.isDevMode())
|
if(!bridgeSettings.isDevMode())
|
||||||
injector.injectMembers(mainObject);
|
injector.injectMembers(mainObject);
|
||||||
mainObject.execute(bridgeSettings);
|
mainObject.execute(bridgeSettings);
|
||||||
@@ -70,7 +73,7 @@ public class HarmonyServer {
|
|||||||
log.info(format("activity changed: [%d] %s", activity.getId(), activity.getLabel()));
|
log.info(format("activity changed: [%d] %s", activity.getId(), activity.getLabel()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
harmonyClient.connect(mySettings.getHarmonyAddress(), mySettings.getHarmonyUser(), mySettings.getHarmonyPwd());
|
harmonyClient.connect(myNameAndIP.getIp(), mySettings.getHarmonyUser(), mySettings.getHarmonyPwd());
|
||||||
}
|
}
|
||||||
myHarmony = new HarmonyHandler(harmonyClient, noopCalls, devResponse);
|
myHarmony = new HarmonyHandler(harmonyClient, noopCalls, devResponse);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ public class Device {
|
|||||||
private String level;
|
private String level;
|
||||||
private String state;
|
private String state;
|
||||||
private String comment;
|
private String comment;
|
||||||
|
private String veraname;
|
||||||
|
private String veraaddress;
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
@@ -79,5 +81,17 @@ public class Device {
|
|||||||
public void setComment(String comment) {
|
public void setComment(String comment) {
|
||||||
this.comment = comment;
|
this.comment = comment;
|
||||||
}
|
}
|
||||||
|
public String getVeraname() {
|
||||||
|
return veraname;
|
||||||
|
}
|
||||||
|
public void setVeraname(String veraname) {
|
||||||
|
this.veraname = veraname;
|
||||||
|
}
|
||||||
|
public String getVeraaddress() {
|
||||||
|
return veraaddress;
|
||||||
|
}
|
||||||
|
public void setVeraaddress(String veraaddress) {
|
||||||
|
this.veraaddress = veraaddress;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ public class Scene {
|
|||||||
private String name;
|
private String name;
|
||||||
private String id;
|
private String id;
|
||||||
private String room;
|
private String room;
|
||||||
|
private String veraname;
|
||||||
|
private String veraaddress;
|
||||||
public String getActive() {
|
public String getActive() {
|
||||||
return active;
|
return active;
|
||||||
}
|
}
|
||||||
@@ -29,5 +31,17 @@ public class Scene {
|
|||||||
public void setRoom(String room) {
|
public void setRoom(String room) {
|
||||||
this.room = room;
|
this.room = room;
|
||||||
}
|
}
|
||||||
|
public String getVeraname() {
|
||||||
|
return veraname;
|
||||||
|
}
|
||||||
|
public void setVeraname(String veraname) {
|
||||||
|
this.veraname = veraname;
|
||||||
|
}
|
||||||
|
public String getVeraaddress() {
|
||||||
|
return veraaddress;
|
||||||
|
}
|
||||||
|
public void setVeraaddress(String veraaddress) {
|
||||||
|
this.veraaddress = veraaddress;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
58
src/main/java/com/bwssystems/vera/VeraHome.java
Normal file
58
src/main/java/com/bwssystems/vera/VeraHome.java
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
package com.bwssystems.vera;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.bwssystems.HABridge.BridgeSettings;
|
||||||
|
import com.bwssystems.HABridge.NamedIP;
|
||||||
|
import com.bwssystems.luupRequests.Device;
|
||||||
|
import com.bwssystems.luupRequests.Scene;
|
||||||
|
|
||||||
|
public class VeraHome {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(VeraHome.class);
|
||||||
|
private Map<String, VeraInfo> veras;
|
||||||
|
|
||||||
|
public VeraHome(BridgeSettings bridgeSettings) {
|
||||||
|
veras = new HashMap<String, VeraInfo>();
|
||||||
|
if(!bridgeSettings.isValidVera())
|
||||||
|
return;
|
||||||
|
Iterator<NamedIP> theList = bridgeSettings.getVeraAddress().getDevices().iterator();
|
||||||
|
while(theList.hasNext()) {
|
||||||
|
NamedIP aVera = theList.next();
|
||||||
|
veras.put(aVera.getName(), new VeraInfo(aVera, bridgeSettings.isValidVera()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Device> getDevices() {
|
||||||
|
log.debug("consolidating devices for veras");
|
||||||
|
Iterator<String> keys = veras.keySet().iterator();
|
||||||
|
ArrayList<Device> deviceList = new ArrayList<Device>();
|
||||||
|
while(keys.hasNext()) {
|
||||||
|
String key = keys.next();
|
||||||
|
Iterator<Device> devices = veras.get(key).getSdata().getDevices().iterator();
|
||||||
|
while(devices.hasNext()) {
|
||||||
|
deviceList.add(devices.next());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return deviceList;
|
||||||
|
}
|
||||||
|
public List<Scene> getScenes() {
|
||||||
|
log.debug("consolidating scenes for veras");
|
||||||
|
Iterator<String> keys = veras.keySet().iterator();
|
||||||
|
ArrayList<Scene> sceneList = new ArrayList<Scene>();
|
||||||
|
while(keys.hasNext()) {
|
||||||
|
String key = keys.next();
|
||||||
|
Iterator<Scene> scenes = veras.get(key).getSdata().getScenes().iterator();
|
||||||
|
while(scenes.hasNext()) {
|
||||||
|
sceneList.add(scenes.next());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sceneList;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ import org.apache.http.util.EntityUtils;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.bwssystems.HABridge.NamedIP;
|
||||||
import com.bwssystems.luupRequests.Categorie;
|
import com.bwssystems.luupRequests.Categorie;
|
||||||
import com.bwssystems.luupRequests.Device;
|
import com.bwssystems.luupRequests.Device;
|
||||||
import com.bwssystems.luupRequests.Room;
|
import com.bwssystems.luupRequests.Room;
|
||||||
@@ -25,13 +26,13 @@ public class VeraInfo {
|
|||||||
private static final Logger log = LoggerFactory.getLogger(VeraInfo.class);
|
private static final Logger log = LoggerFactory.getLogger(VeraInfo.class);
|
||||||
private HttpClient httpClient;
|
private HttpClient httpClient;
|
||||||
private static final String SDATA_REQUEST = ":3480/data_request?id=sdata&output_format=json";
|
private static final String SDATA_REQUEST = ":3480/data_request?id=sdata&output_format=json";
|
||||||
private String veraAddressString;
|
private NamedIP veraAddress;
|
||||||
private Boolean validVera;
|
private Boolean validVera;
|
||||||
|
|
||||||
public VeraInfo(String addressString, Boolean isValidVera) {
|
public VeraInfo(NamedIP addressName, Boolean isValidVera) {
|
||||||
super();
|
super();
|
||||||
httpClient = HttpClients.createMinimal();
|
httpClient = HttpClients.createDefault();
|
||||||
veraAddressString = addressString;
|
veraAddress = addressName;
|
||||||
validVera = isValidVera;
|
validVera = isValidVera;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,7 +40,7 @@ public class VeraInfo {
|
|||||||
if(!validVera)
|
if(!validVera)
|
||||||
return new Sdata();
|
return new Sdata();
|
||||||
|
|
||||||
String theUrl = "http://" + veraAddressString + SDATA_REQUEST;
|
String theUrl = "http://" + veraAddress.getIp() + SDATA_REQUEST;
|
||||||
String theData;
|
String theData;
|
||||||
|
|
||||||
theData = doHttpGETRequest(theUrl);
|
theData = doHttpGETRequest(theUrl);
|
||||||
@@ -71,6 +72,8 @@ public class VeraInfo {
|
|||||||
theDevice.setCategory(categoryMap.get(theDevice.getCategory()).getName());
|
theDevice.setCategory(categoryMap.get(theDevice.getCategory()).getName());
|
||||||
else
|
else
|
||||||
theDevice.setCategory("<unknown>");
|
theDevice.setCategory("<unknown>");
|
||||||
|
theDevice.setVeraaddress(veraAddress.getIp());
|
||||||
|
theDevice.setVeraname(veraAddress.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
ListIterator<Scene> theSecneIter = theSdata.getScenes().listIterator();
|
ListIterator<Scene> theSecneIter = theSdata.getScenes().listIterator();
|
||||||
@@ -81,6 +84,8 @@ public class VeraInfo {
|
|||||||
theScene.setRoom(roomMap.get(theScene.getRoom()).getName());
|
theScene.setRoom(roomMap.get(theScene.getRoom()).getName());
|
||||||
else
|
else
|
||||||
theScene.setRoom("no room");
|
theScene.setRoom("no room");
|
||||||
|
theScene.setVeraaddress(veraAddress.getIp());
|
||||||
|
theScene.setVeraname(veraAddress.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
<ul class="nav navbar-nav">
|
<ul class="nav navbar-nav">
|
||||||
<li class="active"><a href="#">Home</a></li>
|
<li class="active"><a href="#">Home</a></li>
|
||||||
<li><a href="http://echo.amazon.com/#cards" target="_blank">My Echo</a></li>
|
<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">
|
<li class="dropdown">
|
||||||
<a id="dropdownMenu1" href="" class="dropdown-toggle"
|
<a id="dropdownMenu1" href="" class="dropdown-toggle"
|
||||||
data-toggle="dropdown" role="button" aria-haspopup="true"
|
data-toggle="dropdown" role="button" aria-haspopup="true"
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
var app = angular.module('habridge', [
|
var app = angular.module('habridge', ['ngRoute']);
|
||||||
'ngRoute'
|
|
||||||
]);
|
|
||||||
|
|
||||||
app.config(function ($routeProvider) {
|
app.config(function ($routeProvider) {
|
||||||
$routeProvider.when('/#', {
|
$routeProvider.when('/#', {
|
||||||
@@ -24,6 +22,9 @@ app.config(function ($routeProvider) {
|
|||||||
}).when('/harmonyactivities', {
|
}).when('/harmonyactivities', {
|
||||||
templateUrl: 'views/harmonyactivity.html',
|
templateUrl: 'views/harmonyactivity.html',
|
||||||
controller: 'AddingController'
|
controller: 'AddingController'
|
||||||
|
}).when('/nest', {
|
||||||
|
templateUrl: 'views/nestactions.html',
|
||||||
|
controller: 'AddingController'
|
||||||
}).otherwise({
|
}).otherwise({
|
||||||
templateUrl: 'views/configuration.html',
|
templateUrl: 'views/configuration.html',
|
||||||
controller: 'ViewingController'
|
controller: 'ViewingController'
|
||||||
@@ -32,63 +33,12 @@ app.config(function ($routeProvider) {
|
|||||||
|
|
||||||
app.run( function (bridgeService) {
|
app.run( function (bridgeService) {
|
||||||
bridgeService.loadBridgeSettings();
|
bridgeService.loadBridgeSettings();
|
||||||
bridgeService.updateShowVera();
|
|
||||||
bridgeService.updateShowHarmony();
|
|
||||||
bridgeService.getHABridgeVersion();
|
bridgeService.getHABridgeVersion();
|
||||||
});
|
});
|
||||||
|
|
||||||
app.factory('BridgeSettings', function() {
|
app.service('bridgeService', function ($http, $window) {
|
||||||
var BridgeSettings = {};
|
|
||||||
|
|
||||||
BridgeSettings.upnpconfigaddress = "";
|
|
||||||
BridgeSettings.serverport = "";
|
|
||||||
BridgeSettings.upnpdevicedb = "";
|
|
||||||
BridgeSettings.upnpresponseport = "";
|
|
||||||
BridgeSettings.veraaddress = "";
|
|
||||||
BridgeSettings.harmonyaddress = "";
|
|
||||||
BridgeSettings.upnpstrict = "";
|
|
||||||
BridgeSettings.traceupnp = "";
|
|
||||||
BridgeSettings.devmode = "";
|
|
||||||
|
|
||||||
BridgeSettings.setupnpconfigaddress = function(aconfigaddress){
|
|
||||||
BridgeSettings.upnpconfigaddress = aconfigaddress;
|
|
||||||
};
|
|
||||||
|
|
||||||
BridgeSettings.setserverport = function(aserverport){
|
|
||||||
BridgeSettings.serverport = aserverport;
|
|
||||||
};
|
|
||||||
|
|
||||||
BridgeSettings.setupnpdevicedb = function(aupnpdevicedb){
|
|
||||||
BridgeSettings.upnpdevicedb = aupnpdevicedb;
|
|
||||||
};
|
|
||||||
|
|
||||||
BridgeSettings.setupnpresponseport = function(aupnpresponseport){
|
|
||||||
BridgeSettings.upnpresponseport = aupnpresponseport;
|
|
||||||
};
|
|
||||||
|
|
||||||
BridgeSettings.setveraaddress = function(averaaddress){
|
|
||||||
BridgeSettings.veraaddress = averaaddress;
|
|
||||||
};
|
|
||||||
BridgeSettings.setharmonyaddress = function(aharmonyaddress){
|
|
||||||
BridgeSettings.harmonyaddress = aharmonyaddress;
|
|
||||||
};
|
|
||||||
BridgeSettings.setupnpstrict = function(aupnpstrict){
|
|
||||||
BridgeSettings.upnpstrict = aupnpstrict;
|
|
||||||
};
|
|
||||||
BridgeSettings.settraceupnp = function(atraceupnp){
|
|
||||||
BridgeSettings.traceupnp = atraceupnp;
|
|
||||||
};
|
|
||||||
BridgeSettings.setdevmode = function(adevmode){
|
|
||||||
BridgeSettings.devmode = adevmode;
|
|
||||||
};
|
|
||||||
|
|
||||||
return BridgeSettings;
|
|
||||||
});
|
|
||||||
|
|
||||||
app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
|
||||||
var self = this;
|
var self = this;
|
||||||
self.BridgeSettings = BridgeSettings;
|
this.state = {base: window.location.origin + "/api/devices", upnpbase: window.location.origin + "/upnp/settings", huebase: window.location.origin + "/api", backups: [], devices: [], device: [], settings: [], error: "", showVera: false, showHarmony: false, showNest: false, habridgeversion: ""};
|
||||||
this.state = {base: window.location.origin + "/api/devices", upnpbase: window.location.origin + "/upnp/settings", huebase: window.location.origin + "/api", devices: [], device: [], error: "", showVera: false, showHarmony: false, habridgeversion: ""};
|
|
||||||
|
|
||||||
this.viewDevices = function () {
|
this.viewDevices = function () {
|
||||||
this.state.error = "";
|
this.state.error = "";
|
||||||
@@ -124,27 +74,47 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.aContainsB = function (a, b) {
|
||||||
|
return a.indexOf(b) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateShowVera = function () {
|
||||||
|
if(this.aContainsB(self.state.settings.veraaddress.devices[0].ip, "1.1.1.1") || self.state.settings.veraaddress == "" || self.state.settings.veraaddress == null)
|
||||||
|
this.state.showVera = false;
|
||||||
|
else
|
||||||
|
this.state.showVera = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateShowNest = function () {
|
||||||
|
if(self.state.settings.nestconfigured == true)
|
||||||
|
this.state.showNest = true;
|
||||||
|
else
|
||||||
|
this.state.showNest = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateShowHarmony = function () {
|
||||||
|
if(self.state.settings.harmonyaddress.devices) {
|
||||||
|
if(this.aContainsB(self.state.settings.harmonyaddress.devices[0].ip, "1.1.1.1") || self.state.settings.harmonyaddress == "" || self.state.settings.harmonyaddress == null)
|
||||||
|
this.state.showHarmony = false;
|
||||||
|
else
|
||||||
|
this.state.showHarmony = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
this.state.showHarmony = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
this.loadBridgeSettings = function () {
|
this.loadBridgeSettings = function () {
|
||||||
this.state.error = "";
|
this.state.error = "";
|
||||||
return $http.get(this.state.upnpbase).then(
|
return $http.get(this.state.upnpbase).then(
|
||||||
function (response) {
|
function (response) {
|
||||||
self.BridgeSettings.setupnpconfigaddress(response.data.upnpconfigaddress);
|
self.state.settings = response.data;
|
||||||
self.BridgeSettings.setserverport(response.data.serverport);
|
self.updateShowVera();
|
||||||
self.BridgeSettings.setupnpdevicedb(response.data.upnpdevicedb);
|
self.updateShowHarmony();
|
||||||
self.BridgeSettings.setupnpresponseport(response.data.upnpresponseport);
|
self.updateShowNest();
|
||||||
self.BridgeSettings.setveraaddress(response.data.veraaddress);
|
|
||||||
self.BridgeSettings.setharmonyaddress(response.data.harmonyaddress);
|
|
||||||
self.BridgeSettings.settraceupnp(response.data.traceupnp);
|
|
||||||
self.BridgeSettings.setupnpstrict(response.data.upnpstrict);
|
|
||||||
self.BridgeSettings.setdevmode(response.data.devmode);
|
|
||||||
if(self.BridgeSettings.veraaddress == "1.1.1.1" || self.BridgeSettings.veraaddress == "")
|
|
||||||
self.state.showVera = false;
|
|
||||||
else
|
|
||||||
self.state.showVera = true;
|
|
||||||
if(self.BridgeSettings.harmonyaddress == "1.1.1.1" || self.BridgeSettings.harmonyaddress == "")
|
|
||||||
self.state.showHarmony = false;
|
|
||||||
else
|
|
||||||
self.state.showHarmony = true;
|
|
||||||
},
|
},
|
||||||
function (error) {
|
function (error) {
|
||||||
if (error.data) {
|
if (error.data) {
|
||||||
@@ -157,27 +127,44 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.updateShowVera = function () {
|
this.viewBackups = function () {
|
||||||
if(self.BridgeSettings.veraaddress == "1.1.1.1" || self.BridgeSettings.veraaddress == "")
|
this.state.error = "";
|
||||||
this.state.showVera = false;
|
return $http.get(this.state.base + "/backup/available").then(
|
||||||
else
|
function (response) {
|
||||||
this.state.showVera = true;
|
self.state.backups = response.data;
|
||||||
return;
|
},
|
||||||
}
|
function (error) {
|
||||||
|
if (error.data) {
|
||||||
|
$window.alert("Get Backups Error: " + error.data.message);
|
||||||
|
} else {
|
||||||
|
$window.alert("Get Backups Error: unknown");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.viewNestItems = function () {
|
||||||
|
this.state.error = "";
|
||||||
|
if(!this.state.showNest)
|
||||||
|
return;
|
||||||
|
return $http.get(this.state.base + "/nest/items").then(
|
||||||
|
function (response) {
|
||||||
|
self.state.nestitems = response.data;
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
if (error.data) {
|
||||||
|
$window.alert("Get Nest Items Error: " + error.data.message);
|
||||||
|
} else {
|
||||||
|
$window.alert("Get Nest Items Error: unknown");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
this.updateShowHarmony = function () {
|
|
||||||
if(self.BridgeSettings.harmonyaddress == "1.1.1.1" || self.BridgeSettings.harmonyaddress == "")
|
|
||||||
this.state.showHarmony = false;
|
|
||||||
else
|
|
||||||
this.state.showHarmony = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.viewVeraDevices = function () {
|
this.viewVeraDevices = function () {
|
||||||
this.state.error = "";
|
this.state.error = "";
|
||||||
if(!this.state.showVera)
|
if(!this.state.showVera)
|
||||||
return;
|
return;
|
||||||
this.state.error = "";
|
|
||||||
return $http.get(this.state.base + "/vera/devices").then(
|
return $http.get(this.state.base + "/vera/devices").then(
|
||||||
function (response) {
|
function (response) {
|
||||||
self.state.veradevices = response.data;
|
self.state.veradevices = response.data;
|
||||||
@@ -246,9 +233,17 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.findDeviceByMapId = function(id) {
|
this.findDeviceByMapId = function(id, target, type) {
|
||||||
for(var i = 0; i < this.state.devices.length; i++) {
|
for(var i = 0; i < this.state.devices.length; i++) {
|
||||||
if(this.state.devices[i].mapId == id)
|
if(this.state.devices[i].mapId == id && this.state.devices[i].mapType == type && this.state.devices[i].targetDevice == target)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.findNestItemByMapId = function(id, type) {
|
||||||
|
for(var i = 0; i < this.state.devices.length; i++) {
|
||||||
|
if(this.state.devices[i].mapId == id && this.aContainsB(this.state.devices[i].mapType, type))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -258,6 +253,8 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
|||||||
this.state.error = "";
|
this.state.error = "";
|
||||||
if(device.httpVerb != null && device.httpVerb != "")
|
if(device.httpVerb != null && device.httpVerb != "")
|
||||||
device.deviceType = "custom";
|
device.deviceType = "custom";
|
||||||
|
if(device.targetDevice == null || device.targetDevice == "")
|
||||||
|
device.targetDevice = "Encapsulated";
|
||||||
if (device.id) {
|
if (device.id) {
|
||||||
var putUrl = this.state.base + "/" + device.id;
|
var putUrl = this.state.base + "/" + device.id;
|
||||||
return $http.put(putUrl, {
|
return $http.put(putUrl, {
|
||||||
@@ -266,6 +263,7 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
|||||||
mapId: device.mapId,
|
mapId: device.mapId,
|
||||||
mapType: device.mapType,
|
mapType: device.mapType,
|
||||||
deviceType: device.deviceType,
|
deviceType: device.deviceType,
|
||||||
|
targetDevice: device.targetDevice,
|
||||||
onUrl: device.onUrl,
|
onUrl: device.onUrl,
|
||||||
offUrl: device.offUrl,
|
offUrl: device.offUrl,
|
||||||
httpVerb: device.httpVerb,
|
httpVerb: device.httpVerb,
|
||||||
@@ -285,14 +283,13 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if(device.deviceType == null || device.deviceType == "")
|
if(device.deviceType == null || device.deviceType == "")
|
||||||
device.deviceType = "switch";
|
device.deviceType = "custom";
|
||||||
if(device.httpVerb != null && device.httpVerb != "")
|
|
||||||
device.deviceType = "custom";
|
|
||||||
return $http.post(this.state.base, {
|
return $http.post(this.state.base, {
|
||||||
name: device.name,
|
name: device.name,
|
||||||
mapId: device.mapId,
|
mapId: device.mapId,
|
||||||
mapType: device.mapType,
|
mapType: device.mapType,
|
||||||
deviceType: device.deviceType,
|
deviceType: device.deviceType,
|
||||||
|
targetDevice: device.targetDevice,
|
||||||
onUrl: device.onUrl,
|
onUrl: device.onUrl,
|
||||||
offUrl: device.offUrl,
|
offUrl: device.offUrl,
|
||||||
httpVerb: device.httpVerb,
|
httpVerb: device.httpVerb,
|
||||||
@@ -313,6 +310,58 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.backupDeviceDb = function (afilename) {
|
||||||
|
this.state.error = "";
|
||||||
|
return $http.put(this.state.base + "/backup/create", {
|
||||||
|
filename: afilename
|
||||||
|
}).then(
|
||||||
|
function (response) {
|
||||||
|
self.viewBackups();
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
if (error.data) {
|
||||||
|
self.state.error = error.data.message;
|
||||||
|
}
|
||||||
|
$window.alert("Backup Device Db Error: unknown");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.restoreBackup = function (afilename) {
|
||||||
|
this.state.error = "";
|
||||||
|
return $http.post(this.state.base + "/backup/restore", {
|
||||||
|
filename: afilename
|
||||||
|
}).then(
|
||||||
|
function (response) {
|
||||||
|
self.viewBackups();
|
||||||
|
self.viewDevices();
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
if (error.data) {
|
||||||
|
self.state.error = error.data.message;
|
||||||
|
}
|
||||||
|
$window.alert("Backup Db Restore Error: unknown");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.deleteBackup = function (afilename) {
|
||||||
|
this.state.error = "";
|
||||||
|
return $http.post(this.state.base + "/backup/delete", {
|
||||||
|
filename: afilename
|
||||||
|
}).then(
|
||||||
|
function (response) {
|
||||||
|
self.viewBackups();
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
if (error.data) {
|
||||||
|
self.state.error = error.data.message;
|
||||||
|
}
|
||||||
|
$window.alert("Backup Db Frlryr Error: unknown");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
this.deleteDevice = function (id) {
|
this.deleteDevice = function (id) {
|
||||||
this.state.error = "";
|
this.state.error = "";
|
||||||
return $http.delete(this.state.base + "/" + id).then(
|
return $http.delete(this.state.base + "/" + id).then(
|
||||||
@@ -328,9 +377,9 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.deleteDeviceByMapId = function (id) {
|
this.deleteDeviceByMapId = function (id, type) {
|
||||||
for(var i = 0; i < this.state.devices.length; i++) {
|
for(var i = 0; i < this.state.devices.length; i++) {
|
||||||
if(this.state.devices[i].mapId == id)
|
if(this.state.devices[i].mapId == id && this.aContainsB(this.state.devices[i].mapType, type))
|
||||||
return self.deleteDevice(this.state.devices[i].id);
|
return self.deleteDevice(this.state.devices[i].id);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -365,15 +414,16 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
app.controller('ViewingController', function ($scope, $location, $http, $window, bridgeService, BridgeSettings) {
|
app.controller('ViewingController', function ($scope, $location, $http, $window, bridgeService) {
|
||||||
|
|
||||||
$scope.BridgeSettings = bridgeService.BridgeSettings;
|
|
||||||
bridgeService.viewDevices();
|
bridgeService.viewDevices();
|
||||||
|
bridgeService.viewBackups();
|
||||||
$scope.bridge = bridgeService.state;
|
$scope.bridge = bridgeService.state;
|
||||||
bridgeService.updateShowVera();
|
$scope.optionalbackupname = "";
|
||||||
bridgeService.updateShowHarmony();
|
|
||||||
$scope.visible = false;
|
$scope.visible = false;
|
||||||
$scope.imgUrl = "glyphicon glyphicon-plus";
|
$scope.imgUrl = "glyphicon glyphicon-plus";
|
||||||
|
$scope.visibleBk = false;
|
||||||
|
$scope.imgBkUrl = "glyphicon glyphicon-plus";
|
||||||
$scope.predicate = '';
|
$scope.predicate = '';
|
||||||
$scope.reverse = true;
|
$scope.reverse = true;
|
||||||
$scope.order = function(predicate) {
|
$scope.order = function(predicate) {
|
||||||
@@ -390,10 +440,22 @@ app.controller('ViewingController', function ($scope, $location, $http, $window,
|
|||||||
bridgeService.state.base = url;
|
bridgeService.state.base = url;
|
||||||
bridgeService.viewDevices();
|
bridgeService.viewDevices();
|
||||||
};
|
};
|
||||||
|
$scope.goBridgeUrl = function (url) {
|
||||||
|
window.open(url, "_blank");
|
||||||
|
};
|
||||||
$scope.editDevice = function (device) {
|
$scope.editDevice = function (device) {
|
||||||
bridgeService.editDevice(device);
|
bridgeService.editDevice(device);
|
||||||
$location.path('/editdevice');
|
$location.path('/editdevice');
|
||||||
};
|
};
|
||||||
|
$scope.backupDeviceDb = function (optionalbackupname) {
|
||||||
|
bridgeService.backupDeviceDb(optionalbackupname);
|
||||||
|
};
|
||||||
|
$scope.restoreBackup = function (backupname) {
|
||||||
|
bridgeService.restoreBackup(backupname);
|
||||||
|
};
|
||||||
|
$scope.deleteBackup = function (backupname) {
|
||||||
|
bridgeService.deleteBackup(backupname);
|
||||||
|
};
|
||||||
$scope.toggle = function () {
|
$scope.toggle = function () {
|
||||||
$scope.visible = !$scope.visible;
|
$scope.visible = !$scope.visible;
|
||||||
if($scope.visible)
|
if($scope.visible)
|
||||||
@@ -401,43 +463,57 @@ app.controller('ViewingController', function ($scope, $location, $http, $window,
|
|||||||
else
|
else
|
||||||
$scope.imgUrl = "glyphicon glyphicon-plus";
|
$scope.imgUrl = "glyphicon glyphicon-plus";
|
||||||
};
|
};
|
||||||
|
$scope.toggleBk = function () {
|
||||||
|
$scope.visibleBk = !$scope.visibleBk;
|
||||||
|
if($scope.visibleBk)
|
||||||
|
$scope.imgBkUrl = "glyphicon glyphicon-minus";
|
||||||
|
else
|
||||||
|
$scope.imgBkUrl = "glyphicon glyphicon-plus";
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
app.controller('AddingController', function ($scope, $location, $http, bridgeService, BridgeSettings) {
|
app.controller('AddingController', function ($scope, $location, $http, bridgeService) {
|
||||||
|
$scope.bridge = bridgeService.state;
|
||||||
$scope.device = {id: "", name: "", deviceType: "switch", onUrl: "", offUrl: ""};
|
$scope.device = $scope.bridge.device;
|
||||||
$scope.vera = {base: "", port: "3480", id: ""};
|
$scope.device_dim_control = "";
|
||||||
$scope.vera.base = "http://" + BridgeSettings.veraaddress;
|
$scope.bulk = { devices: [] };
|
||||||
bridgeService.device = $scope.device;
|
$scope.vera = {base: "http://" + $scope.bridge.settings.veraaddress, port: "3480", id: ""};
|
||||||
bridgeService.viewVeraDevices();
|
bridgeService.viewVeraDevices();
|
||||||
bridgeService.viewVeraScenes();
|
bridgeService.viewVeraScenes();
|
||||||
bridgeService.viewHarmonyActivities();
|
bridgeService.viewHarmonyActivities();
|
||||||
bridgeService.viewHarmonyDevices();
|
bridgeService.viewHarmonyDevices();
|
||||||
$scope.bridge = bridgeService.state;
|
bridgeService.viewNestItems();
|
||||||
bridgeService.updateShowVera();
|
|
||||||
bridgeService.updateShowHarmony();
|
|
||||||
$scope.device = bridgeService.state.device;
|
|
||||||
$scope.activitiesVisible = false;
|
|
||||||
$scope.imgButtonsUrl = "glyphicon glyphicon-plus";
|
$scope.imgButtonsUrl = "glyphicon glyphicon-plus";
|
||||||
$scope.buttonsVisible = false;
|
$scope.buttonsVisible = false;
|
||||||
$scope.imgActivitiesUrl = "glyphicon glyphicon-plus";
|
|
||||||
$scope.devicesVisible = false;
|
|
||||||
$scope.imgDevicesUrl = "glyphicon glyphicon-plus";
|
|
||||||
$scope.scenesVisible = false;
|
|
||||||
$scope.imgScenesUrl = "glyphicon glyphicon-plus";
|
|
||||||
$scope.predicate = '';
|
$scope.predicate = '';
|
||||||
$scope.reverse = true;
|
$scope.reverse = true;
|
||||||
$scope.device_dim_control = "";
|
|
||||||
$scope.order = function(predicate) {
|
$scope.order = function(predicate) {
|
||||||
$scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false;
|
$scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false;
|
||||||
$scope.predicate = predicate;
|
$scope.predicate = predicate;
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.buildUrlsUsingDevice = function (dim_control) {
|
$scope.clearDevice = function () {
|
||||||
|
$scope.device.id = "";
|
||||||
|
$scope.device.mapType = null;
|
||||||
|
$scope.device.mapId = null;
|
||||||
|
$scope.device.name = "";
|
||||||
|
$scope.device.onUrl = "";
|
||||||
|
$scope.device.deviceType = "custom";
|
||||||
|
$scope.device.targetDevice = null;
|
||||||
|
$scope.device.offUrl = "";
|
||||||
|
$scope.device.httpVerb = null;
|
||||||
|
$scope.device.contentType = null;
|
||||||
|
$scope.device.contentBody = null;
|
||||||
|
$scope.device.contentBodyOff = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.buildUrlsUsingDevice = function (dim_control) {
|
||||||
if ($scope.vera.base.indexOf("http") < 0) {
|
if ($scope.vera.base.indexOf("http") < 0) {
|
||||||
$scope.vera.base = "http://" + $scope.vera.base;
|
$scope.vera.base = "http://" + $scope.vera.base;
|
||||||
}
|
}
|
||||||
$scope.device.deviceType = "switch";
|
$scope.device.deviceType = "switch";
|
||||||
|
$scope.device.targetDevice = $scope.bridge.settings.veraaddress;
|
||||||
$scope.device.mapType = "veraDevice";
|
$scope.device.mapType = "veraDevice";
|
||||||
$scope.device.mapId = $scope.vera.id;
|
$scope.device.mapId = $scope.vera.id;
|
||||||
if(dim_control.indexOf("byte") >= 0 || dim_control.indexOf("percent") >= 0 || dim_control.indexOf("math") >= 0)
|
if(dim_control.indexOf("byte") >= 0 || dim_control.indexOf("percent") >= 0 || dim_control.indexOf("math") >= 0)
|
||||||
@@ -460,6 +536,7 @@ app.controller('AddingController', function ($scope, $location, $http, bridgeSer
|
|||||||
$scope.vera.base = "http://" + $scope.vera.base;
|
$scope.vera.base = "http://" + $scope.vera.base;
|
||||||
}
|
}
|
||||||
$scope.device.deviceType = "scene";
|
$scope.device.deviceType = "scene";
|
||||||
|
$scope.device.targetDevice = $scope.bridge.settings.veraaddress;
|
||||||
$scope.device.mapType = "veraScene";
|
$scope.device.mapType = "veraScene";
|
||||||
$scope.device.mapId = $scope.vera.id;
|
$scope.device.mapId = $scope.vera.id;
|
||||||
$scope.device.onUrl = $scope.vera.base + ":" + $scope.vera.port
|
$scope.device.onUrl = $scope.vera.base + ":" + $scope.vera.port
|
||||||
@@ -476,6 +553,7 @@ app.controller('AddingController', function ($scope, $location, $http, bridgeSer
|
|||||||
}
|
}
|
||||||
$scope.device.deviceType = "switch";
|
$scope.device.deviceType = "switch";
|
||||||
$scope.device.name = veradevice.name;
|
$scope.device.name = veradevice.name;
|
||||||
|
$scope.device.targetDevice = veradevice.veraname;
|
||||||
$scope.device.mapType = "veraDevice";
|
$scope.device.mapType = "veraDevice";
|
||||||
$scope.device.mapId = veradevice.id;
|
$scope.device.mapId = veradevice.id;
|
||||||
if(dim_control.indexOf("byte") >= 0 || dim_control.indexOf("percent") >= 0 || dim_control.indexOf("math") >= 0)
|
if(dim_control.indexOf("byte") >= 0 || dim_control.indexOf("percent") >= 0 || dim_control.indexOf("math") >= 0)
|
||||||
@@ -499,7 +577,8 @@ app.controller('AddingController', function ($scope, $location, $http, bridgeSer
|
|||||||
}
|
}
|
||||||
$scope.device.deviceType = "scene";
|
$scope.device.deviceType = "scene";
|
||||||
$scope.device.name = verascene.name;
|
$scope.device.name = verascene.name;
|
||||||
$scope.devoce.mapType = "veraScene";
|
$scope.device.targetDevice = verascene.veraname;
|
||||||
|
$scope.device.mapType = "veraScene";
|
||||||
$scope.device.mapId = verascene.id;
|
$scope.device.mapId = verascene.id;
|
||||||
$scope.device.onUrl = $scope.vera.base + ":" + $scope.vera.port
|
$scope.device.onUrl = $scope.vera.base + ":" + $scope.vera.port
|
||||||
+ "/data_request?id=action&output_format=json&serviceId=urn:micasaverde-com:serviceId:HomeAutomationGateway1&action=RunScene&SceneNum="
|
+ "/data_request?id=action&output_format=json&serviceId=urn:micasaverde-com:serviceId:HomeAutomationGateway1&action=RunScene&SceneNum="
|
||||||
@@ -511,55 +590,145 @@ app.controller('AddingController', function ($scope, $location, $http, bridgeSer
|
|||||||
|
|
||||||
$scope.buildActivityUrls = function (harmonyactivity) {
|
$scope.buildActivityUrls = function (harmonyactivity) {
|
||||||
$scope.device.deviceType = "activity";
|
$scope.device.deviceType = "activity";
|
||||||
$scope.device.name = harmonyactivity.label;
|
$scope.device.targetDevice = harmonyactivity.hub;
|
||||||
|
$scope.device.name = harmonyactivity.activity.label;
|
||||||
$scope.device.mapType = "harmonyActivity";
|
$scope.device.mapType = "harmonyActivity";
|
||||||
$scope.device.mapId = harmonyactivity.id;
|
$scope.device.mapId = harmonyactivity.activity.id;
|
||||||
$scope.device.onUrl = "{\"name\":\"" + harmonyactivity.id + "\"}";
|
$scope.device.onUrl = "{\"name\":\"" + harmonyactivity.activity.id + "\"}";
|
||||||
$scope.device.offUrl = "{\"name\":\"-1\"}";
|
$scope.device.offUrl = "{\"name\":\"-1\"}";
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.buildButtonUrls = function (harmonydevice, onbutton, offbutton) {
|
$scope.buildButtonUrls = function (harmonydevice, onbutton, offbutton) {
|
||||||
$scope.device.deviceType = "button";
|
var currentOn = $scope.device.onUrl;
|
||||||
$scope.device.name = harmonydevice.label;
|
var currentOff = $scope.device.offUrl;
|
||||||
$scope.device.mapType = "harmonyButton";
|
if( $scope.device.mapType == "harmonyButton") {
|
||||||
$scope.device.mapId = harmonydevice.id + "-" + onbutton + "-" + offbutton;
|
$scope.device.onUrl = currentOn.substr(0, currentOn.indexOf("]")) + ",{\"device\":\"" + harmonydevice.device.id + "\",\"button\":\"" + onbutton + "\"}]";
|
||||||
$scope.device.onUrl = "{\"device\":\"" + harmonydevice.id + "\",\"button\":\"" + onbutton + "\"}";
|
$scope.device.offUrl = currentOff.substr(0, currentOff.indexOf("]")) + ",{\"device\":\"" + harmonydevice.device.id + "\",\"button\":\"" + offbutton + "\"}]";
|
||||||
$scope.device.offUrl = "{\"device\":\"" + harmonydevice.id + "\",\"button\":\"" + offbutton + "\"}";
|
}
|
||||||
|
else if ($scope.device.mapType == null || $scope.device.mapType == "") {
|
||||||
|
$scope.device.deviceType = "button";
|
||||||
|
$scope.device.targetDevice = harmonydevice.hub;
|
||||||
|
$scope.device.name = harmonydevice.device.label;
|
||||||
|
$scope.device.mapType = "harmonyButton";
|
||||||
|
$scope.device.mapId = harmonydevice.device.id + "-" + onbutton + "-" + offbutton;
|
||||||
|
$scope.device.onUrl = "[{\"device\":\"" + harmonydevice.device.id + "\",\"button\":\"" + onbutton + "\"}]";
|
||||||
|
$scope.device.offUrl = "[{\"device\":\"" + harmonydevice.device.id + "\",\"button\":\"" + offbutton + "\"}]";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.buildNestHomeUrls = function (nestitem) {
|
||||||
|
$scope.device.deviceType = "home";
|
||||||
|
$scope.device.name = nestitem.name;
|
||||||
|
$scope.device.targetDevice = nestitem.name;
|
||||||
|
$scope.device.mapType = "nestHomeAway";
|
||||||
|
$scope.device.mapId = nestitem.id;
|
||||||
|
$scope.device.onUrl = "{\"name\":\"" + nestitem.id + "\",\"away\":false,\"control\":\"status\"}";
|
||||||
|
$scope.device.offUrl = "{\"name\":\"" + nestitem.id + "\",\"away\":true,\"control\":\"status\"}";
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.buildNestTempUrls = function (nestitem) {
|
||||||
|
$scope.device.deviceType = "thermo";
|
||||||
|
$scope.device.name = nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Temperature";
|
||||||
|
$scope.device.targetDevice = nestitem.location;
|
||||||
|
$scope.device.mapType = "nestThermoSet";
|
||||||
|
$scope.device.mapId = nestitem.id + "-SetTemp";
|
||||||
|
$scope.device.onUrl = "{\"name\":\"" + nestitem.id + "\",\"control\":\"temp\",\"temp\":\"${intensity.percent}\"}";
|
||||||
|
$scope.device.offUrl = "{\"name\":\"" + nestitem.id + "\",\"control\":\"temp\",\"temp\":\"${intensity.percent}\"}";
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.buildNestHeatUrls = function (nestitem) {
|
||||||
|
$scope.device.deviceType = "thermo";
|
||||||
|
$scope.device.name = nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Heat";
|
||||||
|
$scope.device.targetDevice = nestitem.location;
|
||||||
|
$scope.device.mapType = "nestThermoSet";
|
||||||
|
$scope.device.mapId = nestitem.id + "-SetHeat";
|
||||||
|
$scope.device.onUrl = "{\"name\":\"" + nestitem.id + "\",\"control\":\"heat\"}";
|
||||||
|
$scope.device.offUrl = "{\"name\":\"" + nestitem.id + "\",\"control\":\"off\"}";
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.buildNestCoolUrls = function (nestitem) {
|
||||||
|
$scope.device.deviceType = "thermo";
|
||||||
|
$scope.device.name = nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Cool";
|
||||||
|
$scope.device.targetDevice = nestitem.location;
|
||||||
|
$scope.device.mapType = "nestThermoSet";
|
||||||
|
$scope.device.mapId = nestitem.id + "-SetCool";
|
||||||
|
$scope.device.onUrl = "{\"name\":\"" + nestitem.id + "\",\"control\":\"cool\"}";
|
||||||
|
$scope.device.offUrl = "{\"name\":\"" + nestitem.id + "\",\"control\":\"off\"}";
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.buildNestRangeUrls = function (nestitem) {
|
||||||
|
$scope.device.deviceType = "thermo";
|
||||||
|
$scope.device.name = nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Range";
|
||||||
|
$scope.device.targetDevice = nestitem.location;
|
||||||
|
$scope.device.mapType = "nestThermoSet";
|
||||||
|
$scope.device.mapId = nestitem.id + "-SetRange";
|
||||||
|
$scope.device.onUrl = "{\"name\":\"" + nestitem.id + "\",\"control\":\"range\"}";
|
||||||
|
$scope.device.offUrl = "{\"name\":\"" + nestitem.id + "\",\"control\":\"off\"}";
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.buildNestOffUrls = function (nestitem) {
|
||||||
|
$scope.device.deviceType = "thermo";
|
||||||
|
$scope.device.name = nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Thermostat";
|
||||||
|
$scope.device.targetDevice = nestitem.location;
|
||||||
|
$scope.device.mapType = "nestThermoSet";
|
||||||
|
$scope.device.mapId = nestitem.id + "-TurnOff";
|
||||||
|
$scope.device.onUrl = "{\"name\":\"" + nestitem.id + "\",\"control\":\"range\"}";
|
||||||
|
$scope.device.offUrl = "{\"name\":\"" + nestitem.id + "\",\"control\":\"off\"}";
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.buildNestFanUrls = function (nestitem) {
|
||||||
|
$scope.device.deviceType = "thermo";
|
||||||
|
$scope.device.name = nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Fan";
|
||||||
|
$scope.device.targetDevice = nestitem.location;
|
||||||
|
$scope.device.mapType = "nestThermoSet";
|
||||||
|
$scope.device.mapId = nestitem.id + "-SetFan";
|
||||||
|
$scope.device.onUrl = "{\"name\":\"" + nestitem.id + "\",\"control\":\"fan-on\"}";
|
||||||
|
$scope.device.offUrl = "{\"name\":\"" + nestitem.id + "\",\"control\":\"fan-auto\"}";
|
||||||
|
};
|
||||||
|
|
||||||
$scope.testUrl = function (device, type) {
|
$scope.testUrl = function (device, type) {
|
||||||
bridgeService.testUrl(device, type);
|
bridgeService.testUrl(device, type);
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.addDevice = function () {
|
$scope.addDevice = function () {
|
||||||
|
if($scope.device.name == "" && $scope.device.onUrl == "")
|
||||||
|
return;
|
||||||
bridgeService.addDevice($scope.device).then(
|
bridgeService.addDevice($scope.device).then(
|
||||||
function () {
|
function () {
|
||||||
$scope.device.id = "";
|
$scope.clearDevice();
|
||||||
$scope.device.mapType = null;
|
|
||||||
$scope.device.mapId = null;
|
|
||||||
$scope.device.name = "";
|
|
||||||
$scope.device.onUrl = "";
|
|
||||||
$scope.device.deviceType = "switch";
|
|
||||||
$scope.device.offUrl = "";
|
|
||||||
$scope.device.httpVerb = null;
|
|
||||||
$scope.device.contentType = null;
|
|
||||||
$scope.device.contentBody = null;
|
|
||||||
$scope.device.contentBodyOff = null;
|
|
||||||
$location.path('/#');
|
|
||||||
},
|
},
|
||||||
function (error) {
|
function (error) {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
$scope.toggleActivities = function () {
|
|
||||||
$scope.activitiesVisible = !$scope.activitiesVisible;
|
|
||||||
if($scope.activitiesVisible)
|
|
||||||
$scope.imgActivitiesUrl = "glyphicon glyphicon-minus";
|
|
||||||
else
|
|
||||||
$scope.imgActivitiesUrl = "glyphicon glyphicon-plus";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.bulkAddDevices = function(dim_control) {
|
||||||
|
for(var i = 0; i < $scope.bulk.devices.length; i++) {
|
||||||
|
for(var x = 0; x < bridgeService.state.veradevices.length; x++) {
|
||||||
|
if(bridgeService.state.veradevices[x].id == $scope.bulk.devices[i]) {
|
||||||
|
$scope.buildDeviceUrls(bridgeService.state.veradevices[x],dim_control);
|
||||||
|
$scope.addDevice();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$scope.bulk = { devices: [] };
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.toggleSelection = function toggleSelection(deviceId) {
|
||||||
|
var idx = $scope.bulk.devices.indexOf(deviceId);
|
||||||
|
|
||||||
|
// is currently selected
|
||||||
|
if (idx > -1) {
|
||||||
|
$scope.bulk.devices.splice(idx, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// is newly selected
|
||||||
|
else {
|
||||||
|
$scope.bulk.devices.push(deviceId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
$scope.toggleButtons = function () {
|
$scope.toggleButtons = function () {
|
||||||
$scope.buttonsVisible = !$scope.buttonsVisible;
|
$scope.buttonsVisible = !$scope.buttonsVisible;
|
||||||
if($scope.buttonsVisible)
|
if($scope.buttonsVisible)
|
||||||
@@ -567,36 +736,20 @@ app.controller('AddingController', function ($scope, $location, $http, bridgeSer
|
|||||||
else
|
else
|
||||||
$scope.imgButtonsUrl = "glyphicon glyphicon-plus";
|
$scope.imgButtonsUrl = "glyphicon glyphicon-plus";
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.toggleDevices = function () {
|
$scope.deleteDeviceByMapId = function (id, mapType) {
|
||||||
$scope.devicesVisible = !$scope.devicesVisible;
|
bridgeService.deleteDeviceByMapId(id, mapType);
|
||||||
if($scope.devicesVisible)
|
|
||||||
$scope.imgDevicesUrl = "glyphicon glyphicon-minus";
|
|
||||||
else
|
|
||||||
$scope.imgDevicesUrl = "glyphicon glyphicon-plus";
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.toggleScenes = function () {
|
|
||||||
$scope.scenesVisible = !$scope.scenesVisible;
|
|
||||||
if($scope.scenesVisible)
|
|
||||||
$scope.imgScenesUrl = "glyphicon glyphicon-minus";
|
|
||||||
else
|
|
||||||
$scope.imgScenesUrl = "glyphicon glyphicon-plus";
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.deleteDeviceByMapId = function (id) {
|
|
||||||
bridgeService.deleteDeviceByMapId(id);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
app.filter('availableId', function(bridgeService) {
|
app.filter('availableHarmonyActivityId', function(bridgeService) {
|
||||||
return function(input) {
|
return function(input) {
|
||||||
var out = [];
|
var out = [];
|
||||||
if(input == null)
|
if(input == null)
|
||||||
return out;
|
return out;
|
||||||
for (var i = 0; i < input.length; i++) {
|
for (var i = 0; i < input.length; i++) {
|
||||||
if(!bridgeService.findDeviceByMapId(input[i].id)){
|
if(!bridgeService.findDeviceByMapId(input[i].activity.id, input[i].hub, "harmonyActivity")){
|
||||||
out.push(input[i]);
|
out.push(input[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -604,13 +757,13 @@ app.filter('availableId', function(bridgeService) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
app.filter('unavailableId', function(bridgeService) {
|
app.filter('unavailableHarmonyActivityId', function(bridgeService) {
|
||||||
return function(input) {
|
return function(input) {
|
||||||
var out = [];
|
var out = [];
|
||||||
if(input == null)
|
if(input == null)
|
||||||
return out;
|
return out;
|
||||||
for (var i = 0; i < input.length; i++) {
|
for (var i = 0; i < input.length; i++) {
|
||||||
if(bridgeService.findDeviceByMapId(input[i].id)){
|
if(bridgeService.findDeviceByMapId(input[i].activity.id, input[i].hub, "harmonyActivity")){
|
||||||
out.push(input[i]);
|
out.push(input[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -618,6 +771,90 @@ app.filter('unavailableId', function(bridgeService) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.filter('availableVeraDeviceId', function(bridgeService) {
|
||||||
|
return function(input) {
|
||||||
|
var out = [];
|
||||||
|
if(input == null)
|
||||||
|
return out;
|
||||||
|
for (var i = 0; i < input.length; i++) {
|
||||||
|
if(!bridgeService.findDeviceByMapId(input[i].id, input[i].veraname, "veraDevice")){
|
||||||
|
out.push(input[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.filter('unavailableVeraDeviceId', function(bridgeService) {
|
||||||
|
return function(input) {
|
||||||
|
var out = [];
|
||||||
|
if(input == null)
|
||||||
|
return out;
|
||||||
|
for (var i = 0; i < input.length; i++) {
|
||||||
|
if(bridgeService.findDeviceByMapId(input[i].id, input[i].veraname, "veraDevice")){
|
||||||
|
out.push(input[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.filter('availableVeraSceneId', function(bridgeService) {
|
||||||
|
return function(input) {
|
||||||
|
var out = [];
|
||||||
|
if(input == null)
|
||||||
|
return out;
|
||||||
|
for (var i = 0; i < input.length; i++) {
|
||||||
|
if(!bridgeService.findDeviceByMapId(input[i].id, input[i].veraname, "veraScene")){
|
||||||
|
out.push(input[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.filter('unavailableVeraSceneId', function(bridgeService) {
|
||||||
|
return function(input) {
|
||||||
|
var out = [];
|
||||||
|
if(input == null)
|
||||||
|
return out;
|
||||||
|
for (var i = 0; i < input.length; i++) {
|
||||||
|
if(bridgeService.findDeviceByMapId(input[i].id,input[i].veraname, "veraScene")){
|
||||||
|
out.push(input[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.filter('availableNestItemId', function(bridgeService) {
|
||||||
|
return function(input) {
|
||||||
|
var out = [];
|
||||||
|
if(input == null)
|
||||||
|
return out;
|
||||||
|
for (var i = 0; i < input.length; i++) {
|
||||||
|
if(!bridgeService.findNestItemByMapId(input[i].id, "nestHomeAway")){
|
||||||
|
out.push(input[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.filter('unavailableNestItemId', function(bridgeService) {
|
||||||
|
return function(input) {
|
||||||
|
var out = [];
|
||||||
|
if(input == null)
|
||||||
|
return out;
|
||||||
|
for (var i = 0; i < input.length; i++) {
|
||||||
|
if(input[i].mapType != null && bridgeService.aContainsB(input[i].mapType, "nest")){
|
||||||
|
out.push(input[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
app.filter('configuredButtons', function() {
|
app.filter('configuredButtons', function() {
|
||||||
return function(input) {
|
return function(input) {
|
||||||
var out = [];
|
var out = [];
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
|
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
|
||||||
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>
|
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>
|
||||||
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonydevices">Harmony Devices</a></li>
|
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonydevices">Harmony Devices</a></li>
|
||||||
|
<li ng-if="bridge.showNest" role="presentation"><a href="#/nest">Nest</a></li>
|
||||||
<li role="presentation"><a href="#/editor">Manual Add</a></li>
|
<li role="presentation"><a href="#/editor">Manual Add</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -23,11 +24,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<h2 class="panel-title">Current devices</h2>
|
<h2 class="panel-title">Current devices ({{bridge.devices.length}}) </h2>
|
||||||
</div>
|
</div>
|
||||||
<table class="table table-bordered table-striped table-hover">
|
<table class="table table-bordered table-striped table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th>Row</th>
|
||||||
<th>
|
<th>
|
||||||
<a href="" ng-click="order('id')">ID</a>
|
<a href="" ng-click="order('id')">ID</a>
|
||||||
<span class="sortorder" ng-show="predicate === 'id'" ng-class="{reverse:reverse}"></span></th>
|
<span class="sortorder" ng-show="predicate === 'id'" ng-class="{reverse:reverse}"></span></th>
|
||||||
@@ -37,13 +39,18 @@
|
|||||||
<th>
|
<th>
|
||||||
<a href="" ng-click="order('deviceType')">Type</a>
|
<a href="" ng-click="order('deviceType')">Type</a>
|
||||||
<span class="sortorder" ng-show="predicate === 'deviceType'" ng-class="{reverse:reverse}"></span></th>
|
<span class="sortorder" ng-show="predicate === 'deviceType'" ng-class="{reverse:reverse}"></span></th>
|
||||||
|
<th>
|
||||||
|
<a href="" ng-click="order('targetDevice')">Target</a>
|
||||||
|
<span class="sortorder" ng-show="predicate === 'targetDevice'" ng-class="{reverse:reverse}"></span></th>
|
||||||
<th>Actions</th>
|
<th>Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tr ng-repeat="device in bridge.devices | orderBy:predicate:reverse">
|
<tr ng-repeat="device in bridge.devices | orderBy:predicate:reverse">
|
||||||
|
<td>{{$index+1}}</td>
|
||||||
<td>{{device.id}}</td>
|
<td>{{device.id}}</td>
|
||||||
<td>{{device.name}}</td>
|
<td>{{device.name}}</td>
|
||||||
<td>{{device.deviceType}}</td>
|
<td>{{device.deviceType}}</td>
|
||||||
|
<td>{{device.targetDevice}}</td>
|
||||||
<td>
|
<td>
|
||||||
<button class="btn btn-info" type="submit"
|
<button class="btn btn-info" type="submit"
|
||||||
ng-click="testUrl(device, 'on')">Test ON</button>
|
ng-click="testUrl(device, 'on')">Test ON</button>
|
||||||
@@ -60,13 +67,13 @@
|
|||||||
|
|
||||||
<div class="panel panel-default bridgeServer">
|
<div class="panel panel-default bridgeServer">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<h1 class="panel-title">Bridge settings <a ng-click="toggle()"><span class={{imgUrl}} aria-hidden="true"></a></h1>
|
<h1 class="panel-title">Bridge Settings <a ng-click="toggle()"><span class={{imgUrl}} aria-hidden="true"></a></h1>
|
||||||
</div>
|
</div>
|
||||||
<div ng-if="visible" class="animate-if" class="panel-body">
|
<div ng-if="visible" class="animate-if" class="panel-body">
|
||||||
|
|
||||||
<form class="form-horizontal">
|
<form class="form-horizontal">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-xs-12 col-sm-3 control-label" for="bridge-base">Bridge
|
<label class="col-xs-12 col-sm-2 control-label" for="bridge-base">Bridge
|
||||||
server</label>
|
server</label>
|
||||||
|
|
||||||
<div class="col-xs-8 col-sm-7">
|
<div class="col-xs-8 col-sm-7">
|
||||||
@@ -76,7 +83,7 @@
|
|||||||
<button type="submit" class="col-xs-2 col-sm-1 btn btn-primary"
|
<button type="submit" class="col-xs-2 col-sm-1 btn btn-primary"
|
||||||
ng-click="setBridgeUrl(bridge.base)">Load</button>
|
ng-click="setBridgeUrl(bridge.base)">Load</button>
|
||||||
<button type="submit" class="col-xs-2 col-sm-1 btn btn-primary"
|
<button type="submit" class="col-xs-2 col-sm-1 btn btn-primary"
|
||||||
ng-click="testUrl(bridge.base)">Go</button>
|
ng-click="goBridgeUrl(bridge.base)">Go</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<table class="table table-bordered table-striped table-hover">
|
<table class="table table-bordered table-striped table-hover">
|
||||||
@@ -88,40 +95,81 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tr>
|
<tr>
|
||||||
<td>upnp.config.address</td>
|
<td>upnp.config.address</td>
|
||||||
<td>{{BridgeSettings.upnpconfigaddress}}</td>
|
<td>{{bridge.settings.upnpconfigaddress}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>server.port</td>
|
<td>server.port</td>
|
||||||
<td>{{BridgeSettings.serverport}}</td>
|
<td>{{bridge.settings.serverport}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>upnp.devices.db</td>
|
<td>upnp.devices.db</td>
|
||||||
<td>{{BridgeSettings.upnpdevicedb}}</td>
|
<td>{{bridge.settings.upnpdevicedb}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>upnp.response.port</td>
|
<td>upnp.response.port</td>
|
||||||
<td>{{BridgeSettings.upnpresponseport}}</td>
|
<td>{{bridge.settings.upnpresponseport}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>vera.address</td>
|
<td>vera.address</td>
|
||||||
<td>{{BridgeSettings.veraaddress}}</td>
|
<td>{{bridge.settings.veraaddress}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>harmony.address</td>
|
<td>harmony.address</td>
|
||||||
<td>{{BridgeSettings.harmonyaddress}}</td>
|
<td>{{bridge.settings.harmonyaddress}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>upnp.strict</td>
|
<td>upnp.strict</td>
|
||||||
<td>{{BridgeSettings.upnpstrict}}</td>
|
<td>{{bridge.settings.upnpstrict}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>trace.upnp</td>
|
<td>trace.upnp</td>
|
||||||
<td>{{BridgeSettings.traceupnp}}</td>
|
<td>{{bridge.settings.traceupnp}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>dev.mode</td>
|
<td>dev.mode</td>
|
||||||
<td>{{BridgeSettings.devmode}}</td>
|
<td>{{bridge.settings.devmode}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>nest.configured</td>
|
||||||
|
<td>{{bridge.settings.nestconfigured}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="panel panel-default backup">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h1 class="panel-title">Bridge Device DB Backup <a ng-click="toggleBk()"><span class={{imgBkUrl}} aria-hidden="true"></a></h1>
|
||||||
|
</div>
|
||||||
|
<div ng-if="visibleBk" class="animate-if" class="panel-body">
|
||||||
|
<form class="form-horizontal">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-xs-12 col-sm-2 control-label" for="backup-name">Backup File Name</label>
|
||||||
|
|
||||||
|
<div class="col-xs-8 col-sm-7">
|
||||||
|
<input id="backup-name" class="form-control" type="text"
|
||||||
|
ng-model="optionalbackupname" placeholder="Optional">
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary"
|
||||||
|
ng-click="backupDeviceDb(optionalbackupname)">Backup Device DB</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<table class="table table-bordered table-striped table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Filename</th>
|
||||||
|
<th>Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tr ng-repeat="backup in bridge.backups">
|
||||||
|
<td>{{backup}}</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn btn-danger" type="submit"
|
||||||
|
ng-click="restoreBackup(backup)">Restore</button>
|
||||||
|
<button class="btn btn-warning" type="submit"
|
||||||
|
ng-click="deleteBackup(backup)">Delete</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
|
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
|
||||||
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>
|
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>
|
||||||
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonydevices">Harmony Devices</a></li>
|
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonydevices">Harmony Devices</a></li>
|
||||||
|
<li ng-if="bridge.showNest" role="presentation"><a href="#/nest">Nest</a></li>
|
||||||
<li role="presentation"><a href="#/editor">Manual Add</a></li>
|
<li role="presentation"><a href="#/editor">Manual Add</a></li>
|
||||||
<li role="presentation" class="active"><a href="#/editdevice">Edit Device</a></li>
|
<li role="presentation" class="active"><a href="#/editdevice">Edit Device</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -12,9 +13,11 @@
|
|||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<h2 class="panel-title">Edit a device</h2>
|
<h2 class="panel-title">Edit a device</h2>
|
||||||
</div>
|
</div>
|
||||||
|
<p class="text-muted">This screen allows the modification of many fields the bridge uses. Please use care when
|
||||||
|
updating these fields as you may break the settings used by the bridge to call a specific end point device.</p>
|
||||||
<ul class="list-group">
|
<ul class="list-group">
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<form class="form-horizontal" ng-submit="addDevice()">
|
<form class="form-horizontal">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-xs-12 col-sm-2 control-label" for="device-name">Name
|
<label class="col-xs-12 col-sm-2 control-label" for="device-name">Name
|
||||||
</label>
|
</label>
|
||||||
@@ -23,8 +26,19 @@
|
|||||||
<input type="text" class="form-control" id="device-name"
|
<input type="text" class="form-control" id="device-name"
|
||||||
ng-model="device.name" placeholder="Device Name">
|
ng-model="device.name" placeholder="Device Name">
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="col-xs-4 col-sm-2 btn btn-primary">
|
<button type="submit" class="col-xs-4 col-sm-2 btn btn-primary" ng-click="addDevice()">
|
||||||
Update Device</button>
|
Update Bridge Device</button>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-xs-12 col-sm-2 control-label" for="device-target">Target
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="col-xs-8 col-sm-7">
|
||||||
|
<input type="text" class="form-control" id="device-target"
|
||||||
|
ng-model="device.targetDevice" placeholder="default">
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-danger" ng-click="clearDevice()">
|
||||||
|
Clear Device</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@@ -38,6 +52,8 @@
|
|||||||
<option value="veraScene">Vera Scene</option>
|
<option value="veraScene">Vera Scene</option>
|
||||||
<option value="harmonyActivity">Harmony Activity</option>
|
<option value="harmonyActivity">Harmony Activity</option>
|
||||||
<option value="harmonyButton">Harmony Button</option>
|
<option value="harmonyButton">Harmony Button</option>
|
||||||
|
<option value="nestHomeAway">Nest Home Status</option>
|
||||||
|
<option value="nestThermoSet">Nest Thermostat</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
|
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
|
||||||
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>
|
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>
|
||||||
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonydevices">Harmony Devices</a></li>
|
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonydevices">Harmony Devices</a></li>
|
||||||
|
<li ng-if="bridge.showNest" role="presentation"><a href="#/nest">Nest</a></li>
|
||||||
<li role="presentation" class="active"><a href="#/editor">Manual Add</a></li>
|
<li role="presentation" class="active"><a href="#/editor">Manual Add</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -73,9 +74,11 @@
|
|||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<h2 class="panel-title">Add a new device</h2>
|
<h2 class="panel-title">Add a new device</h2>
|
||||||
</div>
|
</div>
|
||||||
|
<p class="text-muted">This area allows you to create any http or udp call to an endpoint. You can use the default GET or select
|
||||||
|
the http verb type below and configure a payload for either on or off methods. Currently, https is not supported.</p>
|
||||||
<ul class="list-group">
|
<ul class="list-group">
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<form class="form-horizontal" ng-submit="addDevice()">
|
<form class="form-horizontal">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<label class="col-xs-12 col-sm-2 control-label" for="device-name">Name
|
<label class="col-xs-12 col-sm-2 control-label" for="device-name">Name
|
||||||
@@ -85,8 +88,8 @@
|
|||||||
<input type="text" class="form-control" id="device-name"
|
<input type="text" class="form-control" id="device-name"
|
||||||
ng-model="device.name" placeholder="Device Name">
|
ng-model="device.name" placeholder="Device Name">
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="col-xs-4 col-sm-2 btn btn-primary">
|
<button type="submit" class="col-xs-4 col-sm-2 btn btn-primary" ng-click="addDevice()">
|
||||||
Add Device</button>
|
Add Bridge Device</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@@ -98,6 +101,8 @@
|
|||||||
<textarea rows="3" class="form-control" id="device-on-url"
|
<textarea rows="3" class="form-control" id="device-on-url"
|
||||||
ng-model="device.onUrl" placeholder="URL to turn device on"></textarea>
|
ng-model="device.onUrl" placeholder="URL to turn device on"></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
<button class="btn btn-danger" ng-click="clearDevice()">
|
||||||
|
Clear Device</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
|
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
|
||||||
<li role="presentation" class="active"><a href="#/harmonyactivities">Harmony Activities</a></li>
|
<li role="presentation" class="active"><a href="#/harmonyactivities">Harmony Activities</a></li>
|
||||||
<li role="presentation"><a href="#/harmonydevices">Harmony Devices</a></li>
|
<li role="presentation"><a href="#/harmonydevices">Harmony Devices</a></li>
|
||||||
|
<li ng-if="bridge.showNest" role="presentation"><a href="#/nest">Nest</a></li>
|
||||||
<li role="presentation"><a href="#/editor">Manual Add</a></li>
|
<li role="presentation"><a href="#/editor">Manual Add</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -13,12 +14,14 @@
|
|||||||
</div>
|
</div>
|
||||||
<ul class="list-group">
|
<ul class="list-group">
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<p class="text-muted">You can select a Harmony Activity and generate
|
<p class="text-muted">For any Harmony Activity, use the action buttons to generate the device addition information below automatically.
|
||||||
the add activity box selections automatically.</p>
|
Then you can modify the name to anything you want that will be the keyword for Alexa. Click the 'Add Bridge Device' to finish that selection setup.
|
||||||
|
The 'Already Configured Activities' list below will show what is already setup for your Harmony Hubs.</p>
|
||||||
|
|
||||||
<table class="table table-bordered table-striped table-hover">
|
<table class="table table-bordered table-striped table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th>Row</th>
|
||||||
<th>
|
<th>
|
||||||
<a href="" ng-click="order('label')">Name</a>
|
<a href="" ng-click="order('label')">Name</a>
|
||||||
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
|
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
|
||||||
@@ -26,13 +29,19 @@
|
|||||||
<th>
|
<th>
|
||||||
<a href="" ng-click="order('id')">Id</a>
|
<a href="" ng-click="order('id')">Id</a>
|
||||||
<span class="sortorder" ng-show="predicate === 'id'" ng-class="{reverse:reverse}"></span>
|
<span class="sortorder" ng-show="predicate === 'id'" ng-class="{reverse:reverse}"></span>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<a href="" ng-click="order('hub')">Hub</a>
|
||||||
|
<span class="sortorder" ng-show="predicate === 'hub'" ng-class="{reverse:reverse}"></span>
|
||||||
</th>
|
</th>
|
||||||
<th>Actions</th>
|
<th>Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tr ng-repeat="harmonyactivity in bridge.harmonyactivities | availableId | orderBy:predicate:reverse">
|
<tr ng-repeat="harmonyactivity in bridge.harmonyactivities | availableHarmonyActivityId | orderBy:predicate:reverse">
|
||||||
<td>{{harmonyactivity.label}}</td>
|
<td>{{$index+1}}</td>
|
||||||
<td>{{harmonyactivity.id}}</td>
|
<td>{{harmonyactivity.activity.label}}</td>
|
||||||
|
<td>{{harmonyactivity.activity.id}}</td>
|
||||||
|
<td>{{harmonyactivity.hub}}</td>
|
||||||
<td>
|
<td>
|
||||||
<button class="btn btn-success" type="submit"
|
<button class="btn btn-success" type="submit"
|
||||||
ng-click="buildActivityUrls(harmonyactivity)">Generate
|
ng-click="buildActivityUrls(harmonyactivity)">Generate
|
||||||
@@ -43,13 +52,14 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<h2 class="panel-title">Already Configured Activities <a ng-click="toggleActivities()"><span class={{imgActivitiesUrl}} aria-hidden="true"></a></h2>
|
<h2 class="panel-title">Already Configured Activities <a ng-click="toggleButtons()"><span class={{imgButtonsUrl}} aria-hidden="true"></span></a></h2>
|
||||||
</div>
|
</div>
|
||||||
<ul ng-if="activitiesVisible" class="list-group">
|
<ul ng-if="buttonsVisible" class="list-group">
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<table class="table table-bordered table-striped table-hover">
|
<table class="table table-bordered table-striped table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th>Row</th>
|
||||||
<th>
|
<th>
|
||||||
<a href="" ng-click="order('label')">Name</a>
|
<a href="" ng-click="order('label')">Name</a>
|
||||||
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
|
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
|
||||||
@@ -57,15 +67,21 @@
|
|||||||
<th>
|
<th>
|
||||||
<a href="" ng-click="order('id')">Id</a>
|
<a href="" ng-click="order('id')">Id</a>
|
||||||
<span class="sortorder" ng-show="predicate === 'id'" ng-class="{reverse:reverse}"></span>
|
<span class="sortorder" ng-show="predicate === 'id'" ng-class="{reverse:reverse}"></span>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<a href="" ng-click="order('hub')">Hub</a>
|
||||||
|
<span class="sortorder" ng-show="predicate === 'hub'" ng-class="{reverse:reverse}"></span>
|
||||||
</th>
|
</th>
|
||||||
<th>Actions</th>
|
<th>Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tr ng-repeat="harmonyactivity in bridge.harmonyactivities | unavailableId | orderBy:predicate:reverse">
|
<tr ng-repeat="harmonyactivity in bridge.harmonyactivities | unavailableHarmonyActivityId | orderBy:predicate:reverse">
|
||||||
<td>{{harmonyactivity.label}}</td>
|
<td>{{$index+1}}</td>
|
||||||
<td>{{harmonyactivity.id}}</td>
|
<td>{{harmonyactivity.activity.label}}</td>
|
||||||
|
<td>{{harmonyactivity.activity.id}}</td>
|
||||||
|
<td>{{harmonyactivity.hub}}</td>
|
||||||
<td><button class="btn btn-danger" type="submit"
|
<td><button class="btn btn-danger" type="submit"
|
||||||
ng-click="deleteDeviceByMapId(harmonyactivity.id)">Delete</button></td>
|
ng-click="deleteDeviceByMapId(harmonyactivity.activity.id, 'harmonyActivity')">Delete</button></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</li>
|
</li>
|
||||||
@@ -73,11 +89,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="panel panel-default bridgeServer" ng-if="!bridge.error">
|
<div class="panel panel-default bridgeServer" ng-if="!bridge.error">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<h2 class="panel-title">Add a Harmony Activity</h2>
|
<h2 class="panel-title">Add a Bridge Device for a Harmony Activity</h2>
|
||||||
</div>
|
</div>
|
||||||
<ul class="list-group">
|
<ul class="list-group">
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<form class="form-horizontal" ng-submit="addDevice()">
|
<form class="form-horizontal">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-xs-12 col-sm-2 control-label" for="device-name">Name
|
<label class="col-xs-12 col-sm-2 control-label" for="device-name">Name
|
||||||
</label>
|
</label>
|
||||||
@@ -86,8 +102,8 @@
|
|||||||
<input type="text" class="form-control" id="device-name"
|
<input type="text" class="form-control" id="device-name"
|
||||||
ng-model="device.name" placeholder="Device Name">
|
ng-model="device.name" placeholder="Device Name">
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="col-xs-4 col-sm-2 btn btn-primary">
|
<button type="submit" class="col-xs-4 col-sm-2 btn btn-primary" ng-click="addDevice()">
|
||||||
Add Activity</button>
|
Add Bridge Device</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@@ -98,6 +114,8 @@
|
|||||||
<textarea rows="3" class="form-control" id="device-on-url"
|
<textarea rows="3" class="form-control" id="device-on-url"
|
||||||
ng-model="device.onUrl" placeholder="URL to turn device on"></textarea>
|
ng-model="device.onUrl" placeholder="URL to turn device on"></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
<button class="btn btn-danger" ng-click="clearDevice()">
|
||||||
|
Clear Device</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
|
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
|
||||||
<li role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>
|
<li role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>
|
||||||
<li role="presentation" class="active"><a href="#/harmonydevices">Harmony Devices</a></li>
|
<li role="presentation" class="active"><a href="#/harmonydevices">Harmony Devices</a></li>
|
||||||
|
<li ng-if="bridge.showNest" role="presentation"><a href="#/nest">Nest</a></li>
|
||||||
<li role="presentation"><a href="#/editor">Manual Add</a></li>
|
<li role="presentation"><a href="#/editor">Manual Add</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -13,12 +14,15 @@
|
|||||||
</div>
|
</div>
|
||||||
<ul class="list-group">
|
<ul class="list-group">
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<p class="text-muted">You can select a Harmony Device and Button and generate
|
<p class="text-muted">For any Harmony Device and Buttons, use the build button to generate the configuration for this bridge device. You can add button presses by
|
||||||
the add button box selections automatically.</p>
|
selecting yoru devic and buttons and then selecting the Build Button. This will allow multiple button presses to be built for a given device.
|
||||||
|
Then you can modify the name to anything you want that will be the keyword for Alexa. Click the 'Add Bridge Device' to finish that selection setup.
|
||||||
|
The 'Already Configured Harmony Buttons' list below will show what is already setup for your Harmony Hubs.</p>
|
||||||
|
|
||||||
<table class="table table-bordered table-striped table-hover">
|
<table class="table table-bordered table-striped table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th>Row</th>
|
||||||
<th>
|
<th>
|
||||||
<a href="" ng-click="order('label')">Name</a>
|
<a href="" ng-click="order('label')">Name</a>
|
||||||
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
|
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
|
||||||
@@ -26,6 +30,10 @@
|
|||||||
<th>
|
<th>
|
||||||
<a href="" ng-click="order('id')">Id</a>
|
<a href="" ng-click="order('id')">Id</a>
|
||||||
<span class="sortorder" ng-show="predicate === 'id'" ng-class="{reverse:reverse}"></span>
|
<span class="sortorder" ng-show="predicate === 'id'" ng-class="{reverse:reverse}"></span>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<a href="" ng-click="order('hub')">Hub</a>
|
||||||
|
<span class="sortorder" ng-show="predicate === 'hub'" ng-class="{reverse:reverse}"></span>
|
||||||
</th>
|
</th>
|
||||||
<th>On Button</th>
|
<th>On Button</th>
|
||||||
<th>Off Button</th>
|
<th>Off Button</th>
|
||||||
@@ -33,26 +41,28 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tr ng-repeat="harmonydevice in bridge.harmonydevices | orderBy:predicate:reverse">
|
<tr ng-repeat="harmonydevice in bridge.harmonydevices | orderBy:predicate:reverse">
|
||||||
<td>{{harmonydevice.label}}</td>
|
<td>{{$index+1}}</td>
|
||||||
<td>{{harmonydevice.id}}</td>
|
<td>{{harmonydevice.device.label}}</td>
|
||||||
|
<td>{{harmonydevice.device.id}}</td>
|
||||||
|
<td>{{harmonydevice.hub}}</td>
|
||||||
<td>
|
<td>
|
||||||
<select name="device-ctrlon" id="device-ctrlon" ng-model="devicectrlon">
|
<select name="device-ctrlon" id="device-ctrlon" ng-model="devicectrlon">
|
||||||
<optgroup ng-repeat="ctrlon in harmonydevice.controlGroup" label="{{ctrlon.name}}">
|
<optgroup ng-repeat="ctrlon in harmonydevice.device.controlGroup" label="{{ctrlon.name}}">
|
||||||
<option ng-repeat="funcon in ctrlon.function">{{funcon.name}}</option>
|
<option ng-repeat="funcon in ctrlon.function" value="{{funcon.label}}">{{funcon.name}}</option>
|
||||||
</optgroup >
|
</optgroup >
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select name="device-ctrloff" id="device-ctrloff" ng-model="devicectrloff">
|
<select name="device-ctrloff" id="device-ctrloff" ng-model="devicectrloff">
|
||||||
<optgroup ng-repeat="ctrloff in harmonydevice.controlGroup" label="{{ctrloff.name}}">
|
<optgroup ng-repeat="ctrloff in harmonydevice.device.controlGroup" label="{{ctrloff.name}}">
|
||||||
<option ng-repeat="funcoff in ctrloff.function">{{funcoff.name}}</option>
|
<option ng-repeat="funcoff in ctrloff.function" value="{{funcoff.label}}">{{funcoff.name}}</option>
|
||||||
</optgroup >
|
</optgroup >
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<button class="btn btn-success" type="submit"
|
<button class="btn btn-success" type="submit"
|
||||||
ng-click="buildButtonUrls(harmonydevice, devicectrlon, devicectrloff)">Generate
|
ng-click="buildButtonUrls(harmonydevice, devicectrlon, devicectrloff)">Build
|
||||||
Button URLs</button>
|
A Button</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
@@ -66,6 +76,7 @@
|
|||||||
<table class="table table-bordered table-striped table-hover">
|
<table class="table table-bordered table-striped table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th>Row</th>
|
||||||
<th>
|
<th>
|
||||||
<a href="" ng-click="order('name')">Name</a>
|
<a href="" ng-click="order('name')">Name</a>
|
||||||
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
|
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
|
||||||
@@ -73,6 +84,10 @@
|
|||||||
<th>
|
<th>
|
||||||
<a href="" ng-click="order('id')">Device Id</a>
|
<a href="" ng-click="order('id')">Device Id</a>
|
||||||
<span class="sortorder" ng-show="predicate === 'id'" ng-class="{reverse:reverse}"></span>
|
<span class="sortorder" ng-show="predicate === 'id'" ng-class="{reverse:reverse}"></span>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<a href="" ng-click="order('targetDevice')">Hub</a>
|
||||||
|
<span class="sortorder" ng-show="predicate === 'targetDevice'" ng-class="{reverse:reverse}"></span>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<a href="" ng-click="order('mapId')">Harmony Device-Button On-Button Off</a>
|
<a href="" ng-click="order('mapId')">Harmony Device-Button On-Button Off</a>
|
||||||
@@ -82,12 +97,14 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tr ng-repeat="device in bridge.devices | configuredButtons | orderBy:predicate:reverse">
|
<tr ng-repeat="device in bridge.devices | configuredButtons | orderBy:predicate:reverse">
|
||||||
|
<td>{{$index+1}}</td>
|
||||||
<td>{{device.name}}</td>
|
<td>{{device.name}}</td>
|
||||||
<td>{{device.id}}</td>
|
<td>{{device.id}}</td>
|
||||||
|
<td>{{device.targetDevice}}</td>
|
||||||
<td>{{device.mapId}}</td>
|
<td>{{device.mapId}}</td>
|
||||||
<td>
|
<td>
|
||||||
<button class="btn btn-danger" type="submit"
|
<button class="btn btn-danger" type="submit"
|
||||||
ng-click="deleteDeviceByMapId(device.mapId)">Delete</button>
|
ng-click="deleteDeviceByMapId(device.mapId, device.mapType)">Delete</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
@@ -96,11 +113,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="panel panel-default bridgeServer" ng-if="!bridge.error">
|
<div class="panel panel-default bridgeServer" ng-if="!bridge.error">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<h2 class="panel-title">Add a Harmony Button</h2>
|
<h2 class="panel-title">Add a Bridge Device for Harmony Buttons</h2>
|
||||||
</div>
|
</div>
|
||||||
<ul class="list-group">
|
<ul class="list-group">
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<form class="form-horizontal" ng-submit="addDevice()">
|
<form class="form-horizontal">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-xs-12 col-sm-2 control-label" for="device-name">Name
|
<label class="col-xs-12 col-sm-2 control-label" for="device-name">Name
|
||||||
</label>
|
</label>
|
||||||
@@ -109,8 +126,8 @@
|
|||||||
<input type="text" class="form-control" id="device-name"
|
<input type="text" class="form-control" id="device-name"
|
||||||
ng-model="device.name" placeholder="Device Name">
|
ng-model="device.name" placeholder="Device Name">
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="col-xs-4 col-sm-2 btn btn-primary">
|
<button type="submit" class="col-xs-4 col-sm-2 btn btn-primary" ng-click="addDevice()">
|
||||||
Add Button</button>
|
Add Bridge Device</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@@ -121,6 +138,8 @@
|
|||||||
<textarea rows="3" class="form-control" id="device-on-url"
|
<textarea rows="3" class="form-control" id="device-on-url"
|
||||||
ng-model="device.onUrl" placeholder="URL to turn device on"></textarea>
|
ng-model="device.onUrl" placeholder="URL to turn device on"></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
<button class="btn btn-danger" ng-click="clearDevice()">
|
||||||
|
Clear Device</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
|||||||
156
src/main/resources/public/views/nestactions.html
Normal file
156
src/main/resources/public/views/nestactions.html
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
<ul class="nav nav-pills" role="tablist">
|
||||||
|
<li role="presentation"><a href="#">Configuration</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 ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>
|
||||||
|
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonydevices">Harmony Devices</a></li>
|
||||||
|
<li role="presentation" class="active"><a href="#/nest">Nest</a></li>
|
||||||
|
<li role="presentation"><a href="#/editor">Manual Add</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="panel panel-default bridgeServer" ng-if="!bridge.error">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h2 class="panel-title">Nest Items List</h2>
|
||||||
|
</div>
|
||||||
|
<ul class="list-group">
|
||||||
|
<li class="list-group-item">
|
||||||
|
<p class="text-muted">For any Nest Item, use the action buttons to generate the device addition information below automatically.
|
||||||
|
Then you can modify the name to anything you want that will be the keyword for Alexa. Click the 'Add Bridge Device' to finish that selection setup.
|
||||||
|
The 'Already Configured Nest Items' list below will show what is already setup for your Nest.</p>
|
||||||
|
|
||||||
|
<table class="table table-bordered table-striped table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Row</th>
|
||||||
|
<th>
|
||||||
|
<a href="" ng-click="order('name')">Name</a>
|
||||||
|
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<a href="" ng-click="order('type')">Type</a>
|
||||||
|
<span class="sortorder" ng-show="predicate === 'type'" ng-class="{reverse:reverse}"></span>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<a href="" ng-click="order('location')">Location</a>
|
||||||
|
<span class="sortorder" ng-show="predicate === 'location'" ng-class="{reverse:reverse}"></span>
|
||||||
|
</th>
|
||||||
|
<th>Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tr ng-repeat="nestitem in bridge.nestitems | availableNestItemId | orderBy:predicate:reverse">
|
||||||
|
<td>{{$index+1}}</td>
|
||||||
|
<td>{{nestitem.name}}</td>
|
||||||
|
<td>{{nestitem.type}}</td>
|
||||||
|
<td>{{nestitem.location}}</td>
|
||||||
|
<td>
|
||||||
|
<ul class="list-group">
|
||||||
|
<li ng-if="nestitem.type ==='Home' " class="list-group-item">
|
||||||
|
<button class="btn btn-success" type="submit"
|
||||||
|
ng-click="buildNestHomeUrls(nestitem)">Home/Away</button>
|
||||||
|
</li>
|
||||||
|
<li ng-if="nestitem.type ==='Thermostat' " class="list-group-item">
|
||||||
|
<p>
|
||||||
|
<button class="btn btn-success" type="submit"
|
||||||
|
ng-click="buildNestTempUrls(nestitem)">Temp</button>
|
||||||
|
<button class="btn btn-success" type="submit"
|
||||||
|
ng-click="buildNestHeatUrls(nestitem)">Heat</button>
|
||||||
|
<button class="btn btn-success" type="submit"
|
||||||
|
ng-click="buildNestCoolUrls(nestitem)">Cool</button>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<button class="btn btn-success" type="submit"
|
||||||
|
ng-click="buildNestRangeUrls(nestitem)">Range</button>
|
||||||
|
<button class="btn btn-success" type="submit"
|
||||||
|
ng-click="buildNestOffUrls(nestitem)">Off</button>
|
||||||
|
<button class="btn btn-success" type="submit"
|
||||||
|
ng-click="buildNestFanUrls(nestitem)">Fan</button>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h2 class="panel-title">Already Configured Nest Items <a ng-click="toggleButtons()"><span class={{imgButtonsUrl}} aria-hidden="true"></span></a></h2>
|
||||||
|
</div>
|
||||||
|
<ul ng-if="buttonsVisible" class="list-group">
|
||||||
|
<li class="list-group-item">
|
||||||
|
<table class="table table-bordered table-striped table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Row</th>
|
||||||
|
<th>
|
||||||
|
<a href="" ng-click="order('name')">Name</a>
|
||||||
|
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<a href="" ng-click="order('id')">Id</a>
|
||||||
|
<span class="sortorder" ng-show="predicate === 'id'" ng-class="{reverse:reverse}"></span>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<a href="" ng-click="order('mapId')">mapId</a>
|
||||||
|
<span class="sortorder" ng-show="predicate === 'mapId'" ng-class="{reverse:reverse}"></span>
|
||||||
|
</th>
|
||||||
|
<th>Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tr ng-repeat="device in bridge.devices | unavailableNestItemId | orderBy:predicate:reverse">
|
||||||
|
<td>{{$index+1}}</td>
|
||||||
|
<td>{{device.name}}</td>
|
||||||
|
<td>{{device.id}}</td>
|
||||||
|
<td>{{device.mapId}}</td>
|
||||||
|
<td><button class="btn btn-danger" type="submit"
|
||||||
|
ng-click="deleteDeviceByMapId(device.mapId, 'nest')">Delete</button></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="panel panel-default bridgeServer" ng-if="!bridge.error">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h2 class="panel-title">Add a Bridge Device for a Nest Item</h2>
|
||||||
|
</div>
|
||||||
|
<ul class="list-group">
|
||||||
|
<li class="list-group-item">
|
||||||
|
<form class="form-horizontal">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-xs-12 col-sm-2 control-label" for="device-name">Name
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="col-xs-8 col-sm-7">
|
||||||
|
<input type="text" class="form-control" id="device-name"
|
||||||
|
ng-model="device.name" placeholder="Device Name">
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="col-xs-4 col-sm-2 btn btn-primary" ng-click="addDevice()">
|
||||||
|
Add Bridge Device</button>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="row">
|
||||||
|
<label class="col-xs-12 col-sm-2 control-label" for="device-on-url">On
|
||||||
|
URL </label>
|
||||||
|
|
||||||
|
<div class="col-xs-8 col-sm-7">
|
||||||
|
<textarea rows="3" class="form-control" id="device-on-url"
|
||||||
|
ng-model="device.onUrl" placeholder="URL to turn device on"></textarea>
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-danger" ng-click="clearDevice()">
|
||||||
|
Clear Device</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="row">
|
||||||
|
<label class="col-xs-12 col-sm-2 control-label"
|
||||||
|
for="device-off-url">Off URL </label>
|
||||||
|
|
||||||
|
<div class="col-xs-8 col-sm-7">
|
||||||
|
<textarea rows="3" class="form-control" id="device-off-url"
|
||||||
|
ng-model="device.offUrl" placeholder="URL to turn device off"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
@@ -4,17 +4,20 @@
|
|||||||
<li role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
|
<li role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
|
||||||
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>
|
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>
|
||||||
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonydevices">Harmony Devices</a></li>
|
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonydevices">Harmony Devices</a></li>
|
||||||
|
<li ng-if="bridge.showNest" role="presentation"><a href="#/nest">Nest</a></li>
|
||||||
<li role="presentation"><a href="#/editor">Manual Add</a></li>
|
<li role="presentation"><a href="#/editor">Manual Add</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="panel panel-default bridgeServer" ng-if="!bridge.error">
|
<div class="panel panel-default bridgeServer" ng-if="!bridge.error">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<h2 class="panel-title">Vera Device List</h2>
|
<h2 class="panel-title">Vera Device List ({{bridge.veradevices.length}})</h2>
|
||||||
</div>
|
</div>
|
||||||
<ul class="list-group">
|
<ul class="list-group">
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<p class="text-muted">You can select a Vera device and generate
|
<p class="text-muted">For any Vera Device, use the action buttons to generate the device addition information below automatically.
|
||||||
the add device box selections automatically.</p><p>Also, use this select menu for which type of dim
|
Then you can modify the name to anything you want that will be the keyword for Alexa. Click the 'Add Bridge Device' to finish that selection setup.
|
||||||
|
The 'Already Configured Vera Devices' list below will show what is already setup for your Vera.</p>
|
||||||
|
<p>Also, use this select menu for which type of dim
|
||||||
control you would like to be generated:
|
control you would like to be generated:
|
||||||
<select name="device-dim-control" id="device-dim-control" ng-model="device_dim_control">
|
<select name="device-dim-control" id="device-dim-control" ng-model="device_dim_control">
|
||||||
<option value="">none</option>
|
<option value="">none</option>
|
||||||
@@ -23,9 +26,13 @@
|
|||||||
<option value="${intensity.math(X*1)}">Custom Math</option>
|
<option value="${intensity.math(X*1)}">Custom Math</option>
|
||||||
</select>
|
</select>
|
||||||
</p>
|
</p>
|
||||||
|
<p>Use the check boxes by the names to use the bulk addition feature. Select your items and dim control type if wanted, then click bulk add below.
|
||||||
|
Your items will be added with on and off or dim and off if selected with the name of the device from the Vera.
|
||||||
|
</p>
|
||||||
<table class="table table-bordered table-striped table-hover">
|
<table class="table table-bordered table-striped table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th>Row</th>
|
||||||
<th>
|
<th>
|
||||||
<a href="" ng-click="order('name')">Name</a>
|
<a href="" ng-click="order('name')">Name</a>
|
||||||
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
|
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
|
||||||
@@ -41,15 +48,21 @@
|
|||||||
<th>
|
<th>
|
||||||
<a href="" ng-click="order('room')">Room</a>
|
<a href="" ng-click="order('room')">Room</a>
|
||||||
<span class="sortorder" ng-show="predicate === 'room'" ng-class="{reverse:reverse}"></span>
|
<span class="sortorder" ng-show="predicate === 'room'" ng-class="{reverse:reverse}"></span>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<a href="" ng-click="order('vera')">Vera</a>
|
||||||
|
<span class="sortorder" ng-show="predicate === 'vera'" ng-class="{reverse:reverse}"></span>
|
||||||
</th>
|
</th>
|
||||||
<th>Actions</th>
|
<th>Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tr ng-repeat="veradevice in bridge.veradevices | availableId | orderBy:predicate:reverse">
|
<tr ng-repeat="veradevice in bridge.veradevices | availableVeraDeviceId | orderBy:predicate:reverse">
|
||||||
<td>{{veradevice.name}}</td>
|
<td>{{$index+1}}</td>
|
||||||
|
<td><input type="checkbox" name="bulk.devices[]" value="{{veradevice.id}}" ng-checked="bulk.devices.indexOf(veradevice.id) > -1" ng-click="toggleSelection(veradevice.id)"> {{veradevice.name}}</td>
|
||||||
<td>{{veradevice.id}}</td>
|
<td>{{veradevice.id}}</td>
|
||||||
<td>{{veradevice.category}}</td>
|
<td>{{veradevice.category}}</td>
|
||||||
<td>{{veradevice.room}}</td>
|
<td>{{veradevice.room}}</td>
|
||||||
|
<td>{{veradevice.veraname}}</td>
|
||||||
<td>
|
<td>
|
||||||
<button class="btn btn-success" type="submit"
|
<button class="btn btn-success" type="submit"
|
||||||
ng-click="buildDeviceUrls(veradevice, device_dim_control)">Generate
|
ng-click="buildDeviceUrls(veradevice, device_dim_control)">Generate
|
||||||
@@ -57,16 +70,21 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
<p>
|
||||||
|
<button class="btn btn-success" type="submit"
|
||||||
|
ng-click="bulkAddDevices(device_dim_control)">Bulk Add ({{bulk.devices.length}})</button>
|
||||||
|
</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<h2 class="panel-title">Already Configured Vera Devices <a ng-click="toggleDevices()"><span class={{imgDevicesUrl}} aria-hidden="true"></a></h2>
|
<h2 class="panel-title">Already Configured Vera Devices <a ng-click="toggleButtons()"><span class={{imgButtonsUrl}} aria-hidden="true"></span></a></a></h2>
|
||||||
</div>
|
</div>
|
||||||
<ul ng-if="devicesVisible" class="list-group">
|
<ul ng-if="buttonsVisible" class="list-group">
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<table class="table table-bordered table-striped table-hover">
|
<table class="table table-bordered table-striped table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th>Row</th>
|
||||||
<th>
|
<th>
|
||||||
<a href="" ng-click="order('name')">Name</a>
|
<a href="" ng-click="order('name')">Name</a>
|
||||||
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
|
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
|
||||||
@@ -82,18 +100,24 @@
|
|||||||
<th>
|
<th>
|
||||||
<a href="" ng-click="order('room')">Room</a>
|
<a href="" ng-click="order('room')">Room</a>
|
||||||
<span class="sortorder" ng-show="predicate === 'room'" ng-class="{reverse:reverse}"></span>
|
<span class="sortorder" ng-show="predicate === 'room'" ng-class="{reverse:reverse}"></span>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<a href="" ng-click="order('vera')">Vera</a>
|
||||||
|
<span class="sortorder" ng-show="predicate === 'vera'" ng-class="{reverse:reverse}"></span>
|
||||||
</th>
|
</th>
|
||||||
<th>Actions</th>
|
<th>Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tr ng-repeat="veradevice in bridge.veradevices | unavailableId | orderBy:predicate:reverse">
|
<tr ng-repeat="veradevice in bridge.veradevices | unavailableVeraDeviceId | orderBy:predicate:reverse">
|
||||||
|
<td>{{$index+1}}</td>
|
||||||
<td>{{veradevice.name}}</td>
|
<td>{{veradevice.name}}</td>
|
||||||
<td>{{veradevice.id}}</td>
|
<td>{{veradevice.id}}</td>
|
||||||
<td>{{veradevice.category}}</td>
|
<td>{{veradevice.category}}</td>
|
||||||
<td>{{veradevice.room}}</td>
|
<td>{{veradevice.room}}</td>
|
||||||
|
<td>{{veradevice.veraname}}</td>
|
||||||
<td>
|
<td>
|
||||||
<button class="btn btn-danger" type="submit"
|
<button class="btn btn-danger" type="submit"
|
||||||
ng-click="deleteDeviceByMapId(harmonyactivity.id)">Delete</button>
|
ng-click="deleteDeviceByMapId(veradevice.id, 'veraDevice')">Delete</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
@@ -102,11 +126,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="panel panel-default bridgeServer" ng-if="!bridge.error">
|
<div class="panel panel-default bridgeServer" ng-if="!bridge.error">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<h2 class="panel-title">Add a Vera device</h2>
|
<h2 class="panel-title">Add Bridge Device for a Vera Device</h2>
|
||||||
</div>
|
</div>
|
||||||
<ul class="list-group">
|
<ul class="list-group">
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<form class="form-horizontal" ng-submit="addDevice()">
|
<form class="form-horizontal">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-xs-12 col-sm-2 control-label" for="device-name">Name
|
<label class="col-xs-12 col-sm-2 control-label" for="device-name">Name
|
||||||
</label>
|
</label>
|
||||||
@@ -115,8 +139,8 @@
|
|||||||
<input type="text" class="form-control" id="device-name"
|
<input type="text" class="form-control" id="device-name"
|
||||||
ng-model="device.name" placeholder="Device Name">
|
ng-model="device.name" placeholder="Device Name">
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="col-xs-4 col-sm-2 btn btn-primary">
|
<button type="submit" class="col-xs-4 col-sm-2 btn btn-primary" ng-click="addDevice()">
|
||||||
Add Device</button>
|
Add Bridge Device</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@@ -127,6 +151,8 @@
|
|||||||
<textarea rows="3" class="form-control" id="device-on-url"
|
<textarea rows="3" class="form-control" id="device-on-url"
|
||||||
ng-model="device.onUrl" placeholder="URL to turn device on"></textarea>
|
ng-model="device.onUrl" placeholder="URL to turn device on"></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
<button class="btn btn-danger" ng-click="clearDevice()">
|
||||||
|
Clear Device</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
<li role="presentation" class="active"><a href="#/verascenes">Vera Scenes</a></li>
|
<li role="presentation" class="active"><a href="#/verascenes">Vera Scenes</a></li>
|
||||||
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>
|
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>
|
||||||
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonydevices">Harmony Devices</a></li>
|
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonydevices">Harmony Devices</a></li>
|
||||||
|
<li ng-if="bridge.showNest" role="presentation"><a href="#/nest">Nest</a></li>
|
||||||
<li role="presentation"><a href="#/editor">Manual Add</a></li>
|
<li role="presentation"><a href="#/editor">Manual Add</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -13,12 +14,14 @@
|
|||||||
</div>
|
</div>
|
||||||
<ul class="list-group">
|
<ul class="list-group">
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<p class="text-muted">You can select a Vera scene and generate
|
<p class="text-muted">For any Vera Scene, use the action buttons to generate the device addition information below automatically.
|
||||||
the add scene box selections automatically.</p>
|
Then you can modify the name to anything you want that will be the keyword for Alexa. Click the 'Add Bridge Device' to finish that selection setup.
|
||||||
|
The 'Already Configured Vera Scenes' list below will show what is already setup for your Vera.</p>
|
||||||
|
|
||||||
<table class="table table-bordered table-striped table-hover">
|
<table class="table table-bordered table-striped table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th>Row</th>
|
||||||
<th>
|
<th>
|
||||||
<a href="" ng-click="order('name')">Name</a>
|
<a href="" ng-click="order('name')">Name</a>
|
||||||
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
|
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
|
||||||
@@ -30,14 +33,20 @@
|
|||||||
<th>
|
<th>
|
||||||
<a href="" ng-click="order('room')">Room</a>
|
<a href="" ng-click="order('room')">Room</a>
|
||||||
<span class="sortorder" ng-show="predicate === 'room'" ng-class="{reverse:reverse}"></span>
|
<span class="sortorder" ng-show="predicate === 'room'" ng-class="{reverse:reverse}"></span>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<a href="" ng-click="order('vera')">Vera</a>
|
||||||
|
<span class="sortorder" ng-show="predicate === 'vera'" ng-class="{reverse:reverse}"></span>
|
||||||
</th>
|
</th>
|
||||||
<th>Actions</th>
|
<th>Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tr ng-repeat="verascene in bridge.verascenes | availableId | orderBy:predicate:reverse">
|
<tr ng-repeat="verascene in bridge.verascenes | availableVeraSceneId | orderBy:predicate:reverse">
|
||||||
|
<td>{{$index+1}}</td>
|
||||||
<td>{{verascene.name}}</td>
|
<td>{{verascene.name}}</td>
|
||||||
<td>{{verascene.id}}</td>
|
<td>{{verascene.id}}</td>
|
||||||
<td>{{verascene.room}}</td>
|
<td>{{verascene.room}}</td>
|
||||||
|
<td>{{verascene.veraname}}</td>
|
||||||
<td>
|
<td>
|
||||||
<button class="btn btn-success" type="submit"
|
<button class="btn btn-success" type="submit"
|
||||||
ng-click="buildSceneUrls(verascene)">Generate
|
ng-click="buildSceneUrls(verascene)">Generate
|
||||||
@@ -48,13 +57,14 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<h2 class="panel-title">Already Configured Vera Scenes <a ng-click="toggleScenes()"><span class={{imgScenesUrl}} aria-hidden="true"></a></h2>
|
<h2 class="panel-title">Already Configured Vera Scenes <a ng-click="toggleButtons()"><span class={{imgButtonsUrl}} aria-hidden="true"></span></a></h2>
|
||||||
</div>
|
</div>
|
||||||
<ul ng-if="scenesVisible" class="list-group">
|
<ul ng-if="buttonsVisible" class="list-group">
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<table class="table table-bordered table-striped table-hover">
|
<table class="table table-bordered table-striped table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th>Row</th>
|
||||||
<th>
|
<th>
|
||||||
<a href="" ng-click="order('name')">Name</a>
|
<a href="" ng-click="order('name')">Name</a>
|
||||||
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
|
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
|
||||||
@@ -66,17 +76,23 @@
|
|||||||
<th>
|
<th>
|
||||||
<a href="" ng-click="order('room')">Room</a>
|
<a href="" ng-click="order('room')">Room</a>
|
||||||
<span class="sortorder" ng-show="predicate === 'room'" ng-class="{reverse:reverse}"></span>
|
<span class="sortorder" ng-show="predicate === 'room'" ng-class="{reverse:reverse}"></span>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<a href="" ng-click="order('vera')">Vera</a>
|
||||||
|
<span class="sortorder" ng-show="predicate === 'vera'" ng-class="{reverse:reverse}"></span>
|
||||||
</th>
|
</th>
|
||||||
<th>Actions</th>
|
<th>Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tr ng-repeat="verascene in bridge.verascenes | unavailableId | orderBy:predicate:reverse">
|
<tr ng-repeat="verascene in bridge.verascenes | unavailableVeraSceneId | orderBy:predicate:reverse">
|
||||||
|
<td>{{$index+1}}</td>
|
||||||
<td>{{verascene.name}}</td>
|
<td>{{verascene.name}}</td>
|
||||||
<td>{{verascene.id}}</td>
|
<td>{{verascene.id}}</td>
|
||||||
<td>{{verascene.room}}</td>
|
<td>{{verascene.room}}</td>
|
||||||
|
<td>{{verascene.veraname}}</td>
|
||||||
<td>
|
<td>
|
||||||
<button class="btn btn-danger" type="submit"
|
<button class="btn btn-danger" type="submit"
|
||||||
ng-click="deleteDeviceByMapId(harmonyactivity.id)">Delete</button>
|
ng-click="deleteDeviceByMapId(verascene.id, 'veraScene')">Delete</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
@@ -85,11 +101,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="panel panel-default bridgeServer" ng-if="!bridge.error">
|
<div class="panel panel-default bridgeServer" ng-if="!bridge.error">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<h2 class="panel-title">Add a Vera scene</h2>
|
<h2 class="panel-title">Add a Bridge Device for a Vera scene</h2>
|
||||||
</div>
|
</div>
|
||||||
<ul class="list-group">
|
<ul class="list-group">
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<form class="form-horizontal" ng-submit="addDevice()">
|
<form class="form-horizontal">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-xs-12 col-sm-2 control-label" for="device-name">Name
|
<label class="col-xs-12 col-sm-2 control-label" for="device-name">Name
|
||||||
</label>
|
</label>
|
||||||
@@ -98,8 +114,8 @@
|
|||||||
<input type="text" class="form-control" id="device-name"
|
<input type="text" class="form-control" id="device-name"
|
||||||
ng-model="device.name" placeholder="Device Name">
|
ng-model="device.name" placeholder="Device Name">
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="col-xs-4 col-sm-2 btn btn-primary">
|
<button type="submit" class="col-xs-4 col-sm-2 btn btn-primary" ng-click="addDevice()">
|
||||||
Add Scene</button>
|
Add Bridge Device</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@@ -110,6 +126,8 @@
|
|||||||
<textarea rows="3" class="form-control" id="device-on-url"
|
<textarea rows="3" class="form-control" id="device-on-url"
|
||||||
ng-model="device.onUrl" placeholder="URL to turn device on"></textarea>
|
ng-model="device.onUrl" placeholder="URL to turn device on"></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
<button class="btn btn-danger" ng-click="clearDevice()">
|
||||||
|
Clear Device</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|||||||
Reference in New Issue
Block a user